-
Notifications
You must be signed in to change notification settings - Fork 9
/
index.js
151 lines (135 loc) · 3.49 KB
/
index.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
const cheerio = require('cheerio')
const superagent = require('superagent')
const PILOTWEB_BASE_URL = 'https://pilotweb.nas.faa.gov/PilotWeb'
/**
* A shortcut to the fetch() method
*/
const notams = (module.exports = (icaos, options = {}) => {
return notams.fetch(icaos, options)
})
/**
* Main fetching method; accepts one or more ICAO codes
*/
notams.fetch = async (icaos, options = {}) => {
const formatType = options.format || 'ICAO'
if (Array.isArray(icaos)) {
icaos = icaos.join(',')
}
const response = await superagent
.get(`${PILOTWEB_BASE_URL}/notamRetrievalByICAOAction.do`)
.query({
reportType: 'RAW',
method: 'displayByICAOs',
actionType: 'notamRetrievalByICAOs',
retrieveLocId: icaos,
formatType
})
return parse(response.text)
}
/**
* Fetch all NOTAMs of a specific type. Type can be one of:
* - ALLTFR
* - ALLGPS
* - ALLCARF
* - ALLSPECIALNOTICES
*/
notams.fetchAllByType = (type, format = 'ICAO') => fetchAll(type, format)
/**
* Fetch all NOTAMs
*/
notams.fetchAll = async (options = {}) => {
const [ tfrs, gps, carfs, specialNotices ] = [
await notams.fetchAllByType('ALLTFR', options.format),
await notams.fetchAllByType('ALLGPS', options.format),
await notams.fetchAllByType('ALLCARF', options.format),
await notams.fetchAllByType('ALLSPECIALNOTICES', options.format)
]
// Reconstruct/flatten the entire listing
const index = {}
;[ tfrs, gps, carfs, specialNotices ].map(notams => {
notams.map(notam => {
if (index[notam.icao] === undefined) {
index[notam.icao] = []
}
index[notam.icao].push(...notam.notams)
})
})
// Reformat the output
return Object.keys(index).map(icao => {
return {
icao: icao,
notams: index[icao]
}
})
}
/**
* Helper method for the above fetchAll method
*/
const fetchAll = async (queryType, formatType) => {
const response = await superagent
.get(`${PILOTWEB_BASE_URL}/noticesAction.do`)
.query({
reportType: 'RAW',
queryType,
formatType
})
const parsed = parse(response.text)
return parsed.map(r => ({
icao: r.icao,
notams: r.notams.map(n => {
return {
text: n,
type: {
ALLTFR: 'TFR',
ALLGPS: 'GPS',
ALLCARF: 'CARF',
ALLSPECIALNOTICES: 'Special Notice'
}[queryType]
}
})
}))
}
/**
* Extract the NOTAM text from the given page element
*/
const extractNotams = $el => {
const icao = $el.find('a').attr('name')
let $next = $el.parent().next()
const notams = []
while (true) {
const titleText = $next.find('#resultsTitleLeft').html()
const summaryText = $next.find('#alertFont').html()
// 1. Stop if we hit the next ICAO section
// 2. Stop at the end of the reports
if (titleText !== null || summaryText !== null) {
break
}
// Extract the current NOTAM text
const notamText = $next.find('pre').text()
if (notamText !== '') {
notams.push(notamText)
}
$next = $next.next()
}
return {
icao,
notams: notams
}
}
/**
* Parse the response HTML into JSON
*/
const parse = html => {
const $ = cheerio.load(html)
const $resultsElements = $('div[id="resultsHomeLeft"]').find(
'#resultsTitleLeft'
)
if (!$resultsElements) {
console.error('Unable to parse the #resultsTitleLeft page element')
return null
}
const results = $resultsElements.toArray().map(el => extractNotams($(el)))
if (results.length > 0) {
return results
}
}