From 2f45f667938168cc87e1e4d0022fbbcede37ad11 Mon Sep 17 00:00:00 2001 From: Traines Date: Sat, 7 Dec 2024 18:29:16 +0000 Subject: [PATCH] /locations, /locations/nearby, fixes --- format/location-filter.js | 10 +++------ format/locations-req.js | 17 ++++---------- format/nearby-req.js | 25 ++++++--------------- index.js | 47 ++++++++++++++++++++------------------- lib/default-profile.js | 2 ++ lib/request.js | 11 +++++---- p/db/base.json | 2 ++ 7 files changed, 47 insertions(+), 67 deletions(-) diff --git a/format/location-filter.js b/format/location-filter.js index e7bec0ba..0993a0df 100644 --- a/format/location-filter.js +++ b/format/location-filter.js @@ -1,12 +1,8 @@ const formatLocationFilter = (stops, addresses, poi) => { - if (stops && addresses && poi) { - return 'ALL'; + if (!addresses && !poi) { // TODO other combos? + return 'HALTESTELLEN'; } - return ( - (stops ? 'S' : '') - + (addresses ? 'A' : '') - + (poi ? 'P' : '') - ); + return 'ALL'; }; export { diff --git a/format/locations-req.js b/format/locations-req.js index 704af61d..a261ca3f 100644 --- a/format/locations-req.js +++ b/format/locations-req.js @@ -1,19 +1,10 @@ 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? - }}, + return { + typ: profile.formatLocationFilter(opt.stops, opt.addresses, opt.poi), + suchbegriff: query, + limit: opt.results, }; }; diff --git a/format/nearby-req.js b/format/nearby-req.js index 5e4f8f7e..a01fad58 100644 --- a/format/nearby-req.js +++ b/format/nearby-req.js @@ -2,24 +2,13 @@ const formatNearbyReq = (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, - }, - locFltrL: [ - profile.formatProductsFilter(ctx, opt.products || {}), - ], - getPOIs: Boolean(opt.poi), - getStops: Boolean(opt.stops), - maxLoc: opt.results, - }, + long: location.longitude, + lat: location.latitude, + radius: opt.distance || undefined, + products: profile.formatProductsFilter(ctx, opt.products || {}), + // TODO getPOIs: Boolean(opt.poi), + // TODO getStops: Boolean(opt.stops), + maxNo: opt.results, }; }; diff --git a/index.js b/index.js index 83455a16..b7b0a92b 100644 --- a/index.js +++ b/index.js @@ -146,7 +146,7 @@ const createClient = (profile, userAgent, opt = {}) => { results: null, // number of journeys – `null` means "whatever HAFAS returns" via: null, // let journeys pass this station? stopovers: false, // return stations on the way? - transfers: -1, // maximum nr of transfers + transfers: null, // maximum nr of transfers transferTime: 0, // minimum time for a single transfer in minutes // todo: does this work with every endpoint? accessibility: 'none', // 'none', 'partial' or 'complete' @@ -189,17 +189,17 @@ const createClient = (profile, userAgent, opt = {}) => { // TODO opt.accessibility const query = { - //maxUmstiege: opt.transfers, - //minUmstiegszeit: opt.transferTime, + maxUmstiege: opt.transfers, + minUmstiegszeit: opt.transferTime, deutschlandTicketVorhanden: false, nurDeutschlandTicketVerbindungen: false, reservierungsKontingenteVorhanden: false, schnelleVerbindungen: true, sitzplatzOnly: false, abfahrtsHalt: from.lid, - /*zwischenhalte: opt.via + zwischenhalte: opt.via ? [{id: opt.via}] - : [],*/ + : null, ankunftsHalt: to.lid, produktgattungen: filters, bikeCarriage: opt.bike, @@ -208,11 +208,11 @@ const createClient = (profile, userAgent, opt = {}) => { // see rest.exe docs //ushrp: Boolean(opt.startWithWalking), }; - /*if (journeysRef) { TODO - query.ctxScr = journeysRef; - } else {*/ + if (journeysRef) { TODO + query.pagingReference = journeysRef; + } else { query.anfrageZeitpunkt = profile.formatTime(profile, when); - //} + } query.ankunftSuche = outFrwd ? 'ABFAHRT' : 'ANKUNFT'; if (opt.results !== null) { // TODO query.numF = opt.results; @@ -220,7 +220,8 @@ const createClient = (profile, userAgent, opt = {}) => { const {res, common} = await profile.request({profile, opt}, userAgent, { endpoint: profile.journeysEndpoint, - req: profile.transformJourneysQuery({profile, opt}, query), + body: profile.transformJourneysQuery({profile, opt}, query), + method: 'post' }); const ctx = {profile, opt, common, res}; const journeys = res.verbindungen @@ -425,16 +426,17 @@ const createClient = (profile, userAgent, opt = {}) => { entrances: true, // parse & expose entrances of stops/stations? linesOfStops: false, // parse & expose lines at each stop/station? }, opt); - const req = profile.formatLocationsReq({profile, opt}, query); - const {res, common} = await profile.request({profile, opt}, userAgent, req); - if (!res.match || !Array.isArray(res.match.locL)) { - return []; - } + const {res, common} = await profile.request({profile, opt}, userAgent, { + endpoint: profile.locationsEndpoint, + query: req, + method: 'get' + }); + const ctx = {profile, opt, common, res}; - return res.match.locL.map(loc => profile.parseLocation(ctx, loc)); + return res.map(loc => profile.parseLocation(ctx, loc)); }; const stop = async (stop, opt = {}) => { @@ -481,15 +483,14 @@ const createClient = (profile, userAgent, opt = {}) => { }, opt); const req = profile.formatNearbyReq({profile, opt}, location); + const {res, common} = await profile.request({profile, opt}, userAgent, { + endpoint: profile.nearbyEndpoint, + query: req, + method: 'get' + }); - const {res, common} = await profile.request({profile, opt}, userAgent, req); - if (!Array.isArray(res.locL)) { - return []; - } - - // todo: parse `.dur` – walking duration? const ctx = {profile, opt, common, res}; - const results = res.locL.map(loc => profile.parseNearby(ctx, loc)); + const results = res.map(loc => profile.parseLocation(ctx, loc)); return Number.isInteger(opt.results) ? results.slice(0, opt.results) : results; diff --git a/lib/default-profile.js b/lib/default-profile.js index 2723dd03..e64ef707 100644 --- a/lib/default-profile.js +++ b/lib/default-profile.js @@ -7,6 +7,7 @@ import {formatTripReq} from '../format/trip-req.js'; import {formatRefreshJourneyReq} from '../format/refresh-journey-req.js'; import {formatRemarksReq} from '../format/remarks-req.js'; import {formatLinesReq} from '../format/lines-req.js'; +import {formatNearbyReq} from '../format/nearby-req.js'; import {parseDateTime} from '../parse/date-time.js'; import {parsePlatform} from '../parse/platform.js'; @@ -64,6 +65,7 @@ const defaultProfile = { formatRefreshJourneyReq, formatRemarksReq, formatLinesReq, + formatNearbyReq, transformJourneysQuery: id, parseDateTime, diff --git a/lib/request.js b/lib/request.js index 3e995978..ce77f2b1 100644 --- a/lib/request.js +++ b/lib/request.js @@ -101,13 +101,13 @@ const request = async (ctx, userAgent, reqData) => { const endpoint = reqData.endpoint; delete reqData.endpoint; - const rawReqBody = profile.transformReqBody(ctx, reqData); + const rawReqBody = profile.transformReqBody(ctx, reqData.body); //console.log(rawReqBody, JSON.stringify(rawReqBody.req.reisende)); const req = profile.transformReq(ctx, { agent: getAgent(), - method: 'post', + method: reqData.method, // todo: CORS? referrer policy? - body: JSON.stringify(rawReqBody.req), + body: JSON.stringify(rawReqBody), headers: { 'Content-Type': 'application/json', 'Accept-Encoding': 'gzip, br, deflate', @@ -118,11 +118,10 @@ const request = async (ctx, userAgent, reqData) => { 'connection': 'keep-alive', // prevent excessive re-connecting }, redirect: 'follow', - query: {}, + query: reqData.query, }); - const url = endpoint + '?' + stringify(req.query); - + const url = endpoint + '?' + stringify(req.query, {arrayFormat: 'brackets', encodeValuesOnly: true}); const reqId = randomBytes(3) .toString('hex'); const fetchReq = new Request(url, req); diff --git a/p/db/base.json b/p/db/base.json index 6077f786..c206fc51 100644 --- a/p/db/base.json +++ b/p/db/base.json @@ -1,4 +1,6 @@ { "journeysEndpoint": "https://int.bahn.de/web/api/angebote/fahrplan", + "locationsEndpoint": "https://int.bahn.de/web/api/reiseloesung/orte", + "nearbyEndpoint": "https://int.bahn.de/web/api/reiseloesung/orte/nearby", "defaultLanguage": "en" }