From 39a626784bd11e95915e1e8c09ae1d0dbb4709ef Mon Sep 17 00:00:00 2001 From: Jannis R Date: Thu, 31 Oct 2019 20:08:56 +0100 Subject: [PATCH] request formatters via profile --- format/locations-req.js | 20 ++++++ format/nearby-req.js | 25 ++++++++ format/radar-req.js | 26 ++++++++ format/reachable-from-req.js | 22 +++++++ format/station-board-req.js | 26 ++++++++ format/stop-req.js | 12 ++++ format/trip-req.js | 19 ++++++ index.js | 120 ++++++----------------------------- lib/default-profile.js | 15 +++++ lib/validate-profile.js | 8 +++ 10 files changed, 194 insertions(+), 99 deletions(-) create mode 100644 format/locations-req.js create mode 100644 format/nearby-req.js create mode 100644 format/radar-req.js create mode 100644 format/reachable-from-req.js create mode 100644 format/station-board-req.js create mode 100644 format/stop-req.js create mode 100644 format/trip-req.js diff --git a/format/locations-req.js b/format/locations-req.js new file mode 100644 index 00000000..9f4a58df --- /dev/null +++ b/format/locations-req.js @@ -0,0 +1,20 @@ +'use strict' + +const formatLocationsReq = (ctx, query) => { + const {profile, opt} = ctx + + return { + cfg: {polyEnc: 'GPA'}, + meth: 'LocMatch', + req: {input: { + loc: { + type: profile.formatLocationFilter(opt.stops, opt.addresses, opt.poi), + name: opt.fuzzy ? query + '?' : query + }, + maxLoc: opt.results, + field: 'S' // todo: what is this? + }} + } +} + +module.exports = formatLocationsReq diff --git a/format/nearby-req.js b/format/nearby-req.js new file mode 100644 index 00000000..5daa87d0 --- /dev/null +++ b/format/nearby-req.js @@ -0,0 +1,25 @@ +'use strict' + +const nearbyReq = (ctx, location) => { + const {profile, opt} = ctx + + return { + cfg: {polyEnc: 'GPA'}, + meth: 'LocGeoPos', + req: { + ring: { + cCrd: { + x: profile.formatCoord(location.longitude), + y: profile.formatCoord(location.latitude) + }, + maxDist: opt.distance || -1, + minDist: 0 + }, + getPOIs: !!opt.poi, + getStops: !!opt.stops, + maxLoc: opt.results + } + } +} + +module.exports = nearbyReq diff --git a/format/radar-req.js b/format/radar-req.js new file mode 100644 index 00000000..b9bc5f8b --- /dev/null +++ b/format/radar-req.js @@ -0,0 +1,26 @@ +'use strict' + +const formatRadarReq = (ctx, north, west, south, east) => { + const {profile, opt} = ctx + + return { + meth: 'JourneyGeoPos', + req: { + maxJny: opt.results, + onlyRT: false, // todo: does this mean "only realtime"? + date: profile.formatDate(profile, opt.when), + time: profile.formatTime(profile, opt.when), + // todo: would a ring work here as well? + rect: profile.formatRectangle(profile, north, west, south, east), + perSize: opt.duration * 1000, + perStep: Math.round(opt.duration / Math.max(opt.frames, 1) * 1000), + ageOfReport: true, // todo: what is this? + jnyFltrL: [ + profile.formatProductsFilter(ctx, opt.products || {}) + ], + trainPosMode: 'CALC' // todo: what is this? what about realtime? + } + } +} + +module.exports = formatRadarReq diff --git a/format/reachable-from-req.js b/format/reachable-from-req.js new file mode 100644 index 00000000..23e27b45 --- /dev/null +++ b/format/reachable-from-req.js @@ -0,0 +1,22 @@ +'use strict' + +const formatReachableFromReq = (ctx, address) => { + const {profile, opt} = ctx + + return { + meth: 'LocGeoReach', + req: { + loc: profile.formatLocation(profile, address, 'address'), + maxDur: opt.maxDuration === null ? -1 : opt.maxDuration, + maxChg: opt.maxTransfers, + date: profile.formatDate(profile, opt.when), + time: profile.formatTime(profile, opt.when), + period: 120, // todo: what is this? + jnyFltrL: [ + profile.formatProductsFilter(ctx, opt.products || {}) + ] + } + } +} + +module.exports = formatReachableFromReq diff --git a/format/station-board-req.js b/format/station-board-req.js new file mode 100644 index 00000000..c9b28c5c --- /dev/null +++ b/format/station-board-req.js @@ -0,0 +1,26 @@ +'use strict' + +const formatStationBoardReq = (ctx, station, type) => { + const {profile, opt} = ctx + + const req = { + type, + date: profile.formatDate(profile, opt.when), + time: profile.formatTime(profile, opt.when), + stbLoc: station, + dirLoc: opt.direction ? profile.formatStation(opt.direction) : null, + jnyFltrL: [ + profile.formatProductsFilter(ctx, opt.products || {}) + ], + dur: opt.duration + } + if (profile.departuresGetPasslist) req.getPasslist = !!opt.stopovers + if (profile.departuresStbFltrEquiv) req.stbFltrEquiv = !opt.includeRelatedStations + + return { + meth: 'StationBoard', + req + } +} + +module.exports = formatStationBoardReq diff --git a/format/stop-req.js b/format/stop-req.js new file mode 100644 index 00000000..e44ab593 --- /dev/null +++ b/format/stop-req.js @@ -0,0 +1,12 @@ +'use strict' + +const formatStopReq = (ctx, stopRef) => { + return { + meth: 'LocDetails', + req: { + locL: [stopRef] + } + } +} + +module.exports = formatStopReq diff --git a/format/trip-req.js b/format/trip-req.js new file mode 100644 index 00000000..806551bb --- /dev/null +++ b/format/trip-req.js @@ -0,0 +1,19 @@ +'use strict' + +const formatTripReq = ({opt}, id, lineName) => { + return { + cfg: {polyEnc: 'GPA'}, + meth: 'JourneyDetails', + req: { + // todo: getTrainComposition + jid: id, + name: lineName, + // HAFAS apparently ignores the date in the trip ID and uses the `date` field. + // Thus, it will find a different trip if you pass the wrong date via `opt.when`. + // date: profile.formatDate(profile, opt.when), + getPolyline: !!opt.polyline + } + } +} + +module.exports = formatTripReq diff --git a/index.js b/index.js index f381da38..c54487fd 100644 --- a/index.js +++ b/index.js @@ -60,25 +60,10 @@ const createClient = (profile, userAgent, opt = {}) => { }, opt) opt.when = new Date(opt.when || Date.now()) if (Number.isNaN(+opt.when)) throw new Error('opt.when is invalid') - const products = profile.formatProductsFilter({profile}, opt.products || {}) - const dir = opt.direction ? profile.formatStation(opt.direction) : null - const req = { - type, - date: profile.formatDate(profile, opt.when), - time: profile.formatTime(profile, opt.when), - stbLoc: station, - dirLoc: dir, - jnyFltrL: [products], - dur: opt.duration - } - if (profile.departuresGetPasslist) req.getPasslist = !!opt.stopovers - if (profile.departuresStbFltrEquiv) req.stbFltrEquiv = !opt.includeRelatedStations + const req = profile.formatStationBoardReq({profile, opt}, station, type) - return profile.request({profile, opt}, userAgent, { - meth: 'StationBoard', - req - }) + return profile.request({profile, opt}, userAgent, req) .then(({res, common}) => { if (!Array.isArray(res.jnyL)) return [] @@ -297,19 +282,9 @@ const createClient = (profile, userAgent, opt = {}) => { linesOfStops: false // parse & expose lines at each stop/station? }, opt) - const f = profile.formatLocationFilter(opt.stops, opt.addresses, opt.poi) - return profile.request({profile, opt}, userAgent, { - cfg: {polyEnc: 'GPA'}, - meth: 'LocMatch', - req: {input: { - loc: { - type: f, - name: opt.fuzzy ? query + '?' : query - }, - maxLoc: opt.results, - field: 'S' // todo: what is this? - }} - }) + const req = profile.formatLocationsReq({profile, opt}, query) + + return profile.request({profile, opt}, userAgent, req) .then(({res, common}) => { if (!res.match || !Array.isArray(res.match.locL)) return [] @@ -326,12 +301,10 @@ const createClient = (profile, userAgent, opt = {}) => { opt = Object.assign({ linesOfStops: false // parse & expose lines at the stop/station? }, opt) - return profile.request({profile, opt}, userAgent, { - meth: 'LocDetails', - req: { - locL: [stop] - } - }) + + const req = profile.formatStopReq({profile, opt}, stop) + + return profile.request({profile, opt}, userAgent, req) .then(({res, common}) => { if (!res || !Array.isArray(res.locL) || !res.locL[0]) { // todo: proper stack trace? @@ -354,23 +327,9 @@ const createClient = (profile, userAgent, opt = {}) => { linesOfStops: false // parse & expose lines at each stop/station? }, opt) - return profile.request({profile, opt}, userAgent, { - cfg: {polyEnc: 'GPA'}, - meth: 'LocGeoPos', - req: { - ring: { - cCrd: { - x: profile.formatCoord(location.longitude), - y: profile.formatCoord(location.latitude) - }, - maxDist: opt.distance || -1, - minDist: 0 - }, - getPOIs: !!opt.poi, - getStops: !!opt.stops, - maxLoc: opt.results - } - }) + const req = profile.formatNearbyReq({profile, opt}, location) + + return profile.request({profile, opt}, userAgent, req) .then(({common, res}) => { if (!Array.isArray(res.locL)) return [] @@ -392,19 +351,9 @@ const createClient = (profile, userAgent, opt = {}) => { remarks: true // parse & expose hints & warnings? }, opt) - return profile.request({profile, opt}, userAgent, { - cfg: {polyEnc: 'GPA'}, - meth: 'JourneyDetails', - req: { - // todo: getTrainComposition - jid: id, - name: lineName, - // HAFAS apparently ignores the date in the trip ID and uses the `date` field. - // Thus, it will find a different trip if you pass the wrong date via `opt.when`. - // date: profile.formatDate(profile, opt.when), - getPolyline: !!opt.polyline - } - }) + const req = profile.formatTripReq({profile, opt}, id, lineName) + + return profile.request({profile, opt}, userAgent, req) .then(({common, res}) => { const ctx = {profile, opt, common, res} @@ -440,25 +389,9 @@ const createClient = (profile, userAgent, opt = {}) => { opt.when = new Date(opt.when || Date.now()) if (Number.isNaN(+opt.when)) throw new TypeError('opt.when is invalid') - const durationPerStep = opt.duration / Math.max(opt.frames, 1) * 1000 - return profile.request({profile, opt}, userAgent, { - meth: 'JourneyGeoPos', - req: { - maxJny: opt.results, - onlyRT: false, // todo: does this mean "only realtime"? - date: profile.formatDate(profile, opt.when), - time: profile.formatTime(profile, opt.when), - // todo: would a ring work here as well? - rect: profile.formatRectangle(profile, north, west, south, east), - perSize: opt.duration * 1000, - perStep: Math.round(durationPerStep), - ageOfReport: true, // todo: what is this? - jnyFltrL: [ - profile.formatProductsFilter({profile}, opt.products || {}) - ], - trainPosMode: 'CALC' // todo: what is this? what about realtime? - } - }) + const req = profile.formatRadarReq({profile, opt}, north, west, south, east) + + return profile.request({profile, opt}, userAgent, req) .then(({res, common}) => { if (!Array.isArray(res.jnyL)) return [] @@ -478,21 +411,10 @@ const createClient = (profile, userAgent, opt = {}) => { }, opt) if (Number.isNaN(+opt.when)) throw new TypeError('opt.when is invalid') + const req = profile.formatReachableFromReq({profile, opt}, address) + const refetch = () => { - return profile.request({profile, opt}, userAgent, { - meth: 'LocGeoReach', - req: { - loc: profile.formatLocation(profile, address, 'address'), - maxDur: opt.maxDuration === null ? -1 : opt.maxDuration, - maxChg: opt.maxTransfers, - date: profile.formatDate(profile, opt.when), - time: profile.formatTime(profile, opt.when), - period: 120, // todo: what is this? - jnyFltrL: [ - profile.formatProductsFilter({profile}, opt.products || {}) - ] - } - }) + return profile.request({profile, opt}, userAgent, req) .then(({res, common}) => { if (!Array.isArray(res.posL)) { const err = new Error('invalid response') diff --git a/lib/default-profile.js b/lib/default-profile.js index c75c2f56..a1cce89e 100644 --- a/lib/default-profile.js +++ b/lib/default-profile.js @@ -2,6 +2,14 @@ const request = require('../lib/request') +const formatStationBoardReq = require('../format/station-board-req') +const formatLocationsReq = require('../format/locations-req') +const formatStopReq = require('../format/stop-req') +const formatNearbyReq = require('../format/nearby-req') +const formatTripReq = require('../format/trip-req') +const formatRadarReq = require('../format/radar-req') +const formatReachableFromReq = require('../format/reachable-from-req') + const parseDateTime = require('../parse/date-time') const parsePlatform = require('../parse/platform') const parseProductsBitmask = require('../parse/products-bitmask') @@ -44,6 +52,13 @@ const defaultProfile = { addChecksum: false, addMicMac: false, + formatStationBoardReq, + formatLocationsReq, + formatStopReq, + formatNearbyReq, + formatTripReq, + formatRadarReq, + formatReachableFromReq, transformJourneysQuery: id, parseDateTime, diff --git a/lib/validate-profile.js b/lib/validate-profile.js index 27149cba..89b41b1b 100644 --- a/lib/validate-profile.js +++ b/lib/validate-profile.js @@ -7,6 +7,14 @@ const types = { request: 'function', transformReq: 'function', transformReqBody: 'function', + + formatStationBoardReq: 'function', + formatLocationsReq: 'function', + formatStopReq: 'function', + formatNearbyReq: 'function', + formatTripReq: 'function', + formatRadarReq: 'function', + formatReachableFromReq: 'function', transformJourneysQuery: 'function', products: 'array',