diff --git a/docs/lines.md b/docs/lines.md new file mode 100644 index 00000000..451c4053 --- /dev/null +++ b/docs/lines.md @@ -0,0 +1,62 @@ +# `lines([opt])` + +**Fetches all lines known to the HAFAS endpoint**, e.g. warnings about disruptions, planned construction work, and general notices about the operating situation. + +## Example + +As an example, we're going to use the [SVV profile](../p/svv): + +```js +const createClient = require('hafas-client') +const svvProfile = require('hafas-client/p/svv') + +const client = createClient(svvProfile, 'my-awesome-program') + +console.log(await client.lines('S1')) +``` + +```js +[ + { + "id": "obb-1-S1-V-j20-1", + "type": "line", + "name": "S1", + "public": true, + "mode": "train", + "product": "bahn-s-bahn", + "operator": { + "type": "operator", + "id": "montafonerbahn-ag", + "name": "Montafonerbahn AG" + }, + "directions": [ + "Bludenz Bahnhof", + "Bregenz Hafen Bahnhof", + "Lindau Hbf", + "Bregenz Bahnhof", + "Schruns Bahnhof", + "Lochau Bahnhof" + ], + }, + // … + { + "id": "svv-42-50-j20-2", + "type": "line", + "name": "S1", + "public": true, + "mode": "train", + "product": "bahn-s-bahn", + "operator": { + "type": "operator", + "id": "salzburg-ag-salzburger-lokalbahn", + "name": "Salzburg AG - Salzburger Lokalbahn" + }, + "directions": [ + "Lamprechtshausen Bahnhof", + "Salzburg Hauptbahnhof", + "Acharting S-Bahn", + "Weitwörth-Nussdorf Bahnhof" + ], + }, +] +``` diff --git a/docs/readme.md b/docs/readme.md index f416f487..e6fed89e 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -12,6 +12,7 @@ - [`radar(north, west, south, east, [opt])`](radar.md) – find all vehicles currently in a certain area - [`reachableFrom(address, [opt])`](reachable-from.md) – get all stations reachable from an address within `n` minutes - [`remarks([opt])`](remarks.md) – get all remarks +- [`lines(query, [opt])`](lines.md) – get all lines matching a name - [`serverInfo([opt])`](server-info.md) – fetch meta information from HAFAS ## Migrating from an old `hafas-client` version diff --git a/format/lines-req.js b/format/lines-req.js new file mode 100644 index 00000000..d56cb402 --- /dev/null +++ b/format/lines-req.js @@ -0,0 +1,12 @@ +'use strict' + +const formatLinesReq = (ctx, query) => { + return { + meth: 'LineMatch', + req: { + input: query, + } + } +} + +module.exports = formatLinesReq diff --git a/index.js b/index.js index c5283897..f9cdda55 100644 --- a/index.js +++ b/index.js @@ -3,6 +3,7 @@ const isObj = require('lodash/isObject') const sortBy = require('lodash/sortBy') const pRetry = require('p-retry') +const omit = require('lodash/omit') const defaultProfile = require('./lib/default-profile') const validateProfile = require('./lib/validate-profile') @@ -502,6 +503,34 @@ const createClient = (profile, userAgent, opt = {}) => { return res.msgL.map(w => profile.parseWarning(ctx, w)) } + const lines = async (query, opt = {}) => { + if (!isNonEmptyString(query)) { + throw new TypeError('query must be a non-empty string.') + } + + const req = profile.formatLinesReq({profile, opt}, query) + const { + res, common, + } = await profile.request({profile, opt}, userAgent, req) + + if (!Array.isArray(res.lineL)) return [] + const ctx = {profile, opt, common, res} + return res.lineL.map(l => { + const parseDirRef = i => (res.common.dirL[i] || {}).txt || null + return { + ...omit(l.line, ['id', 'fahrtNr']), + id: l.lineId, + // todo: what is locX? + directions: Array.isArray(l.dirRefL) + ? l.dirRefL.map(parseDirRef) + : null, + trips: Array.isArray(l.jnyL) + ? l.jnyL.map(t => profile.parseTrip(ctx, t)) + : null, + } + }) + } + const serverInfo = async (opt = {}) => { const {res, common} = await profile.request({profile, opt}, userAgent, { meth: 'ServerInfo', @@ -528,6 +557,7 @@ const createClient = (profile, userAgent, opt = {}) => { locations, stop, nearby, + lines, serverInfo, } if (profile.trip) client.trip = trip diff --git a/lib/default-profile.js b/lib/default-profile.js index f194d813..13401e14 100644 --- a/lib/default-profile.js +++ b/lib/default-profile.js @@ -11,6 +11,7 @@ const formatRadarReq = require('../format/radar-req') const formatReachableFromReq = require('../format/reachable-from-req') const formatRefreshJourneyReq = require('../format/refresh-journey-req') const formatRemarksReq = require('../format/remarks-req') +const formatLinesReq = require('../format/lines-req') const parseDateTime = require('../parse/date-time') const parsePlatform = require('../parse/platform') @@ -64,6 +65,7 @@ const defaultProfile = { formatReachableFromReq, formatRefreshJourneyReq, formatRemarksReq, + formatLinesReq, transformJourneysQuery: id, parseDateTime, diff --git a/tools/debug-cli/cli.js b/tools/debug-cli/cli.js index 2149c71d..7bca9408 100755 --- a/tools/debug-cli/cli.js +++ b/tools/debug-cli/cli.js @@ -40,6 +40,8 @@ const parseArgs = [ ['reachableFrom', 0, parseJsObject], ['reachableFrom', 1, parseJsObject], ['remarks', 0, parseJsObject], + ['lines', 0, toString], + ['lines', 1, parseJsObject], ['serverInfo', 0, parseJsObject], ]