forked from TransportVic/TransportVic2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ptv-api.js
114 lines (94 loc) · 2.8 KB
/
ptv-api.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
const crypto = require('crypto')
const { ptvKeys } = require('./config.json')
const utils = require('./utils')
const cheerio = require('cheerio')
let blankKey = {ptvDevID: "", ptvKey: ""}
let pastResponseTimes = []
let ptvResponses = []
setInterval(() => {
let now = +new Date()
let hour = 1000 * 60 * 60
ptvResponses = ptvResponses.filter(resp => now - resp.time <= hour)
}, 1000 * 60)
function getPTVCreds() {
if (ptvKeys.length === 0) return blankKey
let key = ptvKeys[Math.floor(Math.random() * ptvKeys.length)]
return {
ptvDevID: key.devID,
ptvKey: key.key
}
}
function getURL(request) {
let {ptvDevID, ptvKey} = getPTVCreds()
request += (request.includes('?') ? '&' : '?') + 'devid=' + ptvDevID
let signature = crypto.createHmac('SHA1', ptvKey).update(request).digest('hex').toString('hex')
return 'https://timetableapi.ptv.vic.gov.au' + request + '&signature=' + signature
}
async function makeRequest(url, maxRetries=2, timeout=2400) {
try {
return await utils.getData('ptv-api', url, async () => {
let start = +new Date()
let data = {}, error
try {
data = JSON.parse(await utils.request(getURL(url), {
maxRetries,
timeout
}))
} catch (e) {
error = e
if (e.response) data = JSON.parse(e.response)
}
let end = +new Date()
let diff = end - start
pastResponseTimes = [...pastResponseTimes.slice(-39), diff]
if (data.Message === 'An error has occurred.') {
ptvResponses.push({
time: end,
fault: true
})
throw new Error('PTV API Fault')
} else {
ptvResponses.push({
time: end,
fault: false
})
}
if (error) throw error
return data
}, 5000)
} catch (e) {
if (e.message && e.message.toLowerCase().includes('network timeout')) {
pastResponseTimes = [...pastResponseTimes.slice(-99), e.timeoutDuration]
return null
} else {
throw e
}
}
}
async function getPTVKey(baseURL='https://ptv.vic.gov.au', timeout=6000) {
return await utils.getData('ptv-key', baseURL, async () => {
let ptvData = await utils.request(baseURL, {
timeout
})
let $ = cheerio.load(ptvData)
let key = $('#fetch-key').val()
return key
}, 1000 * 60 * 60)
}
function getAverageResponseTime() {
let counts = pastResponseTimes.length
let sum = pastResponseTimes.reduce((a, b) => a + b, 0)
let average = sum / counts
return average
}
function getFaultRate() {
let faulty = ptvResponses.filter(r => r.fault).length
return {
rate: faulty / ptvResponses.length * 100,
count: faulty
}
}
module.exports = makeRequest
module.exports.getPTVKey = getPTVKey
module.exports.getAverageResponseTime = getAverageResponseTime
module.exports.getFaultRate = getFaultRate