@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 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)
@@ -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.2`,
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}ATMOSX-PARSER${bootstrap.ansi_colors.RESET}]`} ${options.message}`);
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}ATMOSX-PARSER${bootstrap.ansi_colors.RESET}]`} ${options.message}`);
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.eventsOffshore.ts
14462
- var eventsOffshore = {
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, _e, _f, _g, _h;
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, _e2, _f2;
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 = (_f2 = (_e2 = (_d2 = event.geocode) == null ? void 0 : _d2.office) == null ? void 0 : _e2.office) != null ? _f2 : null;
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: (_g = settings.title) != null ? _g : "AtmosphericX",
14835
- content: (_h = settings.message) != null ? _h : "",
14870
+ username: (_c = settings.title) != null ? _c : "AtmosphericX",
14871
+ content: (_d = settings.message) != null ? _d : "",
14836
14872
  embeds: [embed]
14837
14873
  }));
14838
- form.append("file", Buffer.from(JSON.stringify({ type: "FeatureCollection", features: [getCleanedEvent(options.event)] }, null, 2)), {
14839
- filename: `${event.event}_${event.status}_${event.metadata.tracking}.json`,
14840
- contentType: "application/json"
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(eventsOffshore).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
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() + 5 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
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).toISOString();
15436
+ const expires = new Date(ugc2.expires);
15398
15437
  const header = getEventHeader({ properties: props, getType: stanza.getType });
15399
- let event = Object.keys(eventsOffshore).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
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: !isNaN(new Date(ugc2.expires).getTime()) ? expires : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
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 = (settings) => __async(null, null, function* () {
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(settings);
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: `XMPP Critical Error: ${(_a = err == null ? void 0 : err.code) != null ? _a : "Unknown error code"}. This may indicate a connection issue. Attempting to continue...`,
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
@@ -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.2`,
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}ATMOSX-PARSER${bootstrap.ansi_colors.RESET}]`} ${options.message}`);
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}ATMOSX-PARSER${bootstrap.ansi_colors.RESET}]`} ${options.message}`);
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.eventsOffshore.ts
14444
- var eventsOffshore = {
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, _e, _f, _g, _h;
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, _e2, _f2;
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 = (_f2 = (_e2 = (_d2 = event.geocode) == null ? void 0 : _d2.office) == null ? void 0 : _e2.office) != null ? _f2 : null;
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: (_g = settings.title) != null ? _g : "AtmosphericX",
14817
- content: (_h = settings.message) != null ? _h : "",
14852
+ username: (_c = settings.title) != null ? _c : "AtmosphericX",
14853
+ content: (_d = settings.message) != null ? _d : "",
14818
14854
  embeds: [embed]
14819
14855
  }));
14820
- form.append("file", Buffer.from(JSON.stringify({ type: "FeatureCollection", features: [getCleanedEvent(options.event)] }, null, 2)), {
14821
- filename: `${event.event}_${event.status}_${event.metadata.tracking}.json`,
14822
- contentType: "application/json"
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(eventsOffshore).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
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() + 5 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
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).toISOString();
15418
+ const expires = new Date(ugc2.expires);
15380
15419
  const header = getEventHeader({ properties: props, getType: stanza.getType });
15381
- let event = Object.keys(eventsOffshore).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
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: !isNaN(new Date(ugc2.expires).getTime()) ? expires : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
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 = (settings) => __async(null, null, function* () {
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(settings);
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: `XMPP Critical Error: ${(_a = err == null ? void 0 : err.code) != null ? _a : "Unknown error code"}. This may indicate a connection issue. Attempting to continue...`,
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: (settings: TypeSettings) => Promise<void>;
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: (settings: TypeSettings) => Promise<void>;
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.2",
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.10.0",
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": "^2.88.2",
43
+ "request": "2.88.2",
42
44
  "say": "0.16.0",
43
45
  "shapefile": "0.6.6",
44
46
  "typescript": "5.9.3",
@@ -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 (settings: TypeSettings): Promise<void> => {
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(settings);
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
  }
@@ -17,7 +17,7 @@
17
17
 
18
18
  */
19
19
 
20
- export const eventsOffshore: Record<string, string> = {
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 { eventsOffshore } from "../@dictionaries/dictionaries.eventsOffshore";
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(eventsOffshore).find(event => message.toLowerCase().includes(event.toLowerCase()));
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() + 5 * 1000).toISOString() : (!isNaN(expires.getTime())) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1000).toISOString(),
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 { eventsOffshore } from "../@dictionaries/dictionaries.eventsOffshore";
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).toISOString()
44
+ const expires = new Date(ugc.expires)
45
45
  const header = getEventHeader({properties: props, getType: stanza.getType })
46
- let event = Object.keys(eventsOffshore).find(event => message.toLowerCase().includes(event.toLowerCase()));
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: (!isNaN(new Date(ugc.expires).getTime())) ? expires : new Date(Date.now() + 60 * 60 * 1000).toISOString(),
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
- form.append("file", Buffer.from(JSON.stringify({ type: "FeatureCollection", features: [(getCleanedEvent(options.event))] }, null, 2)), {
90
- filename: `${event.event}_${event.status}_${event.metadata.tracking}.json`,
91
- contentType: "application/json"
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}ATMOSX-PARSER${bootstrap.ansi_colors.RESET}]`} ${options.message}`)
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}ATMOSX-PARSER${bootstrap.ansi_colors.RESET}]`} ${options.message}`)
32
+ console.log(`${options.title ?? `[${bootstrap.ansi_colors.YELLOW}@atmosx/product-parser${bootstrap.ansi_colors.RESET}]`} ${options.message}`)
33
33
  }
34
34
  }
@@ -21,6 +21,7 @@ export type TypeWebhook = {
21
21
  webhook: string
22
22
  title: string
23
23
  message: string
24
+ upload: boolean
24
25
  rate: number
25
26
  events: string[]
26
27
  }
package/src/bootstrap.ts CHANGED
@@ -21,7 +21,7 @@ import path from 'path'
21
21
  import { EventEmitter } from 'node:events';
22
22
 
23
23
  export const bootstrap = {
24
- version: `3.0.2`,
24
+ version: `3.0.3`,
25
25
  isReady: true,
26
26
  ratelimits: {},
27
27
  session_xmpp: null,
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: `XMPP Critical Error: ${err?.code ?? 'Unknown error code'}. This may indicate a connection issue. Attempting to continue...`,
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
  }