diff --git a/index.js b/index.js index 4fd32d44..aa62a0ae 100644 --- a/index.js +++ b/index.js @@ -105,7 +105,7 @@ const createClient = (profile, userAgent, opt = {}) => { const {res} = await profile.request({profile, opt}, userAgent, req); const ctx = {profile, opt, common, res}; - const results = (res[resultsField] || res.items || res.bahnhofstafelAbfahrtPositionen || res.bahnhofstafelAnkunftPositionen) + const results = (res[resultsField] || res.items || res.bahnhofstafelAbfahrtPositionen || res.bahnhofstafelAnkunftPositionen || res.entries) .map(res => parse(ctx, res)); // TODO sort?, slice return { diff --git a/p/db/base.json b/p/db/base.json index a8b54809..01c44e0f 100644 --- a/p/db/base.json +++ b/p/db/base.json @@ -6,6 +6,6 @@ "nearbyEndpoint": "https://int.bahn.de/web/api/reiseloesung/orte/nearby", "tripEndpoint": "https://int.bahn.de/web/api/reiseloesung/fahrt", "regioGuideTripEndpoint": "https://regio-guide.de/@prd/zupo-travel-information/api/public/ri/journey/", - "boardEndpoint": "https://regio-guide.de/@prd/zupo-travel-information/api/public/ri/board/", + "boardEndpoint": "https://int.bahn.de/web/api/reiseloesung/", "defaultLanguage": "en" } diff --git a/p/db/index.js b/p/db/index.js index d7941ffc..3f6154b7 100644 --- a/p/db/index.js +++ b/p/db/index.js @@ -7,6 +7,7 @@ import {formatJourneysReq, formatRefreshJourneyReq} from './journeys-req.js'; import {formatTripReq} from './trip-req.js'; import {formatLocationFilter} from './location-filter.js'; import {formatLocationsReq} from './locations-req.js'; +import {formatStationBoardReq} from './station-board-req.js'; const profile = { ...baseProfile, @@ -19,6 +20,7 @@ const profile = { formatTripReq, formatLocationsReq, formatLocationFilter, + formatStationBoardReq, }; export { diff --git a/p/db/station-board-req.js b/p/db/station-board-req.js new file mode 100644 index 00000000..1b64d616 --- /dev/null +++ b/p/db/station-board-req.js @@ -0,0 +1,23 @@ +const formatStationBoardReq = (ctx, station, type) => { + const {profile, opt} = ctx; + + const maxVias = opt.vias ?? 0; + + return { + endpoint: profile.boardEndpoint, + path: type === 'departures' ? 'abfahrten' : 'ankuenfte', + query: { + ortExtId: station, + zeit: profile.formatTimeOfDay(profile, opt.when), + datum: profile.formatDate(profile, opt.when), + mitVias: maxVias !== 0 ? true : undefined, + maxVias, + verkehrsmittel: profile.formatProductsFilter(ctx, opt.products || {}), + }, + method: 'GET', + }; +}; + +export { + formatStationBoardReq, +}; diff --git a/parse/arrival-or-departure.js b/parse/arrival-or-departure.js index 9c45ef8c..4cc25f6c 100644 --- a/parse/arrival-or-departure.js +++ b/parse/arrival-or-departure.js @@ -10,22 +10,23 @@ const createParseArrOrDep = (prefix) => { const {profile, opt} = ctx; const cancelled = profile.parseCancelled(d); const res = { - tripId: d.journeyID || d.train?.journeyId || d.zuglaufId, - stop: profile.parseLocation(ctx, d.station || d.abfrageOrt), + tripId: d.journeyID || d.journeyId || d.train?.journeyId || d.zuglaufId, + stop: profile.parseLocation(ctx, d.station || d.abfrageOrt || d.bahnhofsId), ...profile.parseWhen( ctx, null, - d.timeSchedule || d.time || d.abgangsDatum || d.ankunftsDatum, - d.timeType != 'SCHEDULE' ? d.timePredicted || d.time || d.ezAbgangsDatum || d.ezAnkunftsDatum : null, + d.timeSchedule || d.time || d.zeit || d.abgangsDatum || d.ankunftsDatum, + d.timeType != 'SCHEDULE' ? d.timePredicted || d.time || d.ezZeit || d.ezAbgangsDatum || d.ezAnkunftsDatum : null, cancelled), - ...profile.parsePlatform(ctx, d.platformSchedule || d.platform || d.gleis, d.platformPredicted || d.platform || d.ezGleis, cancelled), + ...profile.parsePlatform(ctx, d.platformSchedule || d.gleis || d.platform || d.ezGleis, d.platformPredicted || d.platform || d.ezGleis, cancelled), // prognosisType: TODO - direction: d.transport?.direction?.stopPlaces?.length > 0 && profile.parseStationName(ctx, d.transport?.direction?.stopPlaces[0].name) || profile.parseStationName(ctx, d.destination?.name || d.richtung) || null, + direction: d.transport?.direction?.stopPlaces?.length > 0 && profile.parseStationName(ctx, d.transport?.direction?.stopPlaces[0].name) || profile.parseStationName(ctx, d.destination?.name || d.richtung || d.terminus) || null, provenance: profile.parseStationName(ctx, d.transport?.origin?.name || d.origin?.name || d.abgangsOrt?.name) || null, line: profile.parseLine(ctx, d) || null, - remarks: [], + remarks: profile.parseRemarks(ctx, d), origin: profile.parseLocation(ctx, d.transport?.origin || d.origin) || null, destination: profile.parseLocation(ctx, d.transport?.destination || d.destination) || null, + vias: d.ueber, // loadFactor: profile.parseArrOrDepWithLoadFactor(ctx, d) }; diff --git a/parse/line.js b/parse/line.js index 65be7189..d544de93 100644 --- a/parse/line.js +++ b/parse/line.js @@ -2,12 +2,12 @@ import slugg from 'slugg'; const parseLine = (ctx, p) => { const profile = ctx.profile; - const fahrtNr = p.verkehrsmittel?.nummer || p.transport?.number || p.train?.no || p.no || ((p.risZuglaufId || '') + '_').split('_')[1] || p.verkehrsmittelNummer || ((p.mitteltext || '') + ' ').split(' ')[1] || ((p.zugName || '') + ' ').split(' ')[1]; + const fahrtNr = p.verkehrsmittel?.nummer || p.transport?.number || p.train?.no || p.no || ((p.risZuglaufId || '') + '_').split('_')[1] || p.verkehrsmittelNummer || ((p.verkehrmittel.langText || '') + ' ').split(' ')[1] || ((p.mitteltext || '') + ' ').split(' ')[1] || ((p.zugName || '') + ' ').split(' ')[1]; const res = { type: 'line', - id: slugg(p.verkehrsmittel?.langText || p.transport?.journeyDescription || p.risZuglaufId || p.train && p.train.category + ' ' + p.train.lineName + ' ' + p.train.no || p.no && p.name + ' ' + p.no || p.langtext || p.mitteltext || p.zugName), // TODO terrible + id: slugg(p.verkehrsmittel?.langText || p.verkehrmittel?.langText || p.transport?.journeyDescription || p.risZuglaufId || p.train && p.train.category + ' ' + p.train.lineName + ' ' + p.train.no || p.no && p.name + ' ' + p.no || p.langtext || p.mitteltext || p.zugName), // TODO terrible fahrtNr: String(fahrtNr), - name: p.verkehrsmittel?.langText || p.verkehrsmittel?.name || p.zugName || p.transport && p.transport.category + ' ' + p.transport.line || p.train && p.train.category + ' ' + p.train.lineName || p.name || p.mitteltext || p.langtext, + name: p.verkehrsmittel?.langText || p.verkehrsmittel?.name || p.verkehrmittel?.name || p.verkehrmittel?.langText || p.zugName || p.transport && p.transport.category + ' ' + p.transport.line || p.train && p.train.category + ' ' + p.train.lineName || p.name || p.mitteltext || p.langtext, public: true, }; @@ -15,7 +15,7 @@ const parseLine = (ctx, p) => { if (adminCode) { res.adminCode = adminCode; } - res.productName = p.verkehrsmittel?.kurzText || p.transport?.category || p.train?.category || p.category || p.kurztext; + res.productName = p.verkehrsmittel?.kurzText || p.verkehrmittel?.kurzText || p.transport?.category || p.train?.category || p.category || p.kurztext; const foundProduct = profile.products.find(pp => pp.vendo == p.verkehrsmittel?.produktGattung || pp.ris == p.transport?.type || pp.ris == p.train?.type || pp.ris == p.type || pp.ris_alt == p.train?.type || pp.ris_alt == p.type || pp.dbnav_short == p.produktGattung); res.mode = foundProduct?.mode; res.product = foundProduct?.id; diff --git a/parse/location.js b/parse/location.js index 49427426..e3725426 100644 --- a/parse/location.js +++ b/parse/location.js @@ -13,6 +13,10 @@ const parseLocation = (ctx, l) => { return null; } + if (typeof l === 'string') { + return {type: 'station', id: l}; + } + const lid = parse(l.id || l.locationId, {delimiter: '@'}); const res = { type: 'location', diff --git a/parse/remarks.js b/parse/remarks.js index aa082803..b6a53345 100644 --- a/parse/remarks.js +++ b/parse/remarks.js @@ -13,6 +13,7 @@ const parseRemarks = (ctx, ref) => { ref.hims || [], ref.serviceNotiz && [ref.serviceNotiz] || [], ref.messages || [], + ref.meldungen || [], ref.meldungenAsObject || [], ref.attributNotizen || [], ref.attributes || [], @@ -202,11 +203,16 @@ const parseRemarks = (ctx, ref) => { */ const parseCancelled = (ref) => { - return ref.canceled || ref.cancelled || ref.journeyCancelled || (ref.risNotizen || ref.echtzeitNotizen) && Boolean((ref.risNotizen || ref.echtzeitNotizen).find(r => r.key == 'text.realtime.stop.cancelled' - || r.type == 'HALT_AUSFALL' - || r.text == 'Halt entfällt' - || r.text == 'Stop cancelled', - )); + return ref.canceled + || ref.cancelled + || ref.journeyCancelled + || (ref.risNotizen || ref.echtzeitNotizen || ref.meldungen) && Boolean( + (ref.risNotizen || ref.echtzeitNotizen || ref.meldungen).find(r => r.key == 'text.realtime.stop.cancelled' + || r.type == 'HALT_AUSFALL' + || r.text == 'Halt entfällt' + || r.text == 'Stop cancelled', + ), + ); }; export {