digital-im-regio-portal-client
Version:
Query information from the Digital im Regio portal in German Regio trains.
105 lines (93 loc) • 2.37 kB
JavaScript
const {fetch} = require('fetch-ponyfill')({
Promise: require('pinkie-promise')
})
const omit = require('lodash/omit')
const pick = require('lodash/pick')
const {DateTime} = require('luxon')
const endpoint = 'https://wifi-bahn.de/'
const userAgent = 'https://github.com/derhuerst/digital-im-regio-portal-client'
const request = (route, opt = {}) => {
if ('string' !== typeof route) throw new Error('route must be a string')
return fetch(endpoint + route, {
mode: 'cors',
redirect: 'follow',
headers: {
'User-Agent': userAgent,
...(opt.headers || {})
},
...opt
})
.then((res) => {
if (!res.ok) {
const err = new Error(res.statusText)
err.statusCode = res.status
throw err
}
return res.json()
})
}
const formatDate = (unixTime) => {
if ('number' !== typeof unixTime) return null
return DateTime.fromMillis(unixTime * 1000).toISO({
suppressMilliseconds: false
})
}
const parseStopover = (_) => {
const res = {
stop: {
type: 'stop',
...pick(_, ['id', 'name']),
ds100: _.shortTag, // todo: is it always the DS100 code?
location: {
latitude: _.lat,
longitude: _.lng
}
},
arrival: formatDate(_.approach),
arrivalPlatform: _.track || null,
departure: formatDate(_.departure),
departurePlatform: _.track || null,
...pick(_, ['status', 'message']), // todo: parse
distanceToNext: _.distances.next || null
}
if ('number' === typeof _.delay) {
if (res.arrival) {
res.arrival = formatDate(res.arrival + _.delay * 1000)
res.arrivalDelay = _.delay
}
if (res.departure) {
res.departure = formatDate(res.departure + _.delay * 1000)
res.departureDelay = _.delay
}
}
return res
}
const fetchStatus = () => {
return request('schedule.jason', {
headers: {'Accept': 'application/json'}
})
.then((res) => {
if (!res.type) {
throw new Error('got an empty response. are you in the train wifi?')
}
return {
...omit(res, [
'jobs', 'timestamp', 'validUntil', // todo: what are these for?
'lat', 'lng',
'stations',
'afz',
'cards'
]),
nextStopovers: res.stations.map(parseStopover),
position: {
latitude: res.lat,
longitude: res.lng
},
carriageUtilization: omit(res.afz, ['capacity']),
carriageCapacity: res.afz && res.afz.capacity || null,
simCards: res.cards
}
})
}
module.exports = fetchStatus