@atmosx/event-product-parser 3.0.2 → 3.0.4
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 +13 -1
- package/dist/cjs/index.cjs +71 -30
- package/dist/esm/index.mjs +71 -30
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/package.json +5 -3
- package/src/@core/core.start.ts +2 -2
- package/src/@dictionaries/dictionaries.betterEventNames.ts +10 -0
- package/src/@dictionaries/dictionaries.eventTags.ts +9 -0
- package/src/@dictionaries/{dictionaries.eventsOffshore.ts → dictionaries.eventsMatchText.ts} +6 -1
- package/src/@events/events.text.ts +3 -3
- package/src/@events/events.ugc.ts +7 -5
- package/src/@manager/manager.mkEvent.ts +2 -1
- package/src/@modules/@utilities/utilities.createWebhook.ts +22 -7
- package/src/@modules/@utilities/utilities.setWarning.ts +2 -2
- package/src/@types/types.webhook.ts +1 -0
- package/src/bootstrap.ts +1 -1
- package/src/index.ts +2 -2
- package/test.js +2 -0
package/README.md
CHANGED
|
@@ -56,6 +56,7 @@ const Client = new Manager({
|
|
|
56
56
|
webhook: "https://discord.com/api/webhooks/XXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
|
|
57
57
|
title: "AtmosphericX - (@atmosx/event-product-parser)",
|
|
58
58
|
message: ``,
|
|
59
|
+
upload: true,
|
|
59
60
|
events: [`Severe Thunderstorm Warning`, `Radar Indicated Tornado Warning`, `*Warning`, `*Thunderstorm*`],
|
|
60
61
|
rate: 5,
|
|
61
62
|
}
|
|
@@ -124,6 +125,7 @@ const Client = new Manager({
|
|
|
124
125
|
- **webhook**: The URL of the webhook you want to send messages to.
|
|
125
126
|
- **title**: The title of the message you want to send.
|
|
126
127
|
- **message**: The message content you want to send. You can use placeholders like `<@&role_id>` to mention roles in Discord.
|
|
128
|
+
- **upload**: Whether to upload a JSON file as well with the message containing the event data.
|
|
127
129
|
- **events**: An array of event types that will trigger the webhook when they are received by the parser. If this array is empty, the webhook will be triggered for all events.
|
|
128
130
|
- **rate**: The rate limit in seconds for how often the webhook can be triggered. This is to prevent spamming the webhook with too many messages in a short period of time.
|
|
129
131
|
|
|
@@ -151,6 +153,17 @@ const Client = new Manager({
|
|
|
151
153
|
|
|
152
154
|
## Events and Listeners
|
|
153
155
|
|
|
156
|
+
### Event `*`
|
|
157
|
+
Triggers for every event and product received by the parser. This is useful if you want to handle all events with a single listener.
|
|
158
|
+
```ts
|
|
159
|
+
Client.on(`*`, (data: any) => {
|
|
160
|
+
/*
|
|
161
|
+
event: string
|
|
162
|
+
data: object
|
|
163
|
+
*/
|
|
164
|
+
})
|
|
165
|
+
```
|
|
166
|
+
|
|
154
167
|
### Event `onServiceStatus`
|
|
155
168
|
Triggers when an update to the XMPP / API service status occurs.
|
|
156
169
|
```ts
|
|
@@ -331,7 +344,6 @@ await setEasTone(event.properties.description, event.properties.metadata.header)
|
|
|
331
344
|
[Contributing](/CONTRIBUTING.md) |
|
|
332
345
|
[License](/LICENSE) |
|
|
333
346
|
[Security](/SECURITY.md) |
|
|
334
|
-
[Changelogs](/CHANGELOGS.md) |
|
|
335
347
|
|
|
336
348
|
## Acknowledgements
|
|
337
349
|
- [k3yomi](https://github.com/k3yomi)
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -10509,7 +10509,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
10509
10509
|
var import_path = __toESM(require("path"));
|
|
10510
10510
|
var import_node_events = require("events");
|
|
10511
10511
|
var bootstrap = {
|
|
10512
|
-
version: `3.0.
|
|
10512
|
+
version: `3.0.3`,
|
|
10513
10513
|
isReady: true,
|
|
10514
10514
|
ratelimits: {},
|
|
10515
10515
|
session_xmpp: null,
|
|
@@ -10762,9 +10762,9 @@ var setTimeoutAction = (options) => {
|
|
|
10762
10762
|
var setWarning = (options) => {
|
|
10763
10763
|
var _a, _b;
|
|
10764
10764
|
const settings = bootstrap.settings;
|
|
10765
|
-
bootstrap.listener.emit(`log`, `${(_a = options.title) != null ? _a : `[${bootstrap.ansi_colors.YELLOW}
|
|
10765
|
+
bootstrap.listener.emit(`log`, `${(_a = options.title) != null ? _a : `[${bootstrap.ansi_colors.YELLOW}@atmosx/product-parser${bootstrap.ansi_colors.RESET}]`} ${options.message}`);
|
|
10766
10766
|
if (settings.EnableJournal) {
|
|
10767
|
-
console.log(`${(_b = options.title) != null ? _b : `[${bootstrap.ansi_colors.YELLOW}
|
|
10767
|
+
console.log(`${(_b = options.title) != null ? _b : `[${bootstrap.ansi_colors.YELLOW}@atmosx/product-parser${bootstrap.ansi_colors.RESET}]`} ${options.message}`);
|
|
10768
10768
|
}
|
|
10769
10769
|
};
|
|
10770
10770
|
|
|
@@ -14388,7 +14388,16 @@ var eventTags = {
|
|
|
14388
14388
|
"SLOW DOWN AND ALLOW EXTRA TIME": "Slow Down and Allow Extra Time",
|
|
14389
14389
|
"SHOULD EXERCISE CAUTION": "Should Exercise Caution",
|
|
14390
14390
|
"LAKE EFFECT SNOW EXPECTED": "Lake Effect Snow Expected",
|
|
14391
|
-
"MODERATE LAKE EFFECT SNOWFALL RATES AND BLOWING SNOW": "Moderate Lake Effect Snowfall and Blowing Snow"
|
|
14391
|
+
"MODERATE LAKE EFFECT SNOWFALL RATES AND BLOWING SNOW": "Moderate Lake Effect Snowfall and Blowing Snow",
|
|
14392
|
+
"NO TSUNAMI THREAT": "No Active Tsunami Threat",
|
|
14393
|
+
"NO SIGNIFICANT TSUNAMI THREAT": "No Significant Tsunami Threat",
|
|
14394
|
+
"NO TSUNAMI IMPACTS ARE EXPECTED": "No Tsunami Impacts Expected",
|
|
14395
|
+
"A TSUNAMI THREAT EXISTS": "Tsunami Threat Exists",
|
|
14396
|
+
"TSUNAMI THREAT": "Active Tsunami Threat",
|
|
14397
|
+
"HEAT ILLNESSES": "Can cause heat illness",
|
|
14398
|
+
"WATCH POSSIBLE": "Watch Possible",
|
|
14399
|
+
"INTENSIFYING": "Intensifying",
|
|
14400
|
+
"CAPABLE OF PRODUCING A LANDSPOUT": "Landspout Possible"
|
|
14392
14401
|
};
|
|
14393
14402
|
|
|
14394
14403
|
// src/@building/building.tags.ts
|
|
@@ -14458,8 +14467,8 @@ var getEventHeader = (options) => {
|
|
|
14458
14467
|
return `ZCZC-ATMOSX-${options.getType.prefix}-${ugc2}-${(_b = vtec2 == null ? void 0 : vtec2.status) != null ? _b : `Issued`}-${(/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").split(".")[0]}-${(_c = properties2.geocode.office.office) != null ? _c : `KWNS`}`;
|
|
14459
14468
|
};
|
|
14460
14469
|
|
|
14461
|
-
// src/@dictionaries/dictionaries.
|
|
14462
|
-
var
|
|
14470
|
+
// src/@dictionaries/dictionaries.eventsMatchText.ts
|
|
14471
|
+
var eventsMatchText = {
|
|
14463
14472
|
"Special Weather Statement": "Special Weather Statement",
|
|
14464
14473
|
"Hurricane Warning": "Hurricane Warning",
|
|
14465
14474
|
"Hurricane Force Wind Warning": "Hurricane Force Wind Warning",
|
|
@@ -14469,7 +14478,12 @@ var eventsOffshore = {
|
|
|
14469
14478
|
"High Wind Warning": "High Wind Warning",
|
|
14470
14479
|
"Gale Warning": "Gale Warning",
|
|
14471
14480
|
"Small Craft Advisory": "Small Craft Advisory",
|
|
14472
|
-
"Small Craft Warning": "Small Craft Warning"
|
|
14481
|
+
"Small Craft Warning": "Small Craft Warning",
|
|
14482
|
+
"Tsunami Warning": "Tsunami Warning",
|
|
14483
|
+
"Tsunami Watch": "Tsunami Watch",
|
|
14484
|
+
"Tsunami Advisory": "Tsunami Advisory",
|
|
14485
|
+
"Tsunami Information Statement": "Tsunami Information Statement",
|
|
14486
|
+
"Subscribers:": "National Weather Service Policy"
|
|
14473
14487
|
};
|
|
14474
14488
|
|
|
14475
14489
|
// src/@building/building.tracking.ts
|
|
@@ -14528,6 +14542,16 @@ var betterEventNames = {
|
|
|
14528
14542
|
},
|
|
14529
14543
|
"Radar Indicated Tornado Warning": {}
|
|
14530
14544
|
},
|
|
14545
|
+
"Blizzard Warning": {
|
|
14546
|
+
"PDS Blizzard Warning": {
|
|
14547
|
+
description: "particularly dangerous situation"
|
|
14548
|
+
}
|
|
14549
|
+
},
|
|
14550
|
+
"Ice Storm Warning": {
|
|
14551
|
+
"PDS Ice Storm Warning": {
|
|
14552
|
+
description: "particularly dangerous situation"
|
|
14553
|
+
}
|
|
14554
|
+
},
|
|
14531
14555
|
"Special Marine Warning": {
|
|
14532
14556
|
"Special Marine Warning (TPROB)": {
|
|
14533
14557
|
tornado: `POSSIBLE`
|
|
@@ -14775,13 +14799,13 @@ var createHttp = (options) => __async(null, null, function* () {
|
|
|
14775
14799
|
// src/@modules/@utilities/utilities.createWebhook.ts
|
|
14776
14800
|
var import_form_data = __toESM(require_form_data());
|
|
14777
14801
|
var createWebhook = (options) => __async(null, null, function* () {
|
|
14778
|
-
var _a, _b, _c, _d
|
|
14802
|
+
var _a, _b, _c, _d;
|
|
14779
14803
|
const event = options.event.properties;
|
|
14780
14804
|
const settings = options.webhook;
|
|
14781
14805
|
let body = [
|
|
14782
14806
|
event.locations ? `**Locations**: ${event.locations.slice(0, 100)}` : null,
|
|
14783
14807
|
event.issued ? `**Issued**: <t:${Math.floor(new Date(event.issued).getTime() / 1e3)}:R>` : null,
|
|
14784
|
-
event.expires ? `**Expires**: <t:${Math.floor(new Date(event.expires).getTime() / 1e3)}:R>` : null,
|
|
14808
|
+
event.expires && event.status != `Statement` ? `**Expires**: <t:${Math.floor(new Date(event.expires).getTime() / 1e3)}:R>` : null,
|
|
14785
14809
|
(() => {
|
|
14786
14810
|
var _a2, _b2;
|
|
14787
14811
|
const val = (_a2 = event.parameters.estimated_wind_gusts) != null ? _a2 : null;
|
|
@@ -14798,16 +14822,28 @@ var createWebhook = (options) => __async(null, null, function* () {
|
|
|
14798
14822
|
event.parameters.damage_threat ? `**Damage Threat**: ${event.parameters.damage_threat}` : null,
|
|
14799
14823
|
event.parameters.flood_threat ? `**Flood Threat**: ${event.parameters.flood_threat}` : null,
|
|
14800
14824
|
event.parameters.tornado_threat ? `**Tornado Threat**: ${event.parameters.tornado_threat}` : null,
|
|
14825
|
+
event.spc_parameters.spc_max_tornado ? `**Max Tornado Threat**: ${event.spc_parameters.spc_max_tornado}` : null,
|
|
14826
|
+
event.spc_parameters.spc_max_hail ? `**Max Hail Threat**: ${event.spc_parameters.spc_max_hail}` : null,
|
|
14827
|
+
event.spc_parameters.spc_max_wind ? `**Max Wind Threat**: ${event.spc_parameters.spc_max_wind}` : null,
|
|
14828
|
+
event.spc_parameters.spc_watch_issuance ? `**Watch Issuance**: ${event.spc_parameters.spc_watch_issuance}%` : null,
|
|
14829
|
+
event.watch_parameters.watch_number ? `**Watch Number**: ${event.watch_parameters.watch_number}` : null,
|
|
14830
|
+
event.watch_parameters.strong_tornadoes_probability ? `**Strong Tornadoes Probability**: ${event.watch_parameters.strong_tornadoes_probability}%` : null,
|
|
14831
|
+
event.watch_parameters.additional_tornadoes_probability ? `**Additional Tornadoes Probability**: ${event.watch_parameters.additional_tornadoes_probability}%` : null,
|
|
14832
|
+
event.watch_parameters.combined_hail_wind_probability ? `**Combined Hail/Wind Probability**: ${event.watch_parameters.combined_hail_wind_probability}%` : null,
|
|
14833
|
+
event.watch_parameters.severe_hail_probability ? `**Severe Hail Probability**: ${event.watch_parameters.severe_hail_probability}%` : null,
|
|
14834
|
+
event.watch_parameters.hail_2in_probability ? `**Hail \u22652in Probability**: ${event.watch_parameters.hail_2in_probability}%` : null,
|
|
14835
|
+
event.watch_parameters.max_hail_in ? `**Max Hail Inches**: ${event.watch_parameters.max_hail_in}` : null,
|
|
14836
|
+
event.watch_parameters.severe_wind_probability ? `**Severe Wind Probability**: ${event.watch_parameters.severe_wind_probability}%` : null,
|
|
14837
|
+
event.watch_parameters.max_wind_surface ? `**Max Surface Wind**: ${event.watch_parameters.max_wind_surface}` : null,
|
|
14838
|
+
event.watch_parameters.max_tops_x100feet ? `**Max Tops (x100 feet)**: ${event.watch_parameters.max_tops_x100feet}` : null,
|
|
14801
14839
|
((_a = event.parameters.tags) == null ? void 0 : _a.length) > 0 ? `**Tags**: ${event.parameters.tags.join(", ")}` : null,
|
|
14802
14840
|
(() => {
|
|
14803
|
-
var _a2, _b2, _c2, _d2,
|
|
14841
|
+
var _a2, _b2, _c2, _d2, _e, _f;
|
|
14804
14842
|
const val = (_c2 = (_b2 = (_a2 = event.geocode) == null ? void 0 : _a2.office) == null ? void 0 : _b2.name) != null ? _c2 : `N/A`;
|
|
14805
|
-
const th = (
|
|
14843
|
+
const th = (_f = (_e = (_d2 = event.geocode) == null ? void 0 : _d2.office) == null ? void 0 : _e.office) != null ? _f : null;
|
|
14806
14844
|
return val || th ? `**Sender**: ${val} ${th ? `(${th})` : ""}` : null;
|
|
14807
14845
|
})(),
|
|
14808
14846
|
((_b = event.metadata) == null ? void 0 : _b.tracking) ? `**Tracking**: ${event.metadata.tracking}` : null,
|
|
14809
|
-
((_d = (_c = event.metadata) == null ? void 0 : _c.vtec) == null ? void 0 : _d.vtec) ? `**VTEC**: ${(_e = event.metadata.vtec) == null ? void 0 : _e.vtec}` : null,
|
|
14810
|
-
((_f = event.metadata) == null ? void 0 : _f.filtered_proximity) != null ? `**Currently in polygon (Node)**: ${event.metadata.filtered_proximity ? "Yes" : "No"}` : null,
|
|
14811
14847
|
(() => {
|
|
14812
14848
|
const desc = (event.description || "").split("\n").map((l) => l.trim()).filter(Boolean).join("\n");
|
|
14813
14849
|
return desc ? "```\n" + desc + "\n```" : null;
|
|
@@ -14831,14 +14867,16 @@ var createWebhook = (options) => __async(null, null, function* () {
|
|
|
14831
14867
|
footer: { text: settings.title }
|
|
14832
14868
|
};
|
|
14833
14869
|
form.append("payload_json", JSON.stringify({
|
|
14834
|
-
username: (
|
|
14835
|
-
content: (
|
|
14870
|
+
username: (_c = settings.title) != null ? _c : "AtmosphericX",
|
|
14871
|
+
content: (_d = settings.message) != null ? _d : "",
|
|
14836
14872
|
embeds: [embed]
|
|
14837
14873
|
}));
|
|
14838
|
-
|
|
14839
|
-
|
|
14840
|
-
|
|
14841
|
-
|
|
14874
|
+
if (settings.upload) {
|
|
14875
|
+
form.append("file", Buffer.from(JSON.stringify(getCleanedEvent(event), null, 2)), {
|
|
14876
|
+
filename: `${event.event}_${event.status}_${event.metadata.tracking}.json`,
|
|
14877
|
+
contentType: "application/json"
|
|
14878
|
+
});
|
|
14879
|
+
}
|
|
14842
14880
|
yield createHttp({
|
|
14843
14881
|
url: settings.webhook,
|
|
14844
14882
|
timeout: 2e3,
|
|
@@ -15094,12 +15132,13 @@ var mkEvent = (event) => __async(null, null, function* () {
|
|
|
15094
15132
|
})
|
|
15095
15133
|
})
|
|
15096
15134
|
});
|
|
15135
|
+
updateWebhooks(bootstrap.cache.events.features[getIndex]);
|
|
15097
15136
|
} else {
|
|
15098
15137
|
features.push(event);
|
|
15138
|
+
updateWebhooks(event);
|
|
15099
15139
|
}
|
|
15100
15140
|
}
|
|
15101
15141
|
}
|
|
15102
|
-
updateWebhooks(event);
|
|
15103
15142
|
});
|
|
15104
15143
|
|
|
15105
15144
|
// src/@manager/manager.rmEvent.ts
|
|
@@ -15260,7 +15299,7 @@ var text = (stanza) => __async(null, null, function* () {
|
|
|
15260
15299
|
const header = getEventHeader({ properties: props, getType: stanza.getType });
|
|
15261
15300
|
const issued = new Date(attributes.issue);
|
|
15262
15301
|
const expires = new Date(issued.getTime() + 12 * 60 * 60 * 1e3);
|
|
15263
|
-
let event = Object.keys(
|
|
15302
|
+
let event = Object.keys(eventsMatchText).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
|
|
15264
15303
|
let isStatement = false;
|
|
15265
15304
|
if (!event) {
|
|
15266
15305
|
event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
|
|
@@ -15277,7 +15316,7 @@ var text = (stanza) => __async(null, null, function* () {
|
|
|
15277
15316
|
parent: event,
|
|
15278
15317
|
status: isStatement ? `Statement` : `Issued`,
|
|
15279
15318
|
issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
|
|
15280
|
-
expires: isStatement ? new Date(issued.getTime() +
|
|
15319
|
+
expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
|
|
15281
15320
|
}, props), {
|
|
15282
15321
|
metadata: {
|
|
15283
15322
|
ms: performance.now() - tick,
|
|
@@ -15394,11 +15433,13 @@ var ugc = (stanza) => __async(null, null, function* () {
|
|
|
15394
15433
|
if (ugc2 != null) {
|
|
15395
15434
|
const props = properties({ message, attributes, ugc: ugc2 });
|
|
15396
15435
|
const issued = new Date(attributes.issue);
|
|
15397
|
-
const expires = new Date(ugc2.expires)
|
|
15436
|
+
const expires = new Date(ugc2.expires);
|
|
15398
15437
|
const header = getEventHeader({ properties: props, getType: stanza.getType });
|
|
15399
|
-
let event = Object.keys(
|
|
15438
|
+
let event = Object.keys(eventsMatchText).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
|
|
15439
|
+
let isStatement = false;
|
|
15400
15440
|
if (!event) {
|
|
15401
15441
|
event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
|
|
15442
|
+
isStatement = true;
|
|
15402
15443
|
}
|
|
15403
15444
|
processed.push({
|
|
15404
15445
|
type: `Feature`,
|
|
@@ -15409,9 +15450,9 @@ var ugc = (stanza) => __async(null, null, function* () {
|
|
|
15409
15450
|
properties: __spreadProps(__spreadValues({
|
|
15410
15451
|
event,
|
|
15411
15452
|
parent: event,
|
|
15412
|
-
status: `Issued`,
|
|
15453
|
+
status: isStatement ? `Statement` : `Issued`,
|
|
15413
15454
|
issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
|
|
15414
|
-
expires:
|
|
15455
|
+
expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
|
|
15415
15456
|
}, props), {
|
|
15416
15457
|
metadata: {
|
|
15417
15458
|
ms: performance.now() - tick,
|
|
@@ -16108,13 +16149,13 @@ var updateEvents = (selectedEvent) => __async(null, null, function* () {
|
|
|
16108
16149
|
|
|
16109
16150
|
// src/@core/core.start.ts
|
|
16110
16151
|
var import_croner = require("croner");
|
|
16111
|
-
var startService = (
|
|
16152
|
+
var startService = (configurations) => __async(null, null, function* () {
|
|
16112
16153
|
if (!bootstrap.isReady) {
|
|
16113
16154
|
return setWarning({
|
|
16114
16155
|
message: `You can not create another instance without shutting down the current one first, please make sure to call the stop() method first!`
|
|
16115
16156
|
});
|
|
16116
16157
|
}
|
|
16117
|
-
setSettings(
|
|
16158
|
+
const settings = setSettings(configurations);
|
|
16118
16159
|
bootstrap.isReady = true;
|
|
16119
16160
|
yield initializeDatabase();
|
|
16120
16161
|
if (settings.EnableWireService) {
|
|
@@ -16634,12 +16675,12 @@ var Manager = class {
|
|
|
16634
16675
|
trycatch() {
|
|
16635
16676
|
process.on("uncaughtException", (err) => {
|
|
16636
16677
|
var _a;
|
|
16637
|
-
const ignored = ["ETIMEDOUT", "ECONNRESET", "EHOSTUNREACH", "STARTTLS_FAILURE"];
|
|
16678
|
+
const ignored = ["ETIMEDOUT", "ECONNRESET", "EHOSTUNREACH", "ENOTFOUND", "ECONNREFUSED", "EPIPE", "EADDRINUSE", "EALREADY", "EACCES", "EAGAIN", "EHOSTDOWN", "STARTTLS_FAILURE"];
|
|
16638
16679
|
if (ignored.includes(err == null ? void 0 : err.code)) {
|
|
16639
16680
|
setEventEmit({
|
|
16640
16681
|
event: `onServiceStatus`,
|
|
16641
16682
|
metadata: {
|
|
16642
|
-
message: `
|
|
16683
|
+
message: `Ignored Critical Error: ${(_a = err == null ? void 0 : err.code) != null ? _a : "Unknown error code"}. This may indicate a connection issue. Attempting to continue...`,
|
|
16643
16684
|
data: {},
|
|
16644
16685
|
type: `error`,
|
|
16645
16686
|
error: true
|
package/dist/esm/index.mjs
CHANGED
|
@@ -10491,7 +10491,7 @@ var require_form_data = __commonJS({
|
|
|
10491
10491
|
import path from "path";
|
|
10492
10492
|
import { EventEmitter } from "events";
|
|
10493
10493
|
var bootstrap = {
|
|
10494
|
-
version: `3.0.
|
|
10494
|
+
version: `3.0.3`,
|
|
10495
10495
|
isReady: true,
|
|
10496
10496
|
ratelimits: {},
|
|
10497
10497
|
session_xmpp: null,
|
|
@@ -10744,9 +10744,9 @@ var setTimeoutAction = (options) => {
|
|
|
10744
10744
|
var setWarning = (options) => {
|
|
10745
10745
|
var _a, _b;
|
|
10746
10746
|
const settings = bootstrap.settings;
|
|
10747
|
-
bootstrap.listener.emit(`log`, `${(_a = options.title) != null ? _a : `[${bootstrap.ansi_colors.YELLOW}
|
|
10747
|
+
bootstrap.listener.emit(`log`, `${(_a = options.title) != null ? _a : `[${bootstrap.ansi_colors.YELLOW}@atmosx/product-parser${bootstrap.ansi_colors.RESET}]`} ${options.message}`);
|
|
10748
10748
|
if (settings.EnableJournal) {
|
|
10749
|
-
console.log(`${(_b = options.title) != null ? _b : `[${bootstrap.ansi_colors.YELLOW}
|
|
10749
|
+
console.log(`${(_b = options.title) != null ? _b : `[${bootstrap.ansi_colors.YELLOW}@atmosx/product-parser${bootstrap.ansi_colors.RESET}]`} ${options.message}`);
|
|
10750
10750
|
}
|
|
10751
10751
|
};
|
|
10752
10752
|
|
|
@@ -14370,7 +14370,16 @@ var eventTags = {
|
|
|
14370
14370
|
"SLOW DOWN AND ALLOW EXTRA TIME": "Slow Down and Allow Extra Time",
|
|
14371
14371
|
"SHOULD EXERCISE CAUTION": "Should Exercise Caution",
|
|
14372
14372
|
"LAKE EFFECT SNOW EXPECTED": "Lake Effect Snow Expected",
|
|
14373
|
-
"MODERATE LAKE EFFECT SNOWFALL RATES AND BLOWING SNOW": "Moderate Lake Effect Snowfall and Blowing Snow"
|
|
14373
|
+
"MODERATE LAKE EFFECT SNOWFALL RATES AND BLOWING SNOW": "Moderate Lake Effect Snowfall and Blowing Snow",
|
|
14374
|
+
"NO TSUNAMI THREAT": "No Active Tsunami Threat",
|
|
14375
|
+
"NO SIGNIFICANT TSUNAMI THREAT": "No Significant Tsunami Threat",
|
|
14376
|
+
"NO TSUNAMI IMPACTS ARE EXPECTED": "No Tsunami Impacts Expected",
|
|
14377
|
+
"A TSUNAMI THREAT EXISTS": "Tsunami Threat Exists",
|
|
14378
|
+
"TSUNAMI THREAT": "Active Tsunami Threat",
|
|
14379
|
+
"HEAT ILLNESSES": "Can cause heat illness",
|
|
14380
|
+
"WATCH POSSIBLE": "Watch Possible",
|
|
14381
|
+
"INTENSIFYING": "Intensifying",
|
|
14382
|
+
"CAPABLE OF PRODUCING A LANDSPOUT": "Landspout Possible"
|
|
14374
14383
|
};
|
|
14375
14384
|
|
|
14376
14385
|
// src/@building/building.tags.ts
|
|
@@ -14440,8 +14449,8 @@ var getEventHeader = (options) => {
|
|
|
14440
14449
|
return `ZCZC-ATMOSX-${options.getType.prefix}-${ugc2}-${(_b = vtec2 == null ? void 0 : vtec2.status) != null ? _b : `Issued`}-${(/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").split(".")[0]}-${(_c = properties2.geocode.office.office) != null ? _c : `KWNS`}`;
|
|
14441
14450
|
};
|
|
14442
14451
|
|
|
14443
|
-
// src/@dictionaries/dictionaries.
|
|
14444
|
-
var
|
|
14452
|
+
// src/@dictionaries/dictionaries.eventsMatchText.ts
|
|
14453
|
+
var eventsMatchText = {
|
|
14445
14454
|
"Special Weather Statement": "Special Weather Statement",
|
|
14446
14455
|
"Hurricane Warning": "Hurricane Warning",
|
|
14447
14456
|
"Hurricane Force Wind Warning": "Hurricane Force Wind Warning",
|
|
@@ -14451,7 +14460,12 @@ var eventsOffshore = {
|
|
|
14451
14460
|
"High Wind Warning": "High Wind Warning",
|
|
14452
14461
|
"Gale Warning": "Gale Warning",
|
|
14453
14462
|
"Small Craft Advisory": "Small Craft Advisory",
|
|
14454
|
-
"Small Craft Warning": "Small Craft Warning"
|
|
14463
|
+
"Small Craft Warning": "Small Craft Warning",
|
|
14464
|
+
"Tsunami Warning": "Tsunami Warning",
|
|
14465
|
+
"Tsunami Watch": "Tsunami Watch",
|
|
14466
|
+
"Tsunami Advisory": "Tsunami Advisory",
|
|
14467
|
+
"Tsunami Information Statement": "Tsunami Information Statement",
|
|
14468
|
+
"Subscribers:": "National Weather Service Policy"
|
|
14455
14469
|
};
|
|
14456
14470
|
|
|
14457
14471
|
// src/@building/building.tracking.ts
|
|
@@ -14510,6 +14524,16 @@ var betterEventNames = {
|
|
|
14510
14524
|
},
|
|
14511
14525
|
"Radar Indicated Tornado Warning": {}
|
|
14512
14526
|
},
|
|
14527
|
+
"Blizzard Warning": {
|
|
14528
|
+
"PDS Blizzard Warning": {
|
|
14529
|
+
description: "particularly dangerous situation"
|
|
14530
|
+
}
|
|
14531
|
+
},
|
|
14532
|
+
"Ice Storm Warning": {
|
|
14533
|
+
"PDS Ice Storm Warning": {
|
|
14534
|
+
description: "particularly dangerous situation"
|
|
14535
|
+
}
|
|
14536
|
+
},
|
|
14513
14537
|
"Special Marine Warning": {
|
|
14514
14538
|
"Special Marine Warning (TPROB)": {
|
|
14515
14539
|
tornado: `POSSIBLE`
|
|
@@ -14757,13 +14781,13 @@ var createHttp = (options) => __async(null, null, function* () {
|
|
|
14757
14781
|
// src/@modules/@utilities/utilities.createWebhook.ts
|
|
14758
14782
|
var import_form_data = __toESM(require_form_data());
|
|
14759
14783
|
var createWebhook = (options) => __async(null, null, function* () {
|
|
14760
|
-
var _a, _b, _c, _d
|
|
14784
|
+
var _a, _b, _c, _d;
|
|
14761
14785
|
const event = options.event.properties;
|
|
14762
14786
|
const settings = options.webhook;
|
|
14763
14787
|
let body = [
|
|
14764
14788
|
event.locations ? `**Locations**: ${event.locations.slice(0, 100)}` : null,
|
|
14765
14789
|
event.issued ? `**Issued**: <t:${Math.floor(new Date(event.issued).getTime() / 1e3)}:R>` : null,
|
|
14766
|
-
event.expires ? `**Expires**: <t:${Math.floor(new Date(event.expires).getTime() / 1e3)}:R>` : null,
|
|
14790
|
+
event.expires && event.status != `Statement` ? `**Expires**: <t:${Math.floor(new Date(event.expires).getTime() / 1e3)}:R>` : null,
|
|
14767
14791
|
(() => {
|
|
14768
14792
|
var _a2, _b2;
|
|
14769
14793
|
const val = (_a2 = event.parameters.estimated_wind_gusts) != null ? _a2 : null;
|
|
@@ -14780,16 +14804,28 @@ var createWebhook = (options) => __async(null, null, function* () {
|
|
|
14780
14804
|
event.parameters.damage_threat ? `**Damage Threat**: ${event.parameters.damage_threat}` : null,
|
|
14781
14805
|
event.parameters.flood_threat ? `**Flood Threat**: ${event.parameters.flood_threat}` : null,
|
|
14782
14806
|
event.parameters.tornado_threat ? `**Tornado Threat**: ${event.parameters.tornado_threat}` : null,
|
|
14807
|
+
event.spc_parameters.spc_max_tornado ? `**Max Tornado Threat**: ${event.spc_parameters.spc_max_tornado}` : null,
|
|
14808
|
+
event.spc_parameters.spc_max_hail ? `**Max Hail Threat**: ${event.spc_parameters.spc_max_hail}` : null,
|
|
14809
|
+
event.spc_parameters.spc_max_wind ? `**Max Wind Threat**: ${event.spc_parameters.spc_max_wind}` : null,
|
|
14810
|
+
event.spc_parameters.spc_watch_issuance ? `**Watch Issuance**: ${event.spc_parameters.spc_watch_issuance}%` : null,
|
|
14811
|
+
event.watch_parameters.watch_number ? `**Watch Number**: ${event.watch_parameters.watch_number}` : null,
|
|
14812
|
+
event.watch_parameters.strong_tornadoes_probability ? `**Strong Tornadoes Probability**: ${event.watch_parameters.strong_tornadoes_probability}%` : null,
|
|
14813
|
+
event.watch_parameters.additional_tornadoes_probability ? `**Additional Tornadoes Probability**: ${event.watch_parameters.additional_tornadoes_probability}%` : null,
|
|
14814
|
+
event.watch_parameters.combined_hail_wind_probability ? `**Combined Hail/Wind Probability**: ${event.watch_parameters.combined_hail_wind_probability}%` : null,
|
|
14815
|
+
event.watch_parameters.severe_hail_probability ? `**Severe Hail Probability**: ${event.watch_parameters.severe_hail_probability}%` : null,
|
|
14816
|
+
event.watch_parameters.hail_2in_probability ? `**Hail \u22652in Probability**: ${event.watch_parameters.hail_2in_probability}%` : null,
|
|
14817
|
+
event.watch_parameters.max_hail_in ? `**Max Hail Inches**: ${event.watch_parameters.max_hail_in}` : null,
|
|
14818
|
+
event.watch_parameters.severe_wind_probability ? `**Severe Wind Probability**: ${event.watch_parameters.severe_wind_probability}%` : null,
|
|
14819
|
+
event.watch_parameters.max_wind_surface ? `**Max Surface Wind**: ${event.watch_parameters.max_wind_surface}` : null,
|
|
14820
|
+
event.watch_parameters.max_tops_x100feet ? `**Max Tops (x100 feet)**: ${event.watch_parameters.max_tops_x100feet}` : null,
|
|
14783
14821
|
((_a = event.parameters.tags) == null ? void 0 : _a.length) > 0 ? `**Tags**: ${event.parameters.tags.join(", ")}` : null,
|
|
14784
14822
|
(() => {
|
|
14785
|
-
var _a2, _b2, _c2, _d2,
|
|
14823
|
+
var _a2, _b2, _c2, _d2, _e, _f;
|
|
14786
14824
|
const val = (_c2 = (_b2 = (_a2 = event.geocode) == null ? void 0 : _a2.office) == null ? void 0 : _b2.name) != null ? _c2 : `N/A`;
|
|
14787
|
-
const th = (
|
|
14825
|
+
const th = (_f = (_e = (_d2 = event.geocode) == null ? void 0 : _d2.office) == null ? void 0 : _e.office) != null ? _f : null;
|
|
14788
14826
|
return val || th ? `**Sender**: ${val} ${th ? `(${th})` : ""}` : null;
|
|
14789
14827
|
})(),
|
|
14790
14828
|
((_b = event.metadata) == null ? void 0 : _b.tracking) ? `**Tracking**: ${event.metadata.tracking}` : null,
|
|
14791
|
-
((_d = (_c = event.metadata) == null ? void 0 : _c.vtec) == null ? void 0 : _d.vtec) ? `**VTEC**: ${(_e = event.metadata.vtec) == null ? void 0 : _e.vtec}` : null,
|
|
14792
|
-
((_f = event.metadata) == null ? void 0 : _f.filtered_proximity) != null ? `**Currently in polygon (Node)**: ${event.metadata.filtered_proximity ? "Yes" : "No"}` : null,
|
|
14793
14829
|
(() => {
|
|
14794
14830
|
const desc = (event.description || "").split("\n").map((l) => l.trim()).filter(Boolean).join("\n");
|
|
14795
14831
|
return desc ? "```\n" + desc + "\n```" : null;
|
|
@@ -14813,14 +14849,16 @@ var createWebhook = (options) => __async(null, null, function* () {
|
|
|
14813
14849
|
footer: { text: settings.title }
|
|
14814
14850
|
};
|
|
14815
14851
|
form.append("payload_json", JSON.stringify({
|
|
14816
|
-
username: (
|
|
14817
|
-
content: (
|
|
14852
|
+
username: (_c = settings.title) != null ? _c : "AtmosphericX",
|
|
14853
|
+
content: (_d = settings.message) != null ? _d : "",
|
|
14818
14854
|
embeds: [embed]
|
|
14819
14855
|
}));
|
|
14820
|
-
|
|
14821
|
-
|
|
14822
|
-
|
|
14823
|
-
|
|
14856
|
+
if (settings.upload) {
|
|
14857
|
+
form.append("file", Buffer.from(JSON.stringify(getCleanedEvent(event), null, 2)), {
|
|
14858
|
+
filename: `${event.event}_${event.status}_${event.metadata.tracking}.json`,
|
|
14859
|
+
contentType: "application/json"
|
|
14860
|
+
});
|
|
14861
|
+
}
|
|
14824
14862
|
yield createHttp({
|
|
14825
14863
|
url: settings.webhook,
|
|
14826
14864
|
timeout: 2e3,
|
|
@@ -15076,12 +15114,13 @@ var mkEvent = (event) => __async(null, null, function* () {
|
|
|
15076
15114
|
})
|
|
15077
15115
|
})
|
|
15078
15116
|
});
|
|
15117
|
+
updateWebhooks(bootstrap.cache.events.features[getIndex]);
|
|
15079
15118
|
} else {
|
|
15080
15119
|
features.push(event);
|
|
15120
|
+
updateWebhooks(event);
|
|
15081
15121
|
}
|
|
15082
15122
|
}
|
|
15083
15123
|
}
|
|
15084
|
-
updateWebhooks(event);
|
|
15085
15124
|
});
|
|
15086
15125
|
|
|
15087
15126
|
// src/@manager/manager.rmEvent.ts
|
|
@@ -15242,7 +15281,7 @@ var text = (stanza) => __async(null, null, function* () {
|
|
|
15242
15281
|
const header = getEventHeader({ properties: props, getType: stanza.getType });
|
|
15243
15282
|
const issued = new Date(attributes.issue);
|
|
15244
15283
|
const expires = new Date(issued.getTime() + 12 * 60 * 60 * 1e3);
|
|
15245
|
-
let event = Object.keys(
|
|
15284
|
+
let event = Object.keys(eventsMatchText).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
|
|
15246
15285
|
let isStatement = false;
|
|
15247
15286
|
if (!event) {
|
|
15248
15287
|
event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
|
|
@@ -15259,7 +15298,7 @@ var text = (stanza) => __async(null, null, function* () {
|
|
|
15259
15298
|
parent: event,
|
|
15260
15299
|
status: isStatement ? `Statement` : `Issued`,
|
|
15261
15300
|
issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
|
|
15262
|
-
expires: isStatement ? new Date(issued.getTime() +
|
|
15301
|
+
expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
|
|
15263
15302
|
}, props), {
|
|
15264
15303
|
metadata: {
|
|
15265
15304
|
ms: performance.now() - tick,
|
|
@@ -15376,11 +15415,13 @@ var ugc = (stanza) => __async(null, null, function* () {
|
|
|
15376
15415
|
if (ugc2 != null) {
|
|
15377
15416
|
const props = properties({ message, attributes, ugc: ugc2 });
|
|
15378
15417
|
const issued = new Date(attributes.issue);
|
|
15379
|
-
const expires = new Date(ugc2.expires)
|
|
15418
|
+
const expires = new Date(ugc2.expires);
|
|
15380
15419
|
const header = getEventHeader({ properties: props, getType: stanza.getType });
|
|
15381
|
-
let event = Object.keys(
|
|
15420
|
+
let event = Object.keys(eventsMatchText).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
|
|
15421
|
+
let isStatement = false;
|
|
15382
15422
|
if (!event) {
|
|
15383
15423
|
event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
|
|
15424
|
+
isStatement = true;
|
|
15384
15425
|
}
|
|
15385
15426
|
processed.push({
|
|
15386
15427
|
type: `Feature`,
|
|
@@ -15391,9 +15432,9 @@ var ugc = (stanza) => __async(null, null, function* () {
|
|
|
15391
15432
|
properties: __spreadProps(__spreadValues({
|
|
15392
15433
|
event,
|
|
15393
15434
|
parent: event,
|
|
15394
|
-
status: `Issued`,
|
|
15435
|
+
status: isStatement ? `Statement` : `Issued`,
|
|
15395
15436
|
issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
|
|
15396
|
-
expires:
|
|
15437
|
+
expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
|
|
15397
15438
|
}, props), {
|
|
15398
15439
|
metadata: {
|
|
15399
15440
|
ms: performance.now() - tick,
|
|
@@ -16090,13 +16131,13 @@ var updateEvents = (selectedEvent) => __async(null, null, function* () {
|
|
|
16090
16131
|
|
|
16091
16132
|
// src/@core/core.start.ts
|
|
16092
16133
|
import { Cron } from "croner";
|
|
16093
|
-
var startService = (
|
|
16134
|
+
var startService = (configurations) => __async(null, null, function* () {
|
|
16094
16135
|
if (!bootstrap.isReady) {
|
|
16095
16136
|
return setWarning({
|
|
16096
16137
|
message: `You can not create another instance without shutting down the current one first, please make sure to call the stop() method first!`
|
|
16097
16138
|
});
|
|
16098
16139
|
}
|
|
16099
|
-
setSettings(
|
|
16140
|
+
const settings = setSettings(configurations);
|
|
16100
16141
|
bootstrap.isReady = true;
|
|
16101
16142
|
yield initializeDatabase();
|
|
16102
16143
|
if (settings.EnableWireService) {
|
|
@@ -16616,12 +16657,12 @@ var Manager = class {
|
|
|
16616
16657
|
trycatch() {
|
|
16617
16658
|
process.on("uncaughtException", (err) => {
|
|
16618
16659
|
var _a;
|
|
16619
|
-
const ignored = ["ETIMEDOUT", "ECONNRESET", "EHOSTUNREACH", "STARTTLS_FAILURE"];
|
|
16660
|
+
const ignored = ["ETIMEDOUT", "ECONNRESET", "EHOSTUNREACH", "ENOTFOUND", "ECONNREFUSED", "EPIPE", "EADDRINUSE", "EALREADY", "EACCES", "EAGAIN", "EHOSTDOWN", "STARTTLS_FAILURE"];
|
|
16620
16661
|
if (ignored.includes(err == null ? void 0 : err.code)) {
|
|
16621
16662
|
setEventEmit({
|
|
16622
16663
|
event: `onServiceStatus`,
|
|
16623
16664
|
metadata: {
|
|
16624
|
-
message: `
|
|
16665
|
+
message: `Ignored Critical Error: ${(_a = err == null ? void 0 : err.code) != null ? _a : "Unknown error code"}. This may indicate a connection issue. Attempting to continue...`,
|
|
16625
16666
|
data: {},
|
|
16626
16667
|
type: `error`,
|
|
16627
16668
|
error: true
|
package/dist/index.d.mts
CHANGED
|
@@ -2,6 +2,7 @@ type TypeWebhook = {
|
|
|
2
2
|
webhook: string;
|
|
3
3
|
title: string;
|
|
4
4
|
message: string;
|
|
5
|
+
upload: boolean;
|
|
5
6
|
rate: number;
|
|
6
7
|
events: string[];
|
|
7
8
|
};
|
|
@@ -201,7 +202,7 @@ declare const getEventGeometry: (event: TypeEvent) => Promise<GetGeometryRespons
|
|
|
201
202
|
|
|
202
203
|
declare const getCleanedEvent: <T extends Record<string, any>>(event: T) => T;
|
|
203
204
|
|
|
204
|
-
declare const startService: (
|
|
205
|
+
declare const startService: (configurations: TypeSettings) => Promise<void>;
|
|
205
206
|
|
|
206
207
|
declare const stopService: () => Promise<void>;
|
|
207
208
|
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ type TypeWebhook = {
|
|
|
2
2
|
webhook: string;
|
|
3
3
|
title: string;
|
|
4
4
|
message: string;
|
|
5
|
+
upload: boolean;
|
|
5
6
|
rate: number;
|
|
6
7
|
events: string[];
|
|
7
8
|
};
|
|
@@ -201,7 +202,7 @@ declare const getEventGeometry: (event: TypeEvent) => Promise<GetGeometryRespons
|
|
|
201
202
|
|
|
202
203
|
declare const getCleanedEvent: <T extends Record<string, any>>(event: T) => T;
|
|
203
204
|
|
|
204
|
-
declare const startService: (
|
|
205
|
+
declare const startService: (configurations: TypeSettings) => Promise<void>;
|
|
205
206
|
|
|
206
207
|
declare const stopService: () => Promise<void>;
|
|
207
208
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atmosx/event-product-parser",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.4",
|
|
4
4
|
"description": "NOAA Weather Wire & NWS API Parser - Built for standalone and Project AtmosphericX Integration.",
|
|
5
5
|
"main": "dist/cjs/index.cjs",
|
|
6
6
|
"module": "dist/esm/index.mjs",
|
|
@@ -33,12 +33,14 @@
|
|
|
33
33
|
},
|
|
34
34
|
"homepage": "https://github.com/AtmosphericX/event-product-parser#readme",
|
|
35
35
|
"dependencies": {
|
|
36
|
+
"express-ws": "5.0.2",
|
|
37
|
+
"express": "5.2.1",
|
|
36
38
|
"@xmpp/client": "0.14.0",
|
|
37
|
-
"better-sqlite3": "12.
|
|
39
|
+
"better-sqlite3": "12.9.0",
|
|
38
40
|
"croner": "10.0.1",
|
|
39
41
|
"jszip": "3.10.1",
|
|
40
42
|
"polygon-clipping": "0.15.7",
|
|
41
|
-
"request": "
|
|
43
|
+
"request": "2.88.2",
|
|
42
44
|
"say": "0.16.0",
|
|
43
45
|
"shapefile": "0.6.6",
|
|
44
46
|
"typescript": "5.9.3",
|
package/src/@core/core.start.ts
CHANGED
|
@@ -29,13 +29,13 @@ import { updateNode } from "../@manager/manager.updateNodes";
|
|
|
29
29
|
import { updateEvents } from "../@manager/manager.updateEvents";
|
|
30
30
|
import { Cron } from "croner";
|
|
31
31
|
|
|
32
|
-
export const startService = async (
|
|
32
|
+
export const startService = async (configurations: TypeSettings): Promise<void> => {
|
|
33
33
|
if (!bootstrap.isReady) {
|
|
34
34
|
return setWarning({
|
|
35
35
|
message: `You can not create another instance without shutting down the current one first, please make sure to call the stop() method first!`
|
|
36
36
|
})
|
|
37
37
|
}
|
|
38
|
-
setSettings(
|
|
38
|
+
const settings = setSettings(configurations);
|
|
39
39
|
bootstrap.isReady = true;
|
|
40
40
|
await initializeDatabase();
|
|
41
41
|
if (settings.EnableWireService) {
|
|
@@ -42,6 +42,16 @@ export const betterEventNames: Record<string, Record<string, EnhancedEventType>>
|
|
|
42
42
|
},
|
|
43
43
|
"Radar Indicated Tornado Warning": { },
|
|
44
44
|
},
|
|
45
|
+
"Blizzard Warning": {
|
|
46
|
+
"PDS Blizzard Warning": {
|
|
47
|
+
description: "particularly dangerous situation",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
"Ice Storm Warning": {
|
|
51
|
+
"PDS Ice Storm Warning": {
|
|
52
|
+
description: "particularly dangerous situation",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
45
55
|
"Special Marine Warning": {
|
|
46
56
|
"Special Marine Warning (TPROB)": {
|
|
47
57
|
tornado: `POSSIBLE`
|
|
@@ -81,4 +81,13 @@ export const eventTags: Record<string, string> = {
|
|
|
81
81
|
"SHOULD EXERCISE CAUTION": "Should Exercise Caution",
|
|
82
82
|
"LAKE EFFECT SNOW EXPECTED": "Lake Effect Snow Expected",
|
|
83
83
|
"MODERATE LAKE EFFECT SNOWFALL RATES AND BLOWING SNOW": "Moderate Lake Effect Snowfall and Blowing Snow",
|
|
84
|
+
"NO TSUNAMI THREAT": "No Active Tsunami Threat",
|
|
85
|
+
"NO SIGNIFICANT TSUNAMI THREAT": "No Significant Tsunami Threat",
|
|
86
|
+
"NO TSUNAMI IMPACTS ARE EXPECTED": "No Tsunami Impacts Expected",
|
|
87
|
+
"A TSUNAMI THREAT EXISTS": "Tsunami Threat Exists",
|
|
88
|
+
"TSUNAMI THREAT": "Active Tsunami Threat",
|
|
89
|
+
"HEAT ILLNESSES": "Can cause heat illness",
|
|
90
|
+
"WATCH POSSIBLE": "Watch Possible",
|
|
91
|
+
"INTENSIFYING": "Intensifying",
|
|
92
|
+
"CAPABLE OF PRODUCING A LANDSPOUT": "Landspout Possible",
|
|
84
93
|
}
|
package/src/@dictionaries/{dictionaries.eventsOffshore.ts → dictionaries.eventsMatchText.ts}
RENAMED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
export const
|
|
20
|
+
export const eventsMatchText: Record<string, string> = {
|
|
21
21
|
"Special Weather Statement": "Special Weather Statement",
|
|
22
22
|
"Hurricane Warning": "Hurricane Warning",
|
|
23
23
|
"Hurricane Force Wind Warning": "Hurricane Force Wind Warning",
|
|
@@ -28,4 +28,9 @@ export const eventsOffshore: Record<string, string> = {
|
|
|
28
28
|
"Gale Warning": "Gale Warning",
|
|
29
29
|
"Small Craft Advisory": "Small Craft Advisory",
|
|
30
30
|
"Small Craft Warning": "Small Craft Warning",
|
|
31
|
+
"Tsunami Warning": "Tsunami Warning",
|
|
32
|
+
"Tsunami Watch": "Tsunami Watch",
|
|
33
|
+
"Tsunami Advisory": "Tsunami Advisory",
|
|
34
|
+
"Tsunami Information Statement": "Tsunami Information Statement",
|
|
35
|
+
"Subscribers:": "National Weather Service Policy",
|
|
31
36
|
};
|
|
@@ -22,7 +22,7 @@ import { TypeStanzaCompiled } from "../@types/types.compiled"
|
|
|
22
22
|
import { TypeEvent } from "../@types/type.event";
|
|
23
23
|
import { properties } from "../@building/building.properties";
|
|
24
24
|
import { getEventHeader } from "../@building/building.headers";
|
|
25
|
-
import {
|
|
25
|
+
import { eventsMatchText } from "../@dictionaries/dictionaries.eventsMatchText";
|
|
26
26
|
import { getEventTracking } from "../@building/building.tracking";
|
|
27
27
|
import { validateEvents } from "../@building/building.validate";
|
|
28
28
|
|
|
@@ -40,7 +40,7 @@ export const text = async (stanza: TypeStanzaCompiled): Promise<void> => {
|
|
|
40
40
|
const header = getEventHeader({properties: props, getType: stanza.getType})
|
|
41
41
|
const issued = new Date(attributes.issue)
|
|
42
42
|
const expires = new Date(issued.getTime() + 12 * 60 * 60 * 1000)
|
|
43
|
-
let event = Object.keys(
|
|
43
|
+
let event = Object.keys(eventsMatchText).find(event => message.toLowerCase().includes(event.toLowerCase()));
|
|
44
44
|
let isStatement = false;
|
|
45
45
|
if (!event) {
|
|
46
46
|
event = stanza.getType.type.split(`-`).map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `)
|
|
@@ -57,7 +57,7 @@ export const text = async (stanza: TypeStanzaCompiled): Promise<void> => {
|
|
|
57
57
|
parent: event,
|
|
58
58
|
status: isStatement ? `Statement` : `Issued`,
|
|
59
59
|
issued: (!isNaN(issued.getTime())) ? issued.toISOString() : new Date().toISOString(),
|
|
60
|
-
expires: isStatement ? new Date(issued.getTime() +
|
|
60
|
+
expires: isStatement ? new Date(issued.getTime() + 120 * 1000).toISOString() : (!isNaN(expires.getTime())) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1000).toISOString(),
|
|
61
61
|
...props,
|
|
62
62
|
metadata: {
|
|
63
63
|
ms: performance.now() - tick,
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
import { TypeAttributes } from "../@types/types.attributes";
|
|
21
21
|
import { TypeStanzaCompiled } from "../@types/types.compiled"
|
|
22
22
|
import { TypeEvent } from "../@types/type.event";
|
|
23
|
-
import {
|
|
23
|
+
import { eventsMatchText } from "../@dictionaries/dictionaries.eventsMatchText";
|
|
24
24
|
import { ugcExtract } from "../@parsers/@ugc/ugc.extract";
|
|
25
25
|
import { properties } from "../@building/building.properties";
|
|
26
26
|
import { getEventHeader } from "../@building/building.headers";
|
|
@@ -41,11 +41,13 @@ export const ugc = async (stanza: TypeStanzaCompiled): Promise<void> => {
|
|
|
41
41
|
if (ugc != null ) {
|
|
42
42
|
const props = properties({ message, attributes, ugc: ugc })
|
|
43
43
|
const issued = new Date(attributes.issue)
|
|
44
|
-
const expires = new Date(ugc.expires)
|
|
44
|
+
const expires = new Date(ugc.expires)
|
|
45
45
|
const header = getEventHeader({properties: props, getType: stanza.getType })
|
|
46
|
-
let event = Object.keys(
|
|
46
|
+
let event = Object.keys(eventsMatchText).find(event => message.toLowerCase().includes(event.toLowerCase()));
|
|
47
|
+
let isStatement = false;
|
|
47
48
|
if (!event) {
|
|
48
49
|
event = stanza.getType.type.split(`-`).map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `)
|
|
50
|
+
isStatement = true;
|
|
49
51
|
}
|
|
50
52
|
processed.push({
|
|
51
53
|
type: `Feature`,
|
|
@@ -56,9 +58,9 @@ export const ugc = async (stanza: TypeStanzaCompiled): Promise<void> => {
|
|
|
56
58
|
properties: {
|
|
57
59
|
event: event,
|
|
58
60
|
parent: event,
|
|
59
|
-
status: `Issued`,
|
|
61
|
+
status: isStatement ? `Statement` : `Issued`,
|
|
60
62
|
issued: (!isNaN(issued.getTime())) ? issued.toISOString() : new Date().toISOString(),
|
|
61
|
-
expires:
|
|
63
|
+
expires: isStatement ? new Date(issued.getTime() + 120 * 1000).toISOString() : (!isNaN(expires.getTime())) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1000).toISOString(),
|
|
62
64
|
...props,
|
|
63
65
|
metadata: {
|
|
64
66
|
ms: performance.now() - tick,
|
|
@@ -86,10 +86,11 @@ export const mkEvent = async (event: TypeEvent): Promise<void> => {
|
|
|
86
86
|
},
|
|
87
87
|
}
|
|
88
88
|
};
|
|
89
|
+
updateWebhooks(bootstrap.cache.events.features[getIndex])
|
|
89
90
|
} else {
|
|
90
91
|
features.push(event)
|
|
92
|
+
updateWebhooks(event)
|
|
91
93
|
}
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
|
-
updateWebhooks(event)
|
|
95
96
|
}
|
|
@@ -32,10 +32,11 @@ interface CreateWebhookOptions {
|
|
|
32
32
|
export const createWebhook = async (options: CreateWebhookOptions): Promise<void> => {
|
|
33
33
|
const event = options.event.properties;
|
|
34
34
|
const settings = options.webhook;
|
|
35
|
+
|
|
35
36
|
let body = [
|
|
36
37
|
event.locations ? `**Locations**: ${event.locations.slice(0,100)}` : null,
|
|
37
38
|
event.issued ? `**Issued**: <t:${Math.floor(new Date(event.issued).getTime()/1000)}:R>` : null,
|
|
38
|
-
event.expires ? `**Expires**: <t:${Math.floor(new Date(event.expires).getTime()/1000)}:R>` : null,
|
|
39
|
+
event.expires && event.status != `Statement` ? `**Expires**: <t:${Math.floor(new Date(event.expires).getTime()/1000)}:R>` : null,
|
|
39
40
|
(() => {
|
|
40
41
|
const val = event.parameters.estimated_wind_gusts ?? null
|
|
41
42
|
const th = event.parameters.wind_threat ?? null
|
|
@@ -50,6 +51,20 @@ export const createWebhook = async (options: CreateWebhookOptions): Promise<void
|
|
|
50
51
|
event.parameters.damage_threat ? `**Damage Threat**: ${event.parameters.damage_threat}` : null,
|
|
51
52
|
event.parameters.flood_threat ? `**Flood Threat**: ${event.parameters.flood_threat}` : null,
|
|
52
53
|
event.parameters.tornado_threat ? `**Tornado Threat**: ${event.parameters.tornado_threat}` : null,
|
|
54
|
+
event.spc_parameters.spc_max_tornado ? `**Max Tornado Threat**: ${event.spc_parameters.spc_max_tornado}` : null,
|
|
55
|
+
event.spc_parameters.spc_max_hail ? `**Max Hail Threat**: ${event.spc_parameters.spc_max_hail}` : null,
|
|
56
|
+
event.spc_parameters.spc_max_wind ? `**Max Wind Threat**: ${event.spc_parameters.spc_max_wind}` : null,
|
|
57
|
+
event.spc_parameters.spc_watch_issuance ? `**Watch Issuance**: ${event.spc_parameters.spc_watch_issuance}%` : null,
|
|
58
|
+
event.watch_parameters.watch_number ? `**Watch Number**: ${event.watch_parameters.watch_number}` : null,
|
|
59
|
+
event.watch_parameters.strong_tornadoes_probability ? `**Strong Tornadoes Probability**: ${event.watch_parameters.strong_tornadoes_probability}%` : null,
|
|
60
|
+
event.watch_parameters.additional_tornadoes_probability ? `**Additional Tornadoes Probability**: ${event.watch_parameters.additional_tornadoes_probability}%` : null,
|
|
61
|
+
event.watch_parameters.combined_hail_wind_probability ? `**Combined Hail/Wind Probability**: ${event.watch_parameters.combined_hail_wind_probability}%` : null,
|
|
62
|
+
event.watch_parameters.severe_hail_probability ? `**Severe Hail Probability**: ${event.watch_parameters.severe_hail_probability}%` : null,
|
|
63
|
+
event.watch_parameters.hail_2in_probability ? `**Hail ≥2in Probability**: ${event.watch_parameters.hail_2in_probability}%` : null,
|
|
64
|
+
event.watch_parameters.max_hail_in ? `**Max Hail Inches**: ${event.watch_parameters.max_hail_in}` : null,
|
|
65
|
+
event.watch_parameters.severe_wind_probability ? `**Severe Wind Probability**: ${event.watch_parameters.severe_wind_probability}%` : null,
|
|
66
|
+
event.watch_parameters.max_wind_surface ? `**Max Surface Wind**: ${event.watch_parameters.max_wind_surface}` : null,
|
|
67
|
+
event.watch_parameters.max_tops_x100feet ? `**Max Tops (x100 feet)**: ${event.watch_parameters.max_tops_x100feet}` : null,
|
|
53
68
|
(event.parameters.tags?.length > 0) ? `**Tags**: ${event.parameters.tags.join(', ')}` : null,
|
|
54
69
|
(() => {
|
|
55
70
|
const val = event.geocode?.office?.name ?? `N/A`
|
|
@@ -57,8 +72,6 @@ export const createWebhook = async (options: CreateWebhookOptions): Promise<void
|
|
|
57
72
|
return (val || th) ? `**Sender**: ${val} ${th ? `(${th})` : ''}` : null;
|
|
58
73
|
})(),
|
|
59
74
|
event.metadata?.tracking ? `**Tracking**: ${event.metadata.tracking}` : null,
|
|
60
|
-
event.metadata?.vtec?.vtec ? `**VTEC**: ${event.metadata.vtec?.vtec}` : null,
|
|
61
|
-
event.metadata?.filtered_proximity != null ? `**Currently in polygon (Node)**: ${event.metadata.filtered_proximity ? 'Yes' : 'No'}` : null,
|
|
62
75
|
(() => {
|
|
63
76
|
const desc = (event.description || '').split('\n').map(l => l.trim()).filter(Boolean).join('\n');
|
|
64
77
|
return desc ? '```' + '\n' + desc + '\n' + '```' : null;
|
|
@@ -86,10 +99,12 @@ export const createWebhook = async (options: CreateWebhookOptions): Promise<void
|
|
|
86
99
|
content: settings.message ?? "",
|
|
87
100
|
embeds: [embed]
|
|
88
101
|
}));
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
102
|
+
if (settings.upload) {
|
|
103
|
+
form.append("file", Buffer.from(JSON.stringify((getCleanedEvent(event)), null, 2)), {
|
|
104
|
+
filename: `${event.event}_${event.status}_${event.metadata.tracking}.json`,
|
|
105
|
+
contentType: "application/json"
|
|
106
|
+
});
|
|
107
|
+
}
|
|
93
108
|
await createHttp({
|
|
94
109
|
url: settings.webhook,
|
|
95
110
|
timeout: 2000,
|
|
@@ -27,8 +27,8 @@ interface SetWarningOptions {
|
|
|
27
27
|
|
|
28
28
|
export const setWarning = (options: SetWarningOptions): void => {
|
|
29
29
|
const settings = bootstrap.settings as TypeSettings;
|
|
30
|
-
bootstrap.listener.emit(`log`, `${options.title ?? `[${bootstrap.ansi_colors.YELLOW}
|
|
30
|
+
bootstrap.listener.emit(`log`, `${options.title ?? `[${bootstrap.ansi_colors.YELLOW}@atmosx/product-parser${bootstrap.ansi_colors.RESET}]`} ${options.message}`)
|
|
31
31
|
if (settings.EnableJournal) {
|
|
32
|
-
console.log(`${options.title ?? `[${bootstrap.ansi_colors.YELLOW}
|
|
32
|
+
console.log(`${options.title ?? `[${bootstrap.ansi_colors.YELLOW}@atmosx/product-parser${bootstrap.ansi_colors.RESET}]`} ${options.message}`)
|
|
33
33
|
}
|
|
34
34
|
}
|
package/src/bootstrap.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -42,12 +42,12 @@ export class Manager {
|
|
|
42
42
|
|
|
43
43
|
trycatch() {
|
|
44
44
|
process.on('uncaughtException', (err: any) => {
|
|
45
|
-
const ignored = ['ETIMEDOUT', 'ECONNRESET', 'EHOSTUNREACH', 'STARTTLS_FAILURE'];
|
|
45
|
+
const ignored = ['ETIMEDOUT', 'ECONNRESET', 'EHOSTUNREACH', 'ENOTFOUND', 'ECONNREFUSED', 'EPIPE', 'EADDRINUSE', 'EALREADY', 'EACCES', 'EAGAIN', 'EHOSTDOWN', 'STARTTLS_FAILURE'];
|
|
46
46
|
if (ignored.includes(err?.code)) {
|
|
47
47
|
setEventEmit({
|
|
48
48
|
event: `onServiceStatus`,
|
|
49
49
|
metadata: {
|
|
50
|
-
message: `
|
|
50
|
+
message: `Ignored Critical Error: ${err?.code ?? 'Unknown error code'}. This may indicate a connection issue. Attempting to continue...`,
|
|
51
51
|
data: {},
|
|
52
52
|
type: `error`,
|
|
53
53
|
error: true
|
package/test.js
CHANGED
|
@@ -34,6 +34,7 @@ const NOAAWeatherWireService = new Manager({
|
|
|
34
34
|
webhook: "https://discord.com/api/webhooks/XXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
|
|
35
35
|
title: "AtmosphericX - (Severe Weather Events)",
|
|
36
36
|
message: `<@user_id>`,
|
|
37
|
+
upload: true,
|
|
37
38
|
events: [`Severe Thunderstorm Warning`, `Radar Indicated Tornado Warning`],
|
|
38
39
|
rate: 1,
|
|
39
40
|
},
|
|
@@ -41,6 +42,7 @@ const NOAAWeatherWireService = new Manager({
|
|
|
41
42
|
webhook: "https://discord.com/api/webhooks/XXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
|
|
42
43
|
title: "AtmosphericX - (All Events)",
|
|
43
44
|
message: `<@user_id>`,
|
|
45
|
+
upload: false,
|
|
44
46
|
events: [],
|
|
45
47
|
rate: 5,
|
|
46
48
|
}
|