lib/request, index: use ctx object 💥

This commit is contained in:
Jannis R 2019-10-20 01:47:09 +02:00
parent fb7a5653e3
commit 252ce5b515
No known key found for this signature in database
GPG key ID: 0FE83946296A88A5
3 changed files with 73 additions and 61 deletions

116
index.js
View file

@ -44,7 +44,7 @@ const createClient = (profile, userAgent, opt = {}) => {
request
} = Object.assign({}, defaults, opt)
const _stationBoard = (station, type, parser, opt = {}) => {
const _stationBoard = (station, type, parse, opt = {}) => {
if (isObj(station)) station = profile.formatStation(station.id)
else if ('string' === typeof station) station = profile.formatStation(station)
else throw new TypeError('station must be an object or a string.')
@ -87,15 +87,17 @@ const createClient = (profile, userAgent, opt = {}) => {
}
if (profile.departuresGetPasslist) req.getPasslist = !!opt.stopovers
if (profile.departuresStbFltrEquiv) req.stbFltrEquiv = !opt.includeRelatedStations
return request(profile, userAgent, opt, {
return request({profile, opt}, userAgent, {
meth: 'StationBoard',
req
})
.then((d) => {
if (!Array.isArray(d.jnyL)) return []
const parse = parser(profile, opt, d)
return d.jnyL.map(parse)
.sort((a, b) => new Date(a.when) - new Date(b.when))
.then(({res, common}) => {
if (!Array.isArray(res.jnyL)) return []
const ctx = {profile, opt, common, res}
return res.jnyL.map(res => parse(ctx, res))
.sort((a, b) => new Date(a.when) - new Date(b.when)) // todo
})
}
@ -228,35 +230,35 @@ const createClient = (profile, userAgent, opt = {}) => {
if (profile.journeysNumF && opt.results !== null) query.numF = opt.results
if (profile.journeysOutFrwd) query.outFrwd = outFrwd
return request(profile, userAgent, opt, {
return request({profile, opt}, userAgent, {
cfg: {polyEnc: 'GPA'},
meth: 'TripSearch',
req: profile.transformJourneysQuery(query, opt)
req: profile.transformJourneysQuery({profile, opt}, query)
})
.then((d) => {
if (!Array.isArray(d.outConL)) return []
.then(({res, common}) => {
if (!Array.isArray(res.outConL)) return []
// todo: outConGrpL
const parse = profile.parseJourney(profile, opt, d)
const ctx = {profile, opt, common, res}
if (!earlierRef) earlierRef = d.outCtxScrB
if (!earlierRef) earlierRef = res.outCtxScrB
let latestDep = -Infinity
for (let j of d.outConL) {
j = parse(j)
journeys.push(j)
for (const rawJourney of res.outConL) {
const journey = profile.parseJourney(ctx, rawJourney)
journeys.push(journey)
if (opt.results !== null && journeys.length >= opt.results) { // collected enough
laterRef = d.outCtxScrF
laterRef = res.outCtxScrF
return {earlierRef, laterRef, journeys}
}
const dep = +new Date(j.legs[0].departure)
const dep = +new Date(journey.legs[0].departure) // todo
if (dep > latestDep) latestDep = dep
}
if (opt.results === null) return {earlierRef, laterRef, journeys}
const when = new Date(latestDep)
return more(when, d.outCtxScrF) // otherwise continue
return more(when, res.outCtxScrF) // otherwise continue
})
}
@ -275,7 +277,7 @@ const createClient = (profile, userAgent, opt = {}) => {
remarks: true // parse & expose hints & warnings?
}, opt)
return request(profile, userAgent, opt, {
return request({profile, opt}, userAgent, {
meth: 'Reconstruction',
req: {
ctxRecon: refreshToken,
@ -285,13 +287,13 @@ const createClient = (profile, userAgent, opt = {}) => {
getTariff: !!opt.tickets
}
})
.then((d) => {
if (!Array.isArray(d.outConL) || !d.outConL[0]) {
.then(({res, common}) => {
if (!Array.isArray(res.outConL) || !res.outConL[0]) {
throw new Error('invalid response')
}
const parse = profile.parseJourney(profile, opt, d)
return parse(d.outConL[0])
const ctx = {profile, opt, common, res}
return profile.parseJourney(ctx, res.outConL[0])
})
}
@ -309,7 +311,7 @@ const createClient = (profile, userAgent, opt = {}) => {
}, opt)
const f = profile.formatLocationFilter(opt.stops, opt.addresses, opt.poi)
return request(profile, userAgent, opt, {
return request({profile, opt}, userAgent, {
cfg: {polyEnc: 'GPA'},
meth: 'LocMatch',
req: {input: {
@ -321,10 +323,11 @@ const createClient = (profile, userAgent, opt = {}) => {
field: 'S' // todo: what is this?
}}
})
.then((d) => {
if (!d.match || !Array.isArray(d.match.locL)) return []
const parse = profile.parseLocation
return d.match.locL.map(loc => parse(profile, opt, d, loc))
.then(({res, common}) => {
if (!res.match || !Array.isArray(res.match.locL)) return []
const ctx = {profile, opt, common, res}
return res.match.locL.map(loc => profile.parseLocation(ctx, loc))
})
}
@ -336,18 +339,20 @@ const createClient = (profile, userAgent, opt = {}) => {
opt = Object.assign({
linesOfStops: false // parse & expose lines at the stop/station?
}, opt)
return request(profile, userAgent, opt, {
return request({profile, opt}, userAgent, {
meth: 'LocDetails',
req: {
locL: [stop]
}
})
.then((d) => {
if (!d || !Array.isArray(d.locL) || !d.locL[0]) {
.then(({res, common}) => {
if (!res || !Array.isArray(res.locL) || !res.locL[0]) {
// todo: proper stack trace?
throw new Error('invalid response')
}
return profile.parseLocation(profile, opt, d, d.locL[0])
const ctx = {profile, opt, res, common}
return profile.parseLocation(ctx, res.locL[0])
})
}
@ -362,7 +367,7 @@ const createClient = (profile, userAgent, opt = {}) => {
linesOfStops: false // parse & expose lines at each stop/station?
}, opt)
return request(profile, userAgent, opt, {
return request({profile, opt}, userAgent, {
cfg: {polyEnc: 'GPA'},
meth: 'LocGeoPos',
req: {
@ -379,10 +384,11 @@ const createClient = (profile, userAgent, opt = {}) => {
maxLoc: opt.results
}
})
.then((d) => {
if (!Array.isArray(d.locL)) return []
const parse = profile.parseNearby
return d.locL.map(loc => parse(profile, opt, d, loc))
.then(({common, res}) => {
if (!Array.isArray(res.locL)) return []
const ctx = {profile, opt, common, res}
return res.locL.map(loc => profile.parseNearby(ctx, loc))
})
}
@ -399,7 +405,7 @@ const createClient = (profile, userAgent, opt = {}) => {
remarks: true // parse & expose hints & warnings?
}, opt)
return request(profile, userAgent, opt, {
return request({profile, opt}, userAgent, {
cfg: {polyEnc: 'GPA'},
meth: 'JourneyDetails',
req: {
@ -412,16 +418,16 @@ const createClient = (profile, userAgent, opt = {}) => {
getPolyline: !!opt.polyline
}
})
.then((d) => {
const parse = profile.parseJourneyLeg(profile, opt, d)
.then(({common, res}) => {
const ctx = {profile, opt, common, res}
const rawLeg = { // pretend the leg is contained in a journey
type: 'JNY',
dep: minBy(d.journey.stopL, 'idx'),
arr: maxBy(d.journey.stopL, 'idx'),
jny: d.journey
dep: minBy(res.journey.stopL, 'idx'),
arr: maxBy(res.journey.stopL, 'idx'),
jny: res.journey
}
const trip = parse(d.journey, rawLeg, !!opt.stopovers)
const trip = profile.parseJourneyLeg(ctx, rawLeg, res.journey.date)
trip.id = trip.tripId
delete trip.tripId
return trip
@ -448,7 +454,7 @@ const createClient = (profile, userAgent, opt = {}) => {
if (Number.isNaN(+opt.when)) throw new TypeError('opt.when is invalid')
const durationPerStep = opt.duration / Math.max(opt.frames, 1) * 1000
return request(profile, userAgent, opt, {
return request({profile, opt}, userAgent, {
meth: 'JourneyGeoPos',
req: {
maxJny: opt.results,
@ -466,11 +472,11 @@ const createClient = (profile, userAgent, opt = {}) => {
trainPosMode: 'CALC' // todo: what is this? what about realtime?
}
})
.then((d) => {
if (!Array.isArray(d.jnyL) || d.jnyL.length === 0) return []
.then(({res, common}) => {
if (!Array.isArray(res.jnyL)) return []
const parse = profile.parseMovement(profile, opt, d)
return d.jnyL.map(parse)
const ctx = {profile, opt, common, res}
return res.jnyL.map(m => profile.parseMovement(ctx, m))
})
}
@ -486,7 +492,7 @@ const createClient = (profile, userAgent, opt = {}) => {
if (Number.isNaN(+opt.when)) throw new TypeError('opt.when is invalid')
const refetch = () => {
return request(profile, userAgent, opt, {
return request({profile, opt}, userAgent, {
meth: 'LocGeoReach',
req: {
loc: profile.formatLocation(profile, address, 'address'),
@ -500,8 +506,8 @@ const createClient = (profile, userAgent, opt = {}) => {
]
}
})
.then((d) => {
if (!Array.isArray(d.posL)) {
.then(({res, common}) => {
if (!Array.isArray(res.posL)) {
const err = new Error('invalid response')
err.shouldRetry = true
throw err
@ -509,8 +515,8 @@ const createClient = (profile, userAgent, opt = {}) => {
const byDuration = []
let i = 0, lastDuration = NaN
for (const pos of sortBy(d.posL, 'dur')) {
const loc = d.locations[pos.locX]
for (const pos of sortBy(res.posL, 'dur')) {
const loc = common.locations[pos.locX]
if (!loc) continue
if (pos.dur !== lastDuration) {
lastDuration = pos.dur

View file

@ -31,7 +31,7 @@ const formatLocation = require('../format/location')
const formatRectangle = require('../format/rectangle')
const filters = require('../format/filters')
const id = x => x
const id = (ctx, x) => x
const defaultProfile = {
salt: null,

View file

@ -30,14 +30,16 @@ const addErrorInfo = (err, errorCode, errorText) => {
}
}
const request = (profile, userAgent, opt, data) => {
const body = profile.transformReqBody({
const request = (ctx, userAgent, reqData) => {
const {profile, opt} = ctx
const body = profile.transformReqBody(ctx, {
lang: opt.language || 'en', // todo: is it `eng` actually?
svcReqL: [data]
svcReqL: [reqData]
})
if (DEBUG) console.error(JSON.stringify(body))
const req = profile.transformReq({
const req = profile.transformReq(ctx, {
method: 'post',
// todo: CORS? referrer policy?
body: JSON.stringify(body),
@ -106,7 +108,11 @@ const request = (profile, userAgent, opt, data) => {
throw err
}
return profile.parseCommon(profile, opt, b.svcResL[0].res)
const res = b.svcResL[0].res
return {
res,
common: profile.parseCommon({...ctx, res})
}
})
}