@atmosx/event-product-parser 3.0.42 → 3.0.44

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.
Files changed (60) hide show
  1. package/README.md +13 -0
  2. package/dist/cjs/index.cjs +1795 -1666
  3. package/dist/esm/index.mjs +1770 -1641
  4. package/dist/index.d.mts +6 -0
  5. package/dist/index.d.ts +6 -0
  6. package/package.json +1 -1
  7. package/src/@building/building.create.ts +2 -2
  8. package/src/@building/building.enhance.ts +1 -1
  9. package/src/@building/building.geometry.ts +1 -1
  10. package/src/@building/building.headers.ts +1 -1
  11. package/src/@building/building.office.ts +2 -2
  12. package/src/@building/building.outlooks.ts +36 -0
  13. package/src/@building/building.properties.ts +6 -4
  14. package/src/@building/building.tracking.ts +3 -3
  15. package/src/@building/building.validate.ts +4 -2
  16. package/src/@core/core.query.ts +1 -1
  17. package/src/@core/core.start.ts +1 -1
  18. package/src/@events/events.api.ts +4 -1
  19. package/src/@events/events.text.ts +3 -2
  20. package/src/@events/events.ugc.ts +3 -2
  21. package/src/@events/events.vtec.ts +5 -4
  22. package/src/@manager/manager.createWebhook.ts +93 -81
  23. package/src/@manager/manager.mkEvent.ts +1 -1
  24. package/src/@manager/manager.setHash.ts +1 -1
  25. package/src/@manager/manager.updateWebhooks.ts +1 -1
  26. package/src/@modules/@database/database.cache.ts +1 -1
  27. package/src/@modules/@database/database.init.ts +1 -1
  28. package/src/@modules/@database/database.shapefiles.ts +1 -1
  29. package/src/@modules/@database/database.stanza.ts +2 -2
  30. package/src/@modules/@eas/eas.getCleanDescription.ts +89 -0
  31. package/src/@modules/@eas/eas.getTTS.ts +43 -0
  32. package/src/@modules/@eas/eas.setEasTone.ts +29 -24
  33. package/src/@modules/@stanza/stanza.getAwipsType.ts +1 -1
  34. package/src/@modules/@stanza/stanza.validate.ts +2 -2
  35. package/src/@modules/@utilities/utilities.getLatestIssuance.ts +32 -0
  36. package/src/@modules/@utilities/utilities.getSettings.ts +1 -1
  37. package/src/@modules/@utilities/utilities.isImageReady.ts +27 -0
  38. package/src/@modules/@utilities/utilities.setCronSchedule.ts +28 -2
  39. package/src/@modules/@utilities/utilities.setSettings.ts +1 -1
  40. package/src/@modules/@utilities/utilities.setWarning.ts +1 -1
  41. package/src/@modules/@xmpp/xmpp.xDeploy.ts +1 -1
  42. package/src/@modules/@xmpp/xmpp.xReconnect.ts +1 -1
  43. package/src/@modules/@xmpp/xmpp.xStanza.ts +1 -1
  44. package/src/@parsers/@hvtec/hvtec.extract.ts +1 -1
  45. package/src/@parsers/@pvtec/pvtec.extract.ts +1 -1
  46. package/src/@parsers/@ugc/ugc.extract.ts +1 -1
  47. package/src/@types/{types.compiled.ts → type.compiled.ts} +1 -1
  48. package/src/@types/type.event.ts +4 -2
  49. package/src/@types/type.properties.ts +3 -1
  50. package/src/@types/{types.settings.ts → type.settings.ts} +3 -2
  51. package/src/@types/{types.webhook.ts → type.webhook.ts} +1 -0
  52. package/src/bootstrap.ts +2 -1
  53. package/src/index.ts +1 -1
  54. package/src/@dictionaries/dictionaries.transcribedMessageReplacements.ts +0 -68
  55. /package/src/@types/{types.attributes.ts → type.attributes.ts} +0 -0
  56. /package/src/@types/{types.hash.ts → type.hash.ts} +0 -0
  57. /package/src/@types/{types.hvtec.ts → type.hvtec.ts} +0 -0
  58. /package/src/@types/{types.pvtec.ts → type.pvtec.ts} +0 -0
  59. /package/src/@types/{types.stanza.ts → type.stanza.ts} +0 -0
  60. /package/src/@types/{types.ugc.ts → type.ugc.ts} +0 -0
@@ -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.42`,
10494
+ version: `3.0.44`,
10495
10495
  isReady: true,
10496
10496
  ratelimits: {},
10497
10497
  session_xmpp: null,
@@ -10568,6 +10568,7 @@ var bootstrap = {
10568
10568
  IgnoreTestProducts: true
10569
10569
  },
10570
10570
  EASSettings: {
10571
+ ArchiveTTL: 60,
10571
10572
  ArchiveDirectory: null,
10572
10573
  IntroWavFile: null
10573
10574
  }
@@ -14392,7 +14393,7 @@ var getEventTags = (message) => {
14392
14393
 
14393
14394
  // src/@building/building.properties.ts
14394
14395
  var properties = (options) => {
14395
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J;
14396
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L;
14396
14397
  const organization = (_b = (_a = options.message.match(regExp.wmo)) == null ? void 0 : _a[0]) != null ? _b : null;
14397
14398
  const polygons = getPolygonFromProduct(options.message);
14398
14399
  const properties2 = {
@@ -14421,23 +14422,25 @@ var properties = (options) => {
14421
14422
  hail_threat: (_t = getTextFromProduct({ message: options.message, find: [`HAIL THREAT...`], removal: [] })) != null ? _t : null
14422
14423
  },
14423
14424
  spc_parameters: {
14424
- spc_max_tornado: (_u = getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK TORNADO INTENSITY...`] })) != null ? _u : null,
14425
- spc_max_hail: (_v = getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK HAIL SIZE...`] })) != null ? _v : null,
14426
- spc_max_wind: (_w = getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK WIND GUST...`] })) != null ? _w : null,
14427
- spc_watch_issuance: (_x = getTextFromProduct({ message: options.message, find: [`Probability of Watch Issuance...`], removal: [`percent`] })) != null ? _x : null
14425
+ spc_number: (_u = getTextFromProduct({ message: options.message, find: [`Mesoscale Discussion `], removal: [`Mesoscale Discussion`, `Number`, `...`] })) != null ? _u : null,
14426
+ spc_concerning: (_v = getTextFromProduct({ message: options.message, find: [`Concerning...`] })) != null ? _v : null,
14427
+ spc_max_tornado: (_w = getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK TORNADO INTENSITY...`] })) != null ? _w : null,
14428
+ spc_max_hail: (_x = getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK HAIL SIZE...`] })) != null ? _x : null,
14429
+ spc_max_wind: (_y = getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK WIND GUST...`] })) != null ? _y : null,
14430
+ spc_watch_issuance: (_z = getTextFromProduct({ message: options.message, find: [`Probability of Watch Issuance...`], removal: [`percent`] })) != null ? _z : null
14428
14431
  },
14429
14432
  watch_parameters: {
14430
- watch_number: (_A = (_z = (_y = getTextFromProduct({ message: options.message, find: [`ITIES FOR`, `UPDATE FOR`, `Watch Number `], removal: [`%`, `<`, `:`] })) == null ? void 0 : _y.replace(/(WT|WS|)/g, "")) == null ? void 0 : _z.trim()) != null ? _A : null,
14433
+ watch_number: (_C = (_B = (_A = getTextFromProduct({ message: options.message, find: [`ITIES FOR`, `UPDATE FOR`, `Watch Number `], removal: [`%`, `<`, `:`] })) == null ? void 0 : _A.replace(/(WT|WS|)/g, "")) == null ? void 0 : _B.trim()) != null ? _C : null,
14431
14434
  watch_type: options.message.includes(`TORNADO WATCH`) ? `Tornado` : (options == null ? void 0 : options.message.includes(`SEVERE`)) ? `Severe` : null,
14432
- additional_tornadoes_probability: (_B = getTextFromProduct({ message: options.message, find: [`PROB OF 2 OR MORE TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _B : null,
14433
- strong_tornadoes_probability: (_C = getTextFromProduct({ message: options.message, find: [`PROB OF 1 OR MORE STRONG /EF2-EF5/ TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _C : null,
14434
- severe_wind_probability: (_D = getTextFromProduct({ message: options.message, find: [`PROB OF 10 OR MORE SEVERE WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _D : null,
14435
- severe_hail_probability: (_E = getTextFromProduct({ message: options.message, find: [`PROB OF 10 OR MORE SEVERE HAIL EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _E : null,
14436
- hail_2in_probability: (_F = getTextFromProduct({ message: options.message, find: [`PROB OF 1 OR MORE HAIL EVENTS >= 2 INCHES`], removal: [`%`, `<`, `:`] })) != null ? _F : null,
14437
- combined_hail_wind_probability: (_G = getTextFromProduct({ message: options.message, find: [`PROB OF 6 OR MORE COMBINED SEVERE HAIL/WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _G : null,
14438
- max_hail_in: (_H = getTextFromProduct({ message: options.message, find: [`MAX HAIL /INCHES/`], removal: [`%`, `<`, `:`] })) != null ? _H : null,
14439
- max_wind_surface: (_I = getTextFromProduct({ message: options.message, find: [`MAX WIND GUSTS SURFACE /KNOTS/`], removal: [`%`, `<`, `:`] })) != null ? _I : null,
14440
- max_tops_x100feet: (_J = getTextFromProduct({ message: options.message, find: [`MAX TOPS /X 100 FEET/`], removal: [`%`, `<`, `:`] })) != null ? _J : null,
14435
+ additional_tornadoes_probability: (_D = getTextFromProduct({ message: options.message, find: [`PROB OF 2 OR MORE TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _D : null,
14436
+ strong_tornadoes_probability: (_E = getTextFromProduct({ message: options.message, find: [`PROB OF 1 OR MORE STRONG /EF2-EF5/ TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _E : null,
14437
+ severe_wind_probability: (_F = getTextFromProduct({ message: options.message, find: [`PROB OF 10 OR MORE SEVERE WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _F : null,
14438
+ severe_hail_probability: (_G = getTextFromProduct({ message: options.message, find: [`PROB OF 10 OR MORE SEVERE HAIL EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _G : null,
14439
+ hail_2in_probability: (_H = getTextFromProduct({ message: options.message, find: [`PROB OF 1 OR MORE HAIL EVENTS >= 2 INCHES`], removal: [`%`, `<`, `:`] })) != null ? _H : null,
14440
+ combined_hail_wind_probability: (_I = getTextFromProduct({ message: options.message, find: [`PROB OF 6 OR MORE COMBINED SEVERE HAIL/WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _I : null,
14441
+ max_hail_in: (_J = getTextFromProduct({ message: options.message, find: [`MAX HAIL /INCHES/`], removal: [`%`, `<`, `:`] })) != null ? _J : null,
14442
+ max_wind_surface: (_K = getTextFromProduct({ message: options.message, find: [`MAX WIND GUSTS SURFACE /KNOTS/`], removal: [`%`, `<`, `:`] })) != null ? _K : null,
14443
+ max_tops_x100feet: (_L = getTextFromProduct({ message: options.message, find: [`MAX TOPS /X 100 FEET/`], removal: [`%`, `<`, `:`] })) != null ? _L : null,
14441
14444
  pds_watch: getTextFromProduct({ message: options.message, find: [`PARTICULARLY DANGEROUS SITUATION`], removal: [`%`, `<`, `:`] }) === `YES`
14442
14445
  }
14443
14446
  };
@@ -14785,1791 +14788,1917 @@ var createHttp = (options) => __async(null, null, function* () {
14785
14788
  });
14786
14789
  });
14787
14790
 
14788
- // src/@manager/manager.createWebhook.ts
14789
- var import_form_data = __toESM(require_form_data());
14790
- var createWebhook = (options) => __async(null, null, function* () {
14791
- var _a, _b, _c, _d, _e, _f;
14792
- const event = options.event.properties;
14793
- const settings = options.webhook;
14794
- let body = [
14795
- event.locations ? `**Locations**: ${event.locations.slice(0, 100)}` : null,
14796
- event.issued && event.status != `Expired` ? `**Issued**: <t:${Math.floor(new Date(event.issued).getTime() / 1e3)}:R>` : null,
14797
- event.expires && event.status != `Statement` ? `**Expires**: <t:${Math.floor(new Date(event.expires).getTime() / 1e3)}:R>` : null,
14798
- (() => {
14799
- var _a2, _b2;
14800
- const val = (_a2 = event.parameters.estimated_wind_gusts) != null ? _a2 : null;
14801
- const th = (_b2 = event.parameters.wind_threat) != null ? _b2 : null;
14802
- const combined = [val, th].filter(Boolean).join(" ");
14803
- return combined ? `**Wind Gusts**: ${val} ${th ? `(${th})` : ""}` : null;
14804
- })(),
14805
- (() => {
14806
- var _a2, _b2;
14807
- const val = (_a2 = event.parameters.estimated_hail_size) != null ? _a2 : null;
14808
- const th = (_b2 = event.parameters.hail_threat) != null ? _b2 : null;
14809
- return (val != null ? val : th) ? `**Hail Threat**: ${val} ${th ? `(${th})` : ""}` : null;
14810
- })(),
14811
- event.parameters.damage_threat ? `**Damage Threat**: ${event.parameters.damage_threat}` : null,
14812
- event.parameters.flood_threat ? `**Flood Threat**: ${event.parameters.flood_threat}` : null,
14813
- event.parameters.tornado_threat ? `**Tornado Threat**: ${event.parameters.tornado_threat}` : null,
14814
- event.spc_parameters.spc_max_tornado ? `**Max Tornado Threat**: ${event.spc_parameters.spc_max_tornado}` : null,
14815
- event.spc_parameters.spc_max_hail ? `**Max Hail Threat**: ${event.spc_parameters.spc_max_hail}` : null,
14816
- event.spc_parameters.spc_max_wind ? `**Max Wind Threat**: ${event.spc_parameters.spc_max_wind}` : null,
14817
- event.spc_parameters.spc_watch_issuance ? `**Watch Issuance**: ${event.spc_parameters.spc_watch_issuance}%` : null,
14818
- event.watch_parameters.watch_number ? `**Watch Number**: ${event.watch_parameters.watch_number}` : null,
14819
- event.watch_parameters.strong_tornadoes_probability ? `**Strong Tornadoes Probability**: ${event.watch_parameters.strong_tornadoes_probability}%` : null,
14820
- event.watch_parameters.additional_tornadoes_probability ? `**Additional Tornadoes Probability**: ${event.watch_parameters.additional_tornadoes_probability}%` : null,
14821
- event.watch_parameters.combined_hail_wind_probability ? `**Combined Hail/Wind Probability**: ${event.watch_parameters.combined_hail_wind_probability}%` : null,
14822
- event.watch_parameters.severe_hail_probability ? `**Severe Hail Probability**: ${event.watch_parameters.severe_hail_probability}%` : null,
14823
- event.watch_parameters.hail_2in_probability ? `**Hail \u22652in Probability**: ${event.watch_parameters.hail_2in_probability}%` : null,
14824
- event.watch_parameters.max_hail_in ? `**Max Hail Inches**: ${event.watch_parameters.max_hail_in}` : null,
14825
- event.watch_parameters.severe_wind_probability ? `**Severe Wind Probability**: ${event.watch_parameters.severe_wind_probability}%` : null,
14826
- event.watch_parameters.max_wind_surface ? `**Max Surface Wind**: ${event.watch_parameters.max_wind_surface}` : null,
14827
- event.watch_parameters.max_tops_x100feet ? `**Max Tops (x100 feet)**: ${event.watch_parameters.max_tops_x100feet}` : null,
14828
- ((_a = event.parameters.tags) == null ? void 0 : _a.length) > 0 ? `**Tags**: ${event.parameters.tags.join(", ")}` : null,
14829
- (() => {
14830
- var _a2, _b2, _c2, _d2, _e2, _f2;
14831
- const val = (_c2 = (_b2 = (_a2 = event.geocode) == null ? void 0 : _a2.office) == null ? void 0 : _b2.name) != null ? _c2 : `N/A`;
14832
- const th = (_f2 = (_e2 = (_d2 = event.geocode) == null ? void 0 : _d2.office) == null ? void 0 : _e2.office) != null ? _f2 : null;
14833
- return (val != null ? val : th) ? `**Sender**: ${val} ${th ? `(${th})` : ""}` : null;
14834
- })(),
14835
- ((_b = event.metadata) == null ? void 0 : _b.tracking) ? `**Tracking**: ${event.metadata.tracking}` : null,
14836
- ((_c = event.metadata.history) == null ? void 0 : _c.length) > 0 ? `**Logs**: ${event.metadata.history.length}` : null,
14837
- (() => {
14838
- var _a2;
14839
- if (event.status == `Expired`) {
14840
- return null;
14841
- }
14842
- const desc = ((_a2 = event.description) != null ? _a2 : "").split("\n").map((l) => l.trim()).filter(Boolean).join("\n");
14843
- return desc ? "```\n" + desc + "\n```" : null;
14844
- })()
14845
- ].filter(Boolean).join("\n");
14846
- const isLimited = setTimeoutAction({ identifier: options.webhook.webhook, interval: options.webhook.rate, max: options.webhook.rate, addTime: true });
14847
- if (isLimited.limited) {
14848
- return;
14849
- }
14850
- if (body.length > 1900) {
14851
- body = body.substring(0, 1900) + "\n\n[Message truncated due to length]";
14852
- const blocks = ((_d = body.match(/```/g)) != null ? _d : []).length;
14853
- if (blocks % 2 !== 0) body += "```";
14854
- }
14855
- const form = new import_form_data.default();
14856
- const embed = {
14857
- title: `${event.event} (${event.status})`,
14858
- description: body,
14859
- color: 16711680,
14860
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
14861
- footer: { text: settings.title }
14862
- };
14863
- form.append("payload_json", JSON.stringify({
14864
- username: (_e = settings.title) != null ? _e : "AtmosphericX",
14865
- content: (_f = settings.message) != null ? _f : "",
14866
- embeds: [embed]
14867
- }));
14868
- if (settings.upload) {
14869
- form.append("file", Buffer.from(JSON.stringify(getCleanedEvent(event), null, 2)), {
14870
- filename: `${event.event}_${event.status}_${event.metadata.tracking}.json`,
14871
- contentType: "application/json"
14872
- });
14873
- }
14874
- yield createHttp({
14875
- url: settings.webhook,
14876
- timeout: 2e3,
14877
- method: `POST`,
14878
- headers: form.getHeaders(),
14879
- body: form
14880
- });
14881
- });
14882
-
14883
- // src/@manager/manager.updateWebhooks.ts
14884
- var updateWebhooks = (event) => __async(null, null, function* () {
14885
- const settings = bootstrap.settings;
14886
- const webhooks = settings.WebhookSettings;
14887
- const eventName = event.properties.event;
14888
- for (const socket of webhooks) {
14889
- const events = socket.events;
14890
- if (!events || events.length === 0) {
14891
- yield createWebhook({ webhook: socket, event });
14892
- continue;
14893
- }
14894
- const matched = events.some((pattern) => {
14895
- if (!pattern) return false;
14896
- if (pattern === "*" || pattern === eventName) return true;
14897
- if (pattern.includes("*")) {
14898
- const regex = "^" + pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$";
14899
- return new RegExp(regex).test(eventName);
14900
- }
14901
- return false;
14902
- });
14903
- if (matched) {
14904
- yield createWebhook({ webhook: socket, event });
14905
- }
14791
+ // src/@modules/@utilities/utilities.isImageReady.ts
14792
+ var isImageReady = (url) => __async(null, null, function* () {
14793
+ try {
14794
+ const res = yield fetch(url, { method: "HEAD" });
14795
+ return res.ok;
14796
+ } catch (e) {
14797
+ return false;
14906
14798
  }
14907
14799
  });
14908
14800
 
14909
- // src/@modules/@utilities/utilities.getShapeNearestPoint.ts
14910
- var getShapeNearestPoint = (coordinates, point) => {
14911
- if (!coordinates || !point) {
14912
- return { proximity: false, point: [0, 0], distance: null };
14801
+ // src/@modules/@eas/eas.getWavPCM16.ts
14802
+ var getWavPCM16 = (buffer) => {
14803
+ if (buffer.toString("ascii", 0, 4) !== "RIFF" || buffer.toString("ascii", 8, 12) !== "WAVE") {
14804
+ return null;
14913
14805
  }
14914
- const normalize = (coords) => {
14915
- if (!Array.isArray(coords)) return [];
14916
- if (typeof coords[0] === "number" && typeof coords[1] === "number") return [];
14917
- if (Array.isArray(coords[0]) && typeof coords[0][0] === "number") {
14918
- return [[coords]];
14919
- }
14920
- if (Array.isArray(coords[0]) && Array.isArray(coords[0][0]) && typeof coords[0][0][0] === "number") {
14921
- return [coords];
14922
- }
14923
- if (Array.isArray(coords[0]) && Array.isArray(coords[0][0]) && Array.isArray(coords[0][0][0]) && typeof coords[0][0][0][0] === "number") {
14924
- return coords;
14925
- }
14926
- return [];
14927
- };
14928
- const polys = normalize(coordinates);
14929
- if (polys.length === 0) return { proximity: false, point: [0, 0], distance: null };
14930
- const lon = point[0];
14931
- const lat = point[1];
14932
- const pointInRing = (pt, ring) => {
14933
- let x = pt[0], y = pt[1];
14934
- let inside = false;
14935
- for (let i = 0, j2 = ring.length - 1; i < ring.length; j2 = i++) {
14936
- const xi = ring[i][0], yi = ring[i][1];
14937
- const xj = ring[j2][0], yj = ring[j2][1];
14938
- const intersect = yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi + 0) + xi;
14939
- if (intersect) inside = !inside;
14940
- }
14941
- return inside;
14942
- };
14943
- const toRadians = (deg) => deg * Math.PI / 180;
14944
- const haversineMiles = (a, b) => {
14945
- const R = 3958.8;
14946
- const dLat = toRadians(b[1] - a[1]);
14947
- const dLon = toRadians(b[0] - a[0]);
14948
- const lat1 = toRadians(a[1]);
14949
- const lat2 = toRadians(b[1]);
14950
- const sinDLat = Math.sin(dLat / 2);
14951
- const sinDLon = Math.sin(dLon / 2);
14952
- const c = 2 * Math.asin(Math.sqrt(sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon));
14953
- return R * c;
14954
- };
14955
- let minDistance = Infinity;
14956
- let closestPoint = null;
14957
- for (const poly of polys) {
14958
- const outer = poly[0];
14959
- const holes = poly.slice(1);
14960
- if (pointInRing(point, outer)) {
14961
- let inHole = false;
14962
- for (const hole of holes) {
14963
- if (pointInRing(point, hole)) {
14964
- inHole = true;
14965
- break;
14966
- }
14967
- }
14968
- if (!inHole) {
14969
- return { proximity: true, point, distance: 0 };
14970
- }
14971
- }
14972
- for (const ring of poly) {
14973
- for (let i = 0; i < ring.length - 1; i++) {
14974
- const start = [ring[i][0], ring[i][1]];
14975
- const end = [ring[i + 1][0], ring[i + 1][1]];
14976
- const A = lon - start[0];
14977
- const B = lat - start[1];
14978
- const C = end[0] - start[0];
14979
- const D = end[1] - start[1];
14980
- const lenSq = C * C + D * D;
14981
- const t = lenSq === 0 ? 0 : Math.max(0, Math.min(1, (A * C + B * D) / lenSq));
14982
- const candidate = [start[0] + t * C, start[1] + t * D];
14983
- const dist = haversineMiles([lon, lat], candidate);
14984
- if (!isNaN(dist) && dist < minDistance) {
14985
- minDistance = Number(dist.toFixed(3));
14986
- closestPoint = candidate;
14987
- }
14988
- }
14989
- }
14806
+ let fmt = null;
14807
+ let data = null;
14808
+ let i = 12;
14809
+ while (i + 8 <= buffer.length) {
14810
+ const id2 = buffer.toString("ascii", i, i + 4);
14811
+ const size = buffer.readUInt32LE(i + 4);
14812
+ const start = i + 8;
14813
+ const end = start + size;
14814
+ if (id2 === "fmt ") fmt = buffer.slice(start, end);
14815
+ if (id2 === "data") data = buffer.slice(start, end);
14816
+ i = end + size % 2;
14990
14817
  }
14991
- if (!isFinite(minDistance) || closestPoint == null) {
14992
- return { proximity: false, point: [0, 0], distance: null };
14818
+ if (!fmt || !data) return null;
14819
+ const audioFormat = fmt.readUInt16LE(0);
14820
+ const channels = fmt.readUInt16LE(2);
14821
+ const sampleRate = fmt.readUInt32LE(4);
14822
+ const bitsPerSample = fmt.readUInt16LE(14);
14823
+ if (audioFormat !== 1 || bitsPerSample !== 16 || channels !== 1) {
14824
+ return null;
14993
14825
  }
14994
- const distanceMiles = minDistance;
14995
- const distanceKm = Number((distanceMiles * 1.609344).toFixed(3));
14996
- const distanceMeters = Math.round(distanceKm * 1e3);
14997
- return { proximity: distanceMiles === 0, point: closestPoint, distance: distanceMiles, distanceKm, distanceMeters };
14826
+ const samples = new Int16Array(data.buffer, data.byteOffset, data.length / 2);
14827
+ return { samples: new Int16Array(samples), sampleRate, channels, bitsPerSample };
14998
14828
  };
14999
14829
 
15000
- // src/@building/building.polygon.ts
15001
- var getEventNodes = (event) => __async(null, null, function* () {
15002
- var _a, _b;
15003
- const metadata = { nodes: [], proximity: false, filtered: false };
15004
- const geometry = yield getEventGeometry(event);
15005
- if (!geometry || !geometry.coordinates) {
15006
- return { nodes: [], filtered: false, updated: Date.now() };
15007
- }
15008
- const nodes = bootstrap.cache.nodes.features;
15009
- for (const node of nodes) {
15010
- const [longitude, latitude] = node.geometry.coordinates;
15011
- const getPoint = getShapeNearestPoint(geometry.coordinates, [longitude, latitude]);
15012
- const miles = (_a = getPoint.distance) != null ? _a : null;
15013
- const kilometers = Number((miles * 1.609344).toFixed(3));
15014
- const info = {
15015
- id: (_b = node.properties) == null ? void 0 : _b.identifier,
15016
- coordinates: [longitude, latitude],
15017
- nearest: getPoint.point,
15018
- miles,
15019
- kilometers,
15020
- proximity: getPoint.proximity
15021
- };
15022
- metadata.nodes.push(info);
15023
- if (bootstrap.settings.GlobalSettings.EventFiltering.NodeLocationFiltering && miles < bootstrap.settings.GlobalSettings.NodeMinDistance) {
15024
- metadata.proximity = true;
15025
- info.proximity = true;
15026
- }
14830
+ // src/@modules/@eas/eas.getSampledPCM16.ts
14831
+ var getSampledPCM16 = (int16, originalRate, targetRate) => {
14832
+ if (originalRate === targetRate) return int16;
14833
+ const ratio = targetRate / originalRate;
14834
+ const outLen = Math.max(1, Math.round(int16.length * ratio));
14835
+ const out = new Int16Array(outLen);
14836
+ for (let i = 0; i < outLen; i++) {
14837
+ const pos = i / ratio;
14838
+ const i0 = Math.floor(pos);
14839
+ const i1 = Math.min(i0 + 1, int16.length - 1);
14840
+ const frac = pos - i0;
14841
+ const v = int16[i0] * (1 - frac) + int16[i1] * frac;
14842
+ out[i] = Math.round(v);
15027
14843
  }
15028
- return {
15029
- nodes: metadata.nodes,
15030
- filtered: metadata.proximity,
15031
- updated: Date.now()
15032
- };
15033
- });
14844
+ return out;
14845
+ };
15034
14846
 
15035
- // src/@manager/manager.updateNodes.ts
15036
- var updateNode = (selectedEvent) => __async(null, null, function* () {
15037
- const events = bootstrap.cache.events.features;
15038
- const ttl = bootstrap.settings.GlobalSettings.NodeTTL * 1e3;
15039
- let total = 0;
15040
- function update(evt) {
15041
- return __async(this, null, function* () {
15042
- var _a, _b, _c;
15043
- const lastUpdate = (_c = (_b = (_a = evt == null ? void 0 : evt.properties) == null ? void 0 : _a.metadata) == null ? void 0 : _b.updated) != null ? _c : null;
15044
- if (lastUpdate != null && Date.now() - lastUpdate < ttl) {
15045
- return evt;
15046
- }
15047
- const node = yield getEventNodes(evt);
15048
- if (node.nodes.length > 0) {
15049
- total++;
15050
- }
15051
- evt.properties.metadata.nodes = node.nodes;
15052
- evt.properties.metadata.filtered_proximity = node.filtered;
15053
- evt.properties.metadata.updated = node.updated;
15054
- });
15055
- }
15056
- if (!selectedEvent) {
15057
- yield Promise.all(events.map((evt) => __async(null, null, function* () {
15058
- yield update(evt);
15059
- })));
15060
- }
15061
- if (selectedEvent) {
15062
- yield update(selectedEvent);
15063
- }
15064
- if (total > 0) {
15065
- setEventEmit({
15066
- event: `onNodeUpdate`,
15067
- metadata: {
15068
- type: `global-update`,
15069
- updated: total
15070
- }
15071
- });
14847
+ // src/@modules/@eas/eas.getPCMToFloat.ts
14848
+ var getPCMToFloat = (int16) => {
14849
+ const out = new Float32Array(int16.length);
14850
+ for (let i = 0; i < int16.length; i++) out[i] = int16[i] / 32768;
14851
+ return out;
14852
+ };
14853
+
14854
+ // src/@modules/@eas/eas.getFloatPCM16.ts
14855
+ var getFloatPCM16 = (float32) => {
14856
+ const out = new Int16Array(float32.length);
14857
+ for (let i = 0; i < float32.length; i++) {
14858
+ let v = Math.max(-1, Math.min(1, float32[i]));
14859
+ out[i] = Math.round(v * 32767);
15072
14860
  }
15073
- });
14861
+ return out;
14862
+ };
15074
14863
 
15075
- // src/@manager/manager.mkEvent.ts
15076
- var mkEvent = (event) => __async(null, null, function* () {
15077
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w;
15078
- const settings = bootstrap.settings;
15079
- const features = bootstrap.cache.events.features;
15080
- const getHash = event.properties.metadata.hash;
15081
- const getTracking = event.properties.metadata.tracking;
15082
- const isEntry = (_a = bootstrap.cache.hashes) == null ? void 0 : _a.find((hash) => hash.tracking === getTracking);
15083
- const isHashed = (_c = (_b = isEntry == null ? void 0 : isEntry.hashes) == null ? void 0 : _b.includes(getHash)) != null ? _c : false;
15084
- const getFeature = features.find((feature) => feature.properties.metadata.tracking === getTracking);
15085
- if (isHashed || event.properties.status_metadata.is_expired) return;
15086
- setHash(event, isEntry);
15087
- const isFilteredLocation = yield updateNode(event).then(() => event.properties.metadata.filtered_proximity);
15088
- if (!isFilteredLocation && settings.GlobalSettings.EventFiltering.NodeLocationFiltering) {
15089
- return;
14864
+ // src/@modules/@eas/eas.setRadioEffect.ts
14865
+ var setRadioEffect = (int16, sampleRate) => {
14866
+ const hpCut = 3555;
14867
+ const lpCut = 1600;
14868
+ const x = getPCMToFloat(int16);
14869
+ const dt = 1 / sampleRate;
14870
+ const rcHP = 1 / (2 * Math.PI * hpCut);
14871
+ const aHP = rcHP / (rcHP + dt);
14872
+ let yHP = 0, xPrev = 0;
14873
+ for (let i = 0; i < x.length; i++) {
14874
+ const xi = x[i];
14875
+ yHP = aHP * (yHP + xi - xPrev);
14876
+ xPrev = xi;
14877
+ x[i] = yHP;
15090
14878
  }
15091
- setEventEmit({
15092
- event: `onEventStatus`,
15093
- metadata: {
15094
- type: getFeature ? `Updated` : `New`,
15095
- event
15096
- },
15097
- message: `[${getFeature ? "Updated" : "New"}] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
15098
- });
15099
- if (settings.GlobalSettings.EventManagement) {
15100
- if (event.properties.status_metadata.is_issued || event.properties.status_metadata.is_updated) {
15101
- if (getFeature) {
15102
- const getIndex = features.indexOf(getFeature);
15103
- const cHistory = (_f = (_e = (_d = getFeature == null ? void 0 : getFeature.properties) == null ? void 0 : _d.metadata) == null ? void 0 : _e.history) != null ? _f : [];
15104
- const cLocations = (_i = (_h = (_g = getFeature == null ? void 0 : getFeature.properties) == null ? void 0 : _g.locations) == null ? void 0 : _h.split(";").map((l) => l.trim())) != null ? _i : [];
15105
- const cUgc = (_l = (_k = (_j = getFeature == null ? void 0 : getFeature.properties) == null ? void 0 : _j.geocode) == null ? void 0 : _k.ugc) != null ? _l : [];
15106
- const iHistory = (_o = (_n = (_m = event.properties) == null ? void 0 : _m.metadata) == null ? void 0 : _n.history) != null ? _o : [];
15107
- const iLocations = (_r = (_q = (_p = event.properties) == null ? void 0 : _p.locations) == null ? void 0 : _q.split(";").map((l) => l.trim())) != null ? _r : [];
15108
- const iUgc = (_u = (_t = (_s = event.properties) == null ? void 0 : _s.geocode) == null ? void 0 : _t.ugc) != null ? _u : [];
15109
- const mHistory = [...cHistory, ...iHistory].filter((v, i, a) => a.indexOf(v) === i).filter((v, i, a) => a.findIndex((h) => h.description === v.description && h.issued === v.issued) === i);
15110
- const mLocations = [...cLocations, ...iLocations].filter((v, i, a) => a.indexOf(v) === i).join("; ");
15111
- const mUgc = [...cUgc, ...iUgc].filter((v, i, a) => a.indexOf(v) === i);
15112
- bootstrap.cache.events.features[getIndex] = __spreadProps(__spreadValues({}, event), {
15113
- properties: __spreadProps(__spreadValues({}, event.properties), {
15114
- metadata: __spreadProps(__spreadValues({}, (_v = event == null ? void 0 : event.properties) == null ? void 0 : _v.metadata), {
15115
- history: mHistory
15116
- }),
15117
- locations: mLocations,
15118
- geocode: __spreadProps(__spreadValues({}, (_w = event == null ? void 0 : event.properties) == null ? void 0 : _w.geocode), {
15119
- ugc: mUgc
15120
- })
15121
- })
15122
- });
15123
- updateWebhooks(bootstrap.cache.events.features[getIndex]);
15124
- } else {
15125
- features.push(event);
15126
- updateWebhooks(event);
15127
- }
14879
+ const rcLP = 1 / (2 * Math.PI * lpCut);
14880
+ const aLP = dt / (rcLP + dt);
14881
+ let yLP = 0;
14882
+ for (let i = 0; i < x.length; i++) {
14883
+ yLP = yLP + aLP * (x[i] - yLP);
14884
+ x[i] = yLP;
14885
+ }
14886
+ const compGain = 2;
14887
+ const norm = Math.tanh(compGain);
14888
+ for (let i = 0; i < x.length; i++) x[i] = Math.tanh(x[i] * compGain) / norm;
14889
+ return getFloatPCM16(x);
14890
+ };
14891
+
14892
+ // src/@modules/@eas/eas.setAFSK.ts
14893
+ var setAFSK = (bits, sampleRate) => {
14894
+ const baud = 520.83;
14895
+ const markFreq = 2083.3;
14896
+ const spaceFreq = 1562.5;
14897
+ const amplitude = 0.6;
14898
+ const twoPi = Math.PI * 2;
14899
+ const result = [];
14900
+ let phase = 0;
14901
+ let frac = 0;
14902
+ for (let b = 0; b < bits.length; b++) {
14903
+ const bit = bits[b];
14904
+ const freq = bit ? markFreq : spaceFreq;
14905
+ const samplesPerBit = sampleRate / baud + frac;
14906
+ const n = Math.round(samplesPerBit);
14907
+ frac = samplesPerBit - n;
14908
+ const inc = twoPi * freq / sampleRate;
14909
+ for (let i = 0; i < n; i++) {
14910
+ result.push(Math.round(Math.sin(phase) * amplitude * 32767));
14911
+ phase += inc;
14912
+ if (phase > twoPi) phase -= twoPi;
15128
14913
  }
15129
14914
  }
15130
- });
14915
+ const fadeSamples = Math.floor(sampleRate * 2e-3);
14916
+ for (let i = 0; i < fadeSamples; i++) {
14917
+ const gain = i / fadeSamples;
14918
+ result[i] = Math.round(result[i] * gain);
14919
+ result[result.length - 1 - i] = Math.round(result[result.length - 1 - i] * gain);
14920
+ }
14921
+ return Int16Array.from(result);
14922
+ };
15131
14923
 
15132
- // src/@manager/manager.rmEvent.ts
15133
- var rmEvent = (event) => {
15134
- const getEvent = bootstrap.cache.events.features.find((f) => {
15135
- var _a, _b, _c, _d;
15136
- return ((_b = (_a = f == null ? void 0 : f.properties) == null ? void 0 : _a.metadata) == null ? void 0 : _b.tracking) === ((_d = (_c = event == null ? void 0 : event.properties) == null ? void 0 : _c.metadata) == null ? void 0 : _d.tracking);
15137
- });
15138
- const cachedStatus = event.properties.status;
15139
- event.properties.expires = (/* @__PURE__ */ new Date()).toISOString();
15140
- event.properties.status = `Expired`;
15141
- if (getEvent) {
15142
- setEventEmit({
15143
- event: `onEventStatus`,
15144
- metadata: {
15145
- type: `Removed`,
15146
- event
15147
- },
15148
- message: `[Removed] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
15149
- });
15150
- setEventEmit({ event: `onExpiredProduct`, metadata: event });
15151
- if (cachedStatus != `Statement`) updateWebhooks(event);
15152
- bootstrap.cache.events.features.splice(bootstrap.cache.events.features.indexOf(getEvent), 1);
15153
- bootstrap.cache.hashes = bootstrap.cache.hashes.filter((hash) => hash.tracking !== event.properties.metadata.tracking);
14924
+ // src/@modules/@eas/eas.setAsciiToBits.ts
14925
+ var setAsciiToBits = (str) => {
14926
+ const bits = [];
14927
+ for (let i = 0; i < str.length; i++) {
14928
+ const c = str.charCodeAt(i) & 255;
14929
+ bits.push(0);
14930
+ for (let b = 0; b < 8; b++) bits.push(c >> b & 1);
14931
+ bits.push(1, 1);
15154
14932
  }
15155
- setEventEmit({
15156
- event: `onEventCache`,
15157
- metadata: bootstrap.cache.events,
15158
- limited: true
15159
- });
14933
+ return bits;
15160
14934
  };
15161
14935
 
15162
- // src/@building/building.validate.ts
15163
- var validateEvents = (events) => __async(null, null, function* () {
15164
- var _a;
15165
- if (events.length === 0) return;
15166
- const configurations = bootstrap.settings;
15167
- const sets = {};
15168
- const bools = {};
15169
- const megered = __spreadValues(__spreadValues({}, configurations.GlobalSettings), configurations.GlobalSettings.EventFiltering);
15170
- for (const key in megered) {
15171
- const setting = megered[key];
15172
- if (Array.isArray(setting)) {
15173
- sets[key] = new Set(setting.map((item) => item.toLowerCase()));
15174
- }
15175
- if (typeof setting === "boolean") {
15176
- bools[key] = setting;
15177
- }
14936
+ // src/@modules/@eas/eas.getMergedPCM16.ts
14937
+ var getMergedPCM16 = (arrays) => {
14938
+ let total = 0;
14939
+ for (const a of arrays) total += a.length;
14940
+ const out = new Int16Array(total);
14941
+ let o = 0;
14942
+ for (const a of arrays) {
14943
+ out.set(a, o);
14944
+ o += a.length;
15178
14945
  }
15179
- const filterd = events.filter((event) => {
15180
- var _a2, _b, _c, _d, _e;
15181
- const define2 = getEventSignature(event);
15182
- const properties2 = define2.properties;
15183
- const zones = properties2.geocode.ugc;
15184
- const icao = properties2.geocode.office.office;
15185
- const enhancedEventName = properties2.event = getEventEnhancedName(event);
15186
- const filteredProperties = JSON.parse(JSON.stringify(properties2));
15187
- if ((filteredProperties == null ? void 0 : filteredProperties.metadata) && "ms" in filteredProperties.metadata) {
15188
- delete filteredProperties.metadata.ms;
15189
- }
15190
- filteredProperties.metadata = (_a2 = filteredProperties.metadata) != null ? _a2 : {};
15191
- properties2.metadata.hash = createHash("sha256").update(JSON.stringify(filteredProperties)).digest("hex");
15192
- setEventEmit({ event: `onProductType${enhancedEventName.replace(/\s+/g, "")}`, metadata: define2 });
15193
- if (properties2.status_metadata.is_test) {
15194
- setEventEmit({ event: `onTestProduct`, metadata: define2 });
15195
- if (bools == null ? void 0 : bools.IgnoreTestProducts) return false;
14946
+ return out;
14947
+ };
14948
+
14949
+ // src/@modules/@eas/eas.setSameHeader.ts
14950
+ var setSameHeader = (vtec2, repeats, sampleRate = 8e3, options = {}) => {
14951
+ var _a, _b;
14952
+ const preMarkSec = (_a = options.preMarkSec) != null ? _a : 0.3;
14953
+ const gapSec = (_b = options.gapSec) != null ? _b : 0.1;
14954
+ const bursts = [];
14955
+ const gap = new Int16Array(Math.floor(gapSec * sampleRate));
14956
+ for (let i = 0; i < repeats; i++) {
14957
+ const bodyBits = setAsciiToBits(vtec2);
14958
+ const body = setAFSK(bodyBits, sampleRate);
14959
+ const extendedBodyDuration = Math.round(preMarkSec * sampleRate);
14960
+ const extendedBody = new Int16Array(extendedBodyDuration + gap.length);
14961
+ for (let j2 = 0; j2 < extendedBodyDuration; j2++) {
14962
+ extendedBody[j2] = Math.round(body[j2 % body.length] * 0.2);
15196
14963
  }
15197
- if (properties2.status_metadata.is_expired) {
15198
- setEventEmit({ event: `onExpiredProduct`, metadata: define2 });
15199
- rmEvent(define2);
15200
- return false;
14964
+ extendedBody.set(gap, extendedBodyDuration);
14965
+ bursts.push(extendedBody);
14966
+ if (i !== repeats - 1) bursts.push(gap);
14967
+ }
14968
+ return getMergedPCM16(bursts);
14969
+ };
14970
+
14971
+ // src/@modules/@eas/eas.setAttentionTone.ts
14972
+ var setAttentionTone = (ms, sampleRate) => {
14973
+ const len = Math.floor(ms * sampleRate);
14974
+ const out = new Int16Array(len);
14975
+ const f1 = 853;
14976
+ const f2 = 960;
14977
+ const twoPi = Math.PI * 2;
14978
+ const amp = 0.1;
14979
+ const fadeLen = Math.floor(sampleRate * 0);
14980
+ for (let i = 0; i < len; i++) {
14981
+ const t = i / sampleRate;
14982
+ const s = Math.sin(twoPi * f1 * t) + Math.sin(twoPi * f2 * t);
14983
+ let gain = 1;
14984
+ if (i < fadeLen) gain = i / fadeLen;
14985
+ else if (i > len - fadeLen) gain = (len - i) / fadeLen;
14986
+ const v = Math.max(-1, Math.min(1, s / 2 * amp * gain));
14987
+ out[i] = Math.round(v * 32767);
14988
+ }
14989
+ return out;
14990
+ };
14991
+
14992
+ // src/@modules/@eas/eas.setNoise.ts
14993
+ var setNoise = (int16, noiseLevel = 0.02) => {
14994
+ const x = getPCMToFloat(int16);
14995
+ for (let i = 0; i < x.length; i++) x[i] += (Math.random() * 2 - 1) * noiseLevel;
14996
+ let peak = 0;
14997
+ for (let i = 0; i < x.length; i++) peak = Math.max(peak, Math.abs(x[i]));
14998
+ if (peak > 1) for (let i = 0; i < x.length; i++) x[i] *= 0.98 / peak;
14999
+ return getFloatPCM16(x);
15000
+ };
15001
+
15002
+ // src/@modules/@eas/eas.getPCM16.ts
15003
+ var getPCM16 = (samples, sampleRate) => {
15004
+ let o = 0;
15005
+ const bytesPerSample = 2;
15006
+ const blockAlign = 1 * bytesPerSample;
15007
+ const byteRate = sampleRate * blockAlign;
15008
+ const subchunk2Size = samples.length * bytesPerSample;
15009
+ const chunkSize = 36 + subchunk2Size;
15010
+ const buffer = Buffer.alloc(44 + subchunk2Size);
15011
+ buffer.write("RIFF", o);
15012
+ o += 4;
15013
+ buffer.writeUInt32LE(chunkSize, o);
15014
+ o += 4;
15015
+ buffer.write("WAVE", o);
15016
+ o += 4;
15017
+ buffer.write("fmt ", o);
15018
+ o += 4;
15019
+ buffer.writeUInt32LE(16, o);
15020
+ o += 4;
15021
+ buffer.writeUInt16LE(1, o);
15022
+ o += 2;
15023
+ buffer.writeUInt16LE(1, o);
15024
+ o += 2;
15025
+ buffer.writeUInt32LE(sampleRate, o);
15026
+ o += 4;
15027
+ buffer.writeUInt32LE(byteRate, o);
15028
+ o += 4;
15029
+ buffer.writeUInt16LE(blockAlign, o);
15030
+ o += 2;
15031
+ buffer.writeUInt16LE(16, o);
15032
+ o += 2;
15033
+ buffer.write("data", o);
15034
+ o += 4;
15035
+ buffer.writeUInt32LE(subchunk2Size, o);
15036
+ o += 4;
15037
+ for (let i = 0; i < samples.length; i++, o += 2) {
15038
+ buffer.writeInt16LE(samples[i].value, o);
15039
+ }
15040
+ return buffer;
15041
+ };
15042
+
15043
+ // src/@modules/@eas/eas.getTTS.ts
15044
+ import { platform } from "os";
15045
+ import { execSync } from "child_process";
15046
+ var getTTS = (text2, outputPath) => __async(null, null, function* () {
15047
+ const vPlatform = platform();
15048
+ switch (vPlatform) {
15049
+ case "win32": {
15050
+ const command = `Add-Type -AssemblyName System.Speech;$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;$speak.SetOutputToWaveFile('${outputPath}');$speak.Speak('${text2}');$speak.Dispose();`;
15051
+ execSync(`powershell -Command "${command}"`, { stdio: "ignore" });
15052
+ break;
15201
15053
  }
15202
- if ((_c = (_b = properties2.metadata) == null ? void 0 : _b.vtec) == null ? void 0 : _c.is_watch) {
15203
- const isSPC = (_e = (_d = properties2.metadata) == null ? void 0 : _d.vtec) == null ? void 0 : _e.prediction_center;
15204
- setEventEmit({ event: isSPC ? `onStormPredictionWatch` : `onNonStormPredictionWatch`, metadata: define2 });
15205
- if ((bools == null ? void 0 : bools.SPCWatchesOnly) && !isSPC) {
15206
- return false;
15207
- }
15208
- if (!(bools == null ? void 0 : bools.SPCWatchesOnly) && isSPC) {
15209
- return false;
15054
+ case "linux":
15055
+ execSync(`espeak -w "${outputPath}" "${text2.replace(/"/g, '\\"')}"`);
15056
+ break;
15057
+ default:
15058
+ break;
15059
+ }
15060
+ });
15061
+
15062
+ // src/@modules/@eas/eas.getCleanDescription.ts
15063
+ var getCleanDescription = (message) => {
15064
+ const patches = [
15065
+ { regex: /\.{3,}/g, replacement: ". " },
15066
+ { regex: /\bUTC\b/g, replacement: "Coordinated Universal Time" },
15067
+ { regex: /\bGMT\b/g, replacement: "Greenwich Mean Time" },
15068
+ { regex: /\bEST\b(?!\w)/g, replacement: "Eastern Standard Time" },
15069
+ { regex: /\bEDT\b(?!\w)/g, replacement: "Eastern Daylight Time" },
15070
+ { regex: /\bCST\b(?!\w)/g, replacement: "Central Standard Time" },
15071
+ { regex: /\bCDT\b(?!\w)/g, replacement: "Central Daylight Time" },
15072
+ { regex: /\bMST\b(?!\w)/g, replacement: "Mountain Standard Time" },
15073
+ { regex: /\bMDT\b(?!\w)/g, replacement: "Mountain Daylight Time" },
15074
+ { regex: /\bPST\b(?!\w)/g, replacement: "Pacific Standard Time" },
15075
+ { regex: /\bPDT\b(?!\w)/g, replacement: "Pacific Daylight Time" },
15076
+ { regex: /\bAKST\b(?!\w)/g, replacement: "Alaska Standard Time" },
15077
+ { regex: /\bAKDT\b(?!\w)/g, replacement: "Alaska Daylight Time" },
15078
+ { regex: /\bHST\b(?!\w)/g, replacement: "Hawaii Standard Time" },
15079
+ { regex: /\bHDT\b(?!\w)/g, replacement: "Hawaii Daylight Time" },
15080
+ { regex: /\bmph\b(?!\w)/g, replacement: "miles per hour" },
15081
+ { regex: /\bkm\/h\b(?!\w)/g, replacement: "kilometers per hour" },
15082
+ { regex: /\bkmh\b(?!\w)/g, replacement: "kilometers per hour" },
15083
+ { regex: /\bkt\b(?!\w)/g, replacement: "knots" },
15084
+ { regex: /\bNE\b(?!\w)/g, replacement: "northeast" },
15085
+ { regex: /\bNW\b(?!\w)/g, replacement: "northwest" },
15086
+ { regex: /\bSE\b(?!\w)/g, replacement: "southeast" },
15087
+ { regex: /\bSW\b(?!\w)/g, replacement: "southwest" },
15088
+ { regex: /\bNM\b(?!\w)/g, replacement: "nautical miles" },
15089
+ { regex: /\bdeg\b(?!\w)/g, replacement: "degrees" },
15090
+ { regex: /\btstm\b(?!\w)/g, replacement: "thunderstorm" },
15091
+ { regex: /\bmm\b(?!\w)/g, replacement: "millimeters" },
15092
+ { regex: /\bcm\b(?!\w)/g, replacement: "centimeters" },
15093
+ { regex: /\bin.\b(?!\w)/g, replacement: "inches" },
15094
+ { regex: /\bft\b(?!\w)/g, replacement: "feet" },
15095
+ { regex: /\bmi\b(?!\w)/g, replacement: "miles" },
15096
+ { regex: /\bhr\b(?!\w)/g, replacement: "hour" },
15097
+ { regex: /\bhourly\b(?!\w)/g, replacement: "per hour" },
15098
+ { regex: /\bkg\b(?!\w)/g, replacement: "kilograms" },
15099
+ { regex: /\bg\/kg\b(?!\w)/g, replacement: "grams per kilogram" },
15100
+ { regex: /\bmb\b(?!\w)/g, replacement: "millibars" },
15101
+ { regex: /\bhPa\b(?!\w)/g, replacement: "hectopascals" },
15102
+ { regex: /\bPa\b(?!\w)/g, replacement: "pascals" },
15103
+ { regex: /\bKPa\b(?!\w)/g, replacement: "kilopascals" },
15104
+ { regex: /\bC\/hr\b(?!\w)/g, replacement: "degrees Celsius per hour" },
15105
+ { regex: /\bF\/hr\b(?!\w)/g, replacement: "degrees Fahrenheit per hour" },
15106
+ { regex: /\bC\/min\b(?!\w)/g, replacement: "degrees Celsius per minute" },
15107
+ { regex: /\bF\/min\b(?!\w)/g, replacement: "degrees Fahrenheit per minute" },
15108
+ { regex: /\bC\b(?!\w)/g, replacement: "degrees Celsius" },
15109
+ { regex: /\bF\b(?!\w)/g, replacement: "degrees Fahrenheit" }
15110
+ ];
15111
+ const hours = {
15112
+ 0: "twelve",
15113
+ 1: "one",
15114
+ 2: "two",
15115
+ 3: "three",
15116
+ 4: "four",
15117
+ 5: "five",
15118
+ 6: "six",
15119
+ 7: "seven",
15120
+ 8: "eight",
15121
+ 9: "nine",
15122
+ 10: "ten",
15123
+ 11: "eleven",
15124
+ 12: "twelve"
15125
+ };
15126
+ const minWord = (m) => m === 0 ? "o'clock" : m < 10 ? `oh ${m}` : `${m}`;
15127
+ const fmt = (h, m, ap) => `${hours[h % 12]} ${minWord(m)} ${ap}`;
15128
+ for (const { regex, replacement } of patches) {
15129
+ message = message.replace(regex, replacement);
15130
+ }
15131
+ return message.replace(/\b(\d{1,2}):(\d{2})\s*(AM|PM)\b/gi, (_, h, m, ap) => fmt(+h, +m, ap.toUpperCase())).replace(/\b(\d{1,2})\s+(\d{2})\s+(AM|PM)\b/gi, (_, h, m, ap) => fmt(+h, +m, ap.toUpperCase())).replace(/\b(\d{2})(\d{2})\s+(AM|PM)\b/gi, (_, hh, mm, ap) => fmt(+hh, +mm, ap.toUpperCase())).replace(/\*+/g, " ").replace(/-/g, " ").replace(/\n/g, " ").trim();
15132
+ };
15133
+
15134
+ // src/@modules/@eas/eas.setEasTone.ts
15135
+ import { join } from "path";
15136
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
15137
+ import { execSync as execSync2 } from "child_process";
15138
+ import { platform as platform2 } from "os";
15139
+ var setEasTone = (options) => __async(null, null, function* () {
15140
+ const settings = bootstrap.settings;
15141
+ const directory = settings.GlobalSettings.EASSettings.ArchiveDirectory;
15142
+ const prefix = settings.GlobalSettings.EASSettings.IntroWavFile;
15143
+ let message = options.message;
15144
+ let header = options.header;
15145
+ if (!message || !header) {
15146
+ setWarning({
15147
+ title: `EAS`,
15148
+ message: `Message and header are required to generate an EAS tone.`
15149
+ });
15150
+ return null;
15151
+ }
15152
+ let buffTTS;
15153
+ let buffRadio;
15154
+ let buffFull = [];
15155
+ if (!existsSync(directory)) {
15156
+ mkdirSync(directory, { recursive: true });
15157
+ }
15158
+ if (!existsSync(join(directory, `/temp`))) {
15159
+ mkdirSync(join(directory, `/temp`), { recursive: true });
15160
+ }
15161
+ if (!existsSync(join(directory, `/output`))) {
15162
+ mkdirSync(join(directory, `/output`), { recursive: true });
15163
+ }
15164
+ const tmpTTS = join(directory, `/temp/${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, "")}.wav`);
15165
+ const outTTS = join(directory, `/output/${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, "")}.wav`);
15166
+ const vPlatform = platform2();
15167
+ if (vPlatform === "darwin") {
15168
+ setWarning({
15169
+ title: `EAS`,
15170
+ message: `EAS tone generation is not supported on macOS.`
15171
+ });
15172
+ return null;
15173
+ }
15174
+ yield new Promise((resolve6, reject) => {
15175
+ const tMsg = getCleanDescription(message);
15176
+ getTTS(tMsg, tmpTTS).then(() => {
15177
+ buffTTS = readFileSync(tmpTTS);
15178
+ resolve6();
15179
+ });
15180
+ });
15181
+ const vWav = getWavPCM16(buffTTS);
15182
+ const vSamples = getSampledPCM16(vWav.samples, vWav.sampleRate, 8e3);
15183
+ const vRadio = setRadioEffect(vSamples, 8e3);
15184
+ if (existsSync(prefix)) {
15185
+ let tBuffer = readFileSync(prefix);
15186
+ let tWav = getWavPCM16(tBuffer);
15187
+ if (tWav == null) {
15188
+ try {
15189
+ const converted = join(directory, `/temp/${Math.random().toString(36).substring(2, 15)}.converted.wav`);
15190
+ execSync2(`ffmpeg -y -i "${prefix}" -ar 8000 -ac 1 -sample_fmt s16 "${converted}"`, { stdio: "ignore" });
15191
+ if (existsSync(converted)) {
15192
+ tBuffer = readFileSync(converted);
15193
+ tWav = getWavPCM16(tBuffer);
15194
+ try {
15195
+ unlinkSync(converted);
15196
+ } catch (e) {
15197
+ }
15198
+ }
15199
+ } catch (e) {
15210
15200
  }
15211
15201
  }
15212
- for (const key in sets) {
15213
- const setting = sets[key];
15214
- if (key === "ListeningEvents" && setting.size > 0 && !setting.has(define2.properties.event.toLowerCase())) {
15215
- setEventEmit({
15216
- event: `onFilteredEvent`,
15217
- metadata: define2
15218
- });
15219
- return false;
15220
- }
15221
- if (key === "IgnoredEvents" && setting.size > 0 && setting.has(define2.properties.event.toLowerCase())) {
15222
- setEventEmit({
15223
- event: `onIgnoredEvent`,
15224
- metadata: define2
15225
- });
15226
- return false;
15227
- }
15228
- if (key === "ListeningICAO" && setting.size > 0 && icao != null && !setting.has(icao.toLowerCase())) {
15229
- setEventEmit({
15230
- event: `onFilteredICAO`,
15231
- metadata: define2
15232
- });
15233
- return false;
15234
- }
15235
- if (key === "IgnoredICAO" && setting.size > 0 && icao != null && setting.has(icao.toLowerCase())) {
15236
- setEventEmit({
15237
- event: `onIgnoredICAO`,
15238
- metadata: define2
15239
- });
15240
- return false;
15241
- }
15242
- if (key === "ListeningUGC" && setting.size > 0 && zones.length > 0 && !zones.some((ugc2) => setting.has(ugc2.toLowerCase()))) {
15243
- setEventEmit({
15244
- event: `onFilteredUGC`,
15245
- metadata: define2
15246
- });
15247
- return false;
15202
+ if (tWav == null) {
15203
+ setWarning({ title: `EAS`, message: `Intro tone isn't a valid .WAV file or isn't in PCM 16-bit format. Converted attempt failed; please convert it then try again.` });
15204
+ return null;
15205
+ }
15206
+ const tSamples = tWav.sampleRate != 8e3 ? getSampledPCM16(tWav.samples, tWav.sampleRate, 8e3) : tWav.samples;
15207
+ buffRadio = setRadioEffect(tSamples, 8e3);
15208
+ }
15209
+ buffFull = buffRadio != null ? [buffRadio, new Int16Array(Math.floor(0.5 * 8e3))] : [];
15210
+ buffFull.push(
15211
+ setSameHeader(header, 3, 8e3, {
15212
+ preMarkSec: 1.1,
15213
+ gapSec: 0.5
15214
+ }),
15215
+ new Int16Array(Math.floor(0.5 * 8e3)),
15216
+ setAttentionTone(8, 8e3),
15217
+ new Int16Array(Math.floor(0.5 * 8e3)),
15218
+ vRadio
15219
+ );
15220
+ for (let i = 0; i < 3; i++) {
15221
+ buffFull.push(setSameHeader(header, 1, 8e3, { preMarkSec: 0.5, gapSec: 0.1 }));
15222
+ buffFull.push(new Int16Array(Math.floor(0.5 * 8e3)));
15223
+ }
15224
+ const aSamples = getMergedPCM16(buffFull);
15225
+ const aFinal = setNoise(aSamples, 2e-3);
15226
+ const aBuffer = getPCM16(Array.from(aFinal).map((v) => ({ value: v })), 8e3);
15227
+ writeFileSync(outTTS, aBuffer);
15228
+ try {
15229
+ unlinkSync(tmpTTS);
15230
+ } catch (e) {
15231
+ }
15232
+ return outTTS;
15233
+ });
15234
+
15235
+ // src/@manager/manager.createWebhook.ts
15236
+ var import_form_data = __toESM(require_form_data());
15237
+ import { readFileSync as readFileSync2 } from "fs";
15238
+ var createWebhook = (options) => __async(null, null, function* () {
15239
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
15240
+ const event = options.event.properties;
15241
+ const settings = options.webhook;
15242
+ const line = (label, value, condition = true) => condition && value ? `${label} ${value}` : null;
15243
+ const isLimited = setTimeoutAction({ identifier: options.webhook.webhook, interval: options.webhook.rate, max: options.webhook.rate, addTime: true });
15244
+ if (!isLimited.limited) {
15245
+ const isStatement = event.status_metadata.is_statement;
15246
+ const isExpired = event.status_metadata.is_expired;
15247
+ let body = [
15248
+ line(`**Locations:**`, (_a = event == null ? void 0 : event.locations) == null ? void 0 : _a.slice(0, 100)),
15249
+ line(`**Issued:**`, `<t:${Math.floor(new Date(event.issued).getTime() / 1e3)}:R>`),
15250
+ line(`**Expires:**`, `<t:${Math.floor(new Date(event.expires).getTime() / 1e3)}:R>`, !isExpired && !isStatement),
15251
+ line(`**Damage Threat:**`, event.parameters.damage_threat, !isExpired),
15252
+ line(`**Flood Threat:**`, event.parameters.flood_threat, !isExpired),
15253
+ line(`**Tornado Threat:**`, event.parameters.tornado_threat, !isExpired),
15254
+ line(`**Estimated Wind Gusts:**`, `${event.parameters.estimated_wind_gusts} ${event.parameters.wind_threat ? ` (${event.parameters.wind_threat})` : ""}`, !isExpired && event.parameters.estimated_wind_gusts != null),
15255
+ line(`**Estimated Hail Size:**`, `${event.parameters.estimated_hail_size} ${event.parameters.hail_threat ? ` (${event.parameters.hail_threat})` : ""}`, !isExpired && event.parameters.estimated_hail_size != null),
15256
+ line(`**Discussion:**`, event.spc_parameters.spc_number, !isExpired),
15257
+ line(`**Concern:**`, event.spc_parameters.spc_concerning, !isExpired),
15258
+ line(`**SPC Max Tornado Threat:**`, event.spc_parameters.spc_max_tornado, !isExpired),
15259
+ line(`**SPC Max Hail Threat:**`, event.spc_parameters.spc_max_hail, !isExpired),
15260
+ line(`**SPC Max Wind Threat:**`, event.spc_parameters.spc_max_wind, !isExpired),
15261
+ line(`**SPC Watch Issuance Probability:**`, event.spc_parameters.spc_watch_issuance ? `${event.spc_parameters.spc_watch_issuance}%` : null, !isExpired),
15262
+ line(`**Watch Number:**`, event.watch_parameters.watch_number, !isExpired),
15263
+ line(`**Strong Tornadoes Probability:**`, event.watch_parameters.strong_tornadoes_probability ? `${event.watch_parameters.strong_tornadoes_probability}%` : null, !isExpired),
15264
+ line(`**Additional Tornadoes Probability:**`, event.watch_parameters.additional_tornadoes_probability ? `${event.watch_parameters.additional_tornadoes_probability}%` : null, !isExpired),
15265
+ line(`**Combined Hail/Wind Probability:**`, event.watch_parameters.combined_hail_wind_probability ? `${event.watch_parameters.combined_hail_wind_probability}%` : null, !isExpired),
15266
+ line(`**Severe Hail Probability:**`, event.watch_parameters.severe_hail_probability ? `${event.watch_parameters.severe_hail_probability}%` : null, !isExpired),
15267
+ line(`**Hail >2in Probability:**`, event.watch_parameters.hail_2in_probability ? `${event.watch_parameters.hail_2in_probability}%` : null, !isExpired),
15268
+ line(`**Max Hail Inches:**`, event.watch_parameters.max_hail_in, !isExpired),
15269
+ line(`**Severe Wind Probability:**`, event.watch_parameters.severe_wind_probability ? `${event.watch_parameters.severe_wind_probability}%` : null, !isExpired),
15270
+ line(`**Max Surface Wind:**`, event.watch_parameters.max_wind_surface, !isExpired),
15271
+ line(`**Max Tops (x100 feet):**`, event.watch_parameters.max_tops_x100feet, !isExpired),
15272
+ line(`**Tags:**`, ((_b = event.parameters.tags) == null ? void 0 : _b.length) > 0 ? event.parameters.tags.join(", ") : null, !isExpired),
15273
+ line(`**Sender:**`, ((_d = (_c = event.geocode) == null ? void 0 : _c.office) == null ? void 0 : _d.name) ? `${event.geocode.office.name} (${event.geocode.office.office})` : (_f = (_e = event.geocode) == null ? void 0 : _e.office) == null ? void 0 : _f.office),
15274
+ line(`**Tracking:**`, (_g = event.metadata) == null ? void 0 : _g.tracking),
15275
+ line(`**Logs:**`, ((_h = event.metadata.history) == null ? void 0 : _h.length) > 0 ? event.metadata.history.length : null),
15276
+ line(``, event.description ? "```\n" + event.description.split("\n").map((l) => l.trim()).filter(Boolean).join("\n") + "\n```" : null, !isExpired)
15277
+ ].filter(Boolean).join("\n");
15278
+ if (body.length > 1900) {
15279
+ body = body.substring(0, 1900) + "\n\n[Message truncated due to length]";
15280
+ const blocks = ((_i = body.match(/```/g)) != null ? _i : []).length;
15281
+ if (blocks % 2 !== 0) body += "```";
15282
+ }
15283
+ if (event.description.length < 25) {
15284
+ return;
15285
+ }
15286
+ const form = new import_form_data.default();
15287
+ const img = (_j = event.metadata.attachments) == null ? void 0 : _j[0];
15288
+ const embed = {
15289
+ title: `${event.event} (${event.status})`,
15290
+ description: body,
15291
+ color: 16711680,
15292
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
15293
+ image: {},
15294
+ footer: { text: settings.title }
15295
+ };
15296
+ if (img) {
15297
+ for (let i = 0; i < 5; i++) {
15298
+ const ok = yield isImageReady(img);
15299
+ if (ok) break;
15300
+ yield new Promise((r) => setTimeout(r, 5e3));
15248
15301
  }
15249
- if (key === "ListeningStates" && setting.size > 0 && zones.length > 0 && !zones.some((ugc2) => setting.has(ugc2.substring(0, 2).toLowerCase()))) {
15250
- setEventEmit({
15251
- event: `onFilteredState`,
15252
- metadata: define2
15253
- });
15254
- return false;
15302
+ const finalCheck = yield isImageReady(img);
15303
+ if (finalCheck) {
15304
+ embed.image = { url: img };
15255
15305
  }
15256
15306
  }
15257
- return true;
15258
- });
15259
- if (!((_a = configurations == null ? void 0 : configurations.GlobalSettings) == null ? void 0 : _a.DisableGeometryParsing)) {
15260
- for (const event of filterd) {
15261
- event.geometry = yield getEventGeometry(event);
15307
+ form.append("payload_json", JSON.stringify({
15308
+ username: (_k = settings.title) != null ? _k : "AtmosphericX",
15309
+ content: (_l = settings.message) != null ? _l : "",
15310
+ embeds: [embed]
15311
+ }));
15312
+ if (settings.upload) {
15313
+ form.append("fUpload", Buffer.from(`${event.metadata.raw}
15314
+
15315
+ ${JSON.stringify(getCleanedEvent(event), null, 2)}`), { filename: `${event.event}_${event.status}_${event.metadata.tracking}.txt`, contentType: "application/text" });
15262
15316
  }
15263
- }
15264
- if (filterd.length > 0) {
15265
- for (const event of filterd) {
15266
- yield mkEvent(event);
15317
+ if (settings.eas) {
15318
+ const audio = yield setEasTone({
15319
+ message: event.description,
15320
+ header: event.metadata.header
15321
+ });
15322
+ const file = readFileSync2(audio);
15323
+ if (audio) {
15324
+ form.append("fEas", Buffer.from(file), { filename: `${event.event}_${event.status}_${event.metadata.tracking}_eas.mp3`, contentType: "audio/mpeg" });
15325
+ }
15267
15326
  }
15327
+ yield createHttp({
15328
+ url: settings.webhook,
15329
+ timeout: 2e3,
15330
+ method: `POST`,
15331
+ headers: form.getHeaders(),
15332
+ body: form
15333
+ });
15268
15334
  }
15269
- yield updateNode();
15270
- setEventEmit({
15271
- event: `onEventCache`,
15272
- metadata: bootstrap.cache.events,
15273
- limited: true
15274
- });
15275
15335
  });
15276
15336
 
15277
- // src/@events/events.text.ts
15278
- var text = (stanza) => __async(null, null, function* () {
15279
- var _a, _b, _c;
15280
- let processed = [];
15281
- const getMessages = (_c = (_b = (_a = stanza == null ? void 0 : stanza.message) == null ? void 0 : _a.split(/(?=\$\$)/g)) == null ? void 0 : _b.map((message) => message.trim())) == null ? void 0 : _c.filter((message) => message && message !== "$$");
15282
- if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
15283
- for (const message of getMessages) {
15284
- const tick = performance.now();
15285
- const attributes = stanza == null ? void 0 : stanza.attributes;
15286
- const props = properties({ message, attributes });
15287
- const header = getEventHeader({ properties: props, getType: stanza.getType });
15288
- const issued = new Date(attributes.issue);
15289
- const expires = new Date(issued.getTime() + 12 * 60 * 60 * 1e3);
15290
- let event = Object.keys(eventsMatchText).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
15291
- let isStatement = false;
15292
- if (!event) {
15293
- event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
15294
- isStatement = true;
15337
+ // src/@manager/manager.updateWebhooks.ts
15338
+ var updateWebhooks = (event) => __async(null, null, function* () {
15339
+ const settings = bootstrap.settings;
15340
+ const webhooks = settings.WebhookSettings;
15341
+ const eventName = event.properties.event;
15342
+ for (const socket of webhooks) {
15343
+ const events = socket.events;
15344
+ if (!events || events.length === 0) {
15345
+ yield createWebhook({ webhook: socket, event });
15346
+ continue;
15295
15347
  }
15296
- processed.push({
15297
- type: `Feature`,
15298
- geometry: {
15299
- type: `Point`,
15300
- coordinates: []
15301
- },
15302
- properties: __spreadProps(__spreadValues({
15303
- event,
15304
- parent: event,
15305
- status: isStatement ? `Statement` : `Issued`,
15306
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
15307
- expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
15308
- }, props), {
15309
- metadata: {
15310
- ms: performance.now() - tick,
15311
- source: `events.text`,
15312
- tracking: getEventTracking({ type: `RAW`, stanza, attributes, properties: props }),
15313
- header,
15314
- vtec: null,
15315
- hvtec: null,
15316
- history: [
15317
- {
15318
- description: props.description,
15319
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
15320
- status: `Issued`
15321
- }
15322
- ]
15323
- }
15324
- })
15348
+ const matched = events.some((pattern) => {
15349
+ if (!pattern) return false;
15350
+ if (pattern === "*" || pattern === eventName) return true;
15351
+ if (pattern.includes("*")) {
15352
+ const regex = "^" + pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$";
15353
+ return new RegExp(regex).test(eventName);
15354
+ }
15355
+ return false;
15325
15356
  });
15357
+ if (matched) {
15358
+ yield createWebhook({ webhook: socket, event });
15359
+ }
15326
15360
  }
15327
- validateEvents(processed);
15328
15361
  });
15329
15362
 
15330
- // src/@parsers/@ugc/ugc.header.ts
15331
- var getUGCHeader = (message) => {
15332
- const start = message.search(regExp.ugc1);
15333
- const sub = message.substring(start);
15334
- const end = sub.search(regExp.ugc2);
15335
- const fin = sub.substring(0, end).replace(/\s+/g, "").slice(0, -1);
15336
- return fin != null ? fin : null;
15337
- };
15338
-
15339
- // src/@parsers/@ugc/ugc.zones.ts
15340
- var getZones = (header) => {
15341
- const splits = header.split("-");
15342
- const zones = [];
15343
- let state = splits[0].substring(0, 2);
15344
- const format = splits[0].substring(2, 3);
15345
- for (const part of splits) {
15346
- if (/^[A-Z]/.test(part)) {
15347
- state = part.substring(0, 2);
15348
- if (part.includes(">")) {
15349
- const [start, end] = part.split(">");
15350
- const startNum = parseInt(start.substring(3), 10);
15351
- const endNum = parseInt(end, 10);
15352
- for (let j2 = startNum; j2 <= endNum; j2++) {
15353
- zones.push(`${state}${format}${j2.toString().padStart(3, "0")}`);
15363
+ // src/@modules/@utilities/utilities.getShapeNearestPoint.ts
15364
+ var getShapeNearestPoint = (coordinates, point) => {
15365
+ if (!coordinates || !point) {
15366
+ return { proximity: false, point: [0, 0], distance: null };
15367
+ }
15368
+ const normalize = (coords) => {
15369
+ if (!Array.isArray(coords)) return [];
15370
+ if (typeof coords[0] === "number" && typeof coords[1] === "number") return [];
15371
+ if (Array.isArray(coords[0]) && typeof coords[0][0] === "number") {
15372
+ return [[coords]];
15373
+ }
15374
+ if (Array.isArray(coords[0]) && Array.isArray(coords[0][0]) && typeof coords[0][0][0] === "number") {
15375
+ return [coords];
15376
+ }
15377
+ if (Array.isArray(coords[0]) && Array.isArray(coords[0][0]) && Array.isArray(coords[0][0][0]) && typeof coords[0][0][0][0] === "number") {
15378
+ return coords;
15379
+ }
15380
+ return [];
15381
+ };
15382
+ const polys = normalize(coordinates);
15383
+ if (polys.length === 0) return { proximity: false, point: [0, 0], distance: null };
15384
+ const lon = point[0];
15385
+ const lat = point[1];
15386
+ const pointInRing = (pt, ring) => {
15387
+ let x = pt[0], y = pt[1];
15388
+ let inside = false;
15389
+ for (let i = 0, j2 = ring.length - 1; i < ring.length; j2 = i++) {
15390
+ const xi = ring[i][0], yi = ring[i][1];
15391
+ const xj = ring[j2][0], yj = ring[j2][1];
15392
+ const intersect = yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi + 0) + xi;
15393
+ if (intersect) inside = !inside;
15394
+ }
15395
+ return inside;
15396
+ };
15397
+ const toRadians = (deg) => deg * Math.PI / 180;
15398
+ const haversineMiles = (a, b) => {
15399
+ const R = 3958.8;
15400
+ const dLat = toRadians(b[1] - a[1]);
15401
+ const dLon = toRadians(b[0] - a[0]);
15402
+ const lat1 = toRadians(a[1]);
15403
+ const lat2 = toRadians(b[1]);
15404
+ const sinDLat = Math.sin(dLat / 2);
15405
+ const sinDLon = Math.sin(dLon / 2);
15406
+ const c = 2 * Math.asin(Math.sqrt(sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon));
15407
+ return R * c;
15408
+ };
15409
+ let minDistance = Infinity;
15410
+ let closestPoint = null;
15411
+ for (const poly of polys) {
15412
+ const outer = poly[0];
15413
+ const holes = poly.slice(1);
15414
+ if (pointInRing(point, outer)) {
15415
+ let inHole = false;
15416
+ for (const hole of holes) {
15417
+ if (pointInRing(point, hole)) {
15418
+ inHole = true;
15419
+ break;
15354
15420
  }
15355
- } else {
15356
- zones.push(part);
15357
15421
  }
15358
- continue;
15422
+ if (!inHole) {
15423
+ return { proximity: true, point, distance: 0 };
15424
+ }
15359
15425
  }
15360
- if (part.includes(">")) {
15361
- const [start, end] = part.split(">");
15362
- const startNum = parseInt(start, 10);
15363
- const endNum = parseInt(end, 10);
15364
- for (let j2 = startNum; j2 <= endNum; j2++) {
15365
- zones.push(`${state}${format}${j2.toString().padStart(3, "0")}`);
15426
+ for (const ring of poly) {
15427
+ for (let i = 0; i < ring.length - 1; i++) {
15428
+ const start = [ring[i][0], ring[i][1]];
15429
+ const end = [ring[i + 1][0], ring[i + 1][1]];
15430
+ const A = lon - start[0];
15431
+ const B = lat - start[1];
15432
+ const C = end[0] - start[0];
15433
+ const D = end[1] - start[1];
15434
+ const lenSq = C * C + D * D;
15435
+ const t = lenSq === 0 ? 0 : Math.max(0, Math.min(1, (A * C + B * D) / lenSq));
15436
+ const candidate = [start[0] + t * C, start[1] + t * D];
15437
+ const dist = haversineMiles([lon, lat], candidate);
15438
+ if (!isNaN(dist) && dist < minDistance) {
15439
+ minDistance = Number(dist.toFixed(3));
15440
+ closestPoint = candidate;
15441
+ }
15366
15442
  }
15367
- } else {
15368
- zones.push(`${state}${format}${part}`);
15369
15443
  }
15370
15444
  }
15371
- return zones.filter((item) => item !== "");
15445
+ if (!isFinite(minDistance) || closestPoint == null) {
15446
+ return { proximity: false, point: [0, 0], distance: null };
15447
+ }
15448
+ const distanceMiles = minDistance;
15449
+ const distanceKm = Number((distanceMiles * 1.609344).toFixed(3));
15450
+ const distanceMeters = Math.round(distanceKm * 1e3);
15451
+ return { proximity: distanceMiles === 0, point: closestPoint, distance: distanceMiles, distanceKm, distanceMeters };
15372
15452
  };
15373
15453
 
15374
- // src/@parsers/@ugc/ugc.expiry.ts
15375
- var getExpiry = (message) => {
15376
- const match = message.match(/\b(\d{6})-/);
15377
- if (!match) {
15378
- return null;
15454
+ // src/@building/building.polygon.ts
15455
+ var getEventNodes = (event) => __async(null, null, function* () {
15456
+ var _a, _b;
15457
+ const metadata = { nodes: [], proximity: false, filtered: false };
15458
+ const geometry = yield getEventGeometry(event);
15459
+ if (!geometry || !geometry.coordinates) {
15460
+ return { nodes: [], filtered: false, updated: Date.now() };
15461
+ }
15462
+ const nodes = bootstrap.cache.nodes.features;
15463
+ for (const node of nodes) {
15464
+ const [longitude, latitude] = node.geometry.coordinates;
15465
+ const getPoint = getShapeNearestPoint(geometry.coordinates, [longitude, latitude]);
15466
+ const miles = (_a = getPoint.distance) != null ? _a : null;
15467
+ const kilometers = Number((miles * 1.609344).toFixed(3));
15468
+ const info = {
15469
+ id: (_b = node.properties) == null ? void 0 : _b.identifier,
15470
+ coordinates: [longitude, latitude],
15471
+ nearest: getPoint.point,
15472
+ miles,
15473
+ kilometers,
15474
+ proximity: getPoint.proximity
15475
+ };
15476
+ metadata.nodes.push(info);
15477
+ if (bootstrap.settings.GlobalSettings.EventFiltering.NodeLocationFiltering && miles < bootstrap.settings.GlobalSettings.NodeMinDistance) {
15478
+ metadata.proximity = true;
15479
+ info.proximity = true;
15480
+ }
15379
15481
  }
15380
- const date = match == null ? void 0 : match[1];
15381
- const day = parseInt(date == null ? void 0 : date.slice(0, 2), 10);
15382
- const hour = parseInt(date == null ? void 0 : date.slice(2, 4), 10);
15383
- const minute = parseInt(date == null ? void 0 : date.slice(4, 6), 10);
15384
- const now = /* @__PURE__ */ new Date();
15385
- const expires = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), day, hour, minute));
15386
- return expires.toISOString();
15387
- };
15388
-
15389
- // src/@parsers/@ugc/ugc.locations.ts
15390
- var getLocations = (zones) => __async(null, null, function* () {
15391
- const sites = Array.from(new Set(zones));
15392
- const placeholders = sites.map(() => "?").join(",");
15393
- const rows = yield bootstrap.database.prepare(`SELECT id, location FROM shapefiles WHERE id IN (${placeholders})`).all(...sites);
15394
- return rows.map((row) => row.location).sort();
15395
- });
15396
-
15397
- // src/@parsers/@ugc/ugc.extract.ts
15398
- var ugcExtract = (message) => __async(null, null, function* () {
15399
- const head = getUGCHeader(message);
15400
- const ugcs = getZones(head);
15401
- const expires = getExpiry(message);
15402
- const areas = yield getLocations(ugcs);
15403
- if (!head || (ugcs == null ? void 0 : ugcs.length) == 0) return;
15404
15482
  return {
15405
- zones: ugcs,
15406
- locations: areas,
15407
- expires
15483
+ nodes: metadata.nodes,
15484
+ filtered: metadata.proximity,
15485
+ updated: Date.now()
15408
15486
  };
15409
15487
  });
15410
15488
 
15411
- // src/@events/events.ugc.ts
15412
- var ugc = (stanza) => __async(null, null, function* () {
15413
- var _a, _b, _c;
15414
- let processed = [];
15415
- const getMessages = (_c = (_b = (_a = stanza == null ? void 0 : stanza.message) == null ? void 0 : _a.split(/(?=\$\$)/g)) == null ? void 0 : _b.map((message) => message.trim())) == null ? void 0 : _c.filter((message) => message && message !== "$$");
15416
- if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
15417
- for (const message of getMessages) {
15418
- const tick = performance.now();
15419
- const attributes = stanza == null ? void 0 : stanza.attributes;
15420
- const ugc2 = yield ugcExtract(message);
15421
- if (ugc2 != null) {
15422
- const props = properties({ message, attributes, ugc: ugc2 });
15423
- const issued = new Date(attributes.issue);
15424
- const expires = new Date(ugc2.expires);
15425
- const header = getEventHeader({ properties: props, getType: stanza.getType });
15426
- let event = Object.keys(eventsMatchText).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
15427
- let isStatement = false;
15428
- if (!event) {
15429
- event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
15430
- isStatement = true;
15489
+ // src/@manager/manager.updateNodes.ts
15490
+ var updateNode = (selectedEvent) => __async(null, null, function* () {
15491
+ const events = bootstrap.cache.events.features;
15492
+ const ttl = bootstrap.settings.GlobalSettings.NodeTTL * 1e3;
15493
+ let total = 0;
15494
+ function update(evt) {
15495
+ return __async(this, null, function* () {
15496
+ var _a, _b, _c;
15497
+ const lastUpdate = (_c = (_b = (_a = evt == null ? void 0 : evt.properties) == null ? void 0 : _a.metadata) == null ? void 0 : _b.updated) != null ? _c : null;
15498
+ if (lastUpdate != null && Date.now() - lastUpdate < ttl) {
15499
+ return evt;
15431
15500
  }
15432
- processed.push({
15433
- type: `Feature`,
15434
- geometry: {
15435
- type: `Point`,
15436
- coordinates: []
15437
- },
15438
- properties: __spreadProps(__spreadValues({
15439
- event,
15440
- parent: event,
15441
- status: isStatement ? `Statement` : `Issued`,
15442
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
15443
- expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
15444
- }, props), {
15445
- metadata: {
15446
- ms: performance.now() - tick,
15447
- source: `events.ugc`,
15448
- tracking: getEventTracking({ type: `RAW`, stanza, attributes, properties: props }),
15449
- header,
15450
- vtec: null,
15451
- hvtec: null,
15452
- history: [
15453
- {
15454
- description: props.description,
15455
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
15456
- status: `Issued`
15457
- }
15458
- ]
15459
- }
15460
- })
15461
- });
15462
- }
15501
+ const node = yield getEventNodes(evt);
15502
+ if (node.nodes.length > 0) {
15503
+ total++;
15504
+ }
15505
+ evt.properties.metadata.nodes = node.nodes;
15506
+ evt.properties.metadata.filtered_proximity = node.filtered;
15507
+ evt.properties.metadata.updated = node.updated;
15508
+ });
15509
+ }
15510
+ if (!selectedEvent) {
15511
+ yield Promise.all(events.map((evt) => __async(null, null, function* () {
15512
+ yield update(evt);
15513
+ })));
15514
+ }
15515
+ if (selectedEvent) {
15516
+ yield update(selectedEvent);
15517
+ }
15518
+ if (total > 0) {
15519
+ setEventEmit({
15520
+ event: `onNodeUpdate`,
15521
+ metadata: {
15522
+ type: `global-update`,
15523
+ updated: total
15524
+ }
15525
+ });
15463
15526
  }
15464
- validateEvents(processed);
15465
15527
  });
15466
15528
 
15467
- // src/@dictionaries/dictionaries.eventTypes.ts
15468
- var eventTypes = {
15469
- "AF": "Ashfall",
15470
- "AS": "Air Stagnation",
15471
- "BH": "Beach Hazard",
15472
- "BW": "Brisk Wind",
15473
- "BZ": "Blizzard",
15474
- "CF": "Coastal Flood",
15475
- "DF": "Debris Flow",
15476
- "DS": "Dust Storm",
15477
- "EC": "Extreme Cold",
15478
- "EH": "Excessive Heat",
15479
- "XH": "Extreme Heat",
15480
- "EW": "Extreme Wind",
15481
- "FA": "Areal Flood",
15482
- "FF": "Flash Flood",
15483
- "FG": "Dense Fog",
15484
- "FL": "Flood",
15485
- "FR": "Frost",
15486
- "FW": "Fire Weather",
15487
- "FZ": "Freeze",
15488
- "GL": "Gale",
15489
- "HF": "Hurricane Force Wind",
15490
- "HT": "Heat",
15491
- "HU": "Hurricane",
15492
- "HW": "High Wind",
15493
- "HY": "Hydrologic",
15494
- "HZ": "Hard Freeze",
15495
- "IS": "Ice Storm",
15496
- "LE": "Lake Effect Snow",
15497
- "LO": "Low Water",
15498
- "LS": "Lakeshore Flood",
15499
- "LW": "Lake Wind",
15500
- "MA": "Special Marine",
15501
- "EQ": "Earthquake",
15502
- "MF": "Dense Fog",
15503
- "MH": "Ashfall",
15504
- "MS": "Dense Smoke",
15505
- "RB": "Small Craft for Rough Bar",
15506
- "RP": "Rip Current Risk",
15507
- "SC": "Small Craft",
15508
- "SE": "Hazardous Seas",
15509
- "SI": "Small Craft for Winds",
15510
- "SM": "Dense Smoke",
15511
- "SQ": "Snow Squall",
15512
- "SR": "Storm",
15513
- "SS": "Storm Surge",
15514
- "SU": "High Surf",
15515
- "SV": "Severe Thunderstorm",
15516
- "SW": "Small Craft for Hazardous Seas",
15517
- "TO": "Tornado",
15518
- "TR": "Tropical Storm",
15519
- "TS": "Tsunami",
15520
- "TY": "Typhoon",
15521
- "SP": "Special Weather",
15522
- "UP": "Heavy Freezing Spray",
15523
- "WC": "Wind Chill",
15524
- "WI": "Wind",
15525
- "WS": "Winter Storm",
15526
- "WW": "Winter Weather",
15527
- "ZF": "Freezing Fog",
15528
- "ZR": "Freezing Rain",
15529
- "ZY": "Freezing Spray"
15530
- };
15531
-
15532
- // src/@dictionaries/dictionaries.eventActions.ts
15533
- var eventActions = {
15534
- "W": "Warning",
15535
- "F": "Forecast",
15536
- "A": "Watch",
15537
- "O": "Outlook",
15538
- "Y": "Advisory",
15539
- "N": "Synopsis",
15540
- "S": "Statement"
15541
- };
15542
-
15543
- // src/@dictionaries/dictionaries.eventStatus.ts
15544
- var eventStatus = {
15545
- "NEW": "Issued",
15546
- "CON": "Updated",
15547
- "EXT": "Extended",
15548
- "EXA": "Extended",
15549
- "EXB": "Extended",
15550
- "UPG": "Upgraded",
15551
- "COR": "Correction",
15552
- "ROU": "Routine",
15553
- "CAN": "Cancelled",
15554
- "EXP": "Expired"
15555
- };
15556
-
15557
- // src/@parsers/@pvtec/pvtec.expires.ts
15558
- var getExpiry2 = (dates) => {
15559
- if ((dates == null ? void 0 : dates[1]) == `000000T0000Z`) return "Invalid Date Format";
15560
- const expires = `${(/* @__PURE__ */ new Date()).getFullYear().toString().substring(0, 2)}${dates[1].substring(0, 2)}-${dates[1].substring(2, 4)}-${dates[1].substring(4, 6)}T${dates[1].substring(7, 9)}:${dates[1].substring(9, 11)}:00`;
15561
- const local = new Date(new Date(expires).getTime() - 4 * 60 * 6e4);
15562
- const pad = (n) => n.toString().padStart(2, "0");
15563
- return `${local.getFullYear()}-${pad(local.getMonth() + 1)}-${pad(local.getDate())}T${pad(local.getHours())}:${pad(local.getMinutes())}:00.000-04:00`;
15564
- };
15529
+ // src/@manager/manager.mkEvent.ts
15530
+ var mkEvent = (event) => __async(null, null, function* () {
15531
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w;
15532
+ const settings = bootstrap.settings;
15533
+ const features = bootstrap.cache.events.features;
15534
+ const getHash = event.properties.metadata.hash;
15535
+ const getTracking = event.properties.metadata.tracking;
15536
+ const isEntry = (_a = bootstrap.cache.hashes) == null ? void 0 : _a.find((hash) => hash.tracking === getTracking);
15537
+ const isHashed = (_c = (_b = isEntry == null ? void 0 : isEntry.hashes) == null ? void 0 : _b.includes(getHash)) != null ? _c : false;
15538
+ const getFeature = features.find((feature) => feature.properties.metadata.tracking === getTracking);
15539
+ if (isHashed || event.properties.status_metadata.is_expired) return;
15540
+ setHash(event, isEntry);
15541
+ const isFilteredLocation = yield updateNode(event).then(() => event.properties.metadata.filtered_proximity);
15542
+ if (!isFilteredLocation && settings.GlobalSettings.EventFiltering.NodeLocationFiltering) {
15543
+ return;
15544
+ }
15545
+ setEventEmit({
15546
+ event: `onEventStatus`,
15547
+ metadata: {
15548
+ type: getFeature ? `Updated` : `New`,
15549
+ event
15550
+ },
15551
+ message: `[${getFeature ? "Updated" : "New"}] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
15552
+ });
15553
+ if (settings.GlobalSettings.EventManagement) {
15554
+ if (event.properties.status_metadata.is_issued || event.properties.status_metadata.is_updated) {
15555
+ if (getFeature) {
15556
+ const getIndex = features.indexOf(getFeature);
15557
+ const cHistory = (_f = (_e = (_d = getFeature == null ? void 0 : getFeature.properties) == null ? void 0 : _d.metadata) == null ? void 0 : _e.history) != null ? _f : [];
15558
+ const cLocations = (_i = (_h = (_g = getFeature == null ? void 0 : getFeature.properties) == null ? void 0 : _g.locations) == null ? void 0 : _h.split(";").map((l) => l.trim())) != null ? _i : [];
15559
+ const cUgc = (_l = (_k = (_j = getFeature == null ? void 0 : getFeature.properties) == null ? void 0 : _j.geocode) == null ? void 0 : _k.ugc) != null ? _l : [];
15560
+ const iHistory = (_o = (_n = (_m = event.properties) == null ? void 0 : _m.metadata) == null ? void 0 : _n.history) != null ? _o : [];
15561
+ const iLocations = (_r = (_q = (_p = event.properties) == null ? void 0 : _p.locations) == null ? void 0 : _q.split(";").map((l) => l.trim())) != null ? _r : [];
15562
+ const iUgc = (_u = (_t = (_s = event.properties) == null ? void 0 : _s.geocode) == null ? void 0 : _t.ugc) != null ? _u : [];
15563
+ const mHistory = [...cHistory, ...iHistory].filter((v, i, a) => a.indexOf(v) === i).filter((v, i, a) => a.findIndex((h) => h.description === v.description && h.issued === v.issued) === i);
15564
+ const mLocations = [...cLocations, ...iLocations].filter((v, i, a) => a.indexOf(v) === i).join("; ");
15565
+ const mUgc = [...cUgc, ...iUgc].filter((v, i, a) => a.indexOf(v) === i);
15566
+ bootstrap.cache.events.features[getIndex] = __spreadProps(__spreadValues({}, event), {
15567
+ properties: __spreadProps(__spreadValues({}, event.properties), {
15568
+ metadata: __spreadProps(__spreadValues({}, (_v = event == null ? void 0 : event.properties) == null ? void 0 : _v.metadata), {
15569
+ history: mHistory
15570
+ }),
15571
+ locations: mLocations,
15572
+ geocode: __spreadProps(__spreadValues({}, (_w = event == null ? void 0 : event.properties) == null ? void 0 : _w.geocode), {
15573
+ ugc: mUgc
15574
+ })
15575
+ })
15576
+ });
15577
+ updateWebhooks(bootstrap.cache.events.features[getIndex]);
15578
+ } else {
15579
+ features.push(event);
15580
+ updateWebhooks(event);
15581
+ }
15582
+ }
15583
+ }
15584
+ });
15565
15585
 
15566
- // src/@parsers/@pvtec/pvtec.extract.ts
15567
- var pvExtract = (message) => {
15568
- var _a, _b, _c, _d;
15569
- const getVTECs = (_a = message.match(regExp.pvtec)) != null ? _a : [];
15570
- const vtecs = [];
15571
- for (const vtec2 of getVTECs) {
15572
- const sub = vtec2.split(`.`);
15573
- if ((sub == null ? void 0 : sub.length) < 7) continue;
15574
- const dates = (_b = sub[6]) == null ? void 0 : _b.split(`-`);
15575
- vtecs.push({
15576
- vtec: vtec2,
15577
- product: eventProducts[sub[0]],
15578
- tracking: `${sub[2]}.${sub[3]}.${sub[4]}.${sub[5]}`,
15579
- event: `${eventTypes[sub[3]]} ${eventActions[sub[4]]}`,
15580
- status: eventStatus[sub[1]],
15581
- organization: (_d = (_c = message.match(regExp.wmo)) == null ? void 0 : _c[0]) != null ? _d : null,
15582
- expires: getExpiry2(dates),
15583
- is_watch: (sub[4] == `A` || sub[4] == `Y`) && (sub[3] == `TO` || sub[3] == `SV`),
15584
- prediction_center: sub[2] == `KWNS` ? true : false
15586
+ // src/@manager/manager.rmEvent.ts
15587
+ var rmEvent = (event) => {
15588
+ const getEvent = bootstrap.cache.events.features.find((f) => {
15589
+ var _a, _b, _c, _d;
15590
+ return ((_b = (_a = f == null ? void 0 : f.properties) == null ? void 0 : _a.metadata) == null ? void 0 : _b.tracking) === ((_d = (_c = event == null ? void 0 : event.properties) == null ? void 0 : _c.metadata) == null ? void 0 : _d.tracking);
15591
+ });
15592
+ const cachedStatus = event.properties.status;
15593
+ event.properties.expires = (/* @__PURE__ */ new Date()).toISOString();
15594
+ event.properties.status = `Expired`;
15595
+ if (getEvent) {
15596
+ setEventEmit({
15597
+ event: `onEventStatus`,
15598
+ metadata: {
15599
+ type: `Removed`,
15600
+ event
15601
+ },
15602
+ message: `[Removed] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
15585
15603
  });
15604
+ setEventEmit({ event: `onExpiredProduct`, metadata: event });
15605
+ if (cachedStatus != `Statement`) updateWebhooks(event);
15606
+ bootstrap.cache.events.features.splice(bootstrap.cache.events.features.indexOf(getEvent), 1);
15607
+ bootstrap.cache.hashes = bootstrap.cache.hashes.filter((hash) => hash.tracking !== event.properties.metadata.tracking);
15586
15608
  }
15587
- return vtecs.length > 0 ? vtecs : null;
15588
- };
15589
-
15590
- // src/@dictionaries/dictionaries.eventCauses.ts
15591
- var eventCauses = {
15592
- "SM": "Snow Melt",
15593
- "RS": "Rain/Snow Melt",
15594
- "ER": "Excessive Rain",
15595
- "DM": "Dam/Levee Failure",
15596
- "IJ": "Ice Jam",
15597
- "GO": "Glacier Lake Outburst",
15598
- "IC": "Ice",
15599
- "FS": "Flash Flood / Storm Surge",
15600
- "FT": "Tidal Effects",
15601
- "ET": "Elevated Upstream Flow",
15602
- "MC": "Other Multiple Causes",
15603
- "WT": "Wind and/or Tidal Effects",
15604
- "DR": "Reservoir Release",
15605
- "UU": "Unknown",
15606
- "OT": "Other Effects"
15609
+ setEventEmit({
15610
+ event: `onEventCache`,
15611
+ metadata: bootstrap.cache.events,
15612
+ limited: true
15613
+ });
15607
15614
  };
15608
15615
 
15609
- // src/@dictionaries/dictionaries.eventRecords.ts
15610
- var eventRecords = {
15611
- "NO": "No Record Expected",
15612
- "NR": "Near Record or possible record",
15613
- "UU": "Unknown history of records",
15614
- "OO": "Other"
15616
+ // src/@modules/@utilities/utilities.getLatestIssuance.ts
15617
+ var getLatestIssuance = () => {
15618
+ const now = /* @__PURE__ */ new Date();
15619
+ const current = now.getUTCHours() * 100 + now.getUTCMinutes();
15620
+ const issuances = [100, 600, 1300, 1630, 2e3];
15621
+ let latest = issuances[0];
15622
+ for (const issuance of issuances) {
15623
+ if (current >= issuance) {
15624
+ latest = issuance;
15625
+ }
15626
+ }
15627
+ return latest.toString().padStart(4, "0");
15615
15628
  };
15616
15629
 
15617
- // src/@dictionaries/dictionaries.eventSeverity.ts
15618
- var eventSeverity = {
15619
- N: "Not Expected",
15620
- 0: "Areal Flood or FF Product",
15621
- 1: "Minor",
15622
- 2: "Moderate",
15623
- 3: "Major",
15624
- U: "Unknown"
15630
+ // src/@building/building.outlooks.ts
15631
+ var getEventAttachments = (event) => {
15632
+ var _a, _b;
15633
+ const latestTime = getLatestIssuance();
15634
+ const validEvents = [
15635
+ { target: "Day 1", attachment: `https://www.spc.noaa.gov/products/outlook/day1otlk_${latestTime}.png` },
15636
+ { target: "Day 2", attachment: `https://www.spc.noaa.gov/products/outlook/day2otlk.png` },
15637
+ { target: "Day 3", attachment: `https://www.spc.noaa.gov/products/outlook/day3otlk.png` },
15638
+ { target: "Mesoscale Discussion", attachment: `https://www.spc.noaa.gov/products/md/mcd${(_b = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.spc_parameters) == null ? void 0 : _b.spc_number}.png` }
15639
+ ];
15640
+ const isValid = validEvents.find((outlook) => outlook.target == event.properties.event);
15641
+ if (isValid) {
15642
+ return (isValid == null ? void 0 : isValid.attachment) ? [isValid.attachment] : [];
15643
+ }
15644
+ return null;
15625
15645
  };
15626
15646
 
15627
- // src/@parsers/@hvtec/hvtec.extract.ts
15628
- var hvExtract = (message) => {
15647
+ // src/@building/building.validate.ts
15648
+ var validateEvents = (events) => __async(null, null, function* () {
15629
15649
  var _a;
15630
- const getHVTECs = (_a = message.match(regExp.hvtec)) != null ? _a : [];
15631
- const vtecs = [];
15632
- for (const vtec2 of getHVTECs) {
15633
- const sub = vtec2.split(`.`);
15634
- if (sub.length < 7) continue;
15635
- vtecs.push({
15636
- hvtec: vtec2,
15637
- severity: eventSeverity[sub[1]],
15638
- cause: eventCauses[sub[2]],
15639
- record: eventRecords[sub[6]]
15640
- });
15650
+ if (events.length === 0) return;
15651
+ const configurations = bootstrap.settings;
15652
+ const sets = {};
15653
+ const bools = {};
15654
+ const megered = __spreadValues(__spreadValues({}, configurations.GlobalSettings), configurations.GlobalSettings.EventFiltering);
15655
+ for (const key in megered) {
15656
+ const setting = megered[key];
15657
+ if (Array.isArray(setting)) {
15658
+ sets[key] = new Set(setting.map((item) => item.toLowerCase()));
15659
+ }
15660
+ if (typeof setting === "boolean") {
15661
+ bools[key] = setting;
15662
+ }
15641
15663
  }
15642
- return vtecs.length > 0 ? vtecs : null;
15643
- };
15644
-
15645
- // src/@events/events.vtec.ts
15646
- var vtec = (stanza) => __async(null, null, function* () {
15647
- var _a, _b, _c, _d, _e;
15648
- let processed = [];
15649
- const getMessages = (_c = (_b = (_a = stanza == null ? void 0 : stanza.message) == null ? void 0 : _a.split(/(?=\$\$)/g)) == null ? void 0 : _b.map((message) => message.trim())) == null ? void 0 : _c.filter((message) => message && message !== "$$");
15650
- if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
15651
- for (const message of getMessages) {
15652
- const tick = performance.now();
15653
- const attributes = stanza == null ? void 0 : stanza.attributes;
15654
- const pVtec = pvExtract(message);
15655
- const hVtec = hvExtract(message);
15656
- const ugc2 = yield ugcExtract(message);
15657
- if (pVtec != null && ugc2 != null) {
15658
- for (const pv of pVtec) {
15659
- const vtec2 = pv;
15660
- const props = properties({ message, attributes, ugc: ugc2, pVtec: vtec2 });
15661
- const header = getEventHeader({ properties: props, getType: stanza.getType, vtec: vtec2 });
15662
- const issued = (_d = new Date(attributes.issue)) != null ? _d : /* @__PURE__ */ new Date();
15663
- const expires = new Date(vtec2.expires);
15664
- processed.push({
15665
- type: `Feature`,
15666
- geometry: {
15667
- type: `Point`,
15668
- coordinates: []
15669
- },
15670
- properties: __spreadProps(__spreadValues({
15671
- event: pv.event,
15672
- parent: pv.event,
15673
- status: pv.status,
15674
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
15675
- expires: !isNaN(expires.getTime()) ? expires.toISOString() : (_e = ugc2.expires) != null ? _e : new Date(issued.getTime() + 60 * 60 * 1e3).toISOString()
15676
- }, props), {
15677
- metadata: {
15678
- ms: performance.now() - tick,
15679
- source: `events.vtec`,
15680
- tracking: getEventTracking({ type: `VTEC`, stanza, attributes, properties: props, vtec: vtec2 }),
15681
- header,
15682
- vtec: pv,
15683
- hvtec: hVtec,
15684
- history: [
15685
- {
15686
- description: props.description,
15687
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
15688
- status: pv.status
15689
- }
15690
- ]
15691
- }
15692
- })
15664
+ const filterd = events.filter((event) => {
15665
+ var _a2, _b, _c, _d, _e;
15666
+ const define2 = getEventSignature(event);
15667
+ const properties2 = define2.properties;
15668
+ const zones = properties2.geocode.ugc;
15669
+ const icao = properties2.geocode.office.office;
15670
+ const enhancedEventName = properties2.event = getEventEnhancedName(event);
15671
+ const filteredProperties = JSON.parse(JSON.stringify(properties2));
15672
+ if ((filteredProperties == null ? void 0 : filteredProperties.metadata) && "ms" in filteredProperties.metadata) {
15673
+ delete filteredProperties.metadata.ms;
15674
+ }
15675
+ filteredProperties.metadata = (_a2 = filteredProperties.metadata) != null ? _a2 : {};
15676
+ properties2.metadata.hash = createHash("sha256").update(JSON.stringify(filteredProperties)).digest("hex");
15677
+ properties2.metadata.attachments = getEventAttachments(event);
15678
+ setEventEmit({ event: `onProductType${enhancedEventName.replace(/\s+/g, "")}`, metadata: define2 });
15679
+ if (properties2.status_metadata.is_test) {
15680
+ setEventEmit({ event: `onTestProduct`, metadata: define2 });
15681
+ if (bools == null ? void 0 : bools.IgnoreTestProducts) return false;
15682
+ }
15683
+ if (properties2.status_metadata.is_expired) {
15684
+ setEventEmit({ event: `onExpiredProduct`, metadata: define2 });
15685
+ rmEvent(define2);
15686
+ return false;
15687
+ }
15688
+ if ((_c = (_b = properties2.metadata) == null ? void 0 : _b.vtec) == null ? void 0 : _c.is_watch) {
15689
+ const isSPC = (_e = (_d = properties2.metadata) == null ? void 0 : _d.vtec) == null ? void 0 : _e.prediction_center;
15690
+ setEventEmit({ event: isSPC ? `onStormPredictionWatch` : `onNonStormPredictionWatch`, metadata: define2 });
15691
+ if ((bools == null ? void 0 : bools.SPCWatchesOnly) && !isSPC) {
15692
+ return false;
15693
+ }
15694
+ if (!(bools == null ? void 0 : bools.SPCWatchesOnly) && isSPC) {
15695
+ return false;
15696
+ }
15697
+ }
15698
+ for (const key in sets) {
15699
+ const setting = sets[key];
15700
+ if (key === "ListeningEvents" && setting.size > 0 && !setting.has(define2.properties.event.toLowerCase())) {
15701
+ setEventEmit({
15702
+ event: `onFilteredEvent`,
15703
+ metadata: define2
15704
+ });
15705
+ return false;
15706
+ }
15707
+ if (key === "IgnoredEvents" && setting.size > 0 && setting.has(define2.properties.event.toLowerCase())) {
15708
+ setEventEmit({
15709
+ event: `onIgnoredEvent`,
15710
+ metadata: define2
15711
+ });
15712
+ return false;
15713
+ }
15714
+ if (key === "ListeningICAO" && setting.size > 0 && icao != null && !setting.has(icao.toLowerCase())) {
15715
+ setEventEmit({
15716
+ event: `onFilteredICAO`,
15717
+ metadata: define2
15718
+ });
15719
+ return false;
15720
+ }
15721
+ if (key === "IgnoredICAO" && setting.size > 0 && icao != null && setting.has(icao.toLowerCase())) {
15722
+ setEventEmit({
15723
+ event: `onIgnoredICAO`,
15724
+ metadata: define2
15725
+ });
15726
+ return false;
15727
+ }
15728
+ if (key === "ListeningUGC" && setting.size > 0 && zones.length > 0 && !zones.some((ugc2) => setting.has(ugc2.toLowerCase()))) {
15729
+ setEventEmit({
15730
+ event: `onFilteredUGC`,
15731
+ metadata: define2
15732
+ });
15733
+ return false;
15734
+ }
15735
+ if (key === "ListeningStates" && setting.size > 0 && zones.length > 0 && !zones.some((ugc2) => setting.has(ugc2.substring(0, 2).toLowerCase()))) {
15736
+ setEventEmit({
15737
+ event: `onFilteredState`,
15738
+ metadata: define2
15693
15739
  });
15740
+ return false;
15694
15741
  }
15695
15742
  }
15743
+ return true;
15744
+ });
15745
+ if (!((_a = configurations == null ? void 0 : configurations.GlobalSettings) == null ? void 0 : _a.DisableGeometryParsing)) {
15746
+ for (const event of filterd) {
15747
+ event.geometry = yield getEventGeometry(event);
15748
+ }
15696
15749
  }
15697
- validateEvents(processed);
15750
+ if (filterd.length > 0) {
15751
+ for (const event of filterd) {
15752
+ yield mkEvent(event);
15753
+ }
15754
+ }
15755
+ yield updateNode();
15756
+ setEventEmit({
15757
+ event: `onEventCache`,
15758
+ metadata: bootstrap.cache.events,
15759
+ limited: true
15760
+ });
15698
15761
  });
15699
15762
 
15700
- // src/@events/events.api.ts
15701
- var api = (stanza) => __async(null, null, function* () {
15702
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa, _ba, _ca, _da, _ea, _fa, _ga, _ha, _ia, _ja, _ka, _la, _ma, _na, _oa, _pa, _qa, _ra, _sa, _ta, _ua, _va, _wa, _xa, _ya, _za, _Aa, _Ba, _Ca, _Da, _Ea, _Fa, _Ga, _Ha, _Ia, _Ja, _Ka, _La, _Ma, _Na, _Oa, _Pa, _Qa, _Ra, _Sa, _Ta, _Ua, _Va, _Wa, _Xa, _Ya, _Za, __a, _$a, _ab, _bb;
15763
+ // src/@events/events.text.ts
15764
+ var text = (stanza) => __async(null, null, function* () {
15765
+ var _a, _b, _c;
15703
15766
  let processed = [];
15704
- const messages = Object.values(JSON.parse(stanza.message).features);
15705
- for (const feature of messages) {
15767
+ const getMessages = (_c = (_b = (_a = stanza == null ? void 0 : stanza.message) == null ? void 0 : _a.split(/(?=\$\$)/g)) == null ? void 0 : _b.map((message) => message.trim())) == null ? void 0 : _c.filter((message) => message && message !== "$$");
15768
+ if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
15769
+ for (const message of getMessages) {
15706
15770
  const tick = performance.now();
15707
- const pVtec = (_d = (_c = (_b = (_a = feature == null ? void 0 : feature.properties) == null ? void 0 : _a.parameters) == null ? void 0 : _b.VTEC) == null ? void 0 : _c[0]) != null ? _d : null;
15771
+ const attributes = stanza == null ? void 0 : stanza.attributes;
15772
+ const props = properties({ message, attributes });
15773
+ const header = getEventHeader({ properties: props, getType: stanza.getType });
15774
+ const issued = new Date(attributes.issue);
15775
+ const expires = new Date(issued.getTime() + 12 * 60 * 60 * 1e3);
15776
+ let event = Object.keys(eventsMatchText).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
15777
+ let isStatement = false;
15778
+ if (!event) {
15779
+ event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
15780
+ isStatement = true;
15781
+ }
15708
15782
  processed.push({
15709
15783
  type: `Feature`,
15710
15784
  geometry: {
15711
15785
  type: `Point`,
15712
15786
  coordinates: []
15713
15787
  },
15714
- properties: {
15715
- event: (_f = (_e = feature == null ? void 0 : feature.properties) == null ? void 0 : _e.event) != null ? _f : null,
15716
- parent: (_h = (_g = feature == null ? void 0 : feature.properties) == null ? void 0 : _g.event) != null ? _h : null,
15717
- status: (_j = (_i = feature == null ? void 0 : feature.properties) == null ? void 0 : _i.messageType) != null ? _j : null,
15718
- issued: ((_k = feature == null ? void 0 : feature.properties) == null ? void 0 : _k.sent) ? new Date((_l = feature == null ? void 0 : feature.properties) == null ? void 0 : _l.sent).toISOString() : null,
15719
- expires: ((_m = feature == null ? void 0 : feature.properties) == null ? void 0 : _m.expires) ? new Date((_n = feature == null ? void 0 : feature.properties) == null ? void 0 : _n.expires).toISOString() : null,
15720
- locations: (_p = (_o = feature == null ? void 0 : feature.properties) == null ? void 0 : _o.areaDesc) != null ? _p : null,
15721
- description: (_r = (_q = feature == null ? void 0 : feature.properties) == null ? void 0 : _q.description) != null ? _r : null,
15722
- attributes: (_t = (_s = feature == null ? void 0 : feature.properties) == null ? void 0 : _s.attributes) != null ? _t : {},
15723
- geocode: {
15724
- office: {
15725
- office: pVtec ? pVtec.split(`.`)[2] : null,
15726
- name: (_u = officeICAOs[pVtec ? pVtec.split(`.`)[2] : null]) != null ? _u : null
15727
- },
15728
- organization: (_x = (_w = (_v = feature == null ? void 0 : feature.properties) == null ? void 0 : _v.parameters) == null ? void 0 : _w.WMOidentifier) == null ? void 0 : _x[0],
15729
- ugc: (_A = (_z = (_y = feature == null ? void 0 : feature.properties) == null ? void 0 : _y.geocode) == null ? void 0 : _z.UGC) != null ? _A : [],
15730
- polygon: ((_B = feature == null ? void 0 : feature.geometry) == null ? void 0 : _B.coordinates.length) > 0 ? Buffer.from(JSON.stringify([(_C = feature == null ? void 0 : feature.geometry) == null ? void 0 : _C.coordinates[0]])).toString("base64") : null,
15731
- polygon_generated: ((_D = feature == null ? void 0 : feature.geometry) == null ? void 0 : _D.coordinates.length) > 0 ? true : false
15732
- },
15733
- parameters: {
15734
- tags: getEventTags((_E = feature == null ? void 0 : feature.properties) == null ? void 0 : _E.description),
15735
- instructions: (_G = (_F = feature == null ? void 0 : feature.properties) == null ? void 0 : _F.instruction) != null ? _G : null,
15736
- source: (_I = getTextFromProduct({ message: (_H = feature == null ? void 0 : feature.properties) == null ? void 0 : _H.description, find: [`SOURCE...`], removal: [`.`] })) != null ? _I : null,
15737
- hazards: (_K = getTextFromProduct({ message: (_J = feature == null ? void 0 : feature.properties) == null ? void 0 : _J.description, find: [`HAZARD...`], removal: [`.`] })) != null ? _K : null,
15738
- impacts: (_M = getTextFromProduct({ message: (_L = feature == null ? void 0 : feature.properties) == null ? void 0 : _L.description, find: [`IMPACT...`], removal: [`.`] })) != null ? _M : null,
15739
- estimated_hail_size: (_Q = (_P = (_O = (_N = feature == null ? void 0 : feature.properties) == null ? void 0 : _N.parameters) == null ? void 0 : _O.maxHailSize) == null ? void 0 : _P[0]) != null ? _Q : null,
15740
- estimated_wind_gusts: (_U = (_T = (_S = (_R = feature == null ? void 0 : feature.properties) == null ? void 0 : _R.parameters) == null ? void 0 : _S.maxWindGust) == null ? void 0 : _T[0]) != null ? _U : null,
15741
- damage_threat: (_Y = (_X = (_W = (_V = feature == null ? void 0 : feature.properties) == null ? void 0 : _V.parameters) == null ? void 0 : _W.thunderstormDamageThreat) == null ? void 0 : _X[0]) != null ? _Y : null,
15742
- tornado_threat: (_aa = (_$ = (__ = (_Z = feature == null ? void 0 : feature.properties) == null ? void 0 : _Z.parameters) == null ? void 0 : __.tornadoDetection) == null ? void 0 : _$[0]) != null ? _aa : null,
15743
- flood_threat: (_ea = (_da = (_ca = (_ba = feature == null ? void 0 : feature.properties) == null ? void 0 : _ba.parameters) == null ? void 0 : _ca.floodDetection) == null ? void 0 : _da[0]) != null ? _ea : null,
15744
- wind_threat: (_ia = (_ha = (_ga = (_fa = feature == null ? void 0 : feature.properties) == null ? void 0 : _fa.parameters) == null ? void 0 : _ga.windThreat) == null ? void 0 : _ha[0]) != null ? _ia : null,
15745
- hail_threat: (_ma = (_la = (_ka = (_ja = feature == null ? void 0 : feature.properties) == null ? void 0 : _ja.parameters) == null ? void 0 : _ka.hailThreat) == null ? void 0 : _la[0]) != null ? _ma : null
15746
- },
15747
- spc_parameters: {
15748
- spc_max_tornado: (_oa = getTextFromProduct({ message: (_na = feature == null ? void 0 : feature.properties) == null ? void 0 : _na.description, find: [`MOST PROBABLE PEAK TORNADO INTENSITY...`] })) != null ? _oa : null,
15749
- spc_max_hail: (_qa = getTextFromProduct({ message: (_pa = feature == null ? void 0 : feature.properties) == null ? void 0 : _pa.description, find: [`MOST PROBABLE PEAK HAIL SIZE...`] })) != null ? _qa : null,
15750
- spc_max_wind: (_sa = getTextFromProduct({ message: (_ra = feature == null ? void 0 : feature.properties) == null ? void 0 : _ra.description, find: [`MOST PROBABLE PEAK WIND GUST...`] })) != null ? _sa : null,
15751
- spc_watch_issuance: (_ua = getTextFromProduct({ message: (_ta = feature == null ? void 0 : feature.properties) == null ? void 0 : _ta.description, find: [`Probability of Watch Issuance...`], removal: [`percent`] })) != null ? _ua : null
15752
- },
15753
- watch_parameters: {
15754
- watch_number: (_ya = (_xa = (_wa = getTextFromProduct({ message: (_va = feature == null ? void 0 : feature.properties) == null ? void 0 : _va.description, find: [`ITIES FOR`, `UPDATE FOR`, `Watch Number `], removal: [`%`, `<`, `:`] })) == null ? void 0 : _wa.replace(/(WT|WS|)/g, "")) == null ? void 0 : _xa.trim()) != null ? _ya : null,
15755
- watch_type: ((_za = feature == null ? void 0 : feature.properties) == null ? void 0 : _za.description.includes(`TORNADO WATCH`)) ? `Tornado` : ((_Aa = feature == null ? void 0 : feature.properties) == null ? void 0 : _Aa.description.includes(`SEVERE`)) ? `Severe` : null,
15756
- additional_tornadoes_probability: (_Ca = getTextFromProduct({ message: (_Ba = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ba.description, find: [`PROB OF 2 OR MORE TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _Ca : null,
15757
- strong_tornadoes_probability: (_Ea = getTextFromProduct({ message: (_Da = feature == null ? void 0 : feature.properties) == null ? void 0 : _Da.description, find: [`PROB OF 1 OR MORE STRONG /EF2-EF5/ TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _Ea : null,
15758
- severe_wind_probability: (_Ga = getTextFromProduct({ message: (_Fa = feature == null ? void 0 : feature.properties) == null ? void 0 : _Fa.description, find: [`PROB OF 10 OR MORE SEVERE WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _Ga : null,
15759
- severe_hail_probability: (_Ia = getTextFromProduct({ message: (_Ha = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ha.description, find: [`PROB OF 10 OR MORE SEVERE HAIL EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _Ia : null,
15760
- hail_2in_probability: (_Ka = getTextFromProduct({ message: (_Ja = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ja.description, find: [`PROB OF 1 OR MORE HAIL EVENTS >= 2 INCHES`], removal: [`%`, `<`, `:`] })) != null ? _Ka : null,
15761
- combined_hail_wind_probability: (_Ma = getTextFromProduct({ message: (_La = feature == null ? void 0 : feature.properties) == null ? void 0 : _La.description, find: [`PROB OF 6 OR MORE COMBINED SEVERE HAIL/WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _Ma : null,
15762
- max_hail_in: (_Oa = getTextFromProduct({ message: (_Na = feature == null ? void 0 : feature.properties) == null ? void 0 : _Na.description, find: [`MAX HAIL /INCHES/`], removal: [`%`, `<`, `:`] })) != null ? _Oa : null,
15763
- max_wind_surface: (_Qa = getTextFromProduct({ message: (_Pa = feature == null ? void 0 : feature.properties) == null ? void 0 : _Pa.description, find: [`MAX WIND GUSTS SURFACE /KNOTS/`], removal: [`%`, `<`, `:`] })) != null ? _Qa : null,
15764
- max_tops_x100feet: (_Sa = getTextFromProduct({ message: (_Ra = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ra.description, find: [`MAX TOPS /X 100 FEET/`], removal: [`%`, `<`, `:`] })) != null ? _Sa : null,
15765
- pds_watch: getTextFromProduct({ message: (_Ta = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ta.description, find: [`PARTICULARLY DANGEROUS SITUATION`], removal: [`%`, `<`, `:`] }) === `YES`
15766
- },
15788
+ properties: __spreadProps(__spreadValues({
15789
+ event,
15790
+ parent: event,
15791
+ status: isStatement ? `Statement` : `Issued`,
15792
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
15793
+ expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
15794
+ }, props), {
15767
15795
  metadata: {
15768
15796
  ms: performance.now() - tick,
15769
- source: `events.api`,
15770
- tracking: getEventTracking({ type: `API`, organization: { wmoidentifier: (_Wa = (_Va = (_Ua = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ua.parameters) == null ? void 0 : _Va.WMOidentifier) == null ? void 0 : _Wa[0], featureId: feature == null ? void 0 : feature.id }, vtec: pVtec }),
15771
- header: `ZCZC-ATMOSX-${(_Ya = (_Xa = feature == null ? void 0 : feature.properties) == null ? void 0 : _Xa.parameters) == null ? void 0 : _Ya.WMOidentifier}`,
15772
- vtec: pVtec,
15797
+ source: `events.text`,
15798
+ tracking: getEventTracking({ type: `RAW`, stanza, attributes, properties: props }),
15799
+ header,
15800
+ vtec: null,
15773
15801
  hvtec: null,
15802
+ raw: message,
15774
15803
  history: [
15775
15804
  {
15776
- description: (_Za = feature == null ? void 0 : feature.properties) == null ? void 0 : _Za.description,
15777
- issued: ((__a = feature == null ? void 0 : feature.properties) == null ? void 0 : __a.sent) ? new Date((_$a = feature == null ? void 0 : feature.properties) == null ? void 0 : _$a.sent).toISOString() : null,
15778
- status: (_bb = (_ab = feature == null ? void 0 : feature.properties) == null ? void 0 : _ab.messageType) != null ? _bb : null
15805
+ description: props.description,
15806
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
15807
+ status: `Issued`
15779
15808
  }
15780
15809
  ]
15781
15810
  }
15782
- }
15811
+ })
15783
15812
  });
15784
15813
  }
15785
15814
  validateEvents(processed);
15786
15815
  });
15787
15816
 
15788
- // src/@building/building.create.ts
15789
- var createEvent = (stanza) => __async(null, null, function* () {
15790
- const settings = bootstrap.settings;
15791
- const StanzaSettings = settings.NOAAWeatherWireServiceSettings.StanzaSettings;
15792
- const isVtecEvent = stanza.isVTEC && stanza.isUGC;
15793
- const isUgcEvent = !stanza.isVTEC && stanza.isUGC;
15794
- const isTextEvent = !stanza.isVTEC && !stanza.isUGC;
15795
- const isNWWS = stanza.isNWWS;
15796
- if (!isNWWS) return yield api(stanza);
15797
- if (!StanzaSettings.DisableVTEC && isVtecEvent) return yield vtec(stanza);
15798
- if (!StanzaSettings.DisableUGC && isUgcEvent) return yield ugc(stanza);
15799
- if (!StanzaSettings.DisableText && isTextEvent) return yield text(stanza);
15800
- return "nothing picked";
15801
- });
15817
+ // src/@parsers/@ugc/ugc.header.ts
15818
+ var getUGCHeader = (message) => {
15819
+ const start = message.search(regExp.ugc1);
15820
+ const sub = message.substring(start);
15821
+ const end = sub.search(regExp.ugc2);
15822
+ const fin = sub.substring(0, end).replace(/\s+/g, "").slice(0, -1);
15823
+ return fin != null ? fin : null;
15824
+ };
15802
15825
 
15803
- // src/@modules/@database/database.stanza.ts
15804
- var importStanza = (stanza) => __async(null, null, function* () {
15805
- const settings = bootstrap.settings;
15806
- try {
15807
- if (!settings.NOAAWeatherWireServiceSettings.CacheSettings.Enabled) {
15808
- return;
15826
+ // src/@parsers/@ugc/ugc.zones.ts
15827
+ var getZones = (header) => {
15828
+ const splits = header.split("-");
15829
+ const zones = [];
15830
+ let state = splits[0].substring(0, 2);
15831
+ const format = splits[0].substring(2, 3);
15832
+ for (const part of splits) {
15833
+ if (/^[A-Z]/.test(part)) {
15834
+ state = part.substring(0, 2);
15835
+ if (part.includes(">")) {
15836
+ const [start, end] = part.split(">");
15837
+ const startNum = parseInt(start.substring(3), 10);
15838
+ const endNum = parseInt(end, 10);
15839
+ for (let j2 = startNum; j2 <= endNum; j2++) {
15840
+ zones.push(`${state}${format}${j2.toString().padStart(3, "0")}`);
15841
+ }
15842
+ } else {
15843
+ zones.push(part);
15844
+ }
15845
+ continue;
15809
15846
  }
15810
- bootstrap.database.prepare(`INSERT OR IGNORE INTO stanzas (type, stanza, issued) VALUES (?, ?, ?)`).run(stanza.getType.type, JSON.stringify(stanza), stanza.attributes.issue);
15811
- const count = bootstrap.database.prepare(`SELECT COUNT(*) as total FROM stanzas`).get();
15812
- const max = settings.NOAAWeatherWireServiceSettings.CacheSettings.MaxDatabaseHistory;
15813
- if (count.total > max) {
15814
- const toDelete = count.total - max;
15815
- if (toDelete > 0) {
15816
- bootstrap.database.prepare(`DELETE FROM stanzas WHERE id IN (SELECT id FROM stanzas ORDER BY issued ASC LIMIT ?)`).run(toDelete);
15847
+ if (part.includes(">")) {
15848
+ const [start, end] = part.split(">");
15849
+ const startNum = parseInt(start, 10);
15850
+ const endNum = parseInt(end, 10);
15851
+ for (let j2 = startNum; j2 <= endNum; j2++) {
15852
+ zones.push(`${state}${format}${j2.toString().padStart(3, "0")}`);
15817
15853
  }
15854
+ } else {
15855
+ zones.push(`${state}${format}${part}`);
15818
15856
  }
15819
- } catch (error) {
15820
- setWarning({ message: `An error occurred while importing stanza: ${error.message}` });
15821
15857
  }
15858
+ return zones.filter((item) => item !== "");
15859
+ };
15860
+
15861
+ // src/@parsers/@ugc/ugc.expiry.ts
15862
+ var getExpiry = (message) => {
15863
+ const match = message.match(/\b(\d{6})-/);
15864
+ if (!match) {
15865
+ return null;
15866
+ }
15867
+ const date = match == null ? void 0 : match[1];
15868
+ const day = parseInt(date == null ? void 0 : date.slice(0, 2), 10);
15869
+ const hour = parseInt(date == null ? void 0 : date.slice(2, 4), 10);
15870
+ const minute = parseInt(date == null ? void 0 : date.slice(4, 6), 10);
15871
+ const now = /* @__PURE__ */ new Date();
15872
+ const expires = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), day, hour, minute));
15873
+ return expires.toISOString();
15874
+ };
15875
+
15876
+ // src/@parsers/@ugc/ugc.locations.ts
15877
+ var getLocations = (zones) => __async(null, null, function* () {
15878
+ const sites = Array.from(new Set(zones));
15879
+ const placeholders = sites.map(() => "?").join(",");
15880
+ const rows = yield bootstrap.database.prepare(`SELECT id, location FROM shapefiles WHERE id IN (${placeholders})`).all(...sites);
15881
+ return rows.map((row) => row.location).sort();
15822
15882
  });
15823
15883
 
15824
- // src/@modules/@xmpp/xmpp.xStanza.ts
15825
- var xStanza = () => {
15826
- bootstrap.session_xmpp.on(`stanza`, (stanza) => __async(null, null, function* () {
15827
- var _a, _b, _c, _d;
15828
- const msgFrom = (_b = (_a = stanza == null ? void 0 : stanza.attrs) == null ? void 0 : _a.from) != null ? _b : ``;
15829
- const msgType = (_d = (_c = stanza == null ? void 0 : stanza.attrs) == null ? void 0 : _c.type) != null ? _d : ``;
15830
- setEventEmit({
15831
- event: `onServiceStatus`,
15832
- metadata: {
15833
- message: stanza,
15834
- from: msgFrom,
15835
- type: `stanza`
15836
- }
15837
- });
15838
- bootstrap.cache.lastStanza = Date.now();
15839
- if (stanza.is(`message`)) {
15840
- const result = validate({ stanza });
15841
- const isSkippable = result.isIgnored || result.isCapEvent || result.isCapEvent && !result.isCapAreaDescription;
15842
- if (isSkippable) {
15843
- return;
15844
- }
15845
- yield createEvent(result);
15846
- yield importStanza(result);
15847
- }
15848
- if (stanza.is(`presence`) && msgFrom.startsWith("nwws@conference.nwws-oi.weather.gov/")) {
15849
- const getOccupant = msgFrom.split(`/`).slice(1).join(`/`);
15850
- const getAvailability = msgType === `unavailable`;
15851
- setEventEmit({
15852
- event: `onServiceStatus`,
15853
- metadata: {
15854
- message: `Occupant ${getOccupant} has ${getAvailability ? `left` : `joined`} the room`,
15855
- data: {},
15856
- type: `occupant`,
15857
- error: false
15858
- }
15884
+ // src/@parsers/@ugc/ugc.extract.ts
15885
+ var ugcExtract = (message) => __async(null, null, function* () {
15886
+ const head = getUGCHeader(message);
15887
+ const ugcs = getZones(head);
15888
+ const expires = getExpiry(message);
15889
+ const areas = yield getLocations(ugcs);
15890
+ if (!head || (ugcs == null ? void 0 : ugcs.length) == 0) return;
15891
+ return {
15892
+ zones: ugcs,
15893
+ locations: areas,
15894
+ expires
15895
+ };
15896
+ });
15897
+
15898
+ // src/@events/events.ugc.ts
15899
+ var ugc = (stanza) => __async(null, null, function* () {
15900
+ var _a, _b, _c;
15901
+ let processed = [];
15902
+ const getMessages = (_c = (_b = (_a = stanza == null ? void 0 : stanza.message) == null ? void 0 : _a.split(/(?=\$\$)/g)) == null ? void 0 : _b.map((message) => message.trim())) == null ? void 0 : _c.filter((message) => message && message !== "$$");
15903
+ if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
15904
+ for (const message of getMessages) {
15905
+ const tick = performance.now();
15906
+ const attributes = stanza == null ? void 0 : stanza.attributes;
15907
+ const ugc2 = yield ugcExtract(message);
15908
+ if (ugc2 != null) {
15909
+ const props = properties({ message, attributes, ugc: ugc2 });
15910
+ const issued = new Date(attributes.issue);
15911
+ const expires = new Date(ugc2.expires);
15912
+ const header = getEventHeader({ properties: props, getType: stanza.getType });
15913
+ let event = Object.keys(eventsMatchText).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
15914
+ let isStatement = false;
15915
+ if (!event) {
15916
+ event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
15917
+ isStatement = true;
15918
+ }
15919
+ processed.push({
15920
+ type: `Feature`,
15921
+ geometry: {
15922
+ type: `Point`,
15923
+ coordinates: []
15924
+ },
15925
+ properties: __spreadProps(__spreadValues({
15926
+ event,
15927
+ parent: event,
15928
+ status: isStatement ? `Statement` : `Issued`,
15929
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
15930
+ expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
15931
+ }, props), {
15932
+ metadata: {
15933
+ ms: performance.now() - tick,
15934
+ source: `events.ugc`,
15935
+ tracking: getEventTracking({ type: `RAW`, stanza, attributes, properties: props }),
15936
+ header,
15937
+ vtec: null,
15938
+ hvtec: null,
15939
+ raw: message,
15940
+ history: [
15941
+ {
15942
+ description: props.description,
15943
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
15944
+ status: `Issued`
15945
+ }
15946
+ ]
15947
+ }
15948
+ })
15859
15949
  });
15860
15950
  }
15861
- }));
15862
- };
15863
-
15864
- // src/@modules/@xmpp/xmpp.xDeploy.ts
15865
- var xDeploy = () => __async(null, null, function* () {
15866
- var _a, _b;
15867
- let session;
15868
- const settings = bootstrap.settings;
15869
- (_b = (_a = settings.NOAAWeatherWireServiceSettings.CredentialSettings).Nickname) != null ? _b : _a.Nickname = settings.NOAAWeatherWireServiceSettings.CredentialSettings.Username;
15870
- session = bootstrap.session_xmpp = client({
15871
- service: "xmpp://nwws-oi.weather.gov",
15872
- domain: "nwws-oi.weather.gov",
15873
- username: settings.NOAAWeatherWireServiceSettings.CredentialSettings.Username,
15874
- password: settings.NOAAWeatherWireServiceSettings.CredentialSettings.Password
15875
- });
15876
- try {
15877
- yield xOffline();
15878
- yield xError();
15879
- yield xStanza();
15880
- yield xOnline();
15881
- yield session.start();
15882
- } catch (error) {
15883
- setEventEmit({
15884
- event: `onServiceStatus`,
15885
- metadata: {
15886
- message: `Error occured while starting XMPP Session: ${error}`,
15887
- data: {},
15888
- type: `error`,
15889
- error: true
15890
- }
15891
- });
15892
15951
  }
15952
+ validateEvents(processed);
15893
15953
  });
15894
15954
 
15895
- // src/@modules/@database/database.init.ts
15896
- import fs2 from "fs";
15897
- import sqlite3 from "better-sqlite3";
15955
+ // src/@dictionaries/dictionaries.eventTypes.ts
15956
+ var eventTypes = {
15957
+ "AF": "Ashfall",
15958
+ "AS": "Air Stagnation",
15959
+ "BH": "Beach Hazard",
15960
+ "BW": "Brisk Wind",
15961
+ "BZ": "Blizzard",
15962
+ "CF": "Coastal Flood",
15963
+ "DF": "Debris Flow",
15964
+ "DS": "Dust Storm",
15965
+ "EC": "Extreme Cold",
15966
+ "EH": "Excessive Heat",
15967
+ "XH": "Extreme Heat",
15968
+ "EW": "Extreme Wind",
15969
+ "FA": "Areal Flood",
15970
+ "FF": "Flash Flood",
15971
+ "FG": "Dense Fog",
15972
+ "FL": "Flood",
15973
+ "FR": "Frost",
15974
+ "FW": "Fire Weather",
15975
+ "FZ": "Freeze",
15976
+ "GL": "Gale",
15977
+ "HF": "Hurricane Force Wind",
15978
+ "HT": "Heat",
15979
+ "HU": "Hurricane",
15980
+ "HW": "High Wind",
15981
+ "HY": "Hydrologic",
15982
+ "HZ": "Hard Freeze",
15983
+ "IS": "Ice Storm",
15984
+ "LE": "Lake Effect Snow",
15985
+ "LO": "Low Water",
15986
+ "LS": "Lakeshore Flood",
15987
+ "LW": "Lake Wind",
15988
+ "MA": "Special Marine",
15989
+ "EQ": "Earthquake",
15990
+ "MF": "Dense Fog",
15991
+ "MH": "Ashfall",
15992
+ "MS": "Dense Smoke",
15993
+ "RB": "Small Craft for Rough Bar",
15994
+ "RP": "Rip Current Risk",
15995
+ "SC": "Small Craft",
15996
+ "SE": "Hazardous Seas",
15997
+ "SI": "Small Craft for Winds",
15998
+ "SM": "Dense Smoke",
15999
+ "SQ": "Snow Squall",
16000
+ "SR": "Storm",
16001
+ "SS": "Storm Surge",
16002
+ "SU": "High Surf",
16003
+ "SV": "Severe Thunderstorm",
16004
+ "SW": "Small Craft for Hazardous Seas",
16005
+ "TO": "Tornado",
16006
+ "TR": "Tropical Storm",
16007
+ "TS": "Tsunami",
16008
+ "TY": "Typhoon",
16009
+ "SP": "Special Weather",
16010
+ "UP": "Heavy Freezing Spray",
16011
+ "WC": "Wind Chill",
16012
+ "WI": "Wind",
16013
+ "WS": "Winter Storm",
16014
+ "WW": "Winter Weather",
16015
+ "ZF": "Freezing Fog",
16016
+ "ZR": "Freezing Rain",
16017
+ "ZY": "Freezing Spray"
16018
+ };
15898
16019
 
15899
- // src/@modules/@database/database.shapefiles.ts
15900
- import fs from "fs";
15901
- import { resolve as resolve5, extname } from "path";
15902
- import { loadAsync } from "jszip";
15903
- import { read } from "shapefile";
16020
+ // src/@dictionaries/dictionaries.eventActions.ts
16021
+ var eventActions = {
16022
+ "W": "Warning",
16023
+ "F": "Forecast",
16024
+ "A": "Watch",
16025
+ "O": "Outlook",
16026
+ "Y": "Advisory",
16027
+ "N": "Synopsis",
16028
+ "S": "Statement"
16029
+ };
15904
16030
 
15905
- // src/@modules/@utilities/utilities.setSleep.ts
15906
- var setSleep = (options) => __async(null, null, function* () {
15907
- return new Promise((resolve6) => {
15908
- setTimeout(() => {
15909
- resolve6();
15910
- }, options.timeout);
15911
- });
15912
- });
16031
+ // src/@dictionaries/dictionaries.eventStatus.ts
16032
+ var eventStatus = {
16033
+ "NEW": "Issued",
16034
+ "CON": "Updated",
16035
+ "EXT": "Extended",
16036
+ "EXA": "Extended",
16037
+ "EXB": "Extended",
16038
+ "UPG": "Upgraded",
16039
+ "COR": "Correction",
16040
+ "ROU": "Routine",
16041
+ "CAN": "Cancelled",
16042
+ "EXP": "Expired"
16043
+ };
15913
16044
 
15914
- // src/@dictionaries/dictionaries.shapefileLinks.ts
15915
- var shapefileLinks = [
15916
- { name: "us_counties", id: "C", link: "https://www.weather.gov/source/gis/Shapefiles/County/c_16ap26.zip" },
15917
- { name: "us_states_territories", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/County/s_16ap26.zip" },
15918
- { name: "fire_weather_zones", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/WSOM/fz16ap26.zip" },
15919
- { name: "costal_marine_zones", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/WSOM/mz16ap26.zip" },
15920
- { name: "offshore_marine_zones", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/WSOM/oz16ap26.zip" },
15921
- { name: "public_forecast_zones", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/WSOM/z_16ap26.zip" },
15922
- { name: "county_warning_areas", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/WSOM/w_16ap26.zip" },
15923
- { name: "river_forecast_boundaries", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/Misc/rf05mr24.zip" },
15924
- { name: "high_seas_marine_zones", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/WSOM/hz17fe26.zip" }
15925
- ];
16045
+ // src/@parsers/@pvtec/pvtec.expires.ts
16046
+ var getExpiry2 = (dates) => {
16047
+ if ((dates == null ? void 0 : dates[1]) == `000000T0000Z`) return "Invalid Date Format";
16048
+ const expires = `${(/* @__PURE__ */ new Date()).getFullYear().toString().substring(0, 2)}${dates[1].substring(0, 2)}-${dates[1].substring(2, 4)}-${dates[1].substring(4, 6)}T${dates[1].substring(7, 9)}:${dates[1].substring(9, 11)}:00`;
16049
+ const local = new Date(new Date(expires).getTime() - 4 * 60 * 6e4);
16050
+ const pad = (n) => n.toString().padStart(2, "0");
16051
+ return `${local.getFullYear()}-${pad(local.getMonth() + 1)}-${pad(local.getDate())}T${pad(local.getHours())}:${pad(local.getMinutes())}:00.000-04:00`;
16052
+ };
15926
16053
 
15927
- // src/@modules/@database/database.shapefiles.ts
15928
- var importShapefiles = () => __async(null, null, function* () {
15929
- var _a, _b;
15930
- const settings = bootstrap.settings;
15931
- try {
15932
- const tShapefiles = bootstrap.database.prepare(`SELECT COUNT(*) AS count FROM shapefiles`).get().count;
15933
- if (tShapefiles === 0) {
15934
- yield setSleep({ timeout: 1e3 });
15935
- setWarning({ message: `Shapefiles are currently building, please DO NOT close your terminal. The shapefiles will not finish and will remain incomplete. If you do mess up, you will need to delete ${settings.Database} and restart the application.` });
15936
- for (const shapefile of shapefileLinks) {
15937
- const response2 = yield fetch(shapefile.link);
15938
- const arrayBuff = yield response2.arrayBuffer();
15939
- const content = yield loadAsync(arrayBuff);
15940
- const directory = resolve5(__dirname, `../../shapefiles`);
15941
- if (!fs.existsSync(directory)) {
15942
- fs.mkdirSync(directory, { recursive: true });
15943
- }
15944
- for (const file of Object.keys(content.files)) {
15945
- if (file.endsWith(".shp") || file.endsWith(".dbf")) {
15946
- const data = yield content.files[file].async(`nodebuffer`);
15947
- const output = resolve5(directory, `${(_a = shapefile == null ? void 0 : shapefile.name) != null ? _a : ``}_${(_b = shapefile == null ? void 0 : shapefile.id) != null ? _b : ``}${extname(file)}`);
15948
- fs.writeFileSync(output, data);
15949
- }
15950
- }
15951
- const filepath = resolve5(__dirname, "../../shapefiles", shapefile.name + "_" + shapefile.id);
15952
- const { features } = yield read(
15953
- filepath,
15954
- filepath
15955
- );
15956
- setWarning({ message: `Importing ${features.length} features from ${shapefile.name}_${shapefile.id}` });
15957
- const insert = bootstrap.database.prepare(`INSERT OR REPLACE INTO shapefiles (id, location, geometry) VALUES (?, ?, ?)`);
15958
- const transaction = bootstrap.database.transaction((entries) => {
15959
- var _a2, _b2, _c;
15960
- for (const entry of entries) {
15961
- const { properties: properties2, geometry } = entry;
15962
- let final2, location;
15963
- if (properties2.FIPS) {
15964
- final2 = `${properties2.STATE}${shapefile.id}${properties2.FIPS.substring(2)}`;
15965
- location = `${properties2.COUNTYNAME}, ${properties2.STATE}`;
15966
- } else if (properties2.FULLSTAID) {
15967
- final2 = `${properties2.ST}${shapefile.id}${properties2.WFO}`;
15968
- location = `${properties2.CITY}, ${properties2.STATE}`;
15969
- } else if (properties2.STATE) {
15970
- final2 = `${properties2.STATE}${shapefile.id}${(_a2 = properties2.ZONE) != null ? _a2 : properties2.SITE_ID}`;
15971
- location = `${(_b2 = properties2.NAME) != null ? _b2 : `${properties2.RFC_NAME} ${properties2.RFC_CITY}`}, ${properties2.STATE}`;
15972
- } else {
15973
- final2 = (_c = properties2.ID) != null ? _c : properties2.WFO;
15974
- location = properties2.NAME;
15975
- }
15976
- insert.run(final2, location, JSON.stringify(geometry));
15977
- }
15978
- });
15979
- fs.unlinkSync(`${filepath}.shp`);
15980
- fs.unlinkSync(`${filepath}.dbf`);
15981
- setWarning({ message: `Cleaned up temporary files for ${shapefile.name}_${shapefile.id}` });
15982
- transaction(features);
15983
- }
15984
- setWarning({ message: `Shapefiles have finished compiling, you can now continue and close this terminal` });
15985
- fs.rm(resolve5(__dirname, "../../shapefiles"), { recursive: true, force: true }, () => {
15986
- });
15987
- }
15988
- } catch (error) {
15989
- setWarning({ message: `An error occurred while compiling shapefiles: ${error.message}` });
16054
+ // src/@parsers/@pvtec/pvtec.extract.ts
16055
+ var pvExtract = (message) => {
16056
+ var _a, _b, _c, _d;
16057
+ const getVTECs = (_a = message.match(regExp.pvtec)) != null ? _a : [];
16058
+ const vtecs = [];
16059
+ for (const vtec2 of getVTECs) {
16060
+ const sub = vtec2.split(`.`);
16061
+ if ((sub == null ? void 0 : sub.length) < 7) continue;
16062
+ const dates = (_b = sub[6]) == null ? void 0 : _b.split(`-`);
16063
+ vtecs.push({
16064
+ vtec: vtec2,
16065
+ product: eventProducts[sub[0]],
16066
+ tracking: `${sub[2]}.${sub[3]}.${sub[4]}.${sub[5]}`,
16067
+ event: `${eventTypes[sub[3]]} ${eventActions[sub[4]]}`,
16068
+ status: eventStatus[sub[1]],
16069
+ organization: (_d = (_c = message.match(regExp.wmo)) == null ? void 0 : _c[0]) != null ? _d : null,
16070
+ expires: getExpiry2(dates),
16071
+ is_watch: (sub[4] == `A` || sub[4] == `Y`) && (sub[3] == `TO` || sub[3] == `SV`),
16072
+ prediction_center: sub[2] == `KWNS` ? true : false
16073
+ });
15990
16074
  }
15991
- });
16075
+ return vtecs.length > 0 ? vtecs : null;
16076
+ };
15992
16077
 
15993
- // src/@modules/@database/database.init.ts
15994
- var initializeDatabase = () => __async(null, null, function* () {
15995
- const settings = bootstrap.settings;
15996
- try {
15997
- if (!fs2.existsSync(settings.Database)) {
15998
- fs2.writeFileSync(settings.Database, "");
15999
- setWarning({ message: `Creating new database at ${settings.Database}` });
16000
- }
16001
- bootstrap.database = new sqlite3(settings.Database);
16002
- bootstrap.database.prepare(`CREATE TABLE IF NOT EXISTS stanzas ( id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT, issued TEXT, stanza TEXT )`).run();
16003
- bootstrap.database.prepare(`CREATE TABLE IF NOT EXISTS shapefiles (id TEXT PRIMARY KEY, location TEXT, geometry TEXT)`).run();
16004
- yield importShapefiles();
16005
- } catch (error) {
16006
- setWarning({ message: `An error occurred while initializing the database: ${error.message}` });
16007
- }
16008
- });
16078
+ // src/@dictionaries/dictionaries.eventCauses.ts
16079
+ var eventCauses = {
16080
+ "SM": "Snow Melt",
16081
+ "RS": "Rain/Snow Melt",
16082
+ "ER": "Excessive Rain",
16083
+ "DM": "Dam/Levee Failure",
16084
+ "IJ": "Ice Jam",
16085
+ "GO": "Glacier Lake Outburst",
16086
+ "IC": "Ice",
16087
+ "FS": "Flash Flood / Storm Surge",
16088
+ "FT": "Tidal Effects",
16089
+ "ET": "Elevated Upstream Flow",
16090
+ "MC": "Other Multiple Causes",
16091
+ "WT": "Wind and/or Tidal Effects",
16092
+ "DR": "Reservoir Release",
16093
+ "UU": "Unknown",
16094
+ "OT": "Other Effects"
16095
+ };
16009
16096
 
16010
- // src/@modules/@database/database.cache.ts
16011
- var getCachedEvents = () => __async(null, null, function* () {
16097
+ // src/@dictionaries/dictionaries.eventRecords.ts
16098
+ var eventRecords = {
16099
+ "NO": "No Record Expected",
16100
+ "NR": "Near Record or possible record",
16101
+ "UU": "Unknown history of records",
16102
+ "OO": "Other"
16103
+ };
16104
+
16105
+ // src/@dictionaries/dictionaries.eventSeverity.ts
16106
+ var eventSeverity = {
16107
+ N: "Not Expected",
16108
+ 0: "Areal Flood or FF Product",
16109
+ 1: "Minor",
16110
+ 2: "Moderate",
16111
+ 3: "Major",
16112
+ U: "Unknown"
16113
+ };
16114
+
16115
+ // src/@parsers/@hvtec/hvtec.extract.ts
16116
+ var hvExtract = (message) => {
16012
16117
  var _a;
16013
- try {
16014
- const settings = bootstrap.settings;
16015
- const tick = performance.now();
16016
- if (settings.NOAAWeatherWireServiceSettings.CacheSettings.Enabled) {
16017
- const max = (_a = settings.NOAAWeatherWireServiceSettings.CacheSettings.MaxRetentionHistory) != null ? _a : 500;
16018
- const get = yield bootstrap.database.prepare(`SELECT * FROM stanzas ORDER BY rowid DESC LIMIT ?`).all(max);
16019
- setWarning({ message: `Fetched ${get.length} cached events from the database in ${Math.floor(performance.now() - tick)} ms` });
16020
- let events = get.map((row) => JSON.parse(row.stanza)).filter((stanza) => {
16021
- if (!stanza) {
16022
- return;
16023
- }
16024
- const isSkippable = stanza.isIgnored || stanza.isCapEvent || stanza.isCapEvent && !stanza.isCapAreaDescription;
16025
- return !isSkippable;
16026
- });
16027
- events = events.sort((a, b) => b.issued - a.issued);
16028
- yield Promise.all(events.map((event) => createEvent(event)));
16029
- setWarning({ message: `Processed ${events.length} cached events in ${Math.floor(performance.now() - tick)} ms` });
16030
- }
16031
- } catch (error) {
16032
- setWarning({ message: `An error occurred while fetching cached events: ${error.message} -> ${error.stack}` });
16118
+ const getHVTECs = (_a = message.match(regExp.hvtec)) != null ? _a : [];
16119
+ const vtecs = [];
16120
+ for (const vtec2 of getHVTECs) {
16121
+ const sub = vtec2.split(`.`);
16122
+ if (sub.length < 7) continue;
16123
+ vtecs.push({
16124
+ hvtec: vtec2,
16125
+ severity: eventSeverity[sub[1]],
16126
+ cause: eventCauses[sub[2]],
16127
+ record: eventRecords[sub[6]]
16128
+ });
16033
16129
  }
16034
- });
16130
+ return vtecs.length > 0 ? vtecs : null;
16131
+ };
16035
16132
 
16036
- // src/@modules/@xmpp/xmpp.xReconnect.ts
16037
- var xReconnect = (interval) => __async(null, null, function* () {
16038
- const settings = bootstrap.settings;
16039
- const lastStanza = Date.now() - bootstrap.cache.lastStanza;
16040
- if (interval < 15) {
16041
- setWarning({ message: `Reconnection interval of ${interval} seconds is too low, setting to 15 seconds` });
16042
- interval = 15;
16043
- bootstrap.settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval = 15;
16044
- }
16045
- const reconnectThreshold = interval * 1e3;
16046
- if (!bootstrap.cache.isConnected && !bootstrap.cache.sigHault || !bootstrap.session_xmpp) {
16047
- return;
16048
- }
16049
- if (lastStanza > reconnectThreshold) {
16050
- if (!bootstrap.cache.isReconnecting) {
16051
- bootstrap.cache.isReconnecting = true;
16052
- bootstrap.cache.isConnected = false;
16053
- bootstrap.cache.tReconnects += 1;
16054
- try {
16055
- setEventEmit({
16056
- event: `onServiceStatus`,
16057
- metadata: {
16058
- message: `Attempting to reconnect to XMPP Service (Reconnect Attempt ${bootstrap.cache.tReconnects})`,
16059
- data: {
16060
- last_stanza: lastStanza,
16061
- nickname: settings.NOAAWeatherWireServiceSettings.CredentialSettings.Nickname
16062
- },
16063
- type: `reconnect`,
16064
- error: true
16065
- }
16066
- });
16067
- yield bootstrap.session_xmpp.stop().catch(() => {
16068
- });
16069
- yield bootstrap.session_xmpp.start().catch(() => {
16133
+ // src/@events/events.vtec.ts
16134
+ var vtec = (stanza) => __async(null, null, function* () {
16135
+ var _a, _b, _c, _d, _e;
16136
+ let processed = [];
16137
+ const getMessages = (_c = (_b = (_a = stanza == null ? void 0 : stanza.message) == null ? void 0 : _a.split(/(?=\$\$)/g)) == null ? void 0 : _b.map((message) => message.trim())) == null ? void 0 : _c.filter((message) => message && message !== "$$");
16138
+ if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
16139
+ for (const message of getMessages) {
16140
+ const tick = performance.now();
16141
+ const attributes = stanza == null ? void 0 : stanza.attributes;
16142
+ const pVtec = pvExtract(message);
16143
+ const hVtec = hvExtract(message);
16144
+ const ugc2 = yield ugcExtract(message);
16145
+ if (pVtec != null && ugc2 != null) {
16146
+ for (const pv of pVtec) {
16147
+ const vtec2 = pv;
16148
+ const props = properties({ message, attributes, ugc: ugc2, pVtec: vtec2 });
16149
+ const header = getEventHeader({ properties: props, getType: stanza.getType, vtec: vtec2 });
16150
+ const issued = (_d = new Date(attributes.issue)) != null ? _d : /* @__PURE__ */ new Date();
16151
+ const expires = new Date(vtec2.expires);
16152
+ processed.push({
16153
+ type: `Feature`,
16154
+ geometry: {
16155
+ type: `Point`,
16156
+ coordinates: []
16157
+ },
16158
+ properties: __spreadProps(__spreadValues({
16159
+ event: pv.event,
16160
+ parent: pv.event,
16161
+ status: pv.status,
16162
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
16163
+ expires: !isNaN(expires.getTime()) ? expires.toISOString() : (_e = ugc2.expires) != null ? _e : new Date(issued.getTime() + 60 * 60 * 1e3).toISOString()
16164
+ }, props), {
16165
+ metadata: {
16166
+ ms: performance.now() - tick,
16167
+ source: `events.vtec`,
16168
+ tracking: getEventTracking({ type: `VTEC`, stanza, attributes, properties: props, vtec: vtec2 }),
16169
+ header,
16170
+ vtec: pv,
16171
+ hvtec: hVtec,
16172
+ raw: message,
16173
+ history: [
16174
+ {
16175
+ description: props.description,
16176
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
16177
+ status: pv.status
16178
+ }
16179
+ ]
16180
+ }
16181
+ })
16070
16182
  });
16071
- } catch (error) {
16072
- setWarning({ message: `XMPP Reconnect Failed - ${error.message}` });
16073
- } finally {
16074
- bootstrap.cache.isReconnecting = false;
16075
16183
  }
16076
16184
  }
16077
16185
  }
16186
+ validateEvents(processed);
16078
16187
  });
16079
16188
 
16080
- // src/@modules/@utilities/utilities.setCronSchedule.ts
16081
- var setCronSchedule = () => __async(null, null, function* () {
16082
- const settings = bootstrap.settings;
16083
- if (settings.EnableWireService) {
16084
- if (settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.Enabled) {
16085
- void xReconnect(settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval);
16086
- }
16087
- } else {
16088
- const response2 = yield createHttp({
16089
- url: settings.NationalWeatherServiceSettings.EventsEndpoint,
16090
- headers: {
16091
- "User-Agent": "@atmosx/event-product-parser"
16092
- }
16093
- });
16094
- if (response2.error) {
16095
- return setEventEmit({
16096
- event: `onServiceStatus`,
16189
+ // src/@events/events.api.ts
16190
+ var api = (stanza) => __async(null, null, function* () {
16191
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa, _ba, _ca, _da, _ea, _fa, _ga, _ha, _ia, _ja, _ka, _la, _ma, _na, _oa, _pa, _qa, _ra, _sa, _ta, _ua, _va, _wa, _xa, _ya, _za, _Aa, _Ba, _Ca, _Da, _Ea, _Fa, _Ga, _Ha, _Ia, _Ja, _Ka, _La, _Ma, _Na, _Oa, _Pa, _Qa, _Ra, _Sa, _Ta, _Ua, _Va, _Wa, _Xa, _Ya, _Za, __a, _$a, _ab, _bb, _cb, _db, _eb, _fb, _gb;
16192
+ let processed = [];
16193
+ const messages = Object.values(JSON.parse(stanza.message).features);
16194
+ for (const feature of messages) {
16195
+ const tick = performance.now();
16196
+ const pVtec = (_d = (_c = (_b = (_a = feature == null ? void 0 : feature.properties) == null ? void 0 : _a.parameters) == null ? void 0 : _b.VTEC) == null ? void 0 : _c[0]) != null ? _d : null;
16197
+ processed.push({
16198
+ type: `Feature`,
16199
+ geometry: {
16200
+ type: `Point`,
16201
+ coordinates: []
16202
+ },
16203
+ properties: {
16204
+ event: (_f = (_e = feature == null ? void 0 : feature.properties) == null ? void 0 : _e.event) != null ? _f : null,
16205
+ parent: (_h = (_g = feature == null ? void 0 : feature.properties) == null ? void 0 : _g.event) != null ? _h : null,
16206
+ status: (_j = (_i = feature == null ? void 0 : feature.properties) == null ? void 0 : _i.messageType) != null ? _j : null,
16207
+ issued: ((_k = feature == null ? void 0 : feature.properties) == null ? void 0 : _k.sent) ? new Date((_l = feature == null ? void 0 : feature.properties) == null ? void 0 : _l.sent).toISOString() : null,
16208
+ expires: ((_m = feature == null ? void 0 : feature.properties) == null ? void 0 : _m.expires) ? new Date((_n = feature == null ? void 0 : feature.properties) == null ? void 0 : _n.expires).toISOString() : null,
16209
+ locations: (_p = (_o = feature == null ? void 0 : feature.properties) == null ? void 0 : _o.areaDesc) != null ? _p : null,
16210
+ description: (_r = (_q = feature == null ? void 0 : feature.properties) == null ? void 0 : _q.description) != null ? _r : null,
16211
+ attributes: (_t = (_s = feature == null ? void 0 : feature.properties) == null ? void 0 : _s.attributes) != null ? _t : {},
16212
+ geocode: {
16213
+ office: {
16214
+ office: pVtec ? pVtec.split(`.`)[2] : null,
16215
+ name: (_u = officeICAOs[pVtec ? pVtec.split(`.`)[2] : null]) != null ? _u : null
16216
+ },
16217
+ organization: (_x = (_w = (_v = feature == null ? void 0 : feature.properties) == null ? void 0 : _v.parameters) == null ? void 0 : _w.WMOidentifier) == null ? void 0 : _x[0],
16218
+ ugc: (_A = (_z = (_y = feature == null ? void 0 : feature.properties) == null ? void 0 : _y.geocode) == null ? void 0 : _z.UGC) != null ? _A : [],
16219
+ polygon: ((_B = feature == null ? void 0 : feature.geometry) == null ? void 0 : _B.coordinates.length) > 0 ? Buffer.from(JSON.stringify([(_C = feature == null ? void 0 : feature.geometry) == null ? void 0 : _C.coordinates[0]])).toString("base64") : null,
16220
+ polygon_generated: ((_D = feature == null ? void 0 : feature.geometry) == null ? void 0 : _D.coordinates.length) > 0 ? true : false
16221
+ },
16222
+ parameters: {
16223
+ tags: getEventTags((_E = feature == null ? void 0 : feature.properties) == null ? void 0 : _E.description),
16224
+ instructions: (_G = (_F = feature == null ? void 0 : feature.properties) == null ? void 0 : _F.instruction) != null ? _G : null,
16225
+ source: (_I = getTextFromProduct({ message: (_H = feature == null ? void 0 : feature.properties) == null ? void 0 : _H.description, find: [`SOURCE...`], removal: [`.`] })) != null ? _I : null,
16226
+ hazards: (_K = getTextFromProduct({ message: (_J = feature == null ? void 0 : feature.properties) == null ? void 0 : _J.description, find: [`HAZARD...`], removal: [`.`] })) != null ? _K : null,
16227
+ impacts: (_M = getTextFromProduct({ message: (_L = feature == null ? void 0 : feature.properties) == null ? void 0 : _L.description, find: [`IMPACT...`], removal: [`.`] })) != null ? _M : null,
16228
+ estimated_hail_size: (_Q = (_P = (_O = (_N = feature == null ? void 0 : feature.properties) == null ? void 0 : _N.parameters) == null ? void 0 : _O.maxHailSize) == null ? void 0 : _P[0]) != null ? _Q : null,
16229
+ estimated_wind_gusts: (_U = (_T = (_S = (_R = feature == null ? void 0 : feature.properties) == null ? void 0 : _R.parameters) == null ? void 0 : _S.maxWindGust) == null ? void 0 : _T[0]) != null ? _U : null,
16230
+ damage_threat: (_Y = (_X = (_W = (_V = feature == null ? void 0 : feature.properties) == null ? void 0 : _V.parameters) == null ? void 0 : _W.thunderstormDamageThreat) == null ? void 0 : _X[0]) != null ? _Y : null,
16231
+ tornado_threat: (_aa = (_$ = (__ = (_Z = feature == null ? void 0 : feature.properties) == null ? void 0 : _Z.parameters) == null ? void 0 : __.tornadoDetection) == null ? void 0 : _$[0]) != null ? _aa : null,
16232
+ flood_threat: (_ea = (_da = (_ca = (_ba = feature == null ? void 0 : feature.properties) == null ? void 0 : _ba.parameters) == null ? void 0 : _ca.floodDetection) == null ? void 0 : _da[0]) != null ? _ea : null,
16233
+ wind_threat: (_ia = (_ha = (_ga = (_fa = feature == null ? void 0 : feature.properties) == null ? void 0 : _fa.parameters) == null ? void 0 : _ga.windThreat) == null ? void 0 : _ha[0]) != null ? _ia : null,
16234
+ hail_threat: (_ma = (_la = (_ka = (_ja = feature == null ? void 0 : feature.properties) == null ? void 0 : _ja.parameters) == null ? void 0 : _ka.hailThreat) == null ? void 0 : _la[0]) != null ? _ma : null
16235
+ },
16236
+ spc_parameters: {
16237
+ spc_number: (_oa = getTextFromProduct({ message: (_na = feature == null ? void 0 : feature.properties) == null ? void 0 : _na.description, find: [`Mesoscale Discussion `], removal: [`Mesoscale Discussion`, `Number`, `...`] })) != null ? _oa : null,
16238
+ spc_concerning: (_qa = getTextFromProduct({ message: (_pa = feature == null ? void 0 : feature.properties) == null ? void 0 : _pa.description, find: [`Concerning...`] })) != null ? _qa : null,
16239
+ spc_max_tornado: (_sa = getTextFromProduct({ message: (_ra = feature == null ? void 0 : feature.properties) == null ? void 0 : _ra.description, find: [`MOST PROBABLE PEAK TORNADO INTENSITY...`] })) != null ? _sa : null,
16240
+ spc_max_hail: (_ua = getTextFromProduct({ message: (_ta = feature == null ? void 0 : feature.properties) == null ? void 0 : _ta.description, find: [`MOST PROBABLE PEAK HAIL SIZE...`] })) != null ? _ua : null,
16241
+ spc_max_wind: (_wa = getTextFromProduct({ message: (_va = feature == null ? void 0 : feature.properties) == null ? void 0 : _va.description, find: [`MOST PROBABLE PEAK WIND GUST...`] })) != null ? _wa : null,
16242
+ spc_watch_issuance: (_ya = getTextFromProduct({ message: (_xa = feature == null ? void 0 : feature.properties) == null ? void 0 : _xa.description, find: [`Probability of Watch Issuance...`], removal: [`percent`] })) != null ? _ya : null
16243
+ },
16244
+ watch_parameters: {
16245
+ watch_number: (_Ca = (_Ba = (_Aa = getTextFromProduct({ message: (_za = feature == null ? void 0 : feature.properties) == null ? void 0 : _za.description, find: [`ITIES FOR`, `UPDATE FOR`, `Watch Number `], removal: [`%`, `<`, `:`] })) == null ? void 0 : _Aa.replace(/(WT|WS|)/g, "")) == null ? void 0 : _Ba.trim()) != null ? _Ca : null,
16246
+ watch_type: ((_Da = feature == null ? void 0 : feature.properties) == null ? void 0 : _Da.description.includes(`TORNADO WATCH`)) ? `Tornado` : ((_Ea = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ea.description.includes(`SEVERE`)) ? `Severe` : null,
16247
+ additional_tornadoes_probability: (_Ga = getTextFromProduct({ message: (_Fa = feature == null ? void 0 : feature.properties) == null ? void 0 : _Fa.description, find: [`PROB OF 2 OR MORE TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _Ga : null,
16248
+ strong_tornadoes_probability: (_Ia = getTextFromProduct({ message: (_Ha = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ha.description, find: [`PROB OF 1 OR MORE STRONG /EF2-EF5/ TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _Ia : null,
16249
+ severe_wind_probability: (_Ka = getTextFromProduct({ message: (_Ja = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ja.description, find: [`PROB OF 10 OR MORE SEVERE WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _Ka : null,
16250
+ severe_hail_probability: (_Ma = getTextFromProduct({ message: (_La = feature == null ? void 0 : feature.properties) == null ? void 0 : _La.description, find: [`PROB OF 10 OR MORE SEVERE HAIL EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _Ma : null,
16251
+ hail_2in_probability: (_Oa = getTextFromProduct({ message: (_Na = feature == null ? void 0 : feature.properties) == null ? void 0 : _Na.description, find: [`PROB OF 1 OR MORE HAIL EVENTS >= 2 INCHES`], removal: [`%`, `<`, `:`] })) != null ? _Oa : null,
16252
+ combined_hail_wind_probability: (_Qa = getTextFromProduct({ message: (_Pa = feature == null ? void 0 : feature.properties) == null ? void 0 : _Pa.description, find: [`PROB OF 6 OR MORE COMBINED SEVERE HAIL/WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _Qa : null,
16253
+ max_hail_in: (_Sa = getTextFromProduct({ message: (_Ra = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ra.description, find: [`MAX HAIL /INCHES/`], removal: [`%`, `<`, `:`] })) != null ? _Sa : null,
16254
+ max_wind_surface: (_Ua = getTextFromProduct({ message: (_Ta = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ta.description, find: [`MAX WIND GUSTS SURFACE /KNOTS/`], removal: [`%`, `<`, `:`] })) != null ? _Ua : null,
16255
+ max_tops_x100feet: (_Wa = getTextFromProduct({ message: (_Va = feature == null ? void 0 : feature.properties) == null ? void 0 : _Va.description, find: [`MAX TOPS /X 100 FEET/`], removal: [`%`, `<`, `:`] })) != null ? _Wa : null,
16256
+ pds_watch: getTextFromProduct({ message: (_Xa = feature == null ? void 0 : feature.properties) == null ? void 0 : _Xa.description, find: [`PARTICULARLY DANGEROUS SITUATION`], removal: [`%`, `<`, `:`] }) === `YES`
16257
+ },
16097
16258
  metadata: {
16098
- type: "fetch-api",
16099
- message: `Failed to fetch latest events from National Weather Service API - ${response2.message}`,
16100
- data: {},
16101
- error: true
16259
+ ms: performance.now() - tick,
16260
+ source: `events.api`,
16261
+ tracking: getEventTracking({ type: `API`, organization: { wmoidentifier: (__a = (_Za = (_Ya = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ya.parameters) == null ? void 0 : _Za.WMOidentifier) == null ? void 0 : __a[0], featureId: feature == null ? void 0 : feature.id }, vtec: pVtec }),
16262
+ header: `ZCZC-ATMOSX-${(_ab = (_$a = feature == null ? void 0 : feature.properties) == null ? void 0 : _$a.parameters) == null ? void 0 : _ab.WMOidentifier}`,
16263
+ vtec: pVtec,
16264
+ hvtec: null,
16265
+ raw: (_bb = feature == null ? void 0 : feature.properties) == null ? void 0 : _bb.description,
16266
+ history: [
16267
+ {
16268
+ description: (_cb = feature == null ? void 0 : feature.properties) == null ? void 0 : _cb.description,
16269
+ issued: ((_db = feature == null ? void 0 : feature.properties) == null ? void 0 : _db.sent) ? new Date((_eb = feature == null ? void 0 : feature.properties) == null ? void 0 : _eb.sent).toISOString() : null,
16270
+ status: (_gb = (_fb = feature == null ? void 0 : feature.properties) == null ? void 0 : _fb.messageType) != null ? _gb : null
16271
+ }
16272
+ ]
16102
16273
  }
16103
- });
16104
- }
16105
- setEventEmit({
16106
- event: `onServiceStatus`,
16107
- metadata: {
16108
- message: `Fetched latest events from National Weather Service API`,
16109
- data: {},
16110
- type: "fetch-api",
16111
- error: false
16112
- }
16113
- });
16114
- createEvent({ message: response2.message, isNWWS: false });
16115
- }
16116
- });
16117
-
16118
- // src/@manager/manager.updateEvents.ts
16119
- var updateEvents = (selectedEvent) => __async(null, null, function* () {
16120
- const events = bootstrap.cache.events.features;
16121
- function update(evt) {
16122
- return __async(this, null, function* () {
16123
- if (new Date(evt.properties.expires) < /* @__PURE__ */ new Date()) {
16124
- rmEvent(evt);
16125
16274
  }
16126
16275
  });
16127
16276
  }
16128
- if (!selectedEvent) {
16129
- yield Promise.all(events.map((evt) => __async(null, null, function* () {
16130
- yield update(evt);
16131
- })));
16132
- }
16133
- if (selectedEvent) {
16134
- yield update(selectedEvent);
16135
- }
16277
+ validateEvents(processed);
16136
16278
  });
16137
16279
 
16138
- // src/@core/core.start.ts
16139
- import { Cron } from "croner";
16140
- var startService = (configurations) => __async(null, null, function* () {
16141
- if (!bootstrap.isReady) {
16142
- return setWarning({
16143
- message: `You can not create another instance without shutting down the current one first, please make sure to call the stop() method first!`
16144
- });
16145
- }
16146
- const settings = setSettings(configurations);
16147
- bootstrap.isReady = true;
16148
- yield initializeDatabase();
16149
- if (settings.EnableWireService) {
16150
- (() => __async(null, null, function* () {
16151
- yield getCachedEvents();
16152
- yield xDeploy();
16153
- }))();
16154
- }
16155
- yield setCronSchedule();
16156
- let scheduleInterval = !settings.EnableWireService ? settings.NationalWeatherServiceSettings.CallbackInterval : 1;
16157
- if (!settings.EnableWireService && scheduleInterval < 15) {
16158
- setWarning({ message: `Schedule interval of ${scheduleInterval} seconds is too low, setting to 15 seconds` });
16159
- bootstrap.settings.NationalWeatherServiceSettings.CallbackInterval = 15;
16160
- scheduleInterval = 15;
16161
- }
16162
- bootstrap.cron = new Cron(`*/${scheduleInterval} * * * * *`, () => __async(null, null, function* () {
16163
- yield setCronSchedule();
16164
- }));
16165
- bootstrap.cron = new Cron(`* * * * * *`, () => __async(null, null, function* () {
16166
- yield updateNode();
16167
- yield updateEvents();
16168
- }));
16280
+ // src/@building/building.create.ts
16281
+ var createEvent = (stanza) => __async(null, null, function* () {
16282
+ const settings = bootstrap.settings;
16283
+ const StanzaSettings = settings.NOAAWeatherWireServiceSettings.StanzaSettings;
16284
+ const isVtecEvent = stanza.isVTEC && stanza.isUGC;
16285
+ const isUgcEvent = !stanza.isVTEC && stanza.isUGC;
16286
+ const isTextEvent = !stanza.isVTEC && !stanza.isUGC;
16287
+ const isNWWS = stanza.isNWWS;
16288
+ if (!isNWWS) return yield api(stanza);
16289
+ if (!StanzaSettings.DisableVTEC && isVtecEvent) return yield vtec(stanza);
16290
+ if (!StanzaSettings.DisableUGC && isUgcEvent) return yield ugc(stanza);
16291
+ if (!StanzaSettings.DisableText && isTextEvent) return yield text(stanza);
16292
+ return "nothing picked";
16169
16293
  });
16170
16294
 
16171
- // src/@core/core.stop.ts
16172
- var stopService = () => __async(null, null, function* () {
16173
- if (bootstrap.isReady) {
16174
- bootstrap.isReady = false;
16175
- if (bootstrap.session_xmpp) {
16176
- try {
16177
- yield bootstrap.session_xmpp.stop();
16178
- } catch (e) {
16295
+ // src/@modules/@database/database.stanza.ts
16296
+ var importStanza = (stanza) => __async(null, null, function* () {
16297
+ const settings = bootstrap.settings;
16298
+ try {
16299
+ if (!settings.NOAAWeatherWireServiceSettings.CacheSettings.Enabled) {
16300
+ return;
16301
+ }
16302
+ bootstrap.database.prepare(`INSERT OR IGNORE INTO stanzas (type, stanza, issued) VALUES (?, ?, ?)`).run(stanza.getType.type, JSON.stringify(stanza), stanza.attributes.issue);
16303
+ const count = bootstrap.database.prepare(`SELECT COUNT(*) as total FROM stanzas`).get();
16304
+ const max = settings.NOAAWeatherWireServiceSettings.CacheSettings.MaxDatabaseHistory;
16305
+ if (count.total > max) {
16306
+ const toDelete = count.total - max;
16307
+ if (toDelete > 0) {
16308
+ bootstrap.database.prepare(`DELETE FROM stanzas WHERE id IN (SELECT id FROM stanzas ORDER BY issued ASC LIMIT ?)`).run(toDelete);
16179
16309
  }
16180
- bootstrap.cache.isConnected = false;
16181
- bootstrap.cache.sigHault = true;
16182
- bootstrap.session_xmpp = null;
16183
16310
  }
16311
+ } catch (error) {
16312
+ setWarning({ message: `An error occurred while importing stanza: ${error.message}` });
16184
16313
  }
16185
16314
  });
16186
16315
 
16187
- // src/@dictionaries/dictionaries.transcribedMessageReplacements.ts
16188
- var transcribedMessageReplacements = [
16189
- { regex: /\*/g, replacement: "" },
16190
- { regex: /\.{3,}/g, replacement: "" },
16191
- { regex: /\bUTC\b/g, replacement: "Coordinated Universal Time" },
16192
- { regex: /\bGMT\b/g, replacement: "Greenwich Mean Time" },
16193
- { regex: /\bEST\b(?!\w)/g, replacement: "Eastern Standard Time" },
16194
- { regex: /\bEDT\b(?!\w)/g, replacement: "Eastern Daylight Time" },
16195
- { regex: /\bCST\b(?!\w)/g, replacement: "Central Standard Time" },
16196
- { regex: /\bCDT\b(?!\w)/g, replacement: "Central Daylight Time" },
16197
- { regex: /\bMST\b(?!\w)/g, replacement: "Mountain Standard Time" },
16198
- { regex: /\bMDT\b(?!\w)/g, replacement: "Mountain Daylight Time" },
16199
- { regex: /\bPST\b(?!\w)/g, replacement: "Pacific Standard Time" },
16200
- { regex: /\bPDT\b(?!\w)/g, replacement: "Pacific Daylight Time" },
16201
- { regex: /\bAKST\b(?!\w)/g, replacement: "Alaska Standard Time" },
16202
- { regex: /\bAKDT\b(?!\w)/g, replacement: "Alaska Daylight Time" },
16203
- { regex: /\bHST\b(?!\w)/g, replacement: "Hawaii Standard Time" },
16204
- { regex: /\bHDT\b(?!\w)/g, replacement: "Hawaii Daylight Time" },
16205
- { regex: /\bmph\b(?!\w)/g, replacement: "miles per hour" },
16206
- { regex: /\bkm\/h\b(?!\w)/g, replacement: "kilometers per hour" },
16207
- { regex: /\bkmh\b(?!\w)/g, replacement: "kilometers per hour" },
16208
- { regex: /\bkt\b(?!\w)/g, replacement: "knots" },
16209
- { regex: /\bNE\b(?!\w)/g, replacement: "northeast" },
16210
- { regex: /\bNW\b(?!\w)/g, replacement: "northwest" },
16211
- { regex: /\bSE\b(?!\w)/g, replacement: "southeast" },
16212
- { regex: /\bSW\b(?!\w)/g, replacement: "southwest" },
16213
- { regex: /\bNM\b(?!\w)/g, replacement: "nautical miles" },
16214
- { regex: /\bdeg\b(?!\w)/g, replacement: "degrees" },
16215
- { regex: /\btstm\b(?!\w)/g, replacement: "thunderstorm" },
16216
- { regex: /\bmm\b(?!\w)/g, replacement: "millimeters" },
16217
- { regex: /\bcm\b(?!\w)/g, replacement: "centimeters" },
16218
- { regex: /\bin.\b(?!\w)/g, replacement: "inches" },
16219
- { regex: /\bft\b(?!\w)/g, replacement: "feet" },
16220
- { regex: /\bmi\b(?!\w)/g, replacement: "miles" },
16221
- { regex: /\bhr\b(?!\w)/g, replacement: "hour" },
16222
- { regex: /\bhourly\b(?!\w)/g, replacement: "per hour" },
16223
- { regex: /\bkg\b(?!\w)/g, replacement: "kilograms" },
16224
- { regex: /\bg\/kg\b(?!\w)/g, replacement: "grams per kilogram" },
16225
- { regex: /\bmb\b(?!\w)/g, replacement: "millibars" },
16226
- { regex: /\bhPa\b(?!\w)/g, replacement: "hectopascals" },
16227
- { regex: /\bPa\b(?!\w)/g, replacement: "pascals" },
16228
- { regex: /\bKPa\b(?!\w)/g, replacement: "kilopascals" },
16229
- { regex: /\bC\/hr\b(?!\w)/g, replacement: "degrees Celsius per hour" },
16230
- { regex: /\bF\/hr\b(?!\w)/g, replacement: "degrees Fahrenheit per hour" },
16231
- { regex: /\bC\/min\b(?!\w)/g, replacement: "degrees Celsius per minute" },
16232
- { regex: /\bF\/min\b(?!\w)/g, replacement: "degrees Fahrenheit per minute" },
16233
- { regex: /\bC\b(?!\w)/g, replacement: "degrees Celsius" },
16234
- { regex: /\bF\b(?!\w)/g, replacement: "degrees Fahrenheit" }
16235
- ];
16236
-
16237
- // src/@modules/@eas/eas.getWavPCM16.ts
16238
- var getWavPCM16 = (buffer) => {
16239
- if (buffer.toString("ascii", 0, 4) !== "RIFF" || buffer.toString("ascii", 8, 12) !== "WAVE") {
16240
- return null;
16241
- }
16242
- let fmt = null;
16243
- let data = null;
16244
- let i = 12;
16245
- while (i + 8 <= buffer.length) {
16246
- const id2 = buffer.toString("ascii", i, i + 4);
16247
- const size = buffer.readUInt32LE(i + 4);
16248
- const start = i + 8;
16249
- const end = start + size;
16250
- if (id2 === "fmt ") fmt = buffer.slice(start, end);
16251
- if (id2 === "data") data = buffer.slice(start, end);
16252
- i = end + size % 2;
16253
- }
16254
- if (!fmt || !data) return null;
16255
- const audioFormat = fmt.readUInt16LE(0);
16256
- const channels = fmt.readUInt16LE(2);
16257
- const sampleRate = fmt.readUInt32LE(4);
16258
- const bitsPerSample = fmt.readUInt16LE(14);
16259
- if (audioFormat !== 1 || bitsPerSample !== 16 || channels !== 1) {
16260
- return null;
16261
- }
16262
- const samples = new Int16Array(data.buffer, data.byteOffset, data.length / 2);
16263
- return { samples: new Int16Array(samples), sampleRate, channels, bitsPerSample };
16264
- };
16265
-
16266
- // src/@modules/@eas/eas.getSampledPCM16.ts
16267
- var getSampledPCM16 = (int16, originalRate, targetRate) => {
16268
- if (originalRate === targetRate) return int16;
16269
- const ratio = targetRate / originalRate;
16270
- const outLen = Math.max(1, Math.round(int16.length * ratio));
16271
- const out = new Int16Array(outLen);
16272
- for (let i = 0; i < outLen; i++) {
16273
- const pos = i / ratio;
16274
- const i0 = Math.floor(pos);
16275
- const i1 = Math.min(i0 + 1, int16.length - 1);
16276
- const frac = pos - i0;
16277
- const v = int16[i0] * (1 - frac) + int16[i1] * frac;
16278
- out[i] = Math.round(v);
16279
- }
16280
- return out;
16281
- };
16282
-
16283
- // src/@modules/@eas/eas.getPCMToFloat.ts
16284
- var getPCMToFloat = (int16) => {
16285
- const out = new Float32Array(int16.length);
16286
- for (let i = 0; i < int16.length; i++) out[i] = int16[i] / 32768;
16287
- return out;
16288
- };
16289
-
16290
- // src/@modules/@eas/eas.getFloatPCM16.ts
16291
- var getFloatPCM16 = (float32) => {
16292
- const out = new Int16Array(float32.length);
16293
- for (let i = 0; i < float32.length; i++) {
16294
- let v = Math.max(-1, Math.min(1, float32[i]));
16295
- out[i] = Math.round(v * 32767);
16296
- }
16297
- return out;
16298
- };
16299
-
16300
- // src/@modules/@eas/eas.setRadioEffect.ts
16301
- var setRadioEffect = (int16, sampleRate) => {
16302
- const hpCut = 3555;
16303
- const lpCut = 1600;
16304
- const x = getPCMToFloat(int16);
16305
- const dt = 1 / sampleRate;
16306
- const rcHP = 1 / (2 * Math.PI * hpCut);
16307
- const aHP = rcHP / (rcHP + dt);
16308
- let yHP = 0, xPrev = 0;
16309
- for (let i = 0; i < x.length; i++) {
16310
- const xi = x[i];
16311
- yHP = aHP * (yHP + xi - xPrev);
16312
- xPrev = xi;
16313
- x[i] = yHP;
16314
- }
16315
- const rcLP = 1 / (2 * Math.PI * lpCut);
16316
- const aLP = dt / (rcLP + dt);
16317
- let yLP = 0;
16318
- for (let i = 0; i < x.length; i++) {
16319
- yLP = yLP + aLP * (x[i] - yLP);
16320
- x[i] = yLP;
16321
- }
16322
- const compGain = 2;
16323
- const norm = Math.tanh(compGain);
16324
- for (let i = 0; i < x.length; i++) x[i] = Math.tanh(x[i] * compGain) / norm;
16325
- return getFloatPCM16(x);
16326
- };
16327
-
16328
- // src/@modules/@eas/eas.setAFSK.ts
16329
- var setAFSK = (bits, sampleRate) => {
16330
- const baud = 520.83;
16331
- const markFreq = 2083.3;
16332
- const spaceFreq = 1562.5;
16333
- const amplitude = 0.6;
16334
- const twoPi = Math.PI * 2;
16335
- const result = [];
16336
- let phase = 0;
16337
- let frac = 0;
16338
- for (let b = 0; b < bits.length; b++) {
16339
- const bit = bits[b];
16340
- const freq = bit ? markFreq : spaceFreq;
16341
- const samplesPerBit = sampleRate / baud + frac;
16342
- const n = Math.round(samplesPerBit);
16343
- frac = samplesPerBit - n;
16344
- const inc = twoPi * freq / sampleRate;
16345
- for (let i = 0; i < n; i++) {
16346
- result.push(Math.round(Math.sin(phase) * amplitude * 32767));
16347
- phase += inc;
16348
- if (phase > twoPi) phase -= twoPi;
16316
+ // src/@modules/@xmpp/xmpp.xStanza.ts
16317
+ var xStanza = () => {
16318
+ bootstrap.session_xmpp.on(`stanza`, (stanza) => __async(null, null, function* () {
16319
+ var _a, _b, _c, _d;
16320
+ const msgFrom = (_b = (_a = stanza == null ? void 0 : stanza.attrs) == null ? void 0 : _a.from) != null ? _b : ``;
16321
+ const msgType = (_d = (_c = stanza == null ? void 0 : stanza.attrs) == null ? void 0 : _c.type) != null ? _d : ``;
16322
+ setEventEmit({
16323
+ event: `onServiceStatus`,
16324
+ metadata: {
16325
+ message: stanza,
16326
+ from: msgFrom,
16327
+ type: `stanza`
16328
+ }
16329
+ });
16330
+ bootstrap.cache.lastStanza = Date.now();
16331
+ if (stanza.is(`message`)) {
16332
+ const result = validate({ stanza });
16333
+ const isSkippable = result.isIgnored || result.isCapEvent || result.isCapEvent && !result.isCapAreaDescription;
16334
+ if (isSkippable) {
16335
+ return;
16336
+ }
16337
+ yield createEvent(result);
16338
+ yield importStanza(result);
16349
16339
  }
16350
- }
16351
- const fadeSamples = Math.floor(sampleRate * 2e-3);
16352
- for (let i = 0; i < fadeSamples; i++) {
16353
- const gain = i / fadeSamples;
16354
- result[i] = Math.round(result[i] * gain);
16355
- result[result.length - 1 - i] = Math.round(result[result.length - 1 - i] * gain);
16356
- }
16357
- return Int16Array.from(result);
16340
+ if (stanza.is(`presence`) && msgFrom.startsWith("nwws@conference.nwws-oi.weather.gov/")) {
16341
+ const getOccupant = msgFrom.split(`/`).slice(1).join(`/`);
16342
+ const getAvailability = msgType === `unavailable`;
16343
+ setEventEmit({
16344
+ event: `onServiceStatus`,
16345
+ metadata: {
16346
+ message: `Occupant ${getOccupant} has ${getAvailability ? `left` : `joined`} the room`,
16347
+ data: {},
16348
+ type: `occupant`,
16349
+ error: false
16350
+ }
16351
+ });
16352
+ }
16353
+ }));
16358
16354
  };
16359
16355
 
16360
- // src/@modules/@eas/eas.setAsciiToBits.ts
16361
- var setAsciiToBits = (str) => {
16362
- const bits = [];
16363
- for (let i = 0; i < str.length; i++) {
16364
- const c = str.charCodeAt(i) & 255;
16365
- bits.push(0);
16366
- for (let b = 0; b < 8; b++) bits.push(c >> b & 1);
16367
- bits.push(1, 1);
16356
+ // src/@modules/@xmpp/xmpp.xDeploy.ts
16357
+ var xDeploy = () => __async(null, null, function* () {
16358
+ var _a, _b;
16359
+ let session;
16360
+ const settings = bootstrap.settings;
16361
+ (_b = (_a = settings.NOAAWeatherWireServiceSettings.CredentialSettings).Nickname) != null ? _b : _a.Nickname = settings.NOAAWeatherWireServiceSettings.CredentialSettings.Username;
16362
+ session = bootstrap.session_xmpp = client({
16363
+ service: "xmpp://nwws-oi.weather.gov",
16364
+ domain: "nwws-oi.weather.gov",
16365
+ username: settings.NOAAWeatherWireServiceSettings.CredentialSettings.Username,
16366
+ password: settings.NOAAWeatherWireServiceSettings.CredentialSettings.Password
16367
+ });
16368
+ try {
16369
+ yield xOffline();
16370
+ yield xError();
16371
+ yield xStanza();
16372
+ yield xOnline();
16373
+ yield session.start();
16374
+ } catch (error) {
16375
+ setEventEmit({
16376
+ event: `onServiceStatus`,
16377
+ metadata: {
16378
+ message: `Error occured while starting XMPP Session: ${error}`,
16379
+ data: {},
16380
+ type: `error`,
16381
+ error: true
16382
+ }
16383
+ });
16368
16384
  }
16369
- return bits;
16370
- };
16385
+ });
16371
16386
 
16372
- // src/@modules/@eas/eas.getMergedPCM16.ts
16373
- var getMergedPCM16 = (arrays) => {
16374
- let total = 0;
16375
- for (const a of arrays) total += a.length;
16376
- const out = new Int16Array(total);
16377
- let o = 0;
16378
- for (const a of arrays) {
16379
- out.set(a, o);
16380
- o += a.length;
16381
- }
16382
- return out;
16383
- };
16387
+ // src/@modules/@database/database.init.ts
16388
+ import fs2 from "fs";
16389
+ import sqlite3 from "better-sqlite3";
16384
16390
 
16385
- // src/@modules/@eas/eas.setSameHeader.ts
16386
- var setSameHeader = (vtec2, repeats, sampleRate = 8e3, options = {}) => {
16387
- var _a, _b;
16388
- const preMarkSec = (_a = options.preMarkSec) != null ? _a : 0.3;
16389
- const gapSec = (_b = options.gapSec) != null ? _b : 0.1;
16390
- const bursts = [];
16391
- const gap = new Int16Array(Math.floor(gapSec * sampleRate));
16392
- for (let i = 0; i < repeats; i++) {
16393
- const bodyBits = setAsciiToBits(vtec2);
16394
- const body = setAFSK(bodyBits, sampleRate);
16395
- const extendedBodyDuration = Math.round(preMarkSec * sampleRate);
16396
- const extendedBody = new Int16Array(extendedBodyDuration + gap.length);
16397
- for (let j2 = 0; j2 < extendedBodyDuration; j2++) {
16398
- extendedBody[j2] = Math.round(body[j2 % body.length] * 0.2);
16399
- }
16400
- extendedBody.set(gap, extendedBodyDuration);
16401
- bursts.push(extendedBody);
16402
- if (i !== repeats - 1) bursts.push(gap);
16403
- }
16404
- return getMergedPCM16(bursts);
16405
- };
16391
+ // src/@modules/@database/database.shapefiles.ts
16392
+ import fs from "fs";
16393
+ import { resolve as resolve5, extname } from "path";
16394
+ import { loadAsync } from "jszip";
16395
+ import { read } from "shapefile";
16406
16396
 
16407
- // src/@modules/@eas/eas.setAttentionTone.ts
16408
- var setAttentionTone = (ms, sampleRate) => {
16409
- const len = Math.floor(ms * sampleRate);
16410
- const out = new Int16Array(len);
16411
- const f1 = 853;
16412
- const f2 = 960;
16413
- const twoPi = Math.PI * 2;
16414
- const amp = 0.1;
16415
- const fadeLen = Math.floor(sampleRate * 0);
16416
- for (let i = 0; i < len; i++) {
16417
- const t = i / sampleRate;
16418
- const s = Math.sin(twoPi * f1 * t) + Math.sin(twoPi * f2 * t);
16419
- let gain = 1;
16420
- if (i < fadeLen) gain = i / fadeLen;
16421
- else if (i > len - fadeLen) gain = (len - i) / fadeLen;
16422
- const v = Math.max(-1, Math.min(1, s / 2 * amp * gain));
16423
- out[i] = Math.round(v * 32767);
16424
- }
16425
- return out;
16426
- };
16397
+ // src/@modules/@utilities/utilities.setSleep.ts
16398
+ var setSleep = (options) => __async(null, null, function* () {
16399
+ return new Promise((resolve6) => {
16400
+ setTimeout(() => {
16401
+ resolve6();
16402
+ }, options.timeout);
16403
+ });
16404
+ });
16427
16405
 
16428
- // src/@modules/@eas/eas.setNoise.ts
16429
- var setNoise = (int16, noiseLevel = 0.02) => {
16430
- const x = getPCMToFloat(int16);
16431
- for (let i = 0; i < x.length; i++) x[i] += (Math.random() * 2 - 1) * noiseLevel;
16432
- let peak = 0;
16433
- for (let i = 0; i < x.length; i++) peak = Math.max(peak, Math.abs(x[i]));
16434
- if (peak > 1) for (let i = 0; i < x.length; i++) x[i] *= 0.98 / peak;
16435
- return getFloatPCM16(x);
16436
- };
16406
+ // src/@dictionaries/dictionaries.shapefileLinks.ts
16407
+ var shapefileLinks = [
16408
+ { name: "us_counties", id: "C", link: "https://www.weather.gov/source/gis/Shapefiles/County/c_16ap26.zip" },
16409
+ { name: "us_states_territories", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/County/s_16ap26.zip" },
16410
+ { name: "fire_weather_zones", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/WSOM/fz16ap26.zip" },
16411
+ { name: "costal_marine_zones", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/WSOM/mz16ap26.zip" },
16412
+ { name: "offshore_marine_zones", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/WSOM/oz16ap26.zip" },
16413
+ { name: "public_forecast_zones", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/WSOM/z_16ap26.zip" },
16414
+ { name: "county_warning_areas", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/WSOM/w_16ap26.zip" },
16415
+ { name: "river_forecast_boundaries", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/Misc/rf05mr24.zip" },
16416
+ { name: "high_seas_marine_zones", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/WSOM/hz17fe26.zip" }
16417
+ ];
16437
16418
 
16438
- // src/@modules/@eas/eas.getPCM16.ts
16439
- var getPCM16 = (samples, sampleRate) => {
16440
- let o = 0;
16441
- const bytesPerSample = 2;
16442
- const blockAlign = 1 * bytesPerSample;
16443
- const byteRate = sampleRate * blockAlign;
16444
- const subchunk2Size = samples.length * bytesPerSample;
16445
- const chunkSize = 36 + subchunk2Size;
16446
- const buffer = Buffer.alloc(44 + subchunk2Size);
16447
- buffer.write("RIFF", o);
16448
- o += 4;
16449
- buffer.writeUInt32LE(chunkSize, o);
16450
- o += 4;
16451
- buffer.write("WAVE", o);
16452
- o += 4;
16453
- buffer.write("fmt ", o);
16454
- o += 4;
16455
- buffer.writeUInt32LE(16, o);
16456
- o += 4;
16457
- buffer.writeUInt16LE(1, o);
16458
- o += 2;
16459
- buffer.writeUInt16LE(1, o);
16460
- o += 2;
16461
- buffer.writeUInt32LE(sampleRate, o);
16462
- o += 4;
16463
- buffer.writeUInt32LE(byteRate, o);
16464
- o += 4;
16465
- buffer.writeUInt16LE(blockAlign, o);
16466
- o += 2;
16467
- buffer.writeUInt16LE(16, o);
16468
- o += 2;
16469
- buffer.write("data", o);
16470
- o += 4;
16471
- buffer.writeUInt32LE(subchunk2Size, o);
16472
- o += 4;
16473
- for (let i = 0; i < samples.length; i++, o += 2) {
16474
- buffer.writeInt16LE(samples[i].value, o);
16419
+ // src/@modules/@database/database.shapefiles.ts
16420
+ var importShapefiles = () => __async(null, null, function* () {
16421
+ var _a, _b;
16422
+ const settings = bootstrap.settings;
16423
+ try {
16424
+ const tShapefiles = bootstrap.database.prepare(`SELECT COUNT(*) AS count FROM shapefiles`).get().count;
16425
+ if (tShapefiles === 0) {
16426
+ yield setSleep({ timeout: 1e3 });
16427
+ setWarning({ message: `Shapefiles are currently building, please DO NOT close your terminal. The shapefiles will not finish and will remain incomplete. If you do mess up, you will need to delete ${settings.Database} and restart the application.` });
16428
+ for (const shapefile of shapefileLinks) {
16429
+ const response2 = yield fetch(shapefile.link);
16430
+ const arrayBuff = yield response2.arrayBuffer();
16431
+ const content = yield loadAsync(arrayBuff);
16432
+ const directory = resolve5(__dirname, `../../shapefiles`);
16433
+ if (!fs.existsSync(directory)) {
16434
+ fs.mkdirSync(directory, { recursive: true });
16435
+ }
16436
+ for (const file of Object.keys(content.files)) {
16437
+ if (file.endsWith(".shp") || file.endsWith(".dbf")) {
16438
+ const data = yield content.files[file].async(`nodebuffer`);
16439
+ const output = resolve5(directory, `${(_a = shapefile == null ? void 0 : shapefile.name) != null ? _a : ``}_${(_b = shapefile == null ? void 0 : shapefile.id) != null ? _b : ``}${extname(file)}`);
16440
+ fs.writeFileSync(output, data);
16441
+ }
16442
+ }
16443
+ const filepath = resolve5(__dirname, "../../shapefiles", shapefile.name + "_" + shapefile.id);
16444
+ const { features } = yield read(
16445
+ filepath,
16446
+ filepath
16447
+ );
16448
+ setWarning({ message: `Importing ${features.length} features from ${shapefile.name}_${shapefile.id}` });
16449
+ const insert = bootstrap.database.prepare(`INSERT OR REPLACE INTO shapefiles (id, location, geometry) VALUES (?, ?, ?)`);
16450
+ const transaction = bootstrap.database.transaction((entries) => {
16451
+ var _a2, _b2, _c;
16452
+ for (const entry of entries) {
16453
+ const { properties: properties2, geometry } = entry;
16454
+ let final2, location;
16455
+ if (properties2.FIPS) {
16456
+ final2 = `${properties2.STATE}${shapefile.id}${properties2.FIPS.substring(2)}`;
16457
+ location = `${properties2.COUNTYNAME}, ${properties2.STATE}`;
16458
+ } else if (properties2.FULLSTAID) {
16459
+ final2 = `${properties2.ST}${shapefile.id}${properties2.WFO}`;
16460
+ location = `${properties2.CITY}, ${properties2.STATE}`;
16461
+ } else if (properties2.STATE) {
16462
+ final2 = `${properties2.STATE}${shapefile.id}${(_a2 = properties2.ZONE) != null ? _a2 : properties2.SITE_ID}`;
16463
+ location = `${(_b2 = properties2.NAME) != null ? _b2 : `${properties2.RFC_NAME} ${properties2.RFC_CITY}`}, ${properties2.STATE}`;
16464
+ } else {
16465
+ final2 = (_c = properties2.ID) != null ? _c : properties2.WFO;
16466
+ location = properties2.NAME;
16467
+ }
16468
+ insert.run(final2, location, JSON.stringify(geometry));
16469
+ }
16470
+ });
16471
+ fs.unlinkSync(`${filepath}.shp`);
16472
+ fs.unlinkSync(`${filepath}.dbf`);
16473
+ setWarning({ message: `Cleaned up temporary files for ${shapefile.name}_${shapefile.id}` });
16474
+ transaction(features);
16475
+ }
16476
+ setWarning({ message: `Shapefiles have finished compiling, you can now continue and close this terminal` });
16477
+ fs.rm(resolve5(__dirname, "../../shapefiles"), { recursive: true, force: true }, () => {
16478
+ });
16479
+ }
16480
+ } catch (error) {
16481
+ setWarning({ message: `An error occurred while compiling shapefiles: ${error.message}` });
16475
16482
  }
16476
- return buffer;
16477
- };
16483
+ });
16478
16484
 
16479
- // src/@modules/@eas/eas.setEasTone.ts
16480
- import { join } from "path";
16481
- import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
16482
- import { execSync } from "child_process";
16483
- import { platform } from "os";
16484
- import say from "say";
16485
- var setEasTone = (options) => __async(null, null, function* () {
16485
+ // src/@modules/@database/database.init.ts
16486
+ var initializeDatabase = () => __async(null, null, function* () {
16486
16487
  const settings = bootstrap.settings;
16487
- const directory = settings.GlobalSettings.EASSettings.ArchiveDirectory;
16488
- const prefix = settings.GlobalSettings.EASSettings.IntroWavFile;
16489
- let message = options.message;
16490
- let header = options.header;
16491
- let buffTTS;
16492
- let buffRadio;
16493
- let buffFull = [];
16494
- const tmpTTS = join(directory, `/temp/${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, "")}.wav`);
16495
- const outTTS = join(directory, `/output/${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, "")}.wav`);
16496
- const vTTS = process.platform === `win32` ? `Microsoft David Desktop` : `en-US-GuyNerual`;
16497
- const vPlatform = platform();
16498
- if (!existsSync(directory)) {
16499
- mkdirSync(directory, { recursive: true });
16500
- }
16501
- if (!existsSync(join(directory, `/temp`))) {
16502
- mkdirSync(join(directory, `/temp`), { recursive: true });
16503
- }
16504
- if (!existsSync(join(directory, `/output`))) {
16505
- mkdirSync(join(directory, `/output`), { recursive: true });
16488
+ try {
16489
+ if (!fs2.existsSync(settings.Database)) {
16490
+ fs2.writeFileSync(settings.Database, "");
16491
+ setWarning({ message: `Creating new database at ${settings.Database}` });
16492
+ }
16493
+ bootstrap.database = new sqlite3(settings.Database);
16494
+ bootstrap.database.prepare(`CREATE TABLE IF NOT EXISTS stanzas ( id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT, issued TEXT, stanza TEXT )`).run();
16495
+ bootstrap.database.prepare(`CREATE TABLE IF NOT EXISTS shapefiles (id TEXT PRIMARY KEY, location TEXT, geometry TEXT)`).run();
16496
+ yield importShapefiles();
16497
+ } catch (error) {
16498
+ setWarning({ message: `An error occurred while initializing the database: ${error.message}` });
16506
16499
  }
16507
- for (const { regex, replacement } of transcribedMessageReplacements) {
16508
- message = message.replace(regex, replacement);
16500
+ });
16501
+
16502
+ // src/@modules/@database/database.cache.ts
16503
+ var getCachedEvents = () => __async(null, null, function* () {
16504
+ var _a;
16505
+ try {
16506
+ const settings = bootstrap.settings;
16507
+ const tick = performance.now();
16508
+ if (settings.NOAAWeatherWireServiceSettings.CacheSettings.Enabled) {
16509
+ const max = (_a = settings.NOAAWeatherWireServiceSettings.CacheSettings.MaxRetentionHistory) != null ? _a : 500;
16510
+ const get = yield bootstrap.database.prepare(`SELECT * FROM stanzas ORDER BY rowid DESC LIMIT ?`).all(max);
16511
+ setWarning({ message: `Fetched ${get.length} cached events from the database in ${Math.floor(performance.now() - tick)} ms` });
16512
+ let events = get.map((row) => JSON.parse(row.stanza)).filter((stanza) => {
16513
+ if (!stanza) {
16514
+ return;
16515
+ }
16516
+ const isSkippable = stanza.isIgnored || stanza.isCapEvent || stanza.isCapEvent && !stanza.isCapAreaDescription;
16517
+ return !isSkippable;
16518
+ });
16519
+ events = events.sort((a, b) => b.issued - a.issued);
16520
+ yield Promise.all(events.map((event) => createEvent(event)));
16521
+ setWarning({ message: `Processed ${events.length} cached events in ${Math.floor(performance.now() - tick)} ms` });
16522
+ }
16523
+ } catch (error) {
16524
+ setWarning({ message: `An error occurred while fetching cached events: ${error.message} -> ${error.stack}` });
16509
16525
  }
16510
- if (vPlatform != `win32`) {
16511
- setWarning({
16512
- title: `EAS`,
16513
- message: `Generation isn't supported with this OS. Please wait for further updates before trying again`
16514
- });
16515
- return null;
16526
+ });
16527
+
16528
+ // src/@modules/@xmpp/xmpp.xReconnect.ts
16529
+ var xReconnect = (interval) => __async(null, null, function* () {
16530
+ const settings = bootstrap.settings;
16531
+ const lastStanza = Date.now() - bootstrap.cache.lastStanza;
16532
+ if (interval < 15) {
16533
+ setWarning({ message: `Reconnection interval of ${interval} seconds is too low, setting to 15 seconds` });
16534
+ interval = 15;
16535
+ bootstrap.settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval = 15;
16516
16536
  }
16517
- say.export(message, vTTS, 1, tmpTTS);
16518
- while (!existsSync(tmpTTS) || (buffTTS = readFileSync(tmpTTS)).length == 0) {
16519
- yield setSleep({ timeout: 25 });
16537
+ const reconnectThreshold = interval * 1e3;
16538
+ if (!bootstrap.cache.isConnected && !bootstrap.cache.sigHault || !bootstrap.session_xmpp) {
16539
+ return;
16520
16540
  }
16521
- const vWav = getWavPCM16(buffTTS);
16522
- const vSamples = getSampledPCM16(vWav.samples, vWav.sampleRate, 8e3);
16523
- const vRadio = setRadioEffect(vSamples, 8e3);
16524
- if (existsSync(prefix)) {
16525
- let tBuffer = readFileSync(prefix);
16526
- let tWav = getWavPCM16(tBuffer);
16527
- if (tWav == null) {
16541
+ if (lastStanza > reconnectThreshold) {
16542
+ if (!bootstrap.cache.isReconnecting) {
16543
+ bootstrap.cache.isReconnecting = true;
16544
+ bootstrap.cache.isConnected = false;
16545
+ bootstrap.cache.tReconnects += 1;
16528
16546
  try {
16529
- const converted = join(directory, `/temp/${Math.random().toString(36).substring(2, 15)}.converted.wav`);
16530
- execSync(`ffmpeg -y -i "${prefix}" -ar 8000 -ac 1 -sample_fmt s16 "${converted}"`, { stdio: "ignore" });
16531
- if (existsSync(converted)) {
16532
- tBuffer = readFileSync(converted);
16533
- tWav = getWavPCM16(tBuffer);
16547
+ setEventEmit({
16548
+ event: `onServiceStatus`,
16549
+ metadata: {
16550
+ message: `Attempting to reconnect to XMPP Service (Reconnect Attempt ${bootstrap.cache.tReconnects})`,
16551
+ data: {
16552
+ last_stanza: lastStanza,
16553
+ nickname: settings.NOAAWeatherWireServiceSettings.CredentialSettings.Nickname
16554
+ },
16555
+ type: `reconnect`,
16556
+ error: true
16557
+ }
16558
+ });
16559
+ yield bootstrap.session_xmpp.stop().catch(() => {
16560
+ });
16561
+ yield bootstrap.session_xmpp.start().catch(() => {
16562
+ });
16563
+ } catch (error) {
16564
+ setWarning({ message: `XMPP Reconnect Failed - ${error.message}` });
16565
+ } finally {
16566
+ bootstrap.cache.isReconnecting = false;
16567
+ }
16568
+ }
16569
+ }
16570
+ });
16571
+
16572
+ // src/@modules/@utilities/utilities.setCronSchedule.ts
16573
+ import { readdirSync, unlinkSync as unlinkSync2, statSync, existsSync as existsSync2 } from "fs";
16574
+ import { join as join2 } from "path";
16575
+ var setCronSchedule = () => __async(null, null, function* () {
16576
+ const settings = bootstrap.settings;
16577
+ const TTL = settings.GlobalSettings.EASSettings.ArchiveTTL;
16578
+ const TTLCUT = Date.now() - TTL * 1e3;
16579
+ const walk = (dir) => {
16580
+ if (existsSync2(dir)) {
16581
+ const entries = readdirSync(dir, { withFileTypes: true });
16582
+ for (const entry of entries) {
16583
+ const fullPath = join2(dir, entry.name);
16584
+ if (entry.isDirectory()) {
16585
+ walk(fullPath);
16586
+ continue;
16587
+ }
16588
+ const stats = statSync(fullPath);
16589
+ if (stats.mtime.getTime() < TTLCUT) {
16534
16590
  try {
16535
- unlinkSync(converted);
16536
- } catch (e) {
16591
+ unlinkSync2(fullPath);
16592
+ } catch (err) {
16593
+ console.error(`Failed to delete ${fullPath}:`, err);
16537
16594
  }
16538
16595
  }
16539
- } catch (e) {
16540
16596
  }
16541
16597
  }
16542
- if (tWav == null) {
16543
- setWarning({ title: `EAS`, message: `Intro tone isn't a valid .WAV file or isn't in PCM 16-bit format. Converted attempt failed; please convert it then try again.` });
16544
- return null;
16598
+ };
16599
+ walk(settings.GlobalSettings.EASSettings.ArchiveDirectory);
16600
+ if (settings.EnableWireService) {
16601
+ if (settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.Enabled) {
16602
+ void xReconnect(settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval);
16545
16603
  }
16546
- const tSamples = tWav.sampleRate != 8e3 ? getSampledPCM16(tWav.samples, tWav.sampleRate, 8e3) : tWav.samples;
16547
- buffRadio = setRadioEffect(tSamples, 8e3);
16604
+ } else {
16605
+ const response2 = yield createHttp({
16606
+ url: settings.NationalWeatherServiceSettings.EventsEndpoint,
16607
+ headers: {
16608
+ "User-Agent": "@atmosx/event-product-parser"
16609
+ }
16610
+ });
16611
+ if (response2.error) {
16612
+ return setEventEmit({
16613
+ event: `onServiceStatus`,
16614
+ metadata: {
16615
+ type: "fetch-api",
16616
+ message: `Failed to fetch latest events from National Weather Service API - ${response2.message}`,
16617
+ data: {},
16618
+ error: true
16619
+ }
16620
+ });
16621
+ }
16622
+ setEventEmit({
16623
+ event: `onServiceStatus`,
16624
+ metadata: {
16625
+ message: `Fetched latest events from National Weather Service API`,
16626
+ data: {},
16627
+ type: "fetch-api",
16628
+ error: false
16629
+ }
16630
+ });
16631
+ createEvent({ message: response2.message, isNWWS: false });
16548
16632
  }
16549
- buffFull = buffRadio != null ? [buffRadio, new Int16Array(Math.floor(0.5 * 8e3))] : [];
16550
- buffFull.push(
16551
- setSameHeader(header, 3, 8e3, {
16552
- preMarkSec: 1.1,
16553
- gapSec: 0.5
16554
- }),
16555
- new Int16Array(Math.floor(0.5 * 8e3)),
16556
- setAttentionTone(8, 8e3),
16557
- new Int16Array(Math.floor(0.5 * 8e3)),
16558
- vRadio
16559
- );
16560
- for (let i = 0; i < 3; i++) {
16561
- buffFull.push(setSameHeader(header, 1, 8e3, { preMarkSec: 0.5, gapSec: 0.1 }));
16562
- buffFull.push(new Int16Array(Math.floor(0.5 * 8e3)));
16633
+ });
16634
+
16635
+ // src/@manager/manager.updateEvents.ts
16636
+ var updateEvents = (selectedEvent) => __async(null, null, function* () {
16637
+ const events = bootstrap.cache.events.features;
16638
+ function update(evt) {
16639
+ return __async(this, null, function* () {
16640
+ if (new Date(evt.properties.expires) < /* @__PURE__ */ new Date()) {
16641
+ rmEvent(evt);
16642
+ }
16643
+ });
16563
16644
  }
16564
- const aSamples = getMergedPCM16(buffFull);
16565
- const aFinal = setNoise(aSamples, 2e-3);
16566
- const aBuffer = getPCM16(Array.from(aFinal).map((v) => ({ value: v })), 8e3);
16567
- writeFileSync(outTTS, aBuffer);
16568
- try {
16569
- unlinkSync(tmpTTS);
16570
- } catch (e) {
16645
+ if (!selectedEvent) {
16646
+ yield Promise.all(events.map((evt) => __async(null, null, function* () {
16647
+ yield update(evt);
16648
+ })));
16649
+ }
16650
+ if (selectedEvent) {
16651
+ yield update(selectedEvent);
16652
+ }
16653
+ });
16654
+
16655
+ // src/@core/core.start.ts
16656
+ import { Cron } from "croner";
16657
+ var startService = (configurations) => __async(null, null, function* () {
16658
+ if (!bootstrap.isReady) {
16659
+ return setWarning({
16660
+ message: `You can not create another instance without shutting down the current one first, please make sure to call the stop() method first!`
16661
+ });
16662
+ }
16663
+ const settings = setSettings(configurations);
16664
+ bootstrap.isReady = true;
16665
+ yield initializeDatabase();
16666
+ if (settings.EnableWireService) {
16667
+ (() => __async(null, null, function* () {
16668
+ yield getCachedEvents();
16669
+ yield xDeploy();
16670
+ }))();
16671
+ }
16672
+ yield setCronSchedule();
16673
+ let scheduleInterval = !settings.EnableWireService ? settings.NationalWeatherServiceSettings.CallbackInterval : 1;
16674
+ if (!settings.EnableWireService && scheduleInterval < 15) {
16675
+ setWarning({ message: `Schedule interval of ${scheduleInterval} seconds is too low, setting to 15 seconds` });
16676
+ bootstrap.settings.NationalWeatherServiceSettings.CallbackInterval = 15;
16677
+ scheduleInterval = 15;
16678
+ }
16679
+ bootstrap.cron = new Cron(`*/${scheduleInterval} * * * * *`, () => __async(null, null, function* () {
16680
+ yield setCronSchedule();
16681
+ }));
16682
+ bootstrap.cron = new Cron(`* * * * * *`, () => __async(null, null, function* () {
16683
+ yield updateNode();
16684
+ yield updateEvents();
16685
+ }));
16686
+ });
16687
+
16688
+ // src/@core/core.stop.ts
16689
+ var stopService = () => __async(null, null, function* () {
16690
+ if (bootstrap.isReady) {
16691
+ bootstrap.isReady = false;
16692
+ if (bootstrap.session_xmpp) {
16693
+ try {
16694
+ yield bootstrap.session_xmpp.stop();
16695
+ } catch (e) {
16696
+ }
16697
+ bootstrap.cache.isConnected = false;
16698
+ bootstrap.cache.sigHault = true;
16699
+ bootstrap.session_xmpp = null;
16700
+ }
16571
16701
  }
16572
- return outTTS;
16573
16702
  });
16574
16703
 
16575
16704
  // src/@core/core.setNode.ts