/locations, /locations/nearby, fixes

This commit is contained in:
Traines 2024-12-07 18:29:16 +00:00
parent 2e094c2b78
commit 2f45f66793
7 changed files with 47 additions and 67 deletions

View file

@ -1,12 +1,8 @@
const formatLocationFilter = (stops, addresses, poi) => { const formatLocationFilter = (stops, addresses, poi) => {
if (stops && addresses && poi) { if (!addresses && !poi) { // TODO other combos?
return 'ALL'; return 'HALTESTELLEN';
} }
return ( return 'ALL';
(stops ? 'S' : '')
+ (addresses ? 'A' : '')
+ (poi ? 'P' : '')
);
}; };
export { export {

View file

@ -2,18 +2,9 @@ const formatLocationsReq = (ctx, query) => {
const {profile, opt} = ctx; const {profile, opt} = ctx;
return { return {
cfg: {polyEnc: 'GPA'}, typ: profile.formatLocationFilter(opt.stops, opt.addresses, opt.poi),
meth: 'LocMatch', suchbegriff: query,
req: {input: { limit: opt.results,
loc: {
type: profile.formatLocationFilter(opt.stops, opt.addresses, opt.poi),
name: opt.fuzzy
? query + '?'
: query,
},
maxLoc: opt.results,
field: 'S', // todo: what is this?
}},
}; };
}; };

View file

@ -2,24 +2,13 @@ const formatNearbyReq = (ctx, location) => {
const {profile, opt} = ctx; const {profile, opt} = ctx;
return { return {
cfg: {polyEnc: 'GPA'}, long: location.longitude,
meth: 'LocGeoPos', lat: location.latitude,
req: { radius: opt.distance || undefined,
ring: { products: profile.formatProductsFilter(ctx, opt.products || {}),
cCrd: { // TODO getPOIs: Boolean(opt.poi),
x: profile.formatCoord(location.longitude), // TODO getStops: Boolean(opt.stops),
y: profile.formatCoord(location.latitude), maxNo: opt.results,
},
maxDist: opt.distance || -1,
minDist: 0,
},
locFltrL: [
profile.formatProductsFilter(ctx, opt.products || {}),
],
getPOIs: Boolean(opt.poi),
getStops: Boolean(opt.stops),
maxLoc: opt.results,
},
}; };
}; };

View file

@ -146,7 +146,7 @@ const createClient = (profile, userAgent, opt = {}) => {
results: null, // number of journeys `null` means "whatever HAFAS returns" results: null, // number of journeys `null` means "whatever HAFAS returns"
via: null, // let journeys pass this station? via: null, // let journeys pass this station?
stopovers: false, // return stations on the way? 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 transferTime: 0, // minimum time for a single transfer in minutes
// todo: does this work with every endpoint? // todo: does this work with every endpoint?
accessibility: 'none', // 'none', 'partial' or 'complete' accessibility: 'none', // 'none', 'partial' or 'complete'
@ -189,17 +189,17 @@ const createClient = (profile, userAgent, opt = {}) => {
// TODO opt.accessibility // TODO opt.accessibility
const query = { const query = {
//maxUmstiege: opt.transfers, maxUmstiege: opt.transfers,
//minUmstiegszeit: opt.transferTime, minUmstiegszeit: opt.transferTime,
deutschlandTicketVorhanden: false, deutschlandTicketVorhanden: false,
nurDeutschlandTicketVerbindungen: false, nurDeutschlandTicketVerbindungen: false,
reservierungsKontingenteVorhanden: false, reservierungsKontingenteVorhanden: false,
schnelleVerbindungen: true, schnelleVerbindungen: true,
sitzplatzOnly: false, sitzplatzOnly: false,
abfahrtsHalt: from.lid, abfahrtsHalt: from.lid,
/*zwischenhalte: opt.via zwischenhalte: opt.via
? [{id: opt.via}] ? [{id: opt.via}]
: [],*/ : null,
ankunftsHalt: to.lid, ankunftsHalt: to.lid,
produktgattungen: filters, produktgattungen: filters,
bikeCarriage: opt.bike, bikeCarriage: opt.bike,
@ -208,11 +208,11 @@ const createClient = (profile, userAgent, opt = {}) => {
// see rest.exe docs // see rest.exe docs
//ushrp: Boolean(opt.startWithWalking), //ushrp: Boolean(opt.startWithWalking),
}; };
/*if (journeysRef) { TODO if (journeysRef) { TODO
query.ctxScr = journeysRef; query.pagingReference = journeysRef;
} else {*/ } else {
query.anfrageZeitpunkt = profile.formatTime(profile, when); query.anfrageZeitpunkt = profile.formatTime(profile, when);
//} }
query.ankunftSuche = outFrwd ? 'ABFAHRT' : 'ANKUNFT'; query.ankunftSuche = outFrwd ? 'ABFAHRT' : 'ANKUNFT';
if (opt.results !== null) { if (opt.results !== null) {
// TODO query.numF = opt.results; // TODO query.numF = opt.results;
@ -220,7 +220,8 @@ const createClient = (profile, userAgent, opt = {}) => {
const {res, common} = await profile.request({profile, opt}, userAgent, { const {res, common} = await profile.request({profile, opt}, userAgent, {
endpoint: profile.journeysEndpoint, endpoint: profile.journeysEndpoint,
req: profile.transformJourneysQuery({profile, opt}, query), body: profile.transformJourneysQuery({profile, opt}, query),
method: 'post'
}); });
const ctx = {profile, opt, common, res}; const ctx = {profile, opt, common, res};
const journeys = res.verbindungen const journeys = res.verbindungen
@ -425,16 +426,17 @@ const createClient = (profile, userAgent, opt = {}) => {
entrances: true, // parse & expose entrances of stops/stations? entrances: true, // parse & expose entrances of stops/stations?
linesOfStops: false, // parse & expose lines at each stop/station? linesOfStops: false, // parse & expose lines at each stop/station?
}, opt); }, opt);
const req = profile.formatLocationsReq({profile, opt}, query); const req = profile.formatLocationsReq({profile, opt}, query);
const {res, common} = await profile.request({profile, opt}, userAgent, req); const {res, common} = await profile.request({profile, opt}, userAgent, {
if (!res.match || !Array.isArray(res.match.locL)) { endpoint: profile.locationsEndpoint,
return []; query: req,
} method: 'get'
});
const ctx = {profile, opt, common, res}; 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 = {}) => { const stop = async (stop, opt = {}) => {
@ -481,15 +483,14 @@ const createClient = (profile, userAgent, opt = {}) => {
}, opt); }, opt);
const req = profile.formatNearbyReq({profile, opt}, location); 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 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) return Number.isInteger(opt.results)
? results.slice(0, opt.results) ? results.slice(0, opt.results)
: results; : results;

View file

@ -7,6 +7,7 @@ import {formatTripReq} from '../format/trip-req.js';
import {formatRefreshJourneyReq} from '../format/refresh-journey-req.js'; import {formatRefreshJourneyReq} from '../format/refresh-journey-req.js';
import {formatRemarksReq} from '../format/remarks-req.js'; import {formatRemarksReq} from '../format/remarks-req.js';
import {formatLinesReq} from '../format/lines-req.js'; import {formatLinesReq} from '../format/lines-req.js';
import {formatNearbyReq} from '../format/nearby-req.js';
import {parseDateTime} from '../parse/date-time.js'; import {parseDateTime} from '../parse/date-time.js';
import {parsePlatform} from '../parse/platform.js'; import {parsePlatform} from '../parse/platform.js';
@ -64,6 +65,7 @@ const defaultProfile = {
formatRefreshJourneyReq, formatRefreshJourneyReq,
formatRemarksReq, formatRemarksReq,
formatLinesReq, formatLinesReq,
formatNearbyReq,
transformJourneysQuery: id, transformJourneysQuery: id,
parseDateTime, parseDateTime,

View file

@ -101,13 +101,13 @@ const request = async (ctx, userAgent, reqData) => {
const endpoint = reqData.endpoint; const endpoint = reqData.endpoint;
delete 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)); //console.log(rawReqBody, JSON.stringify(rawReqBody.req.reisende));
const req = profile.transformReq(ctx, { const req = profile.transformReq(ctx, {
agent: getAgent(), agent: getAgent(),
method: 'post', method: reqData.method,
// todo: CORS? referrer policy? // todo: CORS? referrer policy?
body: JSON.stringify(rawReqBody.req), body: JSON.stringify(rawReqBody),
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accept-Encoding': 'gzip, br, deflate', 'Accept-Encoding': 'gzip, br, deflate',
@ -118,11 +118,10 @@ const request = async (ctx, userAgent, reqData) => {
'connection': 'keep-alive', // prevent excessive re-connecting 'connection': 'keep-alive', // prevent excessive re-connecting
}, },
redirect: 'follow', 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) const reqId = randomBytes(3)
.toString('hex'); .toString('hex');
const fetchReq = new Request(url, req); const fetchReq = new Request(url, req);

View file

@ -1,4 +1,6 @@
{ {
"journeysEndpoint": "https://int.bahn.de/web/api/angebote/fahrplan", "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" "defaultLanguage": "en"
} }