mirror of
https://github.com/public-transport/db-vendo-client.git
synced 2025-11-04 18:16:45 +02:00
Compare commits
5 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
785f5fcc37 | ||
|
|
ca6ceabbed | ||
|
|
d0120439e6 | ||
|
|
c2216120c9 | ||
|
|
bdbf4f3761 |
9 changed files with 2060 additions and 19 deletions
9
.github/workflows/build.yml
vendored
9
.github/workflows/build.yml
vendored
|
|
@ -10,6 +10,9 @@ env:
|
||||||
REGISTRY: ghcr.io
|
REGISTRY: ghcr.io
|
||||||
IMAGE_NAME: ${{ github.repository }}
|
IMAGE_NAME: ${{ github.repository }}
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
id-token: write # for OIDC-based publishing to npm
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-push-docker:
|
build-and-push-docker:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
@ -53,7 +56,9 @@ jobs:
|
||||||
with:
|
with:
|
||||||
node-version: '20.x'
|
node-version: '20.x'
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
# for OIDC-based publishing to npm
|
||||||
|
- name: setup npm v11
|
||||||
|
run: npm install -g npm@11
|
||||||
|
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm publish --provenance --access public
|
- run: npm publish --provenance --access public
|
||||||
env:
|
|
||||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
||||||
12
p/db/base.json
Normal file
12
p/db/base.json
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"journeysEndpoint": "https://app.vendo.noncd.db.de/mob/angebote/fahrplan",
|
||||||
|
"bestpriceEndpoint": "https://app.vendo.noncd.db.de/mob/angebote/tagesbestpreis",
|
||||||
|
"refreshJourneysEndpointTickets": "https://app.vendo.noncd.db.de/mob/angebote/recon",
|
||||||
|
"refreshJourneysEndpointPolyline": "https://app.vendo.noncd.db.de/mob/trip/recon",
|
||||||
|
"locationsEndpoint": "https://app.vendo.noncd.db.de/mob/location/search",
|
||||||
|
"stopEndpoint": "https://app.vendo.noncd.db.de/mob/location/details/",
|
||||||
|
"nearbyEndpoint": "https://app.vendo.noncd.db.de/mob/location/nearby",
|
||||||
|
"tripEndpoint": "https://app.vendo.noncd.db.de/mob/zuglauf/",
|
||||||
|
"boardEndpoint": "https://app.vendo.noncd.db.de/mob/bahnhofstafel/",
|
||||||
|
"defaultLanguage": "en"
|
||||||
|
}
|
||||||
|
|
@ -1,35 +1,36 @@
|
||||||
import dbnavBase from '../dbnav/base.json' with { type: 'json' };
|
import base from './base.json' with { type: 'json' };
|
||||||
import {products} from '../../lib/products.js';
|
import {products} from '../../lib/products.js';
|
||||||
|
|
||||||
// journeys()
|
// journeys()
|
||||||
import {formatJourneysReq} from '../dbnav/journeys-req.js';
|
import {formatJourneysReq} from '../dbnav/journeys-req.js';
|
||||||
const {journeysEndpoint} = dbnavBase;
|
const {journeysEndpoint} = base;
|
||||||
|
const {bestpriceEndpoint} = base;
|
||||||
|
|
||||||
// refreshJourneys()
|
// refreshJourneys()
|
||||||
import {formatRefreshJourneyReq} from '../dbnav/journeys-req.js';
|
import {formatRefreshJourneyReq} from '../dbnav/journeys-req.js';
|
||||||
const {refreshJourneysEndpointTickets, refreshJourneysEndpointPolyline} = dbnavBase;
|
const {refreshJourneysEndpointTickets, refreshJourneysEndpointPolyline} = base;
|
||||||
|
|
||||||
// locations()
|
// locations()
|
||||||
import {formatLocationsReq} from '../dbnav/locations-req.js';
|
import {formatLocationsReq} from '../dbnav/locations-req.js';
|
||||||
import {formatLocationFilter} from '../dbnav/location-filter.js';
|
import {formatLocationFilter} from '../dbnav/location-filter.js';
|
||||||
const {locationsEndpoint} = dbnavBase;
|
const {locationsEndpoint} = base;
|
||||||
|
|
||||||
// stop()
|
// stop()
|
||||||
import {formatStopReq} from '../dbnav/stop-req.js';
|
import {formatStopReq} from '../dbnav/stop-req.js';
|
||||||
import {parseStop} from '../dbnav/parse-stop.js';
|
import {parseStop} from '../dbnav/parse-stop.js';
|
||||||
const {stopEndpoint} = dbnavBase;
|
const {stopEndpoint} = base;
|
||||||
|
|
||||||
// nearby()
|
// nearby()
|
||||||
import {formatNearbyReq} from '../dbnav/nearby-req.js';
|
import {formatNearbyReq} from '../dbnav/nearby-req.js';
|
||||||
const {nearbyEndpoint} = dbnavBase;
|
const {nearbyEndpoint} = base;
|
||||||
|
|
||||||
// trip()
|
// trip()
|
||||||
import {formatTripReq} from './trip-req.js';
|
import {formatTripReq} from './trip-req.js';
|
||||||
const {tripEndpoint} = dbnavBase;
|
const {tripEndpoint} = base;
|
||||||
|
|
||||||
// arrivals(), departures()
|
// arrivals(), departures()
|
||||||
import {formatStationBoardReq} from '../dbnav/station-board-req.js';
|
import {formatStationBoardReq} from '../dbnav/station-board-req.js';
|
||||||
const {boardEndpoint} = dbnavBase;
|
const {boardEndpoint} = base;
|
||||||
|
|
||||||
const profile = {
|
const profile = {
|
||||||
locale: 'de-DE',
|
locale: 'de-DE',
|
||||||
|
|
@ -39,6 +40,7 @@ const profile = {
|
||||||
|
|
||||||
formatJourneysReq,
|
formatJourneysReq,
|
||||||
journeysEndpoint,
|
journeysEndpoint,
|
||||||
|
bestpriceEndpoint,
|
||||||
|
|
||||||
formatRefreshJourneyReq,
|
formatRefreshJourneyReq,
|
||||||
refreshJourneysEndpointTickets, refreshJourneysEndpointPolyline,
|
refreshJourneysEndpointTickets, refreshJourneysEndpointPolyline,
|
||||||
|
|
|
||||||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "db-vendo-client",
|
"name": "db-vendo-client",
|
||||||
"version": "6.10.3",
|
"version": "6.10.5",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "db-vendo-client",
|
"name": "db-vendo-client",
|
||||||
"version": "6.10.3",
|
"version": "6.10.5",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"content-type": "^1.0.5",
|
"content-type": "^1.0.5",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "db-vendo-client",
|
"name": "db-vendo-client",
|
||||||
"description": "Client for bahn.de public transport APIs.",
|
"description": "Client for bahn.de public transport APIs.",
|
||||||
"version": "6.10.3",
|
"version": "6.10.5",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"files": [
|
"files": [
|
||||||
|
|
@ -95,7 +95,7 @@
|
||||||
"test-e2e": "VCR_OFF=true tap -t60 -j16 test/e2e/*.js",
|
"test-e2e": "VCR_OFF=true tap -t60 -j16 test/e2e/*.js",
|
||||||
"test-spelling": "cspell .",
|
"test-spelling": "cspell .",
|
||||||
"test": "npm run test-unit && npm run test-integration && npm run test-spelling",
|
"test": "npm run test-unit && npm run test-integration && npm run test-spelling",
|
||||||
"prepublishOnly": "npm run lint",
|
"prepublishOnly": "npm run lint && npm test",
|
||||||
"api": "node api.js"
|
"api": "node api.js"
|
||||||
},
|
},
|
||||||
"tap": {
|
"tap": {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,9 @@ const parseTickets = (ctx, j) => {
|
||||||
.flatMap(p => [
|
.flatMap(p => [
|
||||||
p.einfacheFahrt?.standard?.reisePosition,
|
p.einfacheFahrt?.standard?.reisePosition,
|
||||||
p.einfacheFahrt?.upsellEntgelt?.einfacheFahrt?.reisePosition,
|
p.einfacheFahrt?.upsellEntgelt?.einfacheFahrt?.reisePosition,
|
||||||
].filter(p => p)
|
p.einfacheFahrt?.upsellAngebote?.map(a => a.upsellEntgelt?.einfacheFahrt?.reisePosition),
|
||||||
|
].flatMap(p => p)
|
||||||
|
.filter(p => p)
|
||||||
.map(p => {
|
.map(p => {
|
||||||
p.reisePosition.teilpreis = Boolean(p.teilpreisInformationen?.length);
|
p.reisePosition.teilpreis = Boolean(p.teilpreisInformationen?.length);
|
||||||
return p.reisePosition;
|
return p.reisePosition;
|
||||||
|
|
@ -44,7 +46,7 @@ const parseTickets = (ctx, j) => {
|
||||||
amount: Math.round(s.preis?.betrag * 100),
|
amount: Math.round(s.preis?.betrag * 100),
|
||||||
currency: s.preis?.waehrung,
|
currency: s.preis?.waehrung,
|
||||||
},
|
},
|
||||||
firstClass: s.klasse == 'KLASSE_1' || s.premium || Boolean(s.nutzungsInformationen?.find(i => i.klasse == 'KLASSE_1')),
|
firstClass: s.klasse == 'KLASSE_1' || Boolean(s.nutzungsInformationen?.find(i => i.klasse == 'KLASSE_1')),
|
||||||
partialFare: s.teilpreis,
|
partialFare: s.teilpreis,
|
||||||
};
|
};
|
||||||
if (s.teilpreis) {
|
if (s.teilpreis) {
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ Depending on the configured profile, db-vendo-client will use multiple different
|
||||||
|
|
||||||
| Profile | `db` | `dbnav` | `dbweb` | `dbris` |
|
| Profile | `db` | `dbnav` | `dbweb` | `dbris` |
|
||||||
| ------------- | ------------- | ------------- | ------------- | ------------- |
|
| ------------- | ------------- | ------------- | ------------- | ------------- |
|
||||||
| no API key required | ✅ | ✅ | ✅ | ✅ | ❌ |
|
| no API key required | ✅ | ✅ | ✅ | ❌ |
|
||||||
| all above endpoints supported | ✅ | ✅ | except `stop()` | only boards |
|
| all above endpoints supported | ✅ | ✅ | except `stop()` | only boards |
|
||||||
| duration for boards | always 1h | always 1h | always 1h | up to 12h |
|
| duration for boards | always 1h | always 1h | always 1h | up to 12h |
|
||||||
| remarks | for boards only most important remarks | for boards only most important remarks | all remarks on boards and journeys | all remarks |
|
| remarks | for boards only most important remarks | for boards only most important remarks | all remarks on boards and journeys | all remarks |
|
||||||
|
|
@ -37,7 +37,7 @@ Depending on the configured profile, db-vendo-client will use multiple different
|
||||||
| adminCode/operator | only for journeys | only for journeys | only operator | ✅ |
|
| adminCode/operator | only for journeys | only for journeys | only operator | ✅ |
|
||||||
| stopovers | not in boards | not in boards | ✅ | ✅ |
|
| stopovers | not in boards | not in boards | ✅ | ✅ |
|
||||||
| assumed backend API stability | less stable | more stable | less stable | more stable |
|
| assumed backend API stability | less stable | more stable | less stable | more stable |
|
||||||
| quotas | 60 requests per minute (IPv4) | 60 requests per minute (IPv4) | aggressive blocking (IPv4/IPv6) | depends on API key |
|
| quotas | 60 requests per minute (IPv4), current backend possibly shut off soon | 60 requests per minute (IPv4), possibly aggressive blocking | aggressive blocking (IPv4/IPv6) | depends on API key |
|
||||||
|
|
||||||
|
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -17,7 +17,7 @@ const tripIdHafas = '2|#VN#1#ST#1738783727#PI#0#ZI#222242#TA#0#DA#70225#1S#80002
|
||||||
const tripIdRis = '20250207-e6b2807e-bb48-39f9-89eb-8491ebc4b32c';
|
const tripIdRis = '20250207-e6b2807e-bb48-39f9-89eb-8491ebc4b32c';
|
||||||
|
|
||||||
const reqDbNavExpected = {
|
const reqDbNavExpected = {
|
||||||
endpoint: 'https://app.services-bahn.de/mob/zuglauf/',
|
endpoint: 'https://app.vendo.noncd.db.de/mob/zuglauf/',
|
||||||
path: '2%7C%23VN%231%23ST%231738783727%23PI%230%23ZI%23222242%23TA%230%23DA%2370225%231S%238000237%231T%231317%23LS%238000261%23LT%232002%23PU%2380%23RT%231%23CA%23ICE%23ZE%231007%23ZB%23ICE%201007%23PC%230%23FR%238000237%23FT%231317%23TO%238000261%23TT%232002%23',
|
path: '2%7C%23VN%231%23ST%231738783727%23PI%230%23ZI%23222242%23TA%230%23DA%2370225%231S%238000237%231T%231317%23LS%238000261%23LT%232002%23PU%2380%23RT%231%23CA%23ICE%23ZE%231007%23ZB%23ICE%201007%23PC%230%23FR%238000237%23FT%231317%23TO%238000261%23TT%232002%23',
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/x.db.vendo.mob.zuglauf.v2+json',
|
'Accept': 'application/x.db.vendo.mob.zuglauf.v2+json',
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue