atmosx-nwws-parser 1.0.156 → 1.0.181
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/bootstrap.js +4 -0
- package/index.js +37 -4
- package/package.json +1 -1
- package/src/events.js +65 -43
- package/src/stanza.js +2 -2
- package/src/vtec.js +1 -1
- package/test.js +3 -0
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ npm install atmosx-nwws-parser
|
|
|
12
12
|
|
|
13
13
|
## Usage
|
|
14
14
|
```js
|
|
15
|
-
const AtmosXWireParser = require(`atmosx-nwws-parser`);
|
|
15
|
+
const AtmosXWireParser = require(`atmosx-nwws-parser`);
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
## Configuration and Initialization
|
|
@@ -25,6 +25,8 @@ let Client = new AtmosXWireParser({
|
|
|
25
25
|
onlyCap: false, // Set to true to only receive CAP messages only
|
|
26
26
|
betterEvents: true, // Set to true to receive better event handling
|
|
27
27
|
ugcPolygons: false, // Set to true to receive UGC Polygons instead of reading from raw products.
|
|
28
|
+
expiryCheck: true, // Set to true to check for expired alerts and remove them from the list
|
|
29
|
+
filteredAlerts: [] // Alerts you want to only log, leave empty to receive all alerts (Ex. ["Tornado Warning", "Radar Indicated Tornado Warning"])
|
|
28
30
|
},
|
|
29
31
|
xmpp: {
|
|
30
32
|
reconnect: true, // Set to true to enable automatic reconnection if you lose connection
|
|
@@ -32,6 +34,7 @@ let Client = new AtmosXWireParser({
|
|
|
32
34
|
},
|
|
33
35
|
cacheSettings: {
|
|
34
36
|
maxMegabytes: 2, // Maximum cache size in megabytes
|
|
37
|
+
readCache: false, // Set to true if you wish to reupload the cache from earlier (Now supports reading from CAP, SPS, and Alerts)
|
|
35
38
|
cacheDir: `./cache`, // Directory for cache files
|
|
36
39
|
},
|
|
37
40
|
authentication: {
|
package/bootstrap.js
CHANGED
|
@@ -78,6 +78,7 @@ module.exports.definitions = {
|
|
|
78
78
|
{ error: "unreachable-host", message: "The host could not be reached. Please check your internet connection or the host address.", code: "xmpp-error" },
|
|
79
79
|
{ error: "service-error", message: "An error occurred while connecting to the NOAA Weather Wire Service. Please try again later.", code: "xmpp-error" },
|
|
80
80
|
{ error: "no-database-dir", message: "Database directory is not set. Please set the databaseDir in the metadata.", code: "no-database" },
|
|
81
|
+
{ error: "rapid-reconnect", message: "The client is reconnecting too rapidly. Please wait a moment before trying again.", code: "xmpp-error" }
|
|
81
82
|
]
|
|
82
83
|
}
|
|
83
84
|
module.exports.settings = {
|
|
@@ -85,12 +86,15 @@ module.exports.settings = {
|
|
|
85
86
|
ugcPolygons: false,
|
|
86
87
|
onlyCap: false,
|
|
87
88
|
betterEvents: false,
|
|
89
|
+
expiryCheck: true,
|
|
90
|
+
filteredAlerts: [],
|
|
88
91
|
},
|
|
89
92
|
xmpp: {
|
|
90
93
|
reconnect: true,
|
|
91
94
|
reconnectInterval: 60,
|
|
92
95
|
},
|
|
93
96
|
cacheSettings: {
|
|
97
|
+
readCache: false,
|
|
94
98
|
maxMegabytes: 1,
|
|
95
99
|
cacheDir: false,
|
|
96
100
|
},
|
package/index.js
CHANGED
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
let loader = require(`./bootstrap.js`);
|
|
15
15
|
|
|
16
16
|
class NoaaWeatherWireServiceCore {
|
|
17
|
-
|
|
18
17
|
constructor(metadata={}) {
|
|
19
18
|
this.packages = loader.packages;
|
|
20
19
|
this.metadata = metadata;
|
|
@@ -25,6 +24,30 @@ class NoaaWeatherWireServiceCore {
|
|
|
25
24
|
loader.static.events.emit(`onError`, { error: error.stack || error.message || `An unknown error occurred`, code: `uncaught-exception` });
|
|
26
25
|
});
|
|
27
26
|
this.initializeDatabase([{ id: `C`, file: `USCounties` }, { id: `Z`, file: `ForecastZones` }, { id: `Z`, file: `FireZones` }, { id: `Z`, file: `OffShoreZones` }, { id: `Z`, file: `FireCounties` }, { id: `Z`, file: `Marine` }]);
|
|
27
|
+
|
|
28
|
+
if (loader.settings.cacheSettings.readCache && loader.settings.cacheSettings.cacheDir) {
|
|
29
|
+
let target = `${loader.settings.cacheSettings.cacheDir}/nwws-raw-category-defaults-raw-vtec.bin`;
|
|
30
|
+
let targetCap = `${loader.settings.cacheSettings.cacheDir}/nwws-raw-category-defaults-cap-vtec.bin`;
|
|
31
|
+
let targetStatements = `${loader.settings.cacheSettings.cacheDir}/nwws-raw-category-special-weather-statements-raw.bin`;
|
|
32
|
+
let targetMesoscale = `${loader.settings.cacheSettings.cacheDir}/nwws-raw-category-mesoscale-discussions-raw.bin`;
|
|
33
|
+
let targetStormReports = `${loader.settings.cacheSettings.cacheDir}/nwws-raw-category-local-storm-reports-raw.bin`;
|
|
34
|
+
if (loader.packages.fs.existsSync(target) && !loader.settings.alertSettings.onlyCap) {
|
|
35
|
+
this.forwardCustomStanza(loader.packages.fs.readFileSync(target, 'utf8'), { awipsid: 'alert', isCap: false, raw: true, issue: undefined });
|
|
36
|
+
}
|
|
37
|
+
if (loader.packages.fs.existsSync(targetCap) && loader.settings.alertSettings.onlyCap) {
|
|
38
|
+
this.forwardCustomStanza(loader.packages.fs.readFileSync(targetCap, 'utf8'), { awipsid: 'alert', isCap: true, raw: false, issue: undefined });
|
|
39
|
+
}
|
|
40
|
+
if (loader.packages.fs.existsSync(targetStatements)) {
|
|
41
|
+
this.forwardCustomStanza(loader.packages.fs.readFileSync(targetStatements, 'utf8'), { awipsid: 'SPS001', isCap: false, raw: true, issue: undefined });
|
|
42
|
+
}
|
|
43
|
+
if (loader.packages.fs.existsSync(targetMesoscale)) {
|
|
44
|
+
this.forwardCustomStanza(loader.packages.fs.readFileSync(targetMesoscale, 'utf8'), { awipsid: 'SWOMCD001', isCap: false, raw: true, issue: undefined });
|
|
45
|
+
}
|
|
46
|
+
if (loader.packages.fs.existsSync(targetStormReports)) {
|
|
47
|
+
this.forwardCustomStanza(loader.packages.fs.readFileSync(targetStormReports, 'utf8'), { awipsid: 'LSR001', isCap: false, raw: true, issue: undefined });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
28
51
|
setInterval(() => {
|
|
29
52
|
if (loader.settings.cacheSettings.cacheDir) { this.garbageCollect(loader.settings.cacheSettings.maxMegabytes || 1); }
|
|
30
53
|
if (loader.settings.xmpp.reconnect) { this.isReconnectEligible(loader.settings.xmpp.reconnectInterval) }
|
|
@@ -94,7 +117,7 @@ class NoaaWeatherWireServiceCore {
|
|
|
94
117
|
domain: `nwws-oi.weather.gov`,
|
|
95
118
|
username: metadata.username || ``,
|
|
96
119
|
password: metadata.password || ``,
|
|
97
|
-
})
|
|
120
|
+
})
|
|
98
121
|
}
|
|
99
122
|
|
|
100
123
|
/**
|
|
@@ -107,6 +130,14 @@ class NoaaWeatherWireServiceCore {
|
|
|
107
130
|
if (this.metadata.authentication.display == undefined) this.metadata.authentication.display = this.metadata.authentication.username || ``;
|
|
108
131
|
this.initializeClient({ username: this.metadata.authentication.username, password: this.metadata.authentication.password, display: this.metadata.authentication.display });
|
|
109
132
|
loader.static.session.on(`online`, async () => {
|
|
133
|
+
if (loader.static.lastConnect && (new Date().getTime() - loader.static.lastConnect) < 10 * 1000) {
|
|
134
|
+
setTimeout(async () => {
|
|
135
|
+
await loader.static.session.stop().catch(() => {});
|
|
136
|
+
await loader.static.session.start().catch(() => {});
|
|
137
|
+
}, 2 * 1000);
|
|
138
|
+
throw new Error(`rapid-reconnect`);
|
|
139
|
+
}
|
|
140
|
+
loader.static.lastConnect = new Date().getTime();
|
|
110
141
|
loader.cache.isConnected = true;
|
|
111
142
|
loader.static.session.send(loader.packages.xmpp.xml('presence', { to: `nwws@conference.nwws-oi.weather.gov/${this.metadata.authentication.display}`, xmlns: 'http://jabber.org/protocol/muc' }))
|
|
112
143
|
loader.static.session.send(loader.packages.xmpp.xml('presence', { to: `nwws@conference.nwws-oi.weather.gov`, type: 'available' }))
|
|
@@ -116,9 +147,11 @@ class NoaaWeatherWireServiceCore {
|
|
|
116
147
|
}
|
|
117
148
|
})
|
|
118
149
|
loader.static.session.on(`offline`, () => {
|
|
150
|
+
loader.static.session.stop().catch(() => {});
|
|
151
|
+
loader.cache.isConnected = false;
|
|
119
152
|
throw new Error(`unreachable-host`);
|
|
120
153
|
})
|
|
121
|
-
loader.static.session.on(`error`, (error) => {
|
|
154
|
+
loader.static.session.on(`error`, async (error) => {
|
|
122
155
|
throw new Error(error.message || `service-error`);
|
|
123
156
|
})
|
|
124
157
|
loader.static.session.on(`stanza`, (stanza) => {
|
|
@@ -220,7 +253,7 @@ class NoaaWeatherWireServiceCore {
|
|
|
220
253
|
*/
|
|
221
254
|
|
|
222
255
|
onEvent = function(event, listener) {
|
|
223
|
-
loader.static.events.on(event, listener)
|
|
256
|
+
loader.static.events.on(event, listener)
|
|
224
257
|
return () => { loader.static.events.off(event, listener); };
|
|
225
258
|
}
|
|
226
259
|
}
|
package/package.json
CHANGED
package/src/events.js
CHANGED
|
@@ -26,11 +26,14 @@ class NoaaWeatherWireServiceEvents {
|
|
|
26
26
|
let tags = [`No tags found`];
|
|
27
27
|
let eventName = event.properties.event
|
|
28
28
|
let dmgTheat = event.properties.parameters.thunderstormDamageThreat?.[0] || event.properties.parameters.tornadoDamageThreat?.[0] || `N/A`;
|
|
29
|
+
let torThreat = event.properties.parameters.tornadoDetection || `N/A`;
|
|
29
30
|
let description = event.properties.description.toLowerCase() || `No description available.`;
|
|
30
31
|
if (description.includes(`flash flood emergency`) && eventName == `Flash Flood Warning`) eventName = `Flash Flood Emergency`;
|
|
31
|
-
if (description.includes(`particularly dangerous situation`) && eventName == `Tornado Warning` && dmgTheat == `CONSIDERABLE`) eventName = `
|
|
32
|
-
if (description.includes(`particularly dangerous situation`) && eventName == `Tornado Watch`) eventName = `
|
|
32
|
+
if (description.includes(`particularly dangerous situation`) && eventName == `Tornado Warning` && dmgTheat == `CONSIDERABLE`) eventName = `PDS Tornado Warning`;
|
|
33
|
+
if (description.includes(`particularly dangerous situation`) && eventName == `Tornado Watch`) eventName = `PDS Tornado Watch`;
|
|
34
|
+
if (description.includes(`extremely dangerous situation`) && eventName == `Severe Thunderstorm Warning`) eventName = `EDS Severe Thunderstorm Warning`;
|
|
33
35
|
if (description.includes(`tornado emergency`) && eventName == `Tornado Warning` && dmgTheat == `CATASTROPHIC`) eventName = `Tornado Emergency`;
|
|
36
|
+
|
|
34
37
|
if (eventName == `Tornado Warning`) {
|
|
35
38
|
eventName = `Radar Indicated Tornado Warning`;
|
|
36
39
|
if (event.properties.parameters.tornadoDetection == `RADAR INDICATED`) eventName = `Radar Indicated Tornado Warning`;
|
|
@@ -39,6 +42,10 @@ class NoaaWeatherWireServiceEvents {
|
|
|
39
42
|
if (eventName == `Severe Thunderstorm Warning`) {
|
|
40
43
|
if (dmgTheat == `CONSIDERABLE`) eventName = `Considerable Severe Thunderstorm Warning`;
|
|
41
44
|
if (dmgTheat == `DESTRUCTIVE`) eventName = `Destructive Severe Thunderstorm Warning`;
|
|
45
|
+
if (torThreat == `POSSIBLE`) eventName = `${eventName} (TPROB)`;
|
|
46
|
+
}
|
|
47
|
+
if (eventName == `Flash Flood Warning`) {
|
|
48
|
+
if (dmgTheat == `CONSIDERABLE`) eventName = `Considerable Flash Flood Warning`;
|
|
42
49
|
}
|
|
43
50
|
for (let [key, value] of Object.entries(loader.definitions.tags)) {
|
|
44
51
|
if (event.properties.description.toLowerCase().includes(key.toLowerCase())) {
|
|
@@ -64,6 +71,15 @@ class NoaaWeatherWireServiceEvents {
|
|
|
64
71
|
alerts[i].properties.tags = tags;
|
|
65
72
|
}
|
|
66
73
|
}
|
|
74
|
+
if (loader.settings.alertSettings.filteredAlerts && loader.settings.alertSettings.filteredAlerts.length > 0) {
|
|
75
|
+
let pSet = new Set((loader.settings.alertSettings.filteredAlerts || []).map(p => String(p).toLowerCase()));
|
|
76
|
+
alerts = alerts.filter(alert => pSet.has(String(alert.properties?.event || '').toLowerCase()));
|
|
77
|
+
}
|
|
78
|
+
if (loader.settings.alertSettings.expiryCheck) {
|
|
79
|
+
alerts = alerts.filter(alert =>
|
|
80
|
+
new Date(alert.properties.expires) > new Date()
|
|
81
|
+
);
|
|
82
|
+
}
|
|
67
83
|
if (alerts.length === 0) { return; }
|
|
68
84
|
loader.static.events.emit(`onAlert`, alerts);
|
|
69
85
|
}
|
|
@@ -76,47 +92,52 @@ class NoaaWeatherWireServiceEvents {
|
|
|
76
92
|
*/
|
|
77
93
|
|
|
78
94
|
newCapEvent = async function(stanza) {
|
|
79
|
-
let message = stanza.message.
|
|
80
|
-
let
|
|
81
|
-
let
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
let
|
|
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
|
-
|
|
95
|
+
let message = stanza.message.match(/<\?xml[\s\S]*?<\/alert>/g) ?.map(xml => xml.trim()) || [];
|
|
96
|
+
let alerts = []
|
|
97
|
+
for (let msg of message) {
|
|
98
|
+
msg = msg.substring(msg.indexOf(`<?xml version="1.0"`), msg.lastIndexOf(`>`) + 1);
|
|
99
|
+
let data = loader.packages.xml2js.Parser();
|
|
100
|
+
let result = await data.parseStringPromise(msg);
|
|
101
|
+
let tracking = result.alert.info[0].parameter.find(p => p.valueName[0] == "VTEC")?.value[0] || "N/A";
|
|
102
|
+
let action = "N/A";
|
|
103
|
+
if (tracking !== "N/A") {
|
|
104
|
+
let splitVTEC = tracking.split(".");
|
|
105
|
+
tracking = `${splitVTEC[2]}-${splitVTEC[3]}-${splitVTEC[4]}-${splitVTEC[5]}`;
|
|
106
|
+
action = loader.definitions.status[splitVTEC[1]];
|
|
107
|
+
} else {
|
|
108
|
+
action = result.alert.msgType[0];
|
|
109
|
+
tracking = `${result.alert.info[0].parameter.find(p => p.valueName[0] == "WMOidentifier")?.value[0]}-${result.alert.info[0].area[0].geocode.filter(g => g.valueName[0] == "UGC").map(g => g.value[0]).join("-")}`;
|
|
110
|
+
}
|
|
111
|
+
let alert = {
|
|
112
|
+
id: `Wire-${tracking}`,
|
|
113
|
+
tracking: tracking,
|
|
114
|
+
action: action,
|
|
115
|
+
history: [{ description: result.alert.info[0].description[0], action: action, issued: new Date(stanza.attributes.issue) }],
|
|
116
|
+
properties: {
|
|
117
|
+
areaDesc: result.alert.info[0].area[0].areaDesc[0],
|
|
118
|
+
expires: new Date(result.alert.info[0].expires[0]),
|
|
119
|
+
sent: new Date(result.alert.sent[0]),
|
|
120
|
+
messageType: action,
|
|
121
|
+
event: result.alert.info[0].event[0],
|
|
122
|
+
sender: result.alert.sender[0],
|
|
123
|
+
senderName: result.alert.info[0].senderName[0],
|
|
124
|
+
description: result.alert.info[0].description[0],
|
|
125
|
+
geocode: { UGC: result.alert.info[0].area[0].geocode.filter(g => g.valueName[0] == "UGC").map(g => g.value[0]) },
|
|
126
|
+
parameters: {
|
|
127
|
+
WMOidentifier: [result.alert.info[0].parameter.find(p => p.valueName[0] == "WMOidentifier")?.value[0] || "N/A"],
|
|
128
|
+
tornadoDetection: result.alert.info[0].parameter.find(p => p.valueName[0] == "tornadoDetection")?.value[0] || result.alert.info[0].parameter.find(p => p.valueName[0] == "waterspoutDetection")?.value[0] || "N/A",
|
|
129
|
+
maxHailSize: result.alert.info[0].parameter.find(p => p.valueName[0] == "maxHailSize")?.value[0] || "N/A",
|
|
130
|
+
maxWindGust: result.alert.info[0].parameter.find(p => p.valueName[0] == "maxWindGust")?.value[0] || "N/A",
|
|
131
|
+
thunderstormDamageThreat: [result.alert.info[0].parameter.find(p => p.valueName[0] == "thunderstormDamageThreat")?.value[0] || result.alert.info[0].parameter.find(p => p.valueName[0] == "tornadoDamageThreat")?.value[0] || "N/A"],
|
|
132
|
+
},
|
|
113
133
|
},
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
134
|
+
};
|
|
135
|
+
if (result.alert.info[0].area[0].polygon) {
|
|
136
|
+
alert.geometry = { type: "Polygon", coordinates: [result.alert.info[0].area[0].polygon[0].split(" ").map(coord => { let [lat, lon] = coord.split(",").map(parseFloat); return [lon, lat]; })] };
|
|
137
|
+
}
|
|
138
|
+
alerts.push(alert);
|
|
118
139
|
}
|
|
119
|
-
this.onFinished(
|
|
140
|
+
this.onFinished(alerts);
|
|
120
141
|
}
|
|
121
142
|
|
|
122
143
|
/**
|
|
@@ -142,6 +163,7 @@ class NoaaWeatherWireServiceEvents {
|
|
|
142
163
|
let getHail = loader.packages.mText.getString(msg, `MAX HAIL SIZE...`, [`IN`]) || loader.packages.mText.getString(msg, `HAIL...`, [`IN`]);
|
|
143
164
|
let getGusts = loader.packages.mText.getString(msg, `MAX WIND GUST...`) || loader.packages.mText.getString(msg, `WIND...`);
|
|
144
165
|
let getThreat = loader.packages.mText.getString(msg, `DAMAGE THREAT...`);
|
|
166
|
+
let getTempIssue = loader.packages.mText.getString(msg, `ISSUED TIME...`);
|
|
145
167
|
let senderOffice = loader.packages.mText.getOffice(msg) || vtec.tracking.split(`-`)[0];
|
|
146
168
|
let getCoordinates = loader.packages.mText.getPolygonCoordinates(msg);
|
|
147
169
|
let getDescription = loader.packages.mText.getCleanDescription(msg, vtec);
|
|
@@ -153,8 +175,8 @@ class NoaaWeatherWireServiceEvents {
|
|
|
153
175
|
history: [{description: getDescription, action: vtec.status, issued: new Date(vtec.issued)}],
|
|
154
176
|
properties: {
|
|
155
177
|
areaDesc: mUgc.locations.join(`; `) || `N/A`,
|
|
156
|
-
expires: new Date(vtec.expires) == `Invalid Date` ? new Date(
|
|
157
|
-
sent: new Date(vtec.issued),
|
|
178
|
+
expires: new Date(vtec.expires) == `Invalid Date` ? new Date(9999, 0, 1) : new Date(vtec.expires),
|
|
179
|
+
sent: new Date(vtec.issued) == `Invalid Date` ? getTempIssue ? new Date(getTempIssue) : new Date(vtec.issued) : new Date(vtec.issued),
|
|
158
180
|
messageType: vtec.status,
|
|
159
181
|
event: vtec.event || `Unknown Event`,
|
|
160
182
|
sender: senderOffice,
|
package/src/stanza.js
CHANGED
|
@@ -28,7 +28,7 @@ class NoaaWeatherWireServiceStanza {
|
|
|
28
28
|
if (isDebug != false) {
|
|
29
29
|
let message = isDebug.stanza
|
|
30
30
|
let attributes = isDebug.attrs;
|
|
31
|
-
let isCap = message.includes(`<?xml version="1.0"`)
|
|
31
|
+
let isCap = isDebug.isCap || message.includes(`<?xml version="1.0"`);
|
|
32
32
|
let hasCapArea = message.includes(`<areaDesc>`);
|
|
33
33
|
let hasVtec = message.match(loader.definitions.expressions.vtec) != null;
|
|
34
34
|
let getId = this.getAwipsType(attributes)
|
|
@@ -96,7 +96,7 @@ class NoaaWeatherWireServiceStanza {
|
|
|
96
96
|
|
|
97
97
|
saveCache = function(message, attributes, type, isCap, isVtec) {
|
|
98
98
|
if (!loader.settings.cacheSettings.cacheDir) return;
|
|
99
|
-
loader.packages.fs.appendFileSync(`${loader.settings.cacheSettings.cacheDir}/nwws-raw-category-${type}s-${isCap ? 'cap' : 'raw'}${isVtec ? '-vtec' : ''}.bin`, `=================================================\n${new Date().toISOString().replace(/[:.]/g, '-')}\n\n
|
|
99
|
+
loader.packages.fs.appendFileSync(`${loader.settings.cacheSettings.cacheDir}/nwws-raw-category-${type}s-${isCap ? 'cap' : 'raw'}${isVtec ? '-vtec' : ''}.bin`, `=================================================\n${new Date().toISOString().replace(/[:.]/g, '-')}\n=================================================\n\n${message}\nISSUED TIME...${new Date(attributes.issue).toISOString()}\n\n`, 'utf8');
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
package/src/vtec.js
CHANGED
|
@@ -35,7 +35,7 @@ class NoaaWeatherWireServiceVtec {
|
|
|
35
35
|
status: this.getEventStatus(splitVTEC),
|
|
36
36
|
wmo: message.match(new RegExp(loader.definitions.expressions.wmo, 'gimu')),
|
|
37
37
|
expires: this.getExpires(vtecDates),
|
|
38
|
-
issued: attributes.issue
|
|
38
|
+
issued: attributes.issue
|
|
39
39
|
};
|
|
40
40
|
});
|
|
41
41
|
return vtecs;
|
package/test.js
CHANGED
|
@@ -5,6 +5,8 @@ let Client = new AtmosXWireParser({
|
|
|
5
5
|
onlyCap: false, // Set to true to only receive CAP messages only
|
|
6
6
|
betterEvents: true, // Set to true to receive better event handling
|
|
7
7
|
ugcPolygons: false, // Set to true to receive UGC Polygons instead of reading from raw products.
|
|
8
|
+
expiryCheck: true, // Set to true to filter out expired alerts
|
|
9
|
+
filteredAlerts: [] // Alerts you want to only log, leave empty to receive all alerts (Ex. ["Tornado Warning", "Radar Indicated Tornado Warning"])
|
|
8
10
|
},
|
|
9
11
|
xmpp: {
|
|
10
12
|
reconnect: true, // Set to true to enable automatic reconnection if you lose connection
|
|
@@ -13,6 +15,7 @@ let Client = new AtmosXWireParser({
|
|
|
13
15
|
cacheSettings: {
|
|
14
16
|
maxMegabytes: 2, // Maximum cache size in megabytes
|
|
15
17
|
cacheDir: `./cache`, // Directory for cache files
|
|
18
|
+
readCache: false, // Set to true if you wish to reupload the cache from earlier
|
|
16
19
|
},
|
|
17
20
|
authentication: {
|
|
18
21
|
username: `USERNAME_HERE`, // Your XMPP username
|