mirror of
https://github.com/public-transport/db-vendo-client.git
synced 2025-02-23 07:09:35 +02:00
DB profile
mostly copied from db-hafas
This commit is contained in:
parent
47b5ef7ed5
commit
4356032308
5 changed files with 255 additions and 1 deletions
109
p/db/index.js
Normal file
109
p/db/index.js
Normal file
|
@ -0,0 +1,109 @@
|
|||
'use strict'
|
||||
|
||||
const crypto = require('crypto')
|
||||
|
||||
const _formatStation = require('../../format/station')
|
||||
const _parseLine = require('../../parse/line')
|
||||
const {accessibility, bike} = require('../../format/filters')
|
||||
|
||||
const modes = require('./modes')
|
||||
const formatLoyaltyCard = require('./loyalty-cards').format
|
||||
|
||||
const transformReqBody = (body) => {
|
||||
body.client = {id: 'DB', v: '16040000', type: 'IPH', name: 'DB Navigator'}
|
||||
body.ext = 'DB.R15.12.a'
|
||||
body.ver = '1.15'
|
||||
body.auth = {type: 'AID', aid: 'n91dB8Z77MLdoR0K'}
|
||||
|
||||
return body
|
||||
}
|
||||
|
||||
const salt = 'bdI8UVj40K5fvxwf'
|
||||
const transformReq = (req) => {
|
||||
const hash = crypto.createHash('md5')
|
||||
hash.update(req.body + salt)
|
||||
|
||||
if (!req.query) req.query = {}
|
||||
req.query.checksum = hash.digest('hex')
|
||||
|
||||
return req
|
||||
}
|
||||
|
||||
const transformJourneysQuery = (query, opt) => {
|
||||
const filters = query.jnyFltrL
|
||||
if (opt.accessibility && accessibility[opt.accessibility]) {
|
||||
filters.push(accessibility[opt.accessibility])
|
||||
}
|
||||
if (opt.bike) filters.push(bike)
|
||||
|
||||
query.trfReq = {
|
||||
jnyCl: 2, // todo
|
||||
tvlrProf: [{
|
||||
type: 'E',
|
||||
redtnCard: opt.loyaltyCard
|
||||
? formatLoyaltyCard(opt.loyaltyCard)
|
||||
: null
|
||||
}],
|
||||
cType: 'PK'
|
||||
}
|
||||
|
||||
return query
|
||||
}
|
||||
|
||||
const parseLine = (profile, l) => {
|
||||
const res = _parseLine(profile, l)
|
||||
|
||||
res.mode = res.product = null
|
||||
if ('class' in res) {
|
||||
const data = modes.bitmasks[parseInt(res.class)]
|
||||
if (data) {
|
||||
res.mode = data.mode
|
||||
res.product = data.product
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
const isIBNR = /^\d{6,}$/
|
||||
const formatStation = (id) => {
|
||||
if (!isIBNR.test(id)) throw new Error('station ID must be an IBNR.')
|
||||
return _formatStation(id)
|
||||
}
|
||||
|
||||
const defaultProducts = {
|
||||
suburban: true,
|
||||
subway: true,
|
||||
tram: true,
|
||||
bus: true,
|
||||
ferry: true,
|
||||
national: true,
|
||||
nationalExp: true,
|
||||
regional: true,
|
||||
regionalExp: true
|
||||
}
|
||||
|
||||
// todo: find option for absolute number of results
|
||||
|
||||
const dbProfile = {
|
||||
timezone: 'Europe/Berlin',
|
||||
endpoint: 'https://reiseauskunft.bahn.de/bin/mgate.exe',
|
||||
transformReqBody,
|
||||
transformReq,
|
||||
transformJourneysQuery,
|
||||
|
||||
// todo: parseLocation
|
||||
parseLine,
|
||||
|
||||
formatStation,
|
||||
formatProducts: (products) => {
|
||||
products = Object.assign(Object.create(null), defaultProducts, products)
|
||||
return {
|
||||
type: 'PROD',
|
||||
mode: 'INC',
|
||||
value: modes.stringifyBitmask(products) + ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = dbProfile
|
30
p/db/loyalty-cards.js
Normal file
30
p/db/loyalty-cards.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
'use strict'
|
||||
|
||||
const c = {
|
||||
NONE: Symbol('no loyaly card'),
|
||||
BAHNCARD: Symbol('Bahncard'),
|
||||
VORTEILSCARD: Symbol('VorteilsCard'),
|
||||
HALBTAXABO: Symbol('HalbtaxAbo'),
|
||||
VOORDEELURENABO: Symbol('Voordeelurenabo'),
|
||||
SHCARD: Symbol('SH-Card'),
|
||||
GENERALABONNEMENT: Symbol('General-Abonnement')
|
||||
}
|
||||
|
||||
// see https://gist.github.com/juliuste/202bb04f450a79f8fa12a2ec3abcd72d
|
||||
const formatLoyaltyCard = (data) => {
|
||||
if (data.type === c.BAHNCARD) {
|
||||
if (data.discount === 25) return c.class === 1 ? 1 : 2
|
||||
if (data.discount === 50) return c.class === 1 ? 3 : 4
|
||||
}
|
||||
if (data.type === c.VORTEILSCARD) return 9
|
||||
if (data.type === c.HALBTAXABO) return data.railplus ? 10 : 11
|
||||
if (data.type === c.VOORDEELURENABO) return data.railplus ? 12 : 13
|
||||
if (data.type === c.SHCARD) return 14
|
||||
if (data.type === c.GENERALABONNEMENT) return 15
|
||||
return 0
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
data: c,
|
||||
format: formatLoyaltyCard
|
||||
}
|
113
p/db/modes.js
Normal file
113
p/db/modes.js
Normal file
|
@ -0,0 +1,113 @@
|
|||
'use strict'
|
||||
|
||||
const m = {
|
||||
nationalExp: {
|
||||
bitmask: 1,
|
||||
name: 'InterCityExpress',
|
||||
short: 'ICE',
|
||||
mode: 'train',
|
||||
product: 'nationalExp'
|
||||
},
|
||||
national: {
|
||||
bitmask: 2,
|
||||
name: 'InterCity & EuroCity',
|
||||
short: 'IC/EC',
|
||||
mode: 'train',
|
||||
product: 'national'
|
||||
},
|
||||
regionalExp: {
|
||||
bitmask: 4,
|
||||
name: 'InterRegio',
|
||||
short: 'IR',
|
||||
mode: 'train',
|
||||
product: 'regionalExp'
|
||||
},
|
||||
regional: {
|
||||
bitmask: 8,
|
||||
name: 'RegionalExpress & Regio',
|
||||
short: 'RE/RB',
|
||||
mode: 'train',
|
||||
product: 'regional'
|
||||
},
|
||||
suburban: {
|
||||
bitmask: 16,
|
||||
name: 'S-Bahn',
|
||||
short: 'S',
|
||||
mode: 'train',
|
||||
product: 'suburban'
|
||||
},
|
||||
bus: {
|
||||
bitmask: 32,
|
||||
name: 'Bus',
|
||||
short: 'B',
|
||||
mode: 'bus',
|
||||
product: 'bus'
|
||||
},
|
||||
ferry: {
|
||||
bitmask: 64,
|
||||
name: 'Ferry',
|
||||
short: 'F',
|
||||
mode: 'ferry',
|
||||
product: 'ferry'
|
||||
},
|
||||
subway: {
|
||||
bitmask: 128,
|
||||
name: 'U-Bahn',
|
||||
short: 'U',
|
||||
mode: 'train',
|
||||
product: 'subway'
|
||||
},
|
||||
tram: {
|
||||
bitmask: 256,
|
||||
name: 'Tram',
|
||||
short: 'T',
|
||||
mode: 'tram',
|
||||
product: 'tram'
|
||||
},
|
||||
taxi: {
|
||||
bitmask: 512,
|
||||
name: 'Group Taxi',
|
||||
short: 'Taxi',
|
||||
mode: null, // todo
|
||||
product: 'taxi'
|
||||
},
|
||||
unknown: {
|
||||
bitmask: 0,
|
||||
name: 'unknown',
|
||||
short: '?',
|
||||
product: 'unknown'
|
||||
}
|
||||
}
|
||||
|
||||
m.bitmasks = []
|
||||
m.bitmasks[1] = m.nationalExp
|
||||
m.bitmasks[2] = m.national
|
||||
m.bitmasks[4] = m.regionalExp
|
||||
m.bitmasks[8] = m.regional
|
||||
m.bitmasks[16] = m.suburban
|
||||
m.bitmasks[32] = m.bus
|
||||
m.bitmasks[64] = m.ferry
|
||||
m.bitmasks[128] = m.subway
|
||||
m.bitmasks[256] = m.tram
|
||||
m.bitmasks[512] = m.taxi
|
||||
|
||||
// todo: move up
|
||||
m.stringifyBitmask = (products) => {
|
||||
let bitmask = 0
|
||||
for (let product in products) {
|
||||
if (products[product] === true) bitmask += m[product].bitmask
|
||||
}
|
||||
return bitmask
|
||||
}
|
||||
|
||||
// todo: move up
|
||||
m.parseBitmask = (bitmask) => {
|
||||
let products = {}, i = 1
|
||||
do {
|
||||
products[m.bitmasks[i].product] = !!(bitmask & i)
|
||||
i *= 2
|
||||
} while (m.bitmasks[i] && m.bitmasks[i].product)
|
||||
return products
|
||||
}
|
||||
|
||||
module.exports = m
|
|
@ -7,7 +7,8 @@
|
|||
"index.js",
|
||||
"lib",
|
||||
"parse",
|
||||
"format"
|
||||
"format",
|
||||
"p"
|
||||
],
|
||||
"author": "Jannis R <mail@jannisr.de>",
|
||||
"homepage": "https://github.com/derhuerst/hafas-client",
|
||||
|
|
|
@ -5,6 +5,7 @@ const tape = require('tape')
|
|||
const isRoughlyEqual = require('is-roughly-equal')
|
||||
|
||||
const createClient = require('..')
|
||||
const dbProfile = require('../p/db')
|
||||
const {
|
||||
findStation,
|
||||
assertValidStation,
|
||||
|
|
Loading…
Add table
Reference in a new issue