@atmosx/event-product-parser 3.0.48 → 3.0.52

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 (141) hide show
  1. package/.vscode/settings.json +3 -3
  2. package/CODE_OF_CONDUCT.md +9 -9
  3. package/CONTRIBUTING.md +29 -29
  4. package/LICENSE +17 -17
  5. package/README.md +443 -417
  6. package/SECURITY.md +20 -20
  7. package/SUPPORTED_EVENTS.md +369 -368
  8. package/dist/cjs/index.cjs +1925 -1885
  9. package/dist/esm/index.mjs +1927 -1887
  10. package/package.json +52 -52
  11. package/src/@building/building.attachments.ts +82 -82
  12. package/src/@building/building.clean.ts +29 -29
  13. package/src/@building/building.create.ts +55 -41
  14. package/src/@building/building.enhance.ts +59 -59
  15. package/src/@building/building.geometry.ts +47 -47
  16. package/src/@building/building.headers.ts +36 -36
  17. package/src/@building/building.office.ts +42 -42
  18. package/src/@building/building.polygon.ts +69 -70
  19. package/src/@building/building.properties.ts +95 -95
  20. package/src/@building/building.signature.ts +60 -61
  21. package/src/@building/building.tags.ts +23 -23
  22. package/src/@building/building.tracking.ts +67 -67
  23. package/src/@building/building.validate.ts +152 -146
  24. package/src/@core/core.clearEvents.ts +30 -31
  25. package/src/@core/core.createListener.ts +23 -23
  26. package/src/@core/core.getEvents.ts +23 -24
  27. package/src/@core/core.getNodes.ts +23 -24
  28. package/src/@core/core.getRandomEvent.ts +23 -24
  29. package/src/@core/core.getVersion.ts +23 -24
  30. package/src/@core/core.manualEvent.ts +38 -0
  31. package/src/@core/core.query.ts +38 -38
  32. package/src/@core/core.setNode.ts +80 -80
  33. package/src/@core/core.start.ts +60 -60
  34. package/src/@core/core.stop.ts +31 -31
  35. package/src/@dictionaries/dictionaries.actions.ts +27 -27
  36. package/src/@dictionaries/dictionaries.awips.ts +363 -363
  37. package/src/@dictionaries/dictionaries.cancellation.ts +30 -30
  38. package/src/@dictionaries/dictionaries.causes.ts +35 -35
  39. package/src/@dictionaries/dictionaries.correlations.ts +42 -42
  40. package/src/@dictionaries/dictionaries.enhanced.ts +66 -109
  41. package/src/@dictionaries/dictionaries.events.ts +82 -82
  42. package/src/@dictionaries/dictionaries.expressions.ts +28 -28
  43. package/src/@dictionaries/dictionaries.global.ts +24 -0
  44. package/src/@dictionaries/dictionaries.hail.ts +35 -35
  45. package/src/@dictionaries/dictionaries.icao.ts +258 -258
  46. package/src/@dictionaries/dictionaries.matches.ts +54 -35
  47. package/src/@dictionaries/dictionaries.products.ts +24 -24
  48. package/src/@dictionaries/dictionaries.records.ts +25 -25
  49. package/src/@dictionaries/dictionaries.severity.ts +27 -27
  50. package/src/@dictionaries/dictionaries.shapefiles.ts +35 -35
  51. package/src/@dictionaries/dictionaries.states.ts +71 -71
  52. package/src/@dictionaries/dictionaries.status.ts +30 -30
  53. package/src/@dictionaries/dictionaries.tags.ts +92 -92
  54. package/src/@dictionaries/dictionaries.testing.ts +24 -24
  55. package/src/@events/events.api.ts +116 -118
  56. package/src/@events/events.text.ts +84 -81
  57. package/src/@events/events.ugc.ts +89 -85
  58. package/src/@events/events.vtec.ts +86 -87
  59. package/src/@manager/manager.mkEvent.ts +97 -88
  60. package/src/@manager/manager.rmEvent.ts +56 -49
  61. package/src/@manager/manager.setHash.ts +35 -36
  62. package/src/@manager/manager.updateEvents.ts +32 -34
  63. package/src/@manager/manager.updateListener.ts +154 -159
  64. package/src/@manager/manager.updateNodes.ts +53 -54
  65. package/src/@modules/@database/database.broadcastify.ts +66 -66
  66. package/src/@modules/@database/database.cache.ts +49 -47
  67. package/src/@modules/@database/database.init.ts +58 -57
  68. package/src/@modules/@database/database.shapefiles.ts +92 -92
  69. package/src/@modules/@database/database.stanza.ts +46 -47
  70. package/src/@modules/@eas/eas.getCleanDescription.ts +91 -91
  71. package/src/@modules/@eas/eas.getFloatPCM16.ts +29 -29
  72. package/src/@modules/@eas/eas.getMergedPCM16.ts +32 -32
  73. package/src/@modules/@eas/eas.getPCM16.ts +52 -52
  74. package/src/@modules/@eas/eas.getPCMToFloat.ts +26 -26
  75. package/src/@modules/@eas/eas.getSampledPCM16.ts +36 -36
  76. package/src/@modules/@eas/eas.getTTS.ts +54 -54
  77. package/src/@modules/@eas/eas.getWavPCM16.ts +52 -52
  78. package/src/@modules/@eas/eas.setAFSK.ts +51 -52
  79. package/src/@modules/@eas/eas.setAsciiToBits.ts +31 -32
  80. package/src/@modules/@eas/eas.setAttentionTone.ts +40 -40
  81. package/src/@modules/@eas/eas.setEasTone.ts +151 -147
  82. package/src/@modules/@eas/eas.setNoise.ts +32 -31
  83. package/src/@modules/@eas/eas.setRadioEffect.ts +50 -49
  84. package/src/@modules/@eas/eas.setSameHeader.ts +44 -45
  85. package/src/@modules/@stanza/stanza.getAwipsType.ts +45 -45
  86. package/src/@modules/@stanza/stanza.validate.ts +49 -49
  87. package/src/@modules/@utilities/utilities.createHttp.ts +70 -70
  88. package/src/@modules/@utilities/utilities.getFormattedTime.ts +43 -43
  89. package/src/@modules/@utilities/utilities.getLatestIssuance.ts +32 -32
  90. package/src/@modules/@utilities/utilities.getMatched.ts +33 -0
  91. package/src/@modules/@utilities/utilities.getSettings.ts +25 -25
  92. package/src/@modules/@utilities/utilities.getShapeNearestPoint.ts +114 -114
  93. package/src/@modules/@utilities/utilities.setCronSchedule.ts +94 -94
  94. package/src/@modules/@utilities/utilities.setDebug.ts +38 -0
  95. package/src/@modules/@utilities/utilities.setEventEmit.ts +41 -41
  96. package/src/@modules/@utilities/utilities.setListener.ts +30 -30
  97. package/src/@modules/@utilities/utilities.setSettings.ts +42 -42
  98. package/src/@modules/@utilities/utilities.setSleep.ts +33 -33
  99. package/src/@modules/@utilities/utilities.setTimeoutAction.ts +62 -58
  100. package/src/@modules/@utilities/utilities.setWarning.ts +34 -34
  101. package/src/@modules/@xmpp/xmpp.xDeploy.ts +57 -58
  102. package/src/@modules/@xmpp/xmpp.xError.ts +26 -28
  103. package/src/@modules/@xmpp/xmpp.xOffline.ts +36 -37
  104. package/src/@modules/@xmpp/xmpp.xOnline.ts +45 -44
  105. package/src/@modules/@xmpp/xmpp.xReconnect.ts +64 -64
  106. package/src/@modules/@xmpp/xmpp.xStanza.ts +62 -62
  107. package/src/@parsers/@hvtec/hvtec.extract.ts +39 -39
  108. package/src/@parsers/@pvtec/pvtec.expires.ts +25 -25
  109. package/src/@parsers/@pvtec/pvtec.extract.ts +48 -48
  110. package/src/@parsers/@text/text.getDescriptionFromProduct.ts +52 -52
  111. package/src/@parsers/@text/text.getEmbed.ts +55 -57
  112. package/src/@parsers/@text/text.getPolygonFromProduct.ts +53 -32
  113. package/src/@parsers/@text/text.getTextFromProduct.ts +42 -42
  114. package/src/@parsers/@text/text.getXML.ts +60 -60
  115. package/src/@parsers/@ugc/ugc.coordinates.ts +110 -109
  116. package/src/@parsers/@ugc/ugc.expiry.ts +31 -31
  117. package/src/@parsers/@ugc/ugc.extract.ts +36 -36
  118. package/src/@parsers/@ugc/ugc.getCache.ts +24 -0
  119. package/src/@parsers/@ugc/ugc.header.ts +29 -29
  120. package/src/@parsers/@ugc/ugc.locations.ts +57 -29
  121. package/src/@parsers/@ugc/ugc.setCache.ts +28 -0
  122. package/src/@parsers/@ugc/ugc.zones.ts +51 -51
  123. package/src/@types/type.attributes.ts +28 -28
  124. package/src/@types/type.compiled.ts +34 -34
  125. package/src/@types/type.event.ts +69 -69
  126. package/src/@types/type.hash.ts +24 -24
  127. package/src/@types/type.hvtec.ts +25 -25
  128. package/src/@types/type.listener.ts +32 -32
  129. package/src/@types/type.properties.ts +77 -77
  130. package/src/@types/type.pvtec.ts +30 -30
  131. package/src/@types/type.settings.ts +84 -83
  132. package/src/@types/type.stanza.ts +37 -37
  133. package/src/@types/type.ugc.ts +24 -24
  134. package/src/bootstrap.ts +115 -112
  135. package/src/index.ts +74 -74
  136. package/test.js +92 -98
  137. package/tsconfig.json +13 -13
  138. package/tsup.config.ts +15 -15
  139. package/dist/index.d.mts +0 -299
  140. package/dist/index.d.ts +0 -299
  141. package/src/@core/core.createEvent.ts +0 -83
@@ -1104,7 +1104,7 @@ var require_main3 = __commonJS({
1104
1104
  import path from "path";
1105
1105
  import { EventEmitter } from "events";
1106
1106
  var bootstrap = {
1107
- version: `3.0.48`,
1107
+ version: `3.0.52`,
1108
1108
  isReady: true,
1109
1109
  ratelimits: {},
1110
1110
  session_xmpp: null,
@@ -1129,11 +1129,14 @@ var bootstrap = {
1129
1129
  sigHault: false,
1130
1130
  events: { type: "FeatureCollection", features: [] },
1131
1131
  nodes: { type: "FeatureCollection", features: [] },
1132
- hashes: []
1132
+ hashes: [],
1133
+ processed: [],
1134
+ ugc: /* @__PURE__ */ new Map()
1133
1135
  },
1134
1136
  settings: {
1135
1137
  Database: path.join(process.cwd(), "shapefiles.db"),
1136
- EnableWireService: true,
1138
+ EnableWireService: false,
1139
+ EnableDebugging: false,
1137
1140
  EnableJournal: true,
1138
1141
  NOAAWeatherWireServiceSettings: {
1139
1142
  ReconnectionSettings: {
@@ -1170,7 +1173,7 @@ var bootstrap = {
1170
1173
  EventManagement: true,
1171
1174
  BetterEventNames: true,
1172
1175
  DisableGeometryParsing: false,
1173
- UseShapefileCoordinates: false,
1176
+ UseShapefileCoordinates: true,
1174
1177
  SPCWatchesOnly: true,
1175
1178
  ShapefileSkipPoints: 15,
1176
1179
  NodeTTL: 60,
@@ -1302,7 +1305,7 @@ var getZonePolygon = (options) => {
1302
1305
  };
1303
1306
 
1304
1307
  // src/@building/building.geometry.ts
1305
- var getEventGeometry = (event) => __async(null, null, function* () {
1308
+ var getEventGeometry = (event) => {
1306
1309
  var _a, _b, _c, _d, _e, _f;
1307
1310
  const settings = getSettings();
1308
1311
  const generated = (_c = (_b = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.geocode) == null ? void 0 : _b.polygon) != null ? _c : null;
@@ -1312,7 +1315,7 @@ var getEventGeometry = (event) => __async(null, null, function* () {
1312
1315
  coordinates: generated != null ? JSON.parse(Buffer.from(generated, "base64").toString("utf-8")) : null
1313
1316
  };
1314
1317
  if (settings.GlobalSettings.UseShapefileCoordinates && generated == null && ugc2 != null) {
1315
- geo = yield getZonePolygon({ zones: ugc2, isUnion: false });
1318
+ geo = getZonePolygon({ zones: ugc2, isUnion: false });
1316
1319
  if (geo == null) {
1317
1320
  geo = {
1318
1321
  type: `Polygon`,
@@ -1321,7 +1324,7 @@ var getEventGeometry = (event) => __async(null, null, function* () {
1321
1324
  }
1322
1325
  }
1323
1326
  return geo;
1324
- });
1327
+ };
1325
1328
 
1326
1329
  // src/@building/building.clean.ts
1327
1330
  var getCleanedEvent = (event) => {
@@ -1344,6 +1347,9 @@ var setTimeoutAction = (options) => {
1344
1347
  bootstrap.ratelimits[options == null ? void 0 : options.identifier] = [];
1345
1348
  target = bootstrap.ratelimits[options == null ? void 0 : options.identifier];
1346
1349
  }
1350
+ if (options == null ? void 0 : options.expire) {
1351
+ delete bootstrap.ratelimits[options == null ? void 0 : options.identifier];
1352
+ }
1347
1353
  if ((target == null ? void 0 : target.length) > 0) {
1348
1354
  bootstrap.ratelimits[options == null ? void 0 : options.identifier] = target.filter((ts) => Date.now() - ts < (options == null ? void 0 : options.interval) * 1e3);
1349
1355
  target = bootstrap.ratelimits[options == null ? void 0 : options.identifier];
@@ -4174,7 +4180,8 @@ var xOnline = () => {
4174
4180
  data: {},
4175
4181
  type: `online`,
4176
4182
  error: false
4177
- }
4183
+ },
4184
+ message: `Succesfully connected to NOAA Weather Wire Service as "${nickname}"`
4178
4185
  });
4179
4186
  }));
4180
4187
  };
@@ -4496,9 +4503,9 @@ var dict_awips = {
4496
4503
  SVR: `severe-thunderstorm-warning`,
4497
4504
  SVS: `severe-weather-statement`,
4498
4505
  SWOMCD: `mesoscale-discussion`,
4499
- SWODY1: `day-1`,
4500
- SWODY2: `day-2`,
4501
- SWODY3: `day-3`,
4506
+ SWODY1: `SPC-day-1-outlook`,
4507
+ SWODY2: `SPC-day-2-outlook`,
4508
+ SWODY3: `SPC-day-3-outlook`,
4502
4509
  SWS: `state-weather-summary`,
4503
4510
  SYN: `regional-weather-synopsis`,
4504
4511
  TAF: `terminal-aerodrome-forecast`,
@@ -4518,7 +4525,7 @@ var dict_awips = {
4518
4525
  TOE: `telephone-outage-emergency`,
4519
4526
  TOR: `tornado-warning`,
4520
4527
  TPT: `temperature-precipitation-table`,
4521
- TSU: `tsunami-watch`,
4528
+ TSU: `tsunami-information-statement`,
4522
4529
  TUV: `ultraviolet-index`,
4523
4530
  TVL: `travelers-forecast`,
4524
4531
  TWB: `transcribed-weather-broadcast`,
@@ -4612,6 +4619,43 @@ var validate = (options) => {
4612
4619
  return { isIgnored: true };
4613
4620
  };
4614
4621
 
4622
+ // src/@dictionaries/dictionaries.matches.ts
4623
+ var dict_matches = {
4624
+ SPS: [
4625
+ { match: /STRONG THUNDERSTORM/i, label: "Convective Special Weather Statement", statement: false },
4626
+ { match: /SPECIAL WEATHER STATEMENT/i, label: "Special Weather Statement", statement: false }
4627
+ ],
4628
+ TSU: [
4629
+ { match: /TSUNAMI WARNING/i, label: "Tsunami Warning", statement: false },
4630
+ { match: /TSUNAMI WATCH/i, label: "Tsunami Watch", statement: false },
4631
+ { match: /TSUNAMI ADVISORY/i, label: "Tsunami Advisory", statement: false },
4632
+ { match: /TSUNAMI INFORMATION STATEMENT/i, label: "Tsunami Information Statement", statement: false },
4633
+ { match: /TSUNAMI WARNING CANCELLATION/i, label: "Tsunami Cancellation", statement: false }
4634
+ ],
4635
+ TCP: [
4636
+ { match: /HURRICANE WARNING/i, label: "Hurricane Warning", statement: false },
4637
+ { match: /HURRICANE WATCH/i, label: "Hurricane Watch", statement: false },
4638
+ { match: /TROPICAL STORM WARNING/i, label: "Tropical Storm Warning", statement: false },
4639
+ { match: /TROPICAL STORM WATCH/i, label: "Tropical Storm Watch", statement: false },
4640
+ { match: /STORM SURGE WARNING/i, label: "Storm Surge Warning", statement: false },
4641
+ { match: /STORM SURGE WATCH/i, label: "Storm Surge Watch", statement: false }
4642
+ ],
4643
+ MWW: [
4644
+ { match: /SMALL CRAFT ADVISORY/i, label: "Small Craft Advisory", statement: false },
4645
+ { match: /GALE WARNING/i, label: "Gale Warning", statement: false },
4646
+ { match: /STORM WARNING/i, label: "Storm Warning", statement: false },
4647
+ { match: /HURRICANE FORCE WIND WARNING/i, label: "Hurricane Force Wind Warning", statement: false },
4648
+ { match: /HAZARDOUS SEAS WARNING/i, label: "Hazardous Seas Warning", statement: false },
4649
+ { match: /DENSE FOG ADVISORY/i, label: "Dense Fog Advisory", statement: false },
4650
+ { match: /THUNDERSTORMS/i, label: "Convective Marine Weather Statement", statement: false },
4651
+ { match: /MARINE WEATHER STATEMENT/i, label: "Marine Weather Statement", statement: false }
4652
+ ],
4653
+ PNS: [
4654
+ { match: /NOAA WEATHER WIRE SERVICE/i, label: "NOAA Weather Wire Service Report", statement: true },
4655
+ { match: /Public Information Statement/i, label: "Public Information Statement", statement: true }
4656
+ ]
4657
+ };
4658
+
4615
4659
  // src/@parsers/@text/text.getDescriptionFromProduct.ts
4616
4660
  var getDescriptionFromProduct = (options) => {
4617
4661
  let message = options.message;
@@ -4644,18 +4688,32 @@ var getDescriptionFromProduct = (options) => {
4644
4688
  // src/@parsers/@text/text.getPolygonFromProduct.ts
4645
4689
  var getPolygonFromProduct = (message) => {
4646
4690
  const coordinates = [];
4647
- const match = message.match(/LAT\.{3}LON\s+([\d\s]+)/i);
4648
- if (!match || !match[1]) return coordinates;
4649
- const coordStrings = match[1].replace(/\n/g, " ").trim().split(/\s+/);
4650
- for (let i = 0; i < coordStrings.length - 1; i += 2) {
4651
- const lat = parseFloat(coordStrings[i]) / 100;
4652
- const lon = -parseFloat(coordStrings[i + 1]) / 100;
4653
- if (!isNaN(lat) && !isNaN(lon)) {
4654
- coordinates.push([lon, lat]);
4691
+ const match = message.match(
4692
+ /LAT\.\.\.LON\s+([\s\S]*?)(?=\n[A-Z]{2,}(?:\.\.\.|:)|\$\$|&&|$)/i
4693
+ );
4694
+ if (!match) return coordinates;
4695
+ const text2 = match[1];
4696
+ const values = text2.match(/\d{4,8}/g);
4697
+ if (!values) return coordinates;
4698
+ if (values.every((v) => v.length === 8)) {
4699
+ for (const value of values) {
4700
+ const lat = parseInt(value.slice(0, 4), 10) / 100;
4701
+ const lon = -parseInt(value.slice(4, 8), 10) / 100;
4702
+ if (Number.isFinite(lat) && Number.isFinite(lon)) {
4703
+ coordinates.push([lon, lat]);
4704
+ }
4705
+ }
4706
+ } else {
4707
+ for (let i = 0; i + 1 < values.length; i += 2) {
4708
+ const lat = parseInt(values[i], 10) / 100;
4709
+ const lon = -parseInt(values[i + 1], 10) / 100;
4710
+ if (Number.isFinite(lat) && Number.isFinite(lon)) {
4711
+ coordinates.push([lon, lat]);
4712
+ }
4655
4713
  }
4656
4714
  }
4657
4715
  if (coordinates.length > 2) {
4658
- coordinates.push(coordinates[0]);
4716
+ coordinates.push([...coordinates[0]]);
4659
4717
  }
4660
4718
  return coordinates;
4661
4719
  };
@@ -5081,25 +5139,6 @@ var getEventHeader = (options) => {
5081
5139
  return `ZCZC-ATMOSX-${options.getType.prefix}-${ugc2}-${(_b = vtec2 == null ? void 0 : vtec2.status) != null ? _b : `Issued`}-${(/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").split(".")[0]}-${(_c = properties2.geocode.office.office) != null ? _c : `KWNS`}`;
5082
5140
  };
5083
5141
 
5084
- // src/@dictionaries/dictionaries.matches.ts
5085
- var dict_matches = {
5086
- "Special Weather Statement": "Special Weather Statement",
5087
- "Hurricane Warning": "Hurricane Warning",
5088
- "Hurricane Force Wind Warning": "Hurricane Force Wind Warning",
5089
- "Hurricane Watch": "Hurricane Watch",
5090
- "Tropical Storm Warning": "Tropical Storm Warning",
5091
- "Tropical Storm Watch": "Tropical Storm Watch",
5092
- "High Wind Warning": "High Wind Warning",
5093
- "Gale Warning": "Gale Warning",
5094
- "Small Craft Advisory": "Small Craft Advisory",
5095
- "Small Craft Warning": "Small Craft Warning",
5096
- "Tsunami Warning": "Tsunami Warning",
5097
- "Tsunami Watch": "Tsunami Watch",
5098
- "Tsunami Advisory": "Tsunami Advisory",
5099
- "Tsunami Information Statement": "Tsunami Information Statement",
5100
- "Subscribers:": "National Weather Service Policy"
5101
- };
5102
-
5103
5142
  // src/@building/building.tracking.ts
5104
5143
  var getEventTracking = (options) => {
5105
5144
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
@@ -5124,1920 +5163,1967 @@ var getEventTracking = (options) => {
5124
5163
  return `${splitPVTEC[2]}.${splitPVTEC[3]}.${splitPVTEC[4]}.${splitPVTEC[5]}`;
5125
5164
  }
5126
5165
  const wmoMatch = (_e = (_d = options.organization) == null ? void 0 : _d.wmoidentifier) == null ? void 0 : _e.match(/([A-Z]{4}\d{2})\s+([A-Z]{4})/);
5127
- const station = (_f = wmoMatch == null ? void 0 : wmoMatch[2]) != null ? _f : "N/A";
5166
+ const station = (_f = wmoMatch == null ? void 0 : wmoMatch[2]) != null ? _f : "---";
5128
5167
  if (options.organization.featureId) {
5129
5168
  const idMatch = options.organization.featureId.match(/([a-f0-9]+)\.(\d+)\.(\d+)$/);
5130
- return `${station}.${(_h = (_g = idMatch == null ? void 0 : idMatch[0]) == null ? void 0 : _g.replace(/\./g, "")) != null ? _h : "N/A"}`;
5169
+ return `${station}.${(_h = (_g = idMatch == null ? void 0 : idMatch[0]) == null ? void 0 : _g.replace(/\./g, "")) != null ? _h : "---"}`;
5131
5170
  }
5132
- const id2 = (_i = wmoMatch == null ? void 0 : wmoMatch[1]) != null ? _i : "N/A";
5133
- return `${station}.${(_j = id2 == null ? void 0 : id2.replace(/\./g, "")) != null ? _j : "N/A"}`;
5171
+ const id2 = (_i = wmoMatch == null ? void 0 : wmoMatch[1]) != null ? _i : "---";
5172
+ return `${station}.${(_j = id2 == null ? void 0 : id2.replace(/\./g, "")) != null ? _j : "---"}`;
5134
5173
  }
5135
5174
  };
5136
5175
 
5137
- // src/@building/building.validate.ts
5138
- import { createHash } from "crypto";
5176
+ // src/@modules/@utilities/utilities.setDebug.ts
5177
+ var setDebug = (options) => {
5178
+ var _a, _b, _c, _d;
5179
+ const settings = bootstrap.settings;
5180
+ bootstrap.listener.emit(`debug`, {
5181
+ message: options.message,
5182
+ parent: (_b = (_a = options == null ? void 0 : options.title) == null ? void 0 : _a.split(`.`)[0]) == null ? void 0 : _b.replace(`@`, ``),
5183
+ function: (_c = options == null ? void 0 : options.title) == null ? void 0 : _c.split(`.`)[1]
5184
+ });
5185
+ if (settings.EnableDebugging) {
5186
+ console.log(`[${bootstrap.ansi_colors.BLUE}${(_d = options.title) != null ? _d : `debug`}${bootstrap.ansi_colors.RESET}] ${options.message}`);
5187
+ }
5188
+ };
5139
5189
 
5140
- // src/@dictionaries/dictionaries.enhanced.ts
5141
- var dict_enhanced = {
5142
- "Tornado Warning": {
5143
- "Tornado Emergency": {
5144
- description: "tornado emergency"
5145
- },
5146
- "PDS Tornado Warning": {
5147
- description: "particularly dangerous situation",
5148
- damage: `CONSIDERABLE`
5149
- },
5150
- "Radar Confirmed Tornado Warning": {
5151
- description: "source...radar confirmed tornado.",
5152
- tornado: `OBSERVED`
5153
- },
5154
- "Confirmed Tornado Warning": {
5155
- tornado: `OBSERVED`
5156
- },
5157
- "Radar Indicated Tornado Warning": {}
5158
- },
5159
- "Fire Weather Warning": {
5160
- "PDS Fire Weather Warning": {
5161
- description: "particularly dangerous situation"
5162
- }
5163
- },
5164
- "Blizzard Warning": {
5165
- "PDS Blizzard Warning": {
5166
- description: "particularly dangerous situation"
5167
- }
5168
- },
5169
- "Ice Storm Warning": {
5170
- "PDS Ice Storm Warning": {
5171
- description: "particularly dangerous situation"
5172
- }
5173
- },
5174
- "Special Marine Warning": {
5175
- "Special Marine Warning (TPROB)": {
5176
- tornado: `POSSIBLE`
5177
- }
5178
- },
5179
- "Tornado Watch": {
5180
- "PDS Tornado Watch": {
5181
- pdswatch: true
5182
- }
5183
- },
5184
- "Severe Thunderstorm Watch": {
5185
- "PDS Severe Thunderstorm Watch": {
5186
- pdswatch: true
5187
- }
5188
- },
5189
- "Flash Flood Warning": {
5190
- "Flash Flood Emergency": {
5191
- description: "flash flood emergency"
5192
- },
5193
- "Considerable Flash Flood Warning": {
5194
- damage: `CONSIDERABLE`
5195
- }
5196
- },
5197
- "Severe Thunderstorm Warning": {
5198
- "EDS Severe Thunderstorm Warning (TPROB)": {
5199
- description: "extremely dangerous situation",
5200
- tornado: "POSSIBLE"
5201
- },
5202
- "EDS Severe Thunderstorm Warning": {
5203
- description: "extremely dangerous situation"
5204
- },
5205
- "Destructive Severe Thunderstorm Warning (TPROB)": {
5206
- damage: `DESTRUCTIVE`,
5207
- tornado: `POSSIBLE`
5208
- },
5209
- "Destructive Severe Thunderstorm Warning": {
5210
- damage: `DESTRUCTIVE`
5211
- },
5212
- "Considerable Severe Thunderstorm Warning (TPROB)": {
5213
- damage: `CONSIDERABLE`,
5214
- tornado: `POSSIBLE`
5215
- },
5216
- "Considerable Severe Thunderstorm Warning": {
5217
- damage: `CONSIDERABLE`
5218
- },
5219
- "Severe Thunderstorm Warning (TPROB)": {
5220
- tornado: `POSSIBLE`
5190
+ // src/@events/events.text.ts
5191
+ var text = (stanza) => __async(null, null, function* () {
5192
+ var _a, _b, _c, _d, _e;
5193
+ 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 !== "$$");
5194
+ if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
5195
+ for (const message of getMessages) {
5196
+ const tick = performance.now();
5197
+ const attributes = stanza == null ? void 0 : stanza.attributes;
5198
+ const props = properties({ message, attributes });
5199
+ const header = getEventHeader({ properties: props, getType: stanza.getType });
5200
+ const issued = new Date(attributes.issue);
5201
+ const expires = new Date(issued.getTime() + 12 * 60 * 60 * 1e3);
5202
+ const matches = (_d = dict_matches[stanza.getType.prefix]) == null ? void 0 : _d.find((match) => match.match.test(message.toUpperCase()));
5203
+ let event = matches == null ? void 0 : matches.label;
5204
+ let isStatement = (_e = matches == null ? void 0 : matches.statement) != null ? _e : false;
5205
+ if (!event) {
5206
+ event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
5207
+ isStatement = true;
5221
5208
  }
5209
+ bootstrap.cache.processed.push({
5210
+ type: `Feature`,
5211
+ geometry: {
5212
+ type: `Point`,
5213
+ coordinates: []
5214
+ },
5215
+ properties: __spreadProps(__spreadValues({
5216
+ event,
5217
+ parent: event,
5218
+ status: isStatement ? `Statement` : `Issued`,
5219
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
5220
+ expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
5221
+ }, props), {
5222
+ metadata: {
5223
+ ms: performance.now() - tick,
5224
+ source: `events.text`,
5225
+ tracking: getEventTracking({ type: `RAW`, stanza, attributes, properties: props }),
5226
+ header,
5227
+ vtec: null,
5228
+ hvtec: null,
5229
+ raw: message,
5230
+ history: [
5231
+ {
5232
+ description: props.description,
5233
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
5234
+ status: `Issued`
5235
+ }
5236
+ ]
5237
+ }
5238
+ })
5239
+ });
5240
+ setDebug({ title: `@events.text`, message: `Event process took ${performance.now() - tick} ms` });
5222
5241
  }
5242
+ });
5243
+
5244
+ // src/@parsers/@ugc/ugc.header.ts
5245
+ var getUGCHeader = (message) => {
5246
+ const start = message.search(dict_expressions.ugc1);
5247
+ const sub = message.substring(start);
5248
+ const end = sub.search(dict_expressions.ugc2);
5249
+ const fin = sub.substring(0, end).replace(/\s+/g, "").slice(0, -1);
5250
+ return fin != null ? fin : null;
5223
5251
  };
5224
5252
 
5225
- // src/@building/building.enhance.ts
5226
- var getEventEnhancedName = (event) => {
5227
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5228
- const configurations = bootstrap.settings;
5229
- let name = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.event;
5230
- if (!((_b = configurations == null ? void 0 : configurations.GlobalSettings) == null ? void 0 : _b.BetterEventNames)) {
5231
- return name;
5232
- }
5233
- const damage = (_d = (_c = event == null ? void 0 : event.properties) == null ? void 0 : _c.parameters) == null ? void 0 : _d.damage_threat;
5234
- const tornado = (_f = (_e = event == null ? void 0 : event.properties) == null ? void 0 : _e.parameters) == null ? void 0 : _f.tornado_threat;
5235
- const pdswatch = (_h = (_g = event == null ? void 0 : event.properties) == null ? void 0 : _g.watch_parameters) == null ? void 0 : _h.pds_watch;
5236
- const description = (_j = (_i = event == null ? void 0 : event.properties) == null ? void 0 : _i.description) == null ? void 0 : _j.toLowerCase();
5237
- for (const [eventKey, eventConfig] of Object.entries(dict_enhanced)) {
5238
- if (eventKey !== name) continue;
5239
- for (const [paramKey, paramValue] of Object.entries(eventConfig)) {
5240
- let matches = true;
5241
- if (paramValue == null ? void 0 : paramValue.description) {
5242
- if (!description.includes(paramValue.description.toLowerCase())) matches = false;
5243
- }
5244
- if (paramValue == null ? void 0 : paramValue.damage) {
5245
- if (paramValue.damage !== damage) matches = false;
5246
- }
5247
- if (paramValue == null ? void 0 : paramValue.tornado) {
5248
- if (paramValue.tornado !== tornado) matches = false;
5249
- }
5250
- if (paramValue == null ? void 0 : paramValue.pdswatch) {
5251
- if (paramValue.pdswatch !== pdswatch) matches = false;
5253
+ // src/@parsers/@ugc/ugc.zones.ts
5254
+ var getZones = (header) => {
5255
+ const splits = header.split("-");
5256
+ const zones = [];
5257
+ let state = splits[0].substring(0, 2);
5258
+ const format = splits[0].substring(2, 3);
5259
+ for (const part of splits) {
5260
+ if (/^[A-Z]/.test(part)) {
5261
+ state = part.substring(0, 2);
5262
+ if (part.includes(">")) {
5263
+ const [start, end] = part.split(">");
5264
+ const startNum = parseInt(start.substring(3), 10);
5265
+ const endNum = parseInt(end, 10);
5266
+ for (let j2 = startNum; j2 <= endNum; j2++) {
5267
+ zones.push(`${state}${format}${j2.toString().padStart(3, "0")}`);
5268
+ }
5269
+ } else {
5270
+ zones.push(part);
5252
5271
  }
5253
- if (matches) {
5254
- name = paramKey;
5255
- break;
5272
+ continue;
5273
+ }
5274
+ if (part.includes(">")) {
5275
+ const [start, end] = part.split(">");
5276
+ const startNum = parseInt(start, 10);
5277
+ const endNum = parseInt(end, 10);
5278
+ for (let j2 = startNum; j2 <= endNum; j2++) {
5279
+ zones.push(`${state}${format}${j2.toString().padStart(3, "0")}`);
5256
5280
  }
5281
+ } else {
5282
+ zones.push(`${state}${format}${part}`);
5257
5283
  }
5258
5284
  }
5259
- return name;
5285
+ return zones.filter((item) => item !== "");
5260
5286
  };
5261
5287
 
5262
- // src/@dictionaries/dictionaries.correlations.ts
5263
- var dict_correlations = [
5264
- { type: "Statement", name: "Statement", isCancel: false, isUpdate: false, isIssued: true, isStatement: true },
5265
- { type: "Update", name: "Updated", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5266
- { type: "Cancel", name: "Cancelled", isCancel: true, isUpdate: false, isIssued: false, isStatement: false },
5267
- { type: "Alert", name: "Issued", isCancel: false, isUpdate: false, isIssued: true, isStatement: false },
5268
- { type: "Updated", name: "Updated", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5269
- { type: "Expired", name: "Expired", isCancel: true, isUpdate: false, isIssued: false, isStatement: false },
5270
- { type: "Issued", name: "Issued", isCancel: false, isUpdate: false, isIssued: true, isStatement: false },
5271
- { type: "Extended", name: "Extended", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5272
- { type: "Correction", name: "Correction", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5273
- { type: "Upgraded", name: "Upgraded", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5274
- { type: "Cancelled", name: "Cancelled", isCancel: true, isUpdate: false, isIssued: false, isStatement: false },
5275
- { type: "Routine", name: "Routine", isCancel: false, isUpdate: true, isIssued: false, isStatement: false }
5276
- ];
5277
-
5278
- // src/@dictionaries/dictionaries.cancellation.ts
5279
- var dict_cancellation = [
5280
- "has been cancelled",
5281
- "subsided sufficiently for the advisory to be cancelled",
5282
- "has been cancelled",
5283
- "no tsunami threat from a nearby earthquake",
5284
- "will be allowed to expire",
5285
- "has diminished",
5286
- "and no longer",
5287
- "has been replaced",
5288
- "The threat has ended",
5289
- "has weakened below severe"
5290
- ];
5291
-
5292
- // src/@dictionaries/dictionaries.testing.ts
5293
- var dict_testing = [
5294
- `This is a test message`,
5295
- `Monitoring message only.`,
5296
- `THIS_MESSAGE_IS_FOR_TEST_PURPOSES_ONLY`,
5297
- "TEST MESSAGE"
5298
- ];
5288
+ // src/@parsers/@ugc/ugc.expiry.ts
5289
+ var getExpiry = (message) => {
5290
+ const match = message.match(/\b(\d{6})-/);
5291
+ if (!match) {
5292
+ return null;
5293
+ }
5294
+ const date = match == null ? void 0 : match[1];
5295
+ const day = parseInt(date == null ? void 0 : date.slice(0, 2), 10);
5296
+ const hour = parseInt(date == null ? void 0 : date.slice(2, 4), 10);
5297
+ const minute = parseInt(date == null ? void 0 : date.slice(4, 6), 10);
5298
+ const now = /* @__PURE__ */ new Date();
5299
+ const expires = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), day, hour, minute));
5300
+ return expires.toISOString();
5301
+ };
5299
5302
 
5300
- // src/@dictionaries/dictionaries.products.ts
5301
- var dict_products = {
5302
- "O": "Operational Product",
5303
- "T": "Test Product",
5304
- "E": "Experimental Product",
5305
- "X": "Experimental Product (Non-Operational)"
5303
+ // src/@parsers/@ugc/ugc.getCache.ts
5304
+ var getCache = (key) => {
5305
+ return bootstrap.cache.ugc.get(key);
5306
5306
  };
5307
5307
 
5308
- // src/@dictionaries/dictionaries.hail.ts
5309
- var dict_hail = {
5310
- ".25": "Pea",
5311
- ".50": "Penny",
5312
- ".75": "Penny",
5313
- "Up to .75": "Penny",
5314
- ".88": "Nickel",
5315
- "0.75": "Penny",
5316
- "0.88": "Nickel",
5317
- "1.00": "Quarter",
5318
- "1.25": "Half Dollar",
5319
- "1.50": "Ping Pong Ball",
5320
- "1.75": "Golf Ball",
5321
- "2.00": "Hen Egg",
5322
- "2.50": "Tennis Ball",
5323
- "2.75": "Baseball",
5324
- "4.00": "CD/DVD"
5308
+ // src/@parsers/@ugc/ugc.setCache.ts
5309
+ var setCache = (key, value) => {
5310
+ if (bootstrap.cache.ugc.size >= 5e3) {
5311
+ const firstKey = bootstrap.cache.ugc.keys().next().value;
5312
+ bootstrap.cache.ugc.delete(firstKey);
5313
+ }
5314
+ bootstrap.cache.ugc.set(key, value);
5325
5315
  };
5326
5316
 
5327
- // src/@building/building.signature.ts
5328
- var getEventSignature = (event) => {
5329
- var _a, _b, _c, _d, _e, _f, _g, _h;
5330
- const properties2 = event == null ? void 0 : event.properties;
5331
- const vtec2 = (_b = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.metadata) == null ? void 0 : _b.vtec;
5332
- const status = dict_correlations.find((c) => c.type === (properties2 == null ? void 0 : properties2.status));
5333
- const csig = dict_cancellation.find((sig) => properties2.description.toLowerCase().includes(sig.toLowerCase()));
5334
- properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_issued: true, is_test: false });
5335
- if ((_c = properties2 == null ? void 0 : properties2.parameters) == null ? void 0 : _c.estimated_hail_size) {
5336
- properties2.parameters.estimated_hail_size += ` (${(_e = dict_hail[(_d = properties2 == null ? void 0 : properties2.parameters) == null ? void 0 : _d.estimated_hail_size]) != null ? _e : "--"})`;
5337
- }
5338
- if (status) {
5339
- properties2.status = (_f = status.name) != null ? _f : properties2.status;
5340
- properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_updated: !!status.isUpdate, is_issued: !!status.isIssued, is_expired: !!status.isCancel, is_statement: !!status.isStatement });
5341
- }
5342
- if (csig) {
5343
- properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_expired: true });
5344
- }
5345
- const getProduct = (_h = (_g = vtec2 == null ? void 0 : vtec2.vtec) == null ? void 0 : _g.split(`.`)[0]) == null ? void 0 : _h.replace(`/`, ``);
5346
- const isTestProduct = dict_products[getProduct] == `Test Product`;
5347
- if (isTestProduct || dict_testing.some((sig) => {
5348
- var _a2, _b2, _c2, _d2;
5349
- return (_d2 = (_a2 = properties2.description) == null ? void 0 : _a2.toLowerCase().includes(sig.toLowerCase())) != null ? _d2 : (_c2 = (_b2 = properties2 == null ? void 0 : properties2.parameters) == null ? void 0 : _b2.instructions) == null ? void 0 : _c2.toLowerCase().includes(sig.toLowerCase());
5350
- })) {
5351
- properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_test: true });
5317
+ // src/@parsers/@ugc/ugc.locations.ts
5318
+ var getLocations = (zones) => __async(null, null, function* () {
5319
+ const uniqueZones = Array.from(new Set(zones));
5320
+ const results = [];
5321
+ const missing = [];
5322
+ for (let i = 0; i < uniqueZones.length; i++) {
5323
+ const zone = uniqueZones[i];
5324
+ const cached = getCache(zone);
5325
+ if (cached) {
5326
+ for (let j2 = 0; j2 < cached.length; j2++) {
5327
+ results.push(cached[j2]);
5328
+ }
5329
+ } else {
5330
+ missing.push(zone);
5331
+ }
5352
5332
  }
5353
- if (new Date(properties2.expires).getTime() < Date.now()) {
5354
- properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_expired: true });
5333
+ if (missing.length > 0) {
5334
+ const rows = yield bootstrap.database.prepare(
5335
+ `SELECT id, location FROM shapefiles WHERE id IN (${missing.map(() => "?").join(",")})`
5336
+ ).all(...missing);
5337
+ for (let i = 0; i < rows.length; i++) {
5338
+ const r = rows[i];
5339
+ setCache(r.id, [r.location]);
5340
+ results.push(r.location);
5341
+ }
5355
5342
  }
5356
- properties2.status_metadata = __spreadValues({}, properties2.status_metadata);
5357
- return event;
5358
- };
5343
+ return results;
5344
+ });
5359
5345
 
5360
- // src/@manager/manager.setHash.ts
5361
- var setHash = (event, entry) => {
5362
- if (entry) {
5363
- entry.hashes.push(event.properties.metadata.hash);
5364
- entry.expires = event.properties.expires;
5365
- } else {
5366
- bootstrap.cache.hashes.push({
5367
- tracking: event.properties.metadata.tracking,
5368
- hashes: [event.properties.metadata.hash],
5369
- expires: event.properties.expires
5370
- });
5371
- }
5372
- };
5346
+ // src/@parsers/@ugc/ugc.extract.ts
5347
+ var ugcExtract = (message) => __async(null, null, function* () {
5348
+ const head = getUGCHeader(message);
5349
+ const ugcs = getZones(head);
5350
+ const expires = getExpiry(message);
5351
+ const areas = yield getLocations(ugcs);
5352
+ if (!head || (ugcs == null ? void 0 : ugcs.length) == 0) return;
5353
+ return {
5354
+ zones: ugcs,
5355
+ locations: areas,
5356
+ expires
5357
+ };
5358
+ });
5373
5359
 
5374
- // src/@modules/@eas/eas.getWavPCM16.ts
5375
- var getWavPCM16 = (buffer) => {
5376
- if (buffer.toString("ascii", 0, 4) !== "RIFF" || buffer.toString("ascii", 8, 12) !== "WAVE") {
5377
- return null;
5378
- }
5379
- let fmt = null;
5380
- let data = null;
5381
- let i = 12;
5382
- while (i + 8 <= buffer.length) {
5383
- const id2 = buffer.toString("ascii", i, i + 4);
5384
- const size = buffer.readUInt32LE(i + 4);
5385
- const start = i + 8;
5386
- const end = start + size;
5387
- if (id2 === "fmt ") fmt = buffer.slice(start, end);
5388
- if (id2 === "data") data = buffer.slice(start, end);
5389
- i = end + size % 2;
5390
- }
5391
- if (!fmt || !data) return null;
5392
- const audioFormat = fmt.readUInt16LE(0);
5393
- const channels = fmt.readUInt16LE(2);
5394
- const sampleRate = fmt.readUInt32LE(4);
5395
- const bitsPerSample = fmt.readUInt16LE(14);
5396
- if (audioFormat !== 1 || bitsPerSample !== 16 || channels !== 1) {
5397
- return null;
5360
+ // src/@events/events.ugc.ts
5361
+ var ugc = (stanza) => __async(null, null, function* () {
5362
+ var _a, _b, _c, _d, _e;
5363
+ 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 !== "$$");
5364
+ if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
5365
+ for (const message of getMessages) {
5366
+ const tick = performance.now();
5367
+ const attributes = stanza == null ? void 0 : stanza.attributes;
5368
+ const ugc2 = yield ugcExtract(message);
5369
+ if (ugc2 != null) {
5370
+ const props = properties({ message, attributes, ugc: ugc2 });
5371
+ const issued = new Date(attributes.issue);
5372
+ const expires = new Date(ugc2.expires);
5373
+ const header = getEventHeader({ properties: props, getType: stanza.getType });
5374
+ const matches = (_d = dict_matches[stanza.getType.prefix]) == null ? void 0 : _d.find((match) => match.match.test(message.toUpperCase()));
5375
+ let event = matches == null ? void 0 : matches.label;
5376
+ let isStatement = (_e = matches == null ? void 0 : matches.statement) != null ? _e : false;
5377
+ if (!event) {
5378
+ event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
5379
+ isStatement = true;
5380
+ }
5381
+ bootstrap.cache.processed.push({
5382
+ type: `Feature`,
5383
+ geometry: {
5384
+ type: `Point`,
5385
+ coordinates: []
5386
+ },
5387
+ properties: __spreadProps(__spreadValues({
5388
+ event,
5389
+ parent: event,
5390
+ status: isStatement ? `Statement` : `Issued`,
5391
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
5392
+ expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
5393
+ }, props), {
5394
+ metadata: {
5395
+ ms: performance.now() - tick,
5396
+ source: `events.ugc`,
5397
+ tracking: getEventTracking({ type: `RAW`, stanza, attributes, properties: props }),
5398
+ header,
5399
+ vtec: null,
5400
+ hvtec: null,
5401
+ raw: message,
5402
+ history: [
5403
+ {
5404
+ description: props.description,
5405
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
5406
+ status: `Issued`
5407
+ }
5408
+ ]
5409
+ }
5410
+ })
5411
+ });
5412
+ setDebug({ title: `@events.ugc`, message: `Event process took ${performance.now() - tick} ms` });
5413
+ }
5398
5414
  }
5399
- const samples = new Int16Array(data.buffer, data.byteOffset, data.length / 2);
5400
- return { samples: new Int16Array(samples), sampleRate, channels, bitsPerSample };
5415
+ });
5416
+
5417
+ // src/@dictionaries/dictionaries.products.ts
5418
+ var dict_products = {
5419
+ "O": "Operational Product",
5420
+ "T": "Test Product",
5421
+ "E": "Experimental Product",
5422
+ "X": "Experimental Product (Non-Operational)"
5401
5423
  };
5402
5424
 
5403
- // src/@modules/@eas/eas.getSampledPCM16.ts
5404
- var getSampledPCM16 = (int16, originalRate, targetRate) => {
5405
- if (originalRate === targetRate) return int16;
5406
- const ratio = targetRate / originalRate;
5407
- const outLen = Math.max(1, Math.round(int16.length * ratio));
5408
- const out = new Int16Array(outLen);
5409
- for (let i = 0; i < outLen; i++) {
5410
- const pos = i / ratio;
5411
- const i0 = Math.floor(pos);
5412
- const i1 = Math.min(i0 + 1, int16.length - 1);
5413
- const frac = pos - i0;
5414
- const v = int16[i0] * (1 - frac) + int16[i1] * frac;
5415
- out[i] = Math.round(v);
5416
- }
5417
- return out;
5425
+ // src/@dictionaries/dictionaries.events.ts
5426
+ var dict_events = {
5427
+ "AF": "Ashfall",
5428
+ "AS": "Air Stagnation",
5429
+ "BH": "Beach Hazard",
5430
+ "BW": "Brisk Wind",
5431
+ "BZ": "Blizzard",
5432
+ "CF": "Coastal Flood",
5433
+ "DF": "Debris Flow",
5434
+ "DS": "Dust Storm",
5435
+ "EC": "Extreme Cold",
5436
+ "EH": "Excessive Heat",
5437
+ "XH": "Extreme Heat",
5438
+ "EW": "Extreme Wind",
5439
+ "FA": "Areal Flood",
5440
+ "FF": "Flash Flood",
5441
+ "FG": "Dense Fog",
5442
+ "FL": "Flood",
5443
+ "FR": "Frost",
5444
+ "FW": "Fire Weather",
5445
+ "FZ": "Freeze",
5446
+ "GL": "Gale",
5447
+ "HF": "Hurricane Force Wind",
5448
+ "HT": "Heat",
5449
+ "HU": "Hurricane",
5450
+ "HW": "High Wind",
5451
+ "HY": "Hydrologic",
5452
+ "HZ": "Hard Freeze",
5453
+ "IS": "Ice Storm",
5454
+ "LE": "Lake Effect Snow",
5455
+ "LO": "Low Water",
5456
+ "LS": "Lakeshore Flood",
5457
+ "LW": "Lake Wind",
5458
+ "MA": "Special Marine",
5459
+ "EQ": "Earthquake",
5460
+ "MF": "Dense Fog",
5461
+ "MH": "Ashfall",
5462
+ "MS": "Dense Smoke",
5463
+ "RB": "Small Craft for Rough Bar",
5464
+ "RP": "Rip Current Risk",
5465
+ "SC": "Small Craft",
5466
+ "SE": "Hazardous Seas",
5467
+ "SI": "Small Craft for Winds",
5468
+ "SM": "Dense Smoke",
5469
+ "SQ": "Snow Squall",
5470
+ "SR": "Storm",
5471
+ "SS": "Storm Surge",
5472
+ "SU": "High Surf",
5473
+ "SV": "Severe Thunderstorm",
5474
+ "SW": "Small Craft for Hazardous Seas",
5475
+ "TO": "Tornado",
5476
+ "TR": "Tropical Storm",
5477
+ "TS": "Tsunami",
5478
+ "TY": "Typhoon",
5479
+ "SP": "Special Weather",
5480
+ "UP": "Heavy Freezing Spray",
5481
+ "WC": "Wind Chill",
5482
+ "WI": "Wind",
5483
+ "WS": "Winter Storm",
5484
+ "WW": "Winter Weather",
5485
+ "ZF": "Freezing Fog",
5486
+ "ZR": "Freezing Rain",
5487
+ "ZY": "Freezing Spray"
5418
5488
  };
5419
5489
 
5420
- // src/@modules/@eas/eas.getPCMToFloat.ts
5421
- var getPCMToFloat = (int16) => {
5422
- const out = new Float32Array(int16.length);
5423
- for (let i = 0; i < int16.length; i++) out[i] = int16[i] / 32768;
5424
- return out;
5490
+ // src/@dictionaries/dictionaries.actions.ts
5491
+ var dict_actions = {
5492
+ "W": "Warning",
5493
+ "F": "Forecast",
5494
+ "A": "Watch",
5495
+ "O": "Outlook",
5496
+ "Y": "Advisory",
5497
+ "N": "Synopsis",
5498
+ "S": "Statement"
5425
5499
  };
5426
5500
 
5427
- // src/@modules/@eas/eas.getFloatPCM16.ts
5428
- var getFloatPCM16 = (float32) => {
5429
- const out = new Int16Array(float32.length);
5430
- for (let i = 0; i < float32.length; i++) {
5431
- let v = Math.max(-1, Math.min(1, float32[i]));
5432
- out[i] = Math.round(v * 32767);
5433
- }
5434
- return out;
5501
+ // src/@dictionaries/dictionaries.status.ts
5502
+ var dict_status = {
5503
+ "NEW": "Issued",
5504
+ "CON": "Updated",
5505
+ "EXT": "Extended",
5506
+ "EXA": "Extended",
5507
+ "EXB": "Extended",
5508
+ "UPG": "Upgraded",
5509
+ "COR": "Correction",
5510
+ "ROU": "Routine",
5511
+ "CAN": "Cancelled",
5512
+ "EXP": "Expired"
5435
5513
  };
5436
5514
 
5437
- // src/@modules/@eas/eas.setRadioEffect.ts
5438
- var setRadioEffect = (int16, sampleRate) => {
5439
- const hpCut = 3555;
5440
- const lpCut = 1600;
5441
- const x = getPCMToFloat(int16);
5442
- const dt = 1 / sampleRate;
5443
- const rcHP = 1 / (2 * Math.PI * hpCut);
5444
- const aHP = rcHP / (rcHP + dt);
5445
- let yHP = 0, xPrev = 0;
5446
- for (let i = 0; i < x.length; i++) {
5447
- const xi = x[i];
5448
- yHP = aHP * (yHP + xi - xPrev);
5449
- xPrev = xi;
5450
- x[i] = yHP;
5451
- }
5452
- const rcLP = 1 / (2 * Math.PI * lpCut);
5453
- const aLP = dt / (rcLP + dt);
5454
- let yLP = 0;
5455
- for (let i = 0; i < x.length; i++) {
5456
- yLP = yLP + aLP * (x[i] - yLP);
5457
- x[i] = yLP;
5458
- }
5459
- const compGain = 2;
5460
- const norm = Math.tanh(compGain);
5461
- for (let i = 0; i < x.length; i++) x[i] = Math.tanh(x[i] * compGain) / norm;
5462
- return getFloatPCM16(x);
5515
+ // src/@parsers/@pvtec/pvtec.expires.ts
5516
+ var getExpiry2 = (dates) => {
5517
+ if ((dates == null ? void 0 : dates[1]) == `000000T0000Z`) return "Invalid Date Format";
5518
+ 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`;
5519
+ const local = new Date(new Date(expires).getTime() - 4 * 60 * 6e4);
5520
+ const pad = (n) => n.toString().padStart(2, "0");
5521
+ return `${local.getFullYear()}-${pad(local.getMonth() + 1)}-${pad(local.getDate())}T${pad(local.getHours())}:${pad(local.getMinutes())}:00.000-04:00`;
5463
5522
  };
5464
5523
 
5465
- // src/@modules/@eas/eas.setAFSK.ts
5466
- var setAFSK = (bits, sampleRate) => {
5467
- const baud = 520.83;
5468
- const markFreq = 2083.3;
5469
- const spaceFreq = 1562.5;
5470
- const amplitude = 0.6;
5471
- const twoPi = Math.PI * 2;
5472
- const result = [];
5473
- let phase = 0;
5474
- let frac = 0;
5475
- for (let b = 0; b < bits.length; b++) {
5476
- const bit = bits[b];
5477
- const freq = bit ? markFreq : spaceFreq;
5478
- const samplesPerBit = sampleRate / baud + frac;
5479
- const n = Math.round(samplesPerBit);
5480
- frac = samplesPerBit - n;
5481
- const inc = twoPi * freq / sampleRate;
5482
- for (let i = 0; i < n; i++) {
5483
- result.push(Math.round(Math.sin(phase) * amplitude * 32767));
5484
- phase += inc;
5485
- if (phase > twoPi) phase -= twoPi;
5486
- }
5487
- }
5488
- const fadeSamples = Math.floor(sampleRate * 2e-3);
5489
- for (let i = 0; i < fadeSamples; i++) {
5490
- const gain = i / fadeSamples;
5491
- result[i] = Math.round(result[i] * gain);
5492
- result[result.length - 1 - i] = Math.round(result[result.length - 1 - i] * gain);
5524
+ // src/@parsers/@pvtec/pvtec.extract.ts
5525
+ var pvExtract = (message) => {
5526
+ var _a, _b, _c, _d;
5527
+ if (!message) return null;
5528
+ const getVTECs = (_a = message.match(dict_expressions.pvtec)) != null ? _a : [];
5529
+ const vtecs = [];
5530
+ for (const vtec2 of getVTECs) {
5531
+ const sub = vtec2.split(`.`);
5532
+ if ((sub == null ? void 0 : sub.length) < 7) continue;
5533
+ const dates = (_b = sub[6]) == null ? void 0 : _b.split(`-`);
5534
+ vtecs.push({
5535
+ vtec: vtec2,
5536
+ product: dict_products[sub[0]],
5537
+ tracking: `${sub[2]}.${sub[3]}.${sub[4]}.${sub[5]}`,
5538
+ event: `${dict_events[sub[3]]} ${dict_actions[sub[4]]}`,
5539
+ status: dict_status[sub[1]],
5540
+ organization: (_d = (_c = message.match(dict_expressions.wmo)) == null ? void 0 : _c[0]) != null ? _d : null,
5541
+ expires: getExpiry2(dates),
5542
+ is_watch: (sub[4] == `A` || sub[4] == `Y`) && (sub[3] == `TO` || sub[3] == `SV`),
5543
+ prediction_center: sub[2] == `KWNS` ? true : false
5544
+ });
5493
5545
  }
5494
- return Int16Array.from(result);
5546
+ return vtecs.length > 0 ? vtecs : null;
5495
5547
  };
5496
5548
 
5497
- // src/@modules/@eas/eas.setAsciiToBits.ts
5498
- var setAsciiToBits = (str) => {
5499
- const bits = [];
5500
- for (let i = 0; i < str.length; i++) {
5501
- const c = str.charCodeAt(i) & 255;
5502
- bits.push(0);
5503
- for (let b = 0; b < 8; b++) bits.push(c >> b & 1);
5504
- bits.push(1, 1);
5505
- }
5506
- return bits;
5549
+ // src/@dictionaries/dictionaries.causes.ts
5550
+ var dict_causes = {
5551
+ "SM": "Snow Melt",
5552
+ "RS": "Rain/Snow Melt",
5553
+ "ER": "Excessive Rain",
5554
+ "DM": "Dam/Levee Failure",
5555
+ "IJ": "Ice Jam",
5556
+ "GO": "Glacier Lake Outburst",
5557
+ "IC": "Ice",
5558
+ "FS": "Flash Flood / Storm Surge",
5559
+ "FT": "Tidal Effects",
5560
+ "ET": "Elevated Upstream Flow",
5561
+ "MC": "Other Multiple Causes",
5562
+ "WT": "Wind and/or Tidal Effects",
5563
+ "DR": "Reservoir Release",
5564
+ "UU": "Unknown",
5565
+ "OT": "Other Effects"
5507
5566
  };
5508
5567
 
5509
- // src/@modules/@eas/eas.getMergedPCM16.ts
5510
- var getMergedPCM16 = (arrays) => {
5511
- let total = 0;
5512
- for (const a of arrays) total += a.length;
5513
- const out = new Int16Array(total);
5514
- let o = 0;
5515
- for (const a of arrays) {
5516
- out.set(a, o);
5517
- o += a.length;
5518
- }
5519
- return out;
5568
+ // src/@dictionaries/dictionaries.records.ts
5569
+ var dict_records = {
5570
+ "NO": "No Record Expected",
5571
+ "NR": "Near Record or possible record",
5572
+ "UU": "Unknown history of records",
5573
+ "OO": "Other"
5520
5574
  };
5521
5575
 
5522
- // src/@modules/@eas/eas.setSameHeader.ts
5523
- var setSameHeader = (vtec2, repeats, sampleRate = 8e3, options = {}) => {
5524
- var _a, _b;
5525
- const preMarkSec = (_a = options.preMarkSec) != null ? _a : 0.3;
5526
- const gapSec = (_b = options.gapSec) != null ? _b : 0.1;
5527
- const bursts = [];
5528
- const gap = new Int16Array(Math.floor(gapSec * sampleRate));
5529
- for (let i = 0; i < repeats; i++) {
5530
- const bodyBits = setAsciiToBits(vtec2);
5531
- const body = setAFSK(bodyBits, sampleRate);
5532
- const extendedBodyDuration = Math.round(preMarkSec * sampleRate);
5533
- const extendedBody = new Int16Array(extendedBodyDuration + gap.length);
5534
- for (let j2 = 0; j2 < extendedBodyDuration; j2++) {
5535
- extendedBody[j2] = Math.round(body[j2 % body.length] * 0.2);
5536
- }
5537
- extendedBody.set(gap, extendedBodyDuration);
5538
- bursts.push(extendedBody);
5539
- if (i !== repeats - 1) bursts.push(gap);
5540
- }
5541
- return getMergedPCM16(bursts);
5576
+ // src/@dictionaries/dictionaries.severity.ts
5577
+ var dict_severity = {
5578
+ N: "Not Expected",
5579
+ 0: "Areal Flood or FF Product",
5580
+ 1: "Minor",
5581
+ 2: "Moderate",
5582
+ 3: "Major",
5583
+ U: "Unknown"
5542
5584
  };
5543
5585
 
5544
- // src/@modules/@eas/eas.setAttentionTone.ts
5545
- var setAttentionTone = (ms, sampleRate) => {
5546
- const len = Math.floor(ms * sampleRate);
5547
- const out = new Int16Array(len);
5548
- const f1 = 853;
5549
- const f2 = 960;
5550
- const twoPi = Math.PI * 2;
5551
- const amp = 0.1;
5552
- const fadeLen = Math.floor(sampleRate * 0);
5553
- for (let i = 0; i < len; i++) {
5554
- const t = i / sampleRate;
5555
- const s = Math.sin(twoPi * f1 * t) + Math.sin(twoPi * f2 * t);
5556
- let gain = 1;
5557
- if (i < fadeLen) gain = i / fadeLen;
5558
- else if (i > len - fadeLen) gain = (len - i) / fadeLen;
5559
- const v = Math.max(-1, Math.min(1, s / 2 * amp * gain));
5560
- out[i] = Math.round(v * 32767);
5586
+ // src/@parsers/@hvtec/hvtec.extract.ts
5587
+ var hvExtract = (message) => {
5588
+ var _a;
5589
+ const getHVTECs = (_a = message.match(dict_expressions.hvtec)) != null ? _a : [];
5590
+ const vtecs = [];
5591
+ for (const vtec2 of getHVTECs) {
5592
+ const sub = vtec2.split(`.`);
5593
+ if (sub.length < 7) continue;
5594
+ vtecs.push({
5595
+ hvtec: vtec2,
5596
+ severity: dict_severity[sub[1]],
5597
+ cause: dict_causes[sub[2]],
5598
+ record: dict_records[sub[6]]
5599
+ });
5561
5600
  }
5562
- return out;
5601
+ return vtecs.length > 0 ? vtecs : null;
5563
5602
  };
5564
5603
 
5565
- // src/@modules/@eas/eas.setNoise.ts
5566
- var setNoise = (int16, noiseLevel = 0.02) => {
5567
- const x = getPCMToFloat(int16);
5568
- for (let i = 0; i < x.length; i++) x[i] += (Math.random() * 2 - 1) * noiseLevel;
5569
- let peak = 0;
5570
- for (let i = 0; i < x.length; i++) peak = Math.max(peak, Math.abs(x[i]));
5571
- if (peak > 1) for (let i = 0; i < x.length; i++) x[i] *= 0.98 / peak;
5572
- return getFloatPCM16(x);
5573
- };
5604
+ // src/@events/events.vtec.ts
5605
+ var vtec = (stanza) => __async(null, null, function* () {
5606
+ var _a, _b, _c, _d, _e;
5607
+ 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 !== "$$");
5608
+ if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
5609
+ for (const message of getMessages) {
5610
+ const tick = performance.now();
5611
+ const attributes = stanza == null ? void 0 : stanza.attributes;
5612
+ const pVtec = pvExtract(message);
5613
+ const hVtec = hvExtract(message);
5614
+ const ugc2 = yield ugcExtract(message);
5615
+ if (pVtec != null && ugc2 != null) {
5616
+ for (const pv of pVtec) {
5617
+ const vtec2 = pv;
5618
+ const props = properties({ message, attributes, ugc: ugc2, pVtec: vtec2 });
5619
+ const header = getEventHeader({ properties: props, getType: stanza.getType, vtec: vtec2 });
5620
+ const issued = (_d = new Date(attributes.issue)) != null ? _d : /* @__PURE__ */ new Date();
5621
+ const expires = new Date(vtec2.expires);
5622
+ bootstrap.cache.processed.push({
5623
+ type: `Feature`,
5624
+ geometry: {
5625
+ type: `Point`,
5626
+ coordinates: []
5627
+ },
5628
+ properties: __spreadProps(__spreadValues({
5629
+ event: pv.event,
5630
+ parent: pv.event,
5631
+ status: pv.status,
5632
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
5633
+ expires: !isNaN(expires.getTime()) ? expires.toISOString() : (_e = ugc2.expires) != null ? _e : new Date(issued.getTime() + 60 * 60 * 1e3).toISOString()
5634
+ }, props), {
5635
+ metadata: {
5636
+ ms: performance.now() - tick,
5637
+ source: `events.vtec`,
5638
+ tracking: getEventTracking({ type: `VTEC`, stanza, attributes, properties: props, vtec: vtec2 }),
5639
+ header,
5640
+ vtec: pv,
5641
+ hvtec: hVtec,
5642
+ raw: message,
5643
+ history: [
5644
+ {
5645
+ description: props.description,
5646
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
5647
+ status: pv.status
5648
+ }
5649
+ ]
5650
+ }
5651
+ })
5652
+ });
5653
+ setDebug({ title: `@events.vtec`, message: `Event process took ${performance.now() - tick} ms` });
5654
+ }
5655
+ }
5656
+ }
5657
+ });
5574
5658
 
5575
- // src/@modules/@eas/eas.getPCM16.ts
5576
- var getPCM16 = (samples, sampleRate) => {
5577
- let o = 0;
5578
- const bytesPerSample = 2;
5579
- const blockAlign = 1 * bytesPerSample;
5580
- const byteRate = sampleRate * blockAlign;
5581
- const subchunk2Size = samples.length * bytesPerSample;
5582
- const chunkSize = 36 + subchunk2Size;
5583
- const buffer = Buffer.alloc(44 + subchunk2Size);
5584
- buffer.write("RIFF", o);
5585
- o += 4;
5586
- buffer.writeUInt32LE(chunkSize, o);
5587
- o += 4;
5588
- buffer.write("WAVE", o);
5589
- o += 4;
5590
- buffer.write("fmt ", o);
5591
- o += 4;
5592
- buffer.writeUInt32LE(16, o);
5593
- o += 4;
5594
- buffer.writeUInt16LE(1, o);
5595
- o += 2;
5596
- buffer.writeUInt16LE(1, o);
5597
- o += 2;
5598
- buffer.writeUInt32LE(sampleRate, o);
5599
- o += 4;
5600
- buffer.writeUInt32LE(byteRate, o);
5601
- o += 4;
5602
- buffer.writeUInt16LE(blockAlign, o);
5603
- o += 2;
5604
- buffer.writeUInt16LE(16, o);
5605
- o += 2;
5606
- buffer.write("data", o);
5607
- o += 4;
5608
- buffer.writeUInt32LE(subchunk2Size, o);
5609
- o += 4;
5610
- for (let i = 0; i < samples.length; i++, o += 2) {
5611
- buffer.writeInt16LE(samples[i].value, o);
5612
- }
5613
- return buffer;
5614
- };
5615
-
5616
- // src/@modules/@eas/eas.getTTS.ts
5617
- import { platform } from "os";
5618
- import { writeFileSync } from "fs";
5619
- import { execSync } from "child_process";
5620
- var getTTS = (text2, outputPath) => __async(null, null, function* () {
5621
- const vPlatform = platform();
5622
- switch (vPlatform) {
5623
- case "win32": {
5624
- try {
5625
- const txtPath = outputPath + ".txt";
5626
- writeFileSync(txtPath, text2, "utf8");
5627
- const command = [
5628
- "Add-Type -AssemblyName System.Speech;",
5629
- `$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;`,
5630
- `$text = Get-Content -Raw -LiteralPath '${txtPath}';`,
5631
- `$speak.SetOutputToWaveFile('${outputPath}');`,
5632
- `$speak.Speak($text);`,
5633
- `$speak.Dispose();`
5634
- ].join(" ");
5635
- execSync(`powershell -Command "${command}"`, { stdio: "inherit" });
5636
- } catch (error) {
5637
- console.error("Error occurred while generating TTS:", error);
5638
- }
5639
- break;
5640
- }
5641
- case "linux":
5642
- try {
5643
- execSync(`espeak -w "${outputPath}" "${text2.replace(/"/g, '\\"')}"`);
5644
- } catch (e) {
5659
+ // src/@events/events.api.ts
5660
+ var api = (stanza) => __async(null, null, function* () {
5661
+ 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, _hb, _ib, _jb, _kb, _lb, _mb, _nb, _ob, _pb, _qb, _rb, _sb, _tb, _ub;
5662
+ const messages = Object.values(JSON.parse(stanza.message).features);
5663
+ for (const feature of messages) {
5664
+ const tick = performance.now();
5665
+ const pVtec = (_d = pvExtract((_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;
5666
+ bootstrap.cache.processed.push({
5667
+ type: `Feature`,
5668
+ geometry: {
5669
+ type: `Point`,
5670
+ coordinates: []
5671
+ },
5672
+ properties: {
5673
+ event: (_f = (_e = feature == null ? void 0 : feature.properties) == null ? void 0 : _e.event) != null ? _f : null,
5674
+ parent: (_h = (_g = feature == null ? void 0 : feature.properties) == null ? void 0 : _g.event) != null ? _h : null,
5675
+ status: (_j = (_i = feature == null ? void 0 : feature.properties) == null ? void 0 : _i.messageType) != null ? _j : null,
5676
+ 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,
5677
+ 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,
5678
+ locations: (_p = (_o = feature == null ? void 0 : feature.properties) == null ? void 0 : _o.areaDesc) != null ? _p : null,
5679
+ locations_array: ((_q = feature == null ? void 0 : feature.properties) == null ? void 0 : _q.areaDesc) ? (_r = feature == null ? void 0 : feature.properties) == null ? void 0 : _r.areaDesc.split(";") : [],
5680
+ description: (_t = (_s = feature == null ? void 0 : feature.properties) == null ? void 0 : _s.description) != null ? _t : null,
5681
+ attributes: (_v = (_u = feature == null ? void 0 : feature.properties) == null ? void 0 : _u.attributes) != null ? _v : {},
5682
+ geocode: {
5683
+ office: {
5684
+ office: pVtec ? (_w = pVtec == null ? void 0 : pVtec[0]) == null ? void 0 : _w.tracking.split(`.`)[0] : null,
5685
+ name: (_y = dict_icao[pVtec ? (_x = pVtec == null ? void 0 : pVtec[0]) == null ? void 0 : _x.tracking.split(`.`)[0] : null]) != null ? _y : null
5686
+ },
5687
+ organization: (_B = (_A = (_z = feature == null ? void 0 : feature.properties) == null ? void 0 : _z.parameters) == null ? void 0 : _A.WMOidentifier) == null ? void 0 : _B[0],
5688
+ ugc: (_E = (_D = (_C = feature == null ? void 0 : feature.properties) == null ? void 0 : _C.geocode) == null ? void 0 : _D.UGC) != null ? _E : [],
5689
+ polygon: ((_F = feature == null ? void 0 : feature.geometry) == null ? void 0 : _F.coordinates.length) > 0 ? Buffer.from(JSON.stringify([(_G = feature == null ? void 0 : feature.geometry) == null ? void 0 : _G.coordinates[0]])).toString("base64") : null,
5690
+ polygon_generated: ((_H = feature == null ? void 0 : feature.geometry) == null ? void 0 : _H.coordinates.length) > 0 ? true : false
5691
+ },
5692
+ parameters: {
5693
+ tags: getEventTags((_I = feature == null ? void 0 : feature.properties) == null ? void 0 : _I.description),
5694
+ instructions: (_K = (_J = feature == null ? void 0 : feature.properties) == null ? void 0 : _J.instruction) != null ? _K : null,
5695
+ source: (_M = getTextFromProduct({ message: (_L = feature == null ? void 0 : feature.properties) == null ? void 0 : _L.description, find: [`SOURCE...`], removal: [`.`] })) != null ? _M : null,
5696
+ hazards: (_O = getTextFromProduct({ message: (_N = feature == null ? void 0 : feature.properties) == null ? void 0 : _N.description, find: [`HAZARD...`], removal: [`.`] })) != null ? _O : null,
5697
+ impacts: (_Q = getTextFromProduct({ message: (_P = feature == null ? void 0 : feature.properties) == null ? void 0 : _P.description, find: [`IMPACT...`], removal: [`.`] })) != null ? _Q : null,
5698
+ estimated_hail_size: (_U = (_T = (_S = (_R = feature == null ? void 0 : feature.properties) == null ? void 0 : _R.parameters) == null ? void 0 : _S.maxHailSize) == null ? void 0 : _T[0]) != null ? _U : null,
5699
+ estimated_wind_gusts: (_Y = (_X = (_W = (_V = feature == null ? void 0 : feature.properties) == null ? void 0 : _V.parameters) == null ? void 0 : _W.maxWindGust) == null ? void 0 : _X[0]) != null ? _Y : null,
5700
+ damage_threat: (_aa = (_$ = (__ = (_Z = feature == null ? void 0 : feature.properties) == null ? void 0 : _Z.parameters) == null ? void 0 : __.thunderstormDamageThreat) == null ? void 0 : _$[0]) != null ? _aa : null,
5701
+ tornado_threat: (_ea = (_da = (_ca = (_ba = feature == null ? void 0 : feature.properties) == null ? void 0 : _ba.parameters) == null ? void 0 : _ca.tornadoDetection) == null ? void 0 : _da[0]) != null ? _ea : null,
5702
+ flood_threat: (_ia = (_ha = (_ga = (_fa = feature == null ? void 0 : feature.properties) == null ? void 0 : _fa.parameters) == null ? void 0 : _ga.floodDetection) == null ? void 0 : _ha[0]) != null ? _ia : null,
5703
+ wind_threat: (_ma = (_la = (_ka = (_ja = feature == null ? void 0 : feature.properties) == null ? void 0 : _ja.parameters) == null ? void 0 : _ka.windThreat) == null ? void 0 : _la[0]) != null ? _ma : null,
5704
+ hail_threat: (_qa = (_pa = (_oa = (_na = feature == null ? void 0 : feature.properties) == null ? void 0 : _na.parameters) == null ? void 0 : _oa.hailThreat) == null ? void 0 : _pa[0]) != null ? _qa : null
5705
+ },
5706
+ discussion_parameters: {
5707
+ discussion_number: (_ua = (_ta = (_sa = getTextFromProduct({ message: (_ra = feature == null ? void 0 : feature.properties) == null ? void 0 : _ra.description, find: [`Mesoscale Discussion `], removal: [`Mesoscale Discussion`, `Number`, `...`] })) == null ? void 0 : _sa.toString()) == null ? void 0 : _ta.padStart(4, "0")) != null ? _ua : null,
5708
+ discussion_concerning: (_wa = getTextFromProduct({ message: (_va = feature == null ? void 0 : feature.properties) == null ? void 0 : _va.description, find: [`Concerning...`] })) != null ? _wa : null,
5709
+ discussion_max_tornado: (_ya = getTextFromProduct({ message: (_xa = feature == null ? void 0 : feature.properties) == null ? void 0 : _xa.description, find: [`MOST PROBABLE PEAK TORNADO INTENSITY...`] })) != null ? _ya : null,
5710
+ discussion_max_hail: (_Aa = getTextFromProduct({ message: (_za = feature == null ? void 0 : feature.properties) == null ? void 0 : _za.description, find: [`MOST PROBABLE PEAK HAIL SIZE...`] })) != null ? _Aa : null,
5711
+ discussion_max_wind: (_Ca = getTextFromProduct({ message: (_Ba = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ba.description, find: [`MOST PROBABLE PEAK WIND GUST...`] })) != null ? _Ca : null,
5712
+ discussion_watch_issuance: (_Ea = getTextFromProduct({ message: (_Da = feature == null ? void 0 : feature.properties) == null ? void 0 : _Da.description, find: [`Probability of Watch Issuance...`], removal: [`percent`] })) != null ? _Ea : null
5713
+ },
5714
+ watch_parameters: {
5715
+ watch_number: ((_Fa = pVtec == null ? void 0 : pVtec[0]) == null ? void 0 : _Fa.is_watch) && ((_Qa = (_Pa = (_Ka = (_Ja = (_Ia = (_Ha = getTextFromProduct({ message: (_Ga = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ga.description, find: [`ITIES FOR`, `UPDATE FOR`, `Watch Number `], removal: [`%`, `<`, `:`] })) == null ? void 0 : _Ha.replace(/(WT|WS|)/g, "")) == null ? void 0 : _Ia.trim()) == null ? void 0 : _Ja.toString()) == null ? void 0 : _Ka.padStart(4, "0")) != null ? _Pa : (_Oa = (_Na = (_Ma = (_La = pVtec == null ? void 0 : pVtec[0]) == null ? void 0 : _La.tracking) == null ? void 0 : _Ma.slice(-4)) == null ? void 0 : _Na.toString()) == null ? void 0 : _Oa.padStart(4, "0")) != null ? _Qa : null),
5716
+ watch_type: ((_Ra = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ra.description.includes(`TORNADO WATCH`)) ? `Tornado` : ((_Sa = feature == null ? void 0 : feature.properties) == null ? void 0 : _Sa.description.includes(`SEVERE`)) ? `Severe` : null,
5717
+ additional_tornadoes_probability: (_Ua = getTextFromProduct({ message: (_Ta = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ta.description, find: [`PROB OF 2 OR MORE TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _Ua : null,
5718
+ strong_tornadoes_probability: (_Wa = getTextFromProduct({ message: (_Va = feature == null ? void 0 : feature.properties) == null ? void 0 : _Va.description, find: [`PROB OF 1 OR MORE STRONG /EF2-EF5/ TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _Wa : null,
5719
+ severe_wind_probability: (_Ya = getTextFromProduct({ message: (_Xa = feature == null ? void 0 : feature.properties) == null ? void 0 : _Xa.description, find: [`PROB OF 10 OR MORE SEVERE WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _Ya : null,
5720
+ severe_hail_probability: (__a = getTextFromProduct({ message: (_Za = feature == null ? void 0 : feature.properties) == null ? void 0 : _Za.description, find: [`PROB OF 10 OR MORE SEVERE HAIL EVENTS`], removal: [`%`, `<`, `:`] })) != null ? __a : null,
5721
+ hail_2in_probability: (_ab = getTextFromProduct({ message: (_$a = feature == null ? void 0 : feature.properties) == null ? void 0 : _$a.description, find: [`PROB OF 1 OR MORE HAIL EVENTS >= 2 INCHES`], removal: [`%`, `<`, `:`] })) != null ? _ab : null,
5722
+ combined_hail_wind_probability: (_cb = getTextFromProduct({ message: (_bb = feature == null ? void 0 : feature.properties) == null ? void 0 : _bb.description, find: [`PROB OF 6 OR MORE COMBINED SEVERE HAIL/WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _cb : null,
5723
+ max_hail_in: (_eb = getTextFromProduct({ message: (_db = feature == null ? void 0 : feature.properties) == null ? void 0 : _db.description, find: [`MAX HAIL /INCHES/`], removal: [`%`, `<`, `:`] })) != null ? _eb : null,
5724
+ max_wind_surface: (_gb = getTextFromProduct({ message: (_fb = feature == null ? void 0 : feature.properties) == null ? void 0 : _fb.description, find: [`MAX WIND GUSTS SURFACE /KNOTS/`], removal: [`%`, `<`, `:`] })) != null ? _gb : null,
5725
+ max_tops_x100feet: (_ib = getTextFromProduct({ message: (_hb = feature == null ? void 0 : feature.properties) == null ? void 0 : _hb.description, find: [`MAX TOPS /X 100 FEET/`], removal: [`%`, `<`, `:`] })) != null ? _ib : null,
5726
+ pds_watch: getTextFromProduct({ message: (_jb = feature == null ? void 0 : feature.properties) == null ? void 0 : _jb.description, find: [`PARTICULARLY DANGEROUS SITUATION`], removal: [`%`, `<`, `:`] }) === `YES`
5727
+ },
5728
+ metadata: {
5729
+ ms: performance.now() - tick,
5730
+ source: `events.api`,
5731
+ tracking: getEventTracking({ type: `API`, organization: { wmoidentifier: (_mb = (_lb = (_kb = feature == null ? void 0 : feature.properties) == null ? void 0 : _kb.parameters) == null ? void 0 : _lb.WMOidentifier) == null ? void 0 : _mb[0], featureId: feature == null ? void 0 : feature.id }, vtec: pVtec == null ? void 0 : pVtec[0] }),
5732
+ header: `ZCZC-ATMOSX-${(_ob = (_nb = feature == null ? void 0 : feature.properties) == null ? void 0 : _nb.parameters) == null ? void 0 : _ob.WMOidentifier}`,
5733
+ vtec: pVtec == null ? void 0 : pVtec[0],
5734
+ hvtec: null,
5735
+ raw: (_pb = feature == null ? void 0 : feature.properties) == null ? void 0 : _pb.description,
5736
+ history: [
5737
+ {
5738
+ description: (_qb = feature == null ? void 0 : feature.properties) == null ? void 0 : _qb.description,
5739
+ issued: ((_rb = feature == null ? void 0 : feature.properties) == null ? void 0 : _rb.sent) ? new Date((_sb = feature == null ? void 0 : feature.properties) == null ? void 0 : _sb.sent).toISOString() : null,
5740
+ status: (_ub = (_tb = feature == null ? void 0 : feature.properties) == null ? void 0 : _tb.messageType) != null ? _ub : null
5741
+ }
5742
+ ]
5743
+ }
5645
5744
  }
5646
- break;
5647
- default:
5648
- break;
5745
+ });
5746
+ setDebug({ title: `@events.api`, message: `Event process took ${performance.now() - tick} ms` });
5649
5747
  }
5650
5748
  });
5651
5749
 
5652
- // src/@modules/@eas/eas.getCleanDescription.ts
5653
- var getCleanDescription = (message) => {
5654
- const patches = [
5655
- { regex: /\.{3,}/g, replacement: ". " },
5656
- { regex: /\bUTC\b/g, replacement: "Coordinated Universal Time" },
5657
- { regex: /\bGMT\b/g, replacement: "Greenwich Mean Time" },
5658
- { regex: /\bEST\b(?!\w)/g, replacement: "Eastern Standard Time" },
5659
- { regex: /\bEDT\b(?!\w)/g, replacement: "Eastern Daylight Time" },
5660
- { regex: /\bCST\b(?!\w)/g, replacement: "Central Standard Time" },
5661
- { regex: /\bCDT\b(?!\w)/g, replacement: "Central Daylight Time" },
5662
- { regex: /\bMST\b(?!\w)/g, replacement: "Mountain Standard Time" },
5663
- { regex: /\bMDT\b(?!\w)/g, replacement: "Mountain Daylight Time" },
5664
- { regex: /\bPST\b(?!\w)/g, replacement: "Pacific Standard Time" },
5665
- { regex: /\bPDT\b(?!\w)/g, replacement: "Pacific Daylight Time" },
5666
- { regex: /\bAKST\b(?!\w)/g, replacement: "Alaska Standard Time" },
5667
- { regex: /\bAKDT\b(?!\w)/g, replacement: "Alaska Daylight Time" },
5668
- { regex: /\bHST\b(?!\w)/g, replacement: "Hawaii Standard Time" },
5669
- { regex: /\bHDT\b(?!\w)/g, replacement: "Hawaii Daylight Time" },
5670
- { regex: /\bmph\b(?!\w)/g, replacement: "miles per hour" },
5671
- { regex: /\bkm\/h\b(?!\w)/g, replacement: "kilometers per hour" },
5672
- { regex: /\bkmh\b(?!\w)/g, replacement: "kilometers per hour" },
5673
- { regex: /\bkt\b(?!\w)/g, replacement: "knots" },
5674
- { regex: /\bNE\b(?!\w)/g, replacement: "northeast" },
5675
- { regex: /\bNW\b(?!\w)/g, replacement: "northwest" },
5676
- { regex: /\bSE\b(?!\w)/g, replacement: "southeast" },
5677
- { regex: /\bSW\b(?!\w)/g, replacement: "southwest" },
5678
- { regex: /\bNM\b(?!\w)/g, replacement: "nautical miles" },
5679
- { regex: /\bdeg\b(?!\w)/g, replacement: "degrees" },
5680
- { regex: /\btstm\b(?!\w)/g, replacement: "thunderstorm" },
5681
- { regex: /\bmm\b(?!\w)/g, replacement: "millimeters" },
5682
- { regex: /\bcm\b(?!\w)/g, replacement: "centimeters" },
5683
- { regex: /\bin.\b(?!\w)/g, replacement: "inches" },
5684
- { regex: /\bft\b(?!\w)/g, replacement: "feet" },
5685
- { regex: /\bmi\b(?!\w)/g, replacement: "miles" },
5686
- { regex: /\bhr\b(?!\w)/g, replacement: "hour" },
5687
- { regex: /\bhourly\b(?!\w)/g, replacement: "per hour" },
5688
- { regex: /\bkg\b(?!\w)/g, replacement: "kilograms" },
5689
- { regex: /\bg\/kg\b(?!\w)/g, replacement: "grams per kilogram" },
5690
- { regex: /\bmb\b(?!\w)/g, replacement: "millibars" },
5691
- { regex: /\bhPa\b(?!\w)/g, replacement: "hectopascals" },
5692
- { regex: /\bPa\b(?!\w)/g, replacement: "pascals" },
5693
- { regex: /\bKPa\b(?!\w)/g, replacement: "kilopascals" },
5694
- { regex: /\bC\/hr\b(?!\w)/g, replacement: "degrees Celsius per hour" },
5695
- { regex: /\bF\/hr\b(?!\w)/g, replacement: "degrees Fahrenheit per hour" },
5696
- { regex: /\bC\/min\b(?!\w)/g, replacement: "degrees Celsius per minute" },
5697
- { regex: /\bF\/min\b(?!\w)/g, replacement: "degrees Fahrenheit per minute" },
5698
- { regex: /\bC\b(?!\w)/g, replacement: "degrees Celsius" },
5699
- { regex: /\bF\b(?!\w)/g, replacement: "degrees Fahrenheit" }
5700
- ];
5701
- const hours = {
5702
- 0: "twelve",
5703
- 1: "one",
5704
- 2: "two",
5705
- 3: "three",
5706
- 4: "four",
5707
- 5: "five",
5708
- 6: "six",
5709
- 7: "seven",
5710
- 8: "eight",
5711
- 9: "nine",
5712
- 10: "ten",
5713
- 11: "eleven",
5714
- 12: "twelve"
5715
- };
5716
- const minWord = (m) => m === 0 ? "o'clock" : m < 10 ? `oh ${m}` : `${m}`;
5717
- const fmt = (h, m, ap) => `${hours[h % 12]} ${minWord(m)} ${ap}`;
5718
- for (const { regex, replacement } of patches) {
5719
- message = message.replace(regex, replacement);
5750
+ // src/@dictionaries/dictionaries.enhanced.ts
5751
+ var dict_enhanced = {
5752
+ "Tornado Warning": {
5753
+ "Tornado Emergency": { description: "tornado emergency" },
5754
+ "PDS Tornado Warning": { description: "particularly dangerous situation", damage: `CONSIDERABLE` },
5755
+ "Radar Confirmed Tornado Warning": { description: "source...radar confirmed tornado.", tornado: `OBSERVED` },
5756
+ "Confirmed Tornado Warning": { tornado: `OBSERVED` },
5757
+ "Radar Indicated Tornado Warning": {}
5758
+ },
5759
+ "Fire Weather Warning": {
5760
+ "PDS Fire Weather Warning": { description: "particularly dangerous situation" }
5761
+ },
5762
+ "Blizzard Warning": {
5763
+ "PDS Blizzard Warning": { description: "particularly dangerous situation" }
5764
+ },
5765
+ "Ice Storm Warning": {
5766
+ "PDS Ice Storm Warning": { description: "particularly dangerous situation" }
5767
+ },
5768
+ "Special Marine Warning": {
5769
+ "Special Marine Warning (TPROB)": { tornado: `POSSIBLE` }
5770
+ },
5771
+ "Tornado Watch": {
5772
+ "PDS Tornado Watch": { pdswatch: true }
5773
+ },
5774
+ "Severe Thunderstorm Watch": {
5775
+ "PDS Severe Thunderstorm Watch": { pdswatch: true }
5776
+ },
5777
+ "Flash Flood Warning": {
5778
+ "Flash Flood Emergency": { description: "flash flood emergency" },
5779
+ "Considerable Flash Flood Warning": { damage: `CONSIDERABLE` }
5780
+ },
5781
+ "Severe Thunderstorm Warning": {
5782
+ "EDS Severe Thunderstorm Warning (TPROB)": { description: "extremely dangerous situation", tornado: "POSSIBLE" },
5783
+ "EDS Severe Thunderstorm Warning": { description: "extremely dangerous situation" },
5784
+ "Destructive Severe Thunderstorm Warning (TPROB)": { damage: `DESTRUCTIVE`, tornado: `POSSIBLE` },
5785
+ "Destructive Severe Thunderstorm Warning": { damage: `DESTRUCTIVE` },
5786
+ "Considerable Severe Thunderstorm Warning (TPROB)": { damage: `CONSIDERABLE`, tornado: `POSSIBLE` },
5787
+ "Considerable Severe Thunderstorm Warning": { damage: `CONSIDERABLE` },
5788
+ "Severe Thunderstorm Warning (TPROB)": { tornado: `POSSIBLE` }
5720
5789
  }
5721
- return message.replace(/'/g, "''").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(/\b(\d{1,2})\s+(AM|PM)\b/gi, (_, h, ap) => fmt(+h, 0, ap.toUpperCase())).replace(/\*+/g, " ").replace(/-/g, " ").replace(/\n/g, " ").trim();
5722
5790
  };
5723
5791
 
5724
- // src/@modules/@eas/eas.setEasTone.ts
5725
- import { join } from "path";
5726
- import { existsSync, mkdirSync, readFileSync, writeFileSync as writeFileSync2, unlinkSync } from "fs";
5727
- import { execSync as execSync2 } from "child_process";
5728
- import { platform as platform2 } from "os";
5729
- var setEasTone = (options) => __async(null, null, function* () {
5730
- var _a;
5731
- const settings = bootstrap.settings;
5732
- const directory = settings.GlobalSettings.ArchiveSettings.EasDirectory;
5733
- const prefix = settings.GlobalSettings.ArchiveSettings.EasToneout;
5734
- let message = options.message;
5735
- let header = options.header;
5736
- let title = (_a = options.title) != null ? _a : `${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, "")}`;
5737
- if (!message || !header) {
5738
- setWarning({
5739
- title: `EAS`,
5740
- message: `Message and header are required to generate an EAS tone.`
5741
- });
5742
- return null;
5743
- }
5744
- let buffTTS;
5745
- let buffRadio;
5746
- let buffFull = [];
5747
- if (!existsSync(directory)) {
5748
- mkdirSync(directory, { recursive: true });
5749
- }
5750
- if (!existsSync(join(directory, `/tts`))) {
5751
- mkdirSync(join(directory, `/tts`), { recursive: true });
5752
- }
5753
- if (!existsSync(join(directory, `/encoded`))) {
5754
- mkdirSync(join(directory, `/encoded`), { recursive: true });
5755
- }
5756
- const tmpTTS = join(directory, `/tts/${title}.wav`);
5757
- const outTTS = join(directory, `/encoded/${title}.wav`);
5758
- const vPlatform = platform2();
5759
- if (vPlatform === "darwin") {
5760
- setWarning({
5761
- title: `EAS`,
5762
- message: `EAS tone generation is not supported on macOS.`
5763
- });
5764
- return null;
5765
- }
5766
- yield new Promise((resolve6, reject) => {
5767
- const tMsg = getCleanDescription(message);
5768
- getTTS(tMsg, tmpTTS).then(() => {
5769
- resolve6();
5770
- });
5771
- });
5772
- if (!existsSync(tmpTTS)) {
5773
- return null;
5792
+ // src/@building/building.enhance.ts
5793
+ var getEventEnhancedName = (event) => {
5794
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5795
+ const configurations = bootstrap.settings;
5796
+ let name = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.event;
5797
+ if (!((_b = configurations == null ? void 0 : configurations.GlobalSettings) == null ? void 0 : _b.BetterEventNames)) {
5798
+ return name;
5774
5799
  }
5775
- buffTTS = readFileSync(tmpTTS);
5776
- const vWav = getWavPCM16(buffTTS);
5777
- const vSamples = getSampledPCM16(vWav.samples, vWav.sampleRate, 8e3);
5778
- const vRadio = setRadioEffect(vSamples, 8e3);
5779
- if (existsSync(prefix)) {
5780
- let tBuffer = readFileSync(prefix);
5781
- let tWav = getWavPCM16(tBuffer);
5782
- if (tWav == null) {
5783
- try {
5784
- const converted = join(directory, `/tts/${title}.converted.wav`);
5785
- execSync2(`ffmpeg -y -i "${prefix}" -ar 8000 -ac 1 -sample_fmt s16 "${converted}"`, { stdio: "ignore" });
5786
- if (existsSync(converted)) {
5787
- tBuffer = readFileSync(converted);
5788
- tWav = getWavPCM16(tBuffer);
5789
- try {
5790
- unlinkSync(converted);
5791
- } catch (e) {
5792
- }
5793
- }
5794
- } catch (e) {
5800
+ const damage = (_d = (_c = event == null ? void 0 : event.properties) == null ? void 0 : _c.parameters) == null ? void 0 : _d.damage_threat;
5801
+ const tornado = (_f = (_e = event == null ? void 0 : event.properties) == null ? void 0 : _e.parameters) == null ? void 0 : _f.tornado_threat;
5802
+ const pdswatch = (_h = (_g = event == null ? void 0 : event.properties) == null ? void 0 : _g.watch_parameters) == null ? void 0 : _h.pds_watch;
5803
+ const description = (_j = (_i = event == null ? void 0 : event.properties) == null ? void 0 : _i.description) == null ? void 0 : _j.toLowerCase();
5804
+ for (const [eventKey, eventConfig] of Object.entries(dict_enhanced)) {
5805
+ if (eventKey !== name) continue;
5806
+ for (const [paramKey, paramValue] of Object.entries(eventConfig)) {
5807
+ let matches = true;
5808
+ if (paramValue == null ? void 0 : paramValue.description) {
5809
+ if (!description.includes(paramValue.description.toLowerCase())) matches = false;
5810
+ }
5811
+ if (paramValue == null ? void 0 : paramValue.damage) {
5812
+ if (paramValue.damage !== damage) matches = false;
5813
+ }
5814
+ if (paramValue == null ? void 0 : paramValue.tornado) {
5815
+ if (paramValue.tornado !== tornado) matches = false;
5816
+ }
5817
+ if (paramValue == null ? void 0 : paramValue.pdswatch) {
5818
+ if (paramValue.pdswatch !== pdswatch) matches = false;
5819
+ }
5820
+ if (matches) {
5821
+ name = paramKey;
5822
+ break;
5795
5823
  }
5796
5824
  }
5797
- if (tWav == null) {
5798
- 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.` });
5799
- return null;
5800
- }
5801
- const tSamples = tWav.sampleRate != 8e3 ? getSampledPCM16(tWav.samples, tWav.sampleRate, 8e3) : tWav.samples;
5802
- buffRadio = setRadioEffect(tSamples, 8e3);
5803
5825
  }
5804
- buffFull = buffRadio != null ? [buffRadio, new Int16Array(Math.floor(0.5 * 8e3))] : [];
5805
- buffFull.push(
5806
- setSameHeader(header, 3, 8e3, {
5807
- preMarkSec: 1.1,
5808
- gapSec: 0.5
5809
- }),
5810
- new Int16Array(Math.floor(0.5 * 8e3)),
5811
- setAttentionTone(8, 8e3),
5812
- new Int16Array(Math.floor(0.5 * 8e3)),
5813
- vRadio
5814
- );
5815
- for (let i = 0; i < 3; i++) {
5816
- buffFull.push(setSameHeader(header, 1, 8e3, { preMarkSec: 0.5, gapSec: 0.1 }));
5817
- buffFull.push(new Int16Array(Math.floor(0.5 * 8e3)));
5818
- }
5819
- const aSamples = getMergedPCM16(buffFull);
5820
- const aFinal = setNoise(aSamples, 2e-3);
5821
- const aBuffer = getPCM16(Array.from(aFinal).map((v) => ({ value: v })), 8e3);
5822
- writeFileSync2(outTTS, aBuffer);
5823
- try {
5824
- unlinkSync(tmpTTS);
5825
- } catch (e) {
5826
- }
5827
- return outTTS;
5828
- });
5826
+ return name;
5827
+ };
5829
5828
 
5830
- // src/@parsers/@text/text.getEmbed.ts
5831
- var getEmebed = (event) => {
5832
- 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;
5833
- const line = (label, value, condition = true) => condition && value ? `${label} ${value}` : null;
5834
- const isStatement = event.properties.status_metadata.is_statement;
5835
- const isExpired = event.properties.status_metadata.is_expired;
5836
- return [
5837
- line(`**Locations:**`, (_b = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.locations) == null ? void 0 : _b.slice(0, 100)),
5838
- line(`**Issued:**`, `<t:${Math.floor(new Date(event.properties.issued).getTime() / 1e3)}:R>`, !isExpired),
5839
- line(`**Expires:**`, `<t:${Math.floor(new Date(event.properties.expires).getTime() / 1e3)}:R>`, !isStatement),
5840
- line(`**Damage Threat:**`, (_d = (_c = event == null ? void 0 : event.properties) == null ? void 0 : _c.parameters) == null ? void 0 : _d.damage_threat, !isExpired),
5841
- line(`**Flood Threat:**`, (_f = (_e = event == null ? void 0 : event.properties) == null ? void 0 : _e.parameters) == null ? void 0 : _f.flood_threat, !isExpired),
5842
- line(`**Tornado Threat:**`, (_h = (_g = event == null ? void 0 : event.properties) == null ? void 0 : _g.parameters) == null ? void 0 : _h.tornado_threat, !isExpired),
5843
- line(`**Estimated Wind Gusts:**`, `${(_j = (_i = event == null ? void 0 : event.properties) == null ? void 0 : _i.parameters) == null ? void 0 : _j.estimated_wind_gusts} ${((_l = (_k = event == null ? void 0 : event.properties) == null ? void 0 : _k.parameters) == null ? void 0 : _l.wind_threat) ? ` (${(_n = (_m = event == null ? void 0 : event.properties) == null ? void 0 : _m.parameters) == null ? void 0 : _n.wind_threat})` : ""}`, !isExpired && ((_p = (_o = event == null ? void 0 : event.properties) == null ? void 0 : _o.parameters) == null ? void 0 : _p.estimated_wind_gusts) != null),
5844
- line(`**Estimated Hail Size:**`, `${(_r = (_q = event == null ? void 0 : event.properties) == null ? void 0 : _q.parameters) == null ? void 0 : _r.estimated_hail_size} ${((_t = (_s = event == null ? void 0 : event.properties) == null ? void 0 : _s.parameters) == null ? void 0 : _t.hail_threat) ? ` (${(_v = (_u = event == null ? void 0 : event.properties) == null ? void 0 : _u.parameters) == null ? void 0 : _v.hail_threat})` : ""}`, !isExpired && ((_x = (_w = event == null ? void 0 : event.properties) == null ? void 0 : _w.parameters) == null ? void 0 : _x.estimated_hail_size) != null),
5845
- line(`**Discussion:**`, (_z = (_y = event == null ? void 0 : event.properties) == null ? void 0 : _y.discussion_parameters) == null ? void 0 : _z.discussion_number, !isExpired),
5846
- line(`**Concern:**`, (_B = (_A = event == null ? void 0 : event.properties) == null ? void 0 : _A.discussion_parameters) == null ? void 0 : _B.discussion_concerning, !isExpired),
5847
- line(`**SPC Max Tornado Threat:**`, (_D = (_C = event == null ? void 0 : event.properties) == null ? void 0 : _C.discussion_parameters) == null ? void 0 : _D.discussion_max_tornado, !isExpired),
5848
- line(`**SPC Max Hail Threat:**`, (_F = (_E = event == null ? void 0 : event.properties) == null ? void 0 : _E.discussion_parameters) == null ? void 0 : _F.discussion_max_hail, !isExpired),
5849
- line(`**SPC Max Wind Threat:**`, (_H = (_G = event == null ? void 0 : event.properties) == null ? void 0 : _G.discussion_parameters) == null ? void 0 : _H.discussion_max_wind, !isExpired),
5850
- line(`**SPC Watch Issuance Probability:**`, ((_J = (_I = event == null ? void 0 : event.properties) == null ? void 0 : _I.discussion_parameters) == null ? void 0 : _J.discussion_watch_issuance) ? `${(_L = (_K = event == null ? void 0 : event.properties) == null ? void 0 : _K.discussion_parameters) == null ? void 0 : _L.discussion_watch_issuance}%` : null, !isExpired),
5851
- line(`**Watch Number:**`, (_N = (_M = event == null ? void 0 : event.properties) == null ? void 0 : _M.watch_parameters) == null ? void 0 : _N.watch_number, !isExpired),
5852
- line(`**Strong Tornadoes Probability:**`, ((_P = (_O = event == null ? void 0 : event.properties) == null ? void 0 : _O.watch_parameters) == null ? void 0 : _P.strong_tornadoes_probability) ? `${(_R = (_Q = event == null ? void 0 : event.properties) == null ? void 0 : _Q.watch_parameters) == null ? void 0 : _R.strong_tornadoes_probability}%` : null, !isExpired),
5853
- line(`**Additional Tornadoes Probability:**`, ((_T = (_S = event == null ? void 0 : event.properties) == null ? void 0 : _S.watch_parameters) == null ? void 0 : _T.additional_tornadoes_probability) ? `${(_V = (_U = event == null ? void 0 : event.properties) == null ? void 0 : _U.watch_parameters) == null ? void 0 : _V.additional_tornadoes_probability}%` : null, !isExpired),
5854
- line(`**Combined Hail/Wind Probability:**`, ((_X = (_W = event == null ? void 0 : event.properties) == null ? void 0 : _W.watch_parameters) == null ? void 0 : _X.combined_hail_wind_probability) ? `${(_Z = (_Y = event == null ? void 0 : event.properties) == null ? void 0 : _Y.watch_parameters) == null ? void 0 : _Z.combined_hail_wind_probability}%` : null, !isExpired),
5855
- line(`**Severe Hail Probability:**`, ((_$ = (__ = event == null ? void 0 : event.properties) == null ? void 0 : __.watch_parameters) == null ? void 0 : _$.severe_hail_probability) ? `${(_ba = (_aa = event == null ? void 0 : event.properties) == null ? void 0 : _aa.watch_parameters) == null ? void 0 : _ba.severe_hail_probability}%` : null, !isExpired),
5856
- line(`**Hail >2in Probability:**`, ((_da = (_ca = event == null ? void 0 : event.properties) == null ? void 0 : _ca.watch_parameters) == null ? void 0 : _da.hail_2in_probability) ? `${(_fa = (_ea = event == null ? void 0 : event.properties) == null ? void 0 : _ea.watch_parameters) == null ? void 0 : _fa.hail_2in_probability}%` : null, !isExpired),
5857
- line(`**Max Hail Inches:**`, (_ha = (_ga = event == null ? void 0 : event.properties) == null ? void 0 : _ga.watch_parameters) == null ? void 0 : _ha.max_hail_in, !isExpired),
5858
- line(`**Severe Wind Probability:**`, ((_ja = (_ia = event == null ? void 0 : event.properties) == null ? void 0 : _ia.watch_parameters) == null ? void 0 : _ja.severe_wind_probability) ? `${(_la = (_ka = event == null ? void 0 : event.properties) == null ? void 0 : _ka.watch_parameters) == null ? void 0 : _la.severe_wind_probability}%` : null, !isExpired),
5859
- line(`**Max Surface Wind:**`, (_na = (_ma = event == null ? void 0 : event.properties) == null ? void 0 : _ma.watch_parameters) == null ? void 0 : _na.max_wind_surface, !isExpired),
5860
- line(`**Max Tops (x100 feet):**`, (_pa = (_oa = event == null ? void 0 : event.properties) == null ? void 0 : _oa.watch_parameters) == null ? void 0 : _pa.max_tops_x100feet, !isExpired),
5861
- line(`**Tags:**`, ((_sa = (_ra = (_qa = event == null ? void 0 : event.properties) == null ? void 0 : _qa.parameters) == null ? void 0 : _ra.tags) == null ? void 0 : _sa.length) > 0 ? (_ua = (_ta = event == null ? void 0 : event.properties) == null ? void 0 : _ta.parameters) == null ? void 0 : _ua.tags.join(", ") : null, !isExpired),
5862
- line(`**Sender:**`, ((_xa = (_wa = (_va = event == null ? void 0 : event.properties) == null ? void 0 : _va.geocode) == null ? void 0 : _wa.office) == null ? void 0 : _xa.name) ? `${(_Aa = (_za = (_ya = event == null ? void 0 : event.properties) == null ? void 0 : _ya.geocode) == null ? void 0 : _za.office) == null ? void 0 : _Aa.name} (${(_Da = (_Ca = (_Ba = event == null ? void 0 : event.properties) == null ? void 0 : _Ba.geocode) == null ? void 0 : _Ca.office) == null ? void 0 : _Da.office})` : (_Ga = (_Fa = (_Ea = event == null ? void 0 : event.properties) == null ? void 0 : _Ea.geocode) == null ? void 0 : _Fa.office) == null ? void 0 : _Ga.office),
5863
- line(`**Tracking:**`, (_Ia = (_Ha = event == null ? void 0 : event.properties) == null ? void 0 : _Ha.metadata) == null ? void 0 : _Ia.tracking),
5864
- line(`**Logs:**`, ((_La = (_Ka = (_Ja = event == null ? void 0 : event.properties) == null ? void 0 : _Ja.metadata) == null ? void 0 : _Ka.history) == null ? void 0 : _La.length) > 0 ? (_Na = (_Ma = event == null ? void 0 : event.properties) == null ? void 0 : _Ma.metadata) == null ? void 0 : _Na.history.length : null)
5865
- ].filter(Boolean).join("\n");
5829
+ // src/@dictionaries/dictionaries.correlations.ts
5830
+ var dict_correlations = [
5831
+ { type: "Statement", name: "Statement", isCancel: false, isUpdate: false, isIssued: true, isStatement: true },
5832
+ { type: "Update", name: "Updated", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5833
+ { type: "Cancel", name: "Cancelled", isCancel: true, isUpdate: false, isIssued: false, isStatement: false },
5834
+ { type: "Alert", name: "Issued", isCancel: false, isUpdate: false, isIssued: true, isStatement: false },
5835
+ { type: "Updated", name: "Updated", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5836
+ { type: "Expired", name: "Expired", isCancel: true, isUpdate: false, isIssued: false, isStatement: false },
5837
+ { type: "Issued", name: "Issued", isCancel: false, isUpdate: false, isIssued: true, isStatement: false },
5838
+ { type: "Extended", name: "Extended", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5839
+ { type: "Correction", name: "Correction", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5840
+ { type: "Upgraded", name: "Upgraded", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5841
+ { type: "Cancelled", name: "Cancelled", isCancel: true, isUpdate: false, isIssued: false, isStatement: false },
5842
+ { type: "Routine", name: "Routine", isCancel: false, isUpdate: true, isIssued: false, isStatement: false }
5843
+ ];
5844
+
5845
+ // src/@dictionaries/dictionaries.cancellation.ts
5846
+ var dict_cancellation = [
5847
+ "has been cancelled",
5848
+ "subsided sufficiently for the advisory to be cancelled",
5849
+ "has been cancelled",
5850
+ "no tsunami threat from a nearby earthquake",
5851
+ "will be allowed to expire",
5852
+ "has diminished",
5853
+ "and no longer",
5854
+ "has been replaced",
5855
+ "The threat has ended",
5856
+ "has weakened below severe"
5857
+ ];
5858
+
5859
+ // src/@dictionaries/dictionaries.testing.ts
5860
+ var dict_testing = [
5861
+ `This is a test message`,
5862
+ `Monitoring message only.`,
5863
+ `THIS_MESSAGE_IS_FOR_TEST_PURPOSES_ONLY`,
5864
+ "TEST MESSAGE"
5865
+ ];
5866
+
5867
+ // src/@dictionaries/dictionaries.hail.ts
5868
+ var dict_hail = {
5869
+ ".25": "Pea",
5870
+ ".50": "Penny",
5871
+ ".75": "Penny",
5872
+ "Up to .75": "Penny",
5873
+ ".88": "Nickel",
5874
+ "0.75": "Penny",
5875
+ "0.88": "Nickel",
5876
+ "1.00": "Quarter",
5877
+ "1.25": "Half Dollar",
5878
+ "1.50": "Ping Pong Ball",
5879
+ "1.75": "Golf Ball",
5880
+ "2.00": "Hen Egg",
5881
+ "2.50": "Tennis Ball",
5882
+ "2.75": "Baseball",
5883
+ "4.00": "CD/DVD"
5866
5884
  };
5867
5885
 
5868
- // src/@modules/@utilities/utilities.createHttp.ts
5869
- var createHttp = (options) => __async(null, null, function* () {
5870
- var _a, _b, _c, _d;
5871
- const requestOptions = {
5872
- method: (_a = options.method) != null ? _a : "GET",
5873
- headers: (_b = options.headers) != null ? _b : {
5874
- "User-Agent": "AtmosphericX",
5875
- "Accept": "application/geo+json, text/plain, */*; q=0.9",
5876
- "Accept-Language": "en-US,en;q=0.9"
5877
- },
5878
- signal: AbortSignal.timeout((_c = options.timeout) != null ? _c : 1e4),
5879
- redirect: "follow"
5880
- };
5881
- const returnHttp = function(error, status, message) {
5882
- return { error, options: requestOptions, status, message };
5883
- };
5884
- if (options == null ? void 0 : options.formData) {
5885
- requestOptions.body = options.formData;
5886
- } else if ((options == null ? void 0 : options.body) != void 0) {
5887
- requestOptions.body = options.body instanceof FormData ? options.body : typeof options.body === "string" ? options.body : JSON.stringify(options.body);
5886
+ // src/@building/building.signature.ts
5887
+ var getEventSignature = (event) => {
5888
+ var _a, _b, _c, _d, _e, _f, _g, _h;
5889
+ const properties2 = event == null ? void 0 : event.properties;
5890
+ const vtec2 = (_b = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.metadata) == null ? void 0 : _b.vtec;
5891
+ const status = dict_correlations.find((c) => c.type === (properties2 == null ? void 0 : properties2.status));
5892
+ const csig = dict_cancellation.find((sig) => properties2.description.toLowerCase().includes(sig.toLowerCase()));
5893
+ properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_issued: true, is_test: false });
5894
+ if ((_c = properties2 == null ? void 0 : properties2.parameters) == null ? void 0 : _c.estimated_hail_size) {
5895
+ properties2.parameters.estimated_hail_size += ` (${(_e = dict_hail[(_d = properties2 == null ? void 0 : properties2.parameters) == null ? void 0 : _d.estimated_hail_size]) != null ? _e : "--"})`;
5896
+ }
5897
+ if (status) {
5898
+ properties2.status = (_f = status.name) != null ? _f : properties2.status;
5899
+ properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_updated: !!status.isUpdate, is_issued: !!status.isIssued, is_expired: !!status.isCancel, is_statement: !!status.isStatement });
5900
+ }
5901
+ if (csig) {
5902
+ properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_expired: true });
5903
+ }
5904
+ const getProduct = (_h = (_g = vtec2 == null ? void 0 : vtec2.vtec) == null ? void 0 : _g.split(`.`)[0]) == null ? void 0 : _h.replace(`/`, ``);
5905
+ const isTestProduct = dict_products[getProduct] == `Test Product`;
5906
+ if (isTestProduct || dict_testing.some((sig) => {
5907
+ var _a2, _b2, _c2, _d2;
5908
+ return (_d2 = (_a2 = properties2.description) == null ? void 0 : _a2.toLowerCase().includes(sig.toLowerCase())) != null ? _d2 : (_c2 = (_b2 = properties2 == null ? void 0 : properties2.parameters) == null ? void 0 : _b2.instructions) == null ? void 0 : _c2.toLowerCase().includes(sig.toLowerCase());
5909
+ })) {
5910
+ properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_test: true });
5888
5911
  }
5889
- try {
5890
- const response2 = yield fetch(
5891
- (_d = options == null ? void 0 : options.url) != null ? _d : `https://api.weather.gov/alerts/active`,
5892
- requestOptions
5893
- );
5894
- const body = yield response2.text();
5895
- if (!response2.ok) {
5896
- return returnHttp(true, response2.status, `HTTP Status Code ${response2.status} (${response2.statusText})`);
5897
- }
5898
- return returnHttp(false, response2.status, body);
5899
- } catch (error) {
5900
- return returnHttp(true, 500, `Internal Server Error: ${error}`);
5912
+ if (new Date(properties2.expires).getTime() < Date.now()) {
5913
+ properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_expired: true });
5901
5914
  }
5902
- });
5915
+ properties2.status_metadata = __spreadValues({}, properties2.status_metadata);
5916
+ return event;
5917
+ };
5903
5918
 
5904
- // src/@manager/manager.updateListener.ts
5905
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3, readFileSync as readFileSync2, appendFileSync } from "fs";
5906
- var updateListener = (event) => __async(null, null, function* () {
5907
- var _a, _b, _c, _d;
5908
- const settings = bootstrap.settings;
5909
- const listeners2 = settings.ListenerSettings;
5910
- const properties2 = event.properties;
5911
- const metadata = {
5912
- file: null,
5913
- eas: null,
5914
- name: properties2.event,
5915
- status: properties2.status,
5916
- description: properties2.description,
5917
- tracking: properties2.metadata.tracking,
5918
- header: properties2.metadata.header,
5919
- raw: properties2.metadata.raw,
5920
- expired: properties2.status_metadata.is_expired,
5921
- attachments: properties2.metadata.attachments
5922
- };
5923
- for (const listener2 of listeners2) {
5924
- const events = listener2 == null ? void 0 : listener2.events;
5925
- const webhook = listener2 == null ? void 0 : listener2.webhook;
5926
- const uploads = listener2 == null ? void 0 : listener2.uploads;
5927
- const isMatched = events.some((pattern) => {
5928
- if (!pattern) return false;
5929
- if (pattern === "*" || pattern === metadata.name) return true;
5930
- if (pattern.includes("*")) {
5931
- const regex = "^" + pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$";
5932
- return new RegExp(regex).test(metadata.name);
5933
- }
5934
- return false;
5919
+ // src/@dictionaries/dictionaries.global.ts
5920
+ var dict_global = [
5921
+ "spc day 1 outlook",
5922
+ "spc day 2 outlook",
5923
+ "spc day 3 outlook"
5924
+ ];
5925
+
5926
+ // src/@manager/manager.setHash.ts
5927
+ var setHash = (event, entry) => {
5928
+ if (entry) {
5929
+ entry.hashes.push(event.properties.metadata.hash);
5930
+ entry.expires = event.properties.expires;
5931
+ } else {
5932
+ bootstrap.cache.hashes.push({
5933
+ tracking: event.properties.metadata.tracking,
5934
+ hashes: [event.properties.metadata.hash],
5935
+ expires: event.properties.expires
5935
5936
  });
5936
- if ((events == null ? void 0 : events.length) == 0 || isMatched) {
5937
- if (uploads == null ? void 0 : uploads.eas) {
5938
- metadata.eas = yield setEasTone({
5939
- title: `${metadata.name}_${metadata.status}_${metadata.tracking}`,
5940
- message: metadata.description,
5941
- header: metadata.header
5942
- });
5943
- }
5944
- if (uploads == null ? void 0 : uploads.file) {
5945
- const fDestination = settings.GlobalSettings.ArchiveSettings.TextDirectory;
5946
- if (fDestination) {
5947
- if (!existsSync2(fDestination)) {
5948
- mkdirSync2(fDestination, { recursive: true });
5949
- }
5950
- if (existsSync2(`${fDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.txt`)) {
5951
- appendFileSync(`${fDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.txt`, metadata.raw);
5952
- } else {
5953
- writeFileSync3(`${fDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.txt`, metadata.raw);
5954
- }
5955
- }
5956
- metadata.file = metadata.raw;
5957
- }
5958
- if (uploads == null ? void 0 : uploads.event) {
5959
- const eDestination = settings.GlobalSettings.ArchiveSettings.EventDirectory;
5960
- if (eDestination) {
5961
- if (!existsSync2(eDestination)) {
5962
- mkdirSync2(eDestination, { recursive: true });
5963
- }
5964
- writeFileSync3(`${eDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.json`, JSON.stringify(getCleanedEvent(event), null, 2));
5965
- }
5966
- }
5967
- if (webhook.enabled && webhook.destination) {
5968
- const ratelimit = setTimeoutAction({ identifier: webhook.destination, interval: webhook.ratelimit * 2, max: webhook.ratelimit, addTime: true });
5969
- const form = new FormData();
5970
- const embed = {
5971
- title: `${metadata.name} (${metadata.status})`,
5972
- description: getEmebed(event),
5973
- fields: [],
5974
- color: 16711680,
5975
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5976
- footer: { text: (_a = webhook.title) != null ? _a : `AtmosphericX` }
5977
- };
5978
- if (ratelimit.limited) {
5979
- return;
5980
- }
5981
- if (metadata.description && !metadata.expired) {
5982
- if (metadata.description.length > 900) {
5983
- metadata.description = metadata.description.substring(0, 900) + "\n\n[Message truncated due to length]";
5984
- }
5985
- embed.fields.push({
5986
- name: "Description",
5987
- value: metadata.description ? "```\n" + metadata.description.split("\n").map((l) => l.trim()).filter(Boolean).join("\n") + "\n```" : ""
5988
- });
5989
- }
5990
- if (((_b = metadata.attachments) == null ? void 0 : _b.length) > 0) {
5991
- metadata.attachments = metadata.attachments.slice(0, 5);
5992
- embed.fields.push({
5993
- name: "Attachments",
5994
- value: metadata.attachments.map((attachment) => `- [${attachment.name.length > 45 ? attachment.name.substring(0, 45) + "..." : attachment.name}](${attachment.link})`).join("\n")
5995
- });
5996
- }
5997
- if (uploads == null ? void 0 : uploads.file) {
5998
- form.append("fUpload", new Blob([Buffer.from(metadata.file)], { type: "application/text" }), `${properties2.event}_${properties2.status}_${properties2.metadata.tracking}.txt`);
5999
- }
6000
- if (uploads == null ? void 0 : uploads.eas) {
6001
- if (metadata.eas) {
6002
- const file = readFileSync2(metadata.eas);
6003
- form.append("fEas", new Blob([Buffer.from(file)], { type: "audio/mpeg" }), `${properties2.event}_${properties2.status}_${properties2.metadata.tracking}_eas.mp3`);
6004
- }
6005
- }
6006
- form.append("payload_json", JSON.stringify({
6007
- username: (_c = webhook.title) != null ? _c : "AtmosphericX",
6008
- content: (_d = webhook.message) != null ? _d : "",
6009
- embeds: [embed]
6010
- }));
6011
- const a = yield createHttp({
6012
- url: webhook.destination,
6013
- timeout: 5e3,
6014
- method: `POST`,
6015
- body: form
6016
- });
6017
- if (a.error) {
6018
- setWarning({ message: `Failed to send webhook: ${a.error.message}` });
6019
- }
6020
- }
6021
- }
6022
5937
  }
6023
- });
5938
+ };
6024
5939
 
6025
- // src/@modules/@utilities/utilities.getShapeNearestPoint.ts
6026
- var getShapeNearestPoint = (coordinates, point) => {
6027
- if (!coordinates || !point) {
6028
- return { proximity: false, point: [0, 0], distance: null };
5940
+ // src/@modules/@eas/eas.getWavPCM16.ts
5941
+ var getWavPCM16 = (buffer) => {
5942
+ if (buffer.toString("ascii", 0, 4) !== "RIFF" || buffer.toString("ascii", 8, 12) !== "WAVE") {
5943
+ return null;
6029
5944
  }
6030
- const normalize = (coords) => {
6031
- if (!Array.isArray(coords)) return [];
6032
- if (typeof coords[0] === "number" && typeof coords[1] === "number") return [];
6033
- if (Array.isArray(coords[0]) && typeof coords[0][0] === "number") {
6034
- return [[coords]];
6035
- }
6036
- if (Array.isArray(coords[0]) && Array.isArray(coords[0][0]) && typeof coords[0][0][0] === "number") {
6037
- return [coords];
6038
- }
6039
- if (Array.isArray(coords[0]) && Array.isArray(coords[0][0]) && Array.isArray(coords[0][0][0]) && typeof coords[0][0][0][0] === "number") {
6040
- return coords;
6041
- }
6042
- return [];
6043
- };
6044
- const polys = normalize(coordinates);
6045
- if (polys.length === 0) return { proximity: false, point: [0, 0], distance: null };
6046
- const lon = point[0];
6047
- const lat = point[1];
6048
- const pointInRing = (pt, ring) => {
6049
- let x = pt[0], y = pt[1];
6050
- let inside = false;
6051
- for (let i = 0, j2 = ring.length - 1; i < ring.length; j2 = i++) {
6052
- const xi = ring[i][0], yi = ring[i][1];
6053
- const xj = ring[j2][0], yj = ring[j2][1];
6054
- const intersect = yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi + 0) + xi;
6055
- if (intersect) inside = !inside;
6056
- }
6057
- return inside;
6058
- };
6059
- const toRadians = (deg) => deg * Math.PI / 180;
6060
- const haversineMiles = (a, b) => {
6061
- const R = 3958.8;
6062
- const dLat = toRadians(b[1] - a[1]);
6063
- const dLon = toRadians(b[0] - a[0]);
6064
- const lat1 = toRadians(a[1]);
6065
- const lat2 = toRadians(b[1]);
6066
- const sinDLat = Math.sin(dLat / 2);
6067
- const sinDLon = Math.sin(dLon / 2);
6068
- const c = 2 * Math.asin(Math.sqrt(sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon));
6069
- return R * c;
6070
- };
6071
- let minDistance = Infinity;
6072
- let closestPoint = null;
6073
- for (const poly of polys) {
6074
- const outer = poly[0];
6075
- const holes = poly.slice(1);
6076
- if (pointInRing(point, outer)) {
6077
- let inHole = false;
6078
- for (const hole of holes) {
6079
- if (pointInRing(point, hole)) {
6080
- inHole = true;
6081
- break;
6082
- }
6083
- }
6084
- if (!inHole) {
6085
- return { proximity: true, point, distance: 0 };
6086
- }
6087
- }
6088
- for (const ring of poly) {
6089
- for (let i = 0; i < ring.length - 1; i++) {
6090
- const start = [ring[i][0], ring[i][1]];
6091
- const end = [ring[i + 1][0], ring[i + 1][1]];
6092
- const A = lon - start[0];
6093
- const B = lat - start[1];
6094
- const C = end[0] - start[0];
6095
- const D = end[1] - start[1];
6096
- const lenSq = C * C + D * D;
6097
- const t = lenSq === 0 ? 0 : Math.max(0, Math.min(1, (A * C + B * D) / lenSq));
6098
- const candidate = [start[0] + t * C, start[1] + t * D];
6099
- const dist = haversineMiles([lon, lat], candidate);
6100
- if (!isNaN(dist) && dist < minDistance) {
6101
- minDistance = Number(dist.toFixed(3));
6102
- closestPoint = candidate;
6103
- }
6104
- }
6105
- }
5945
+ let fmt = null;
5946
+ let data = null;
5947
+ let i = 12;
5948
+ while (i + 8 <= buffer.length) {
5949
+ const id2 = buffer.toString("ascii", i, i + 4);
5950
+ const size = buffer.readUInt32LE(i + 4);
5951
+ const start = i + 8;
5952
+ const end = start + size;
5953
+ if (id2 === "fmt ") fmt = buffer.slice(start, end);
5954
+ if (id2 === "data") data = buffer.slice(start, end);
5955
+ i = end + size % 2;
6106
5956
  }
6107
- if (!isFinite(minDistance) || closestPoint == null) {
6108
- return { proximity: false, point: [0, 0], distance: null };
5957
+ if (!fmt || !data) return null;
5958
+ const audioFormat = fmt.readUInt16LE(0);
5959
+ const channels = fmt.readUInt16LE(2);
5960
+ const sampleRate = fmt.readUInt32LE(4);
5961
+ const bitsPerSample = fmt.readUInt16LE(14);
5962
+ if (audioFormat !== 1 || bitsPerSample !== 16 || channels !== 1) {
5963
+ return null;
5964
+ }
5965
+ const samples = new Int16Array(data.buffer, data.byteOffset, data.length / 2);
5966
+ return { samples: new Int16Array(samples), sampleRate, channels, bitsPerSample };
5967
+ };
5968
+
5969
+ // src/@modules/@eas/eas.getSampledPCM16.ts
5970
+ var getSampledPCM16 = (int16, originalRate, targetRate) => {
5971
+ if (originalRate === targetRate) return int16;
5972
+ const ratio = targetRate / originalRate;
5973
+ const outLen = Math.max(1, Math.round(int16.length * ratio));
5974
+ const out = new Int16Array(outLen);
5975
+ for (let i = 0; i < outLen; i++) {
5976
+ const pos = i / ratio;
5977
+ const i0 = Math.floor(pos);
5978
+ const i1 = Math.min(i0 + 1, int16.length - 1);
5979
+ const frac = pos - i0;
5980
+ const v = int16[i0] * (1 - frac) + int16[i1] * frac;
5981
+ out[i] = Math.round(v);
5982
+ }
5983
+ return out;
5984
+ };
5985
+
5986
+ // src/@modules/@eas/eas.getPCMToFloat.ts
5987
+ var getPCMToFloat = (int16) => {
5988
+ const out = new Float32Array(int16.length);
5989
+ for (let i = 0; i < int16.length; i++) out[i] = int16[i] / 32768;
5990
+ return out;
5991
+ };
5992
+
5993
+ // src/@modules/@eas/eas.getFloatPCM16.ts
5994
+ var getFloatPCM16 = (float32) => {
5995
+ const out = new Int16Array(float32.length);
5996
+ for (let i = 0; i < float32.length; i++) {
5997
+ let v = Math.max(-1, Math.min(1, float32[i]));
5998
+ out[i] = Math.round(v * 32767);
6109
5999
  }
6110
- const distanceMiles = minDistance;
6111
- const distanceKm = Number((distanceMiles * 1.609344).toFixed(3));
6112
- const distanceMeters = Math.round(distanceKm * 1e3);
6113
- return { proximity: distanceMiles === 0, point: closestPoint, distance: distanceMiles, distanceKm, distanceMeters };
6000
+ return out;
6114
6001
  };
6115
6002
 
6116
- // src/@building/building.polygon.ts
6117
- var getEventNodes = (event) => __async(null, null, function* () {
6118
- var _a, _b;
6119
- const metadata = { nodes: [], proximity: false, filtered: false };
6120
- const geometry = yield getEventGeometry(event);
6121
- if (!geometry || !geometry.coordinates) {
6122
- return { nodes: [], filtered: false, updated: Date.now() };
6003
+ // src/@modules/@eas/eas.setRadioEffect.ts
6004
+ var setRadioEffect = (int16, sampleRate) => {
6005
+ const hpCut = 3555;
6006
+ const lpCut = 1600;
6007
+ const x = getPCMToFloat(int16);
6008
+ const dt = 1 / sampleRate;
6009
+ const rcHP = 1 / (2 * Math.PI * hpCut);
6010
+ const aHP = rcHP / (rcHP + dt);
6011
+ let yHP = 0, xPrev = 0;
6012
+ for (let i = 0; i < x.length; i++) {
6013
+ const xi = x[i];
6014
+ yHP = aHP * (yHP + xi - xPrev);
6015
+ xPrev = xi;
6016
+ x[i] = yHP;
6123
6017
  }
6124
- const nodes = bootstrap.cache.nodes.features;
6125
- for (const node of nodes) {
6126
- const [longitude, latitude] = node.geometry.coordinates;
6127
- const getPoint = getShapeNearestPoint(geometry.coordinates, [longitude, latitude]);
6128
- const miles = (_a = getPoint.distance) != null ? _a : null;
6129
- const kilometers = Number((miles * 1.609344).toFixed(3));
6130
- const info = {
6131
- id: (_b = node.properties) == null ? void 0 : _b.identifier,
6132
- coordinates: [longitude, latitude],
6133
- nearest: getPoint.point,
6134
- miles,
6135
- kilometers,
6136
- proximity: getPoint.proximity
6137
- };
6138
- metadata.nodes.push(info);
6139
- if (bootstrap.settings.GlobalSettings.EventFiltering.NodeLocationFiltering && miles < bootstrap.settings.GlobalSettings.NodeMinDistance) {
6140
- metadata.proximity = true;
6141
- info.proximity = true;
6142
- }
6018
+ const rcLP = 1 / (2 * Math.PI * lpCut);
6019
+ const aLP = dt / (rcLP + dt);
6020
+ let yLP = 0;
6021
+ for (let i = 0; i < x.length; i++) {
6022
+ yLP = yLP + aLP * (x[i] - yLP);
6023
+ x[i] = yLP;
6143
6024
  }
6144
- return {
6145
- nodes: metadata.nodes,
6146
- filtered: metadata.proximity,
6147
- updated: Date.now()
6148
- };
6149
- });
6025
+ const compGain = 2;
6026
+ const norm = Math.tanh(compGain);
6027
+ for (let i = 0; i < x.length; i++) x[i] = Math.tanh(x[i] * compGain) / norm;
6028
+ return getFloatPCM16(x);
6029
+ };
6150
6030
 
6151
- // src/@manager/manager.updateNodes.ts
6152
- var updateNode = (selectedEvent) => __async(null, null, function* () {
6153
- const events = bootstrap.cache.events.features;
6154
- const ttl = bootstrap.settings.GlobalSettings.NodeTTL * 1e3;
6155
- let total = 0;
6156
- function update(evt) {
6157
- return __async(this, null, function* () {
6158
- var _a, _b, _c;
6159
- const lastUpdate = (_c = (_b = (_a = evt == null ? void 0 : evt.properties) == null ? void 0 : _a.metadata) == null ? void 0 : _b.updated) != null ? _c : null;
6160
- if (lastUpdate != null && Date.now() - lastUpdate < ttl) {
6161
- return evt;
6162
- }
6163
- const node = yield getEventNodes(evt);
6164
- if (node.nodes.length > 0) {
6165
- total++;
6166
- }
6167
- evt.properties.metadata.nodes = node.nodes;
6168
- evt.properties.metadata.filtered_proximity = node.filtered;
6169
- evt.properties.metadata.updated = node.updated;
6170
- });
6171
- }
6172
- if (!selectedEvent) {
6173
- yield Promise.all(events.map((evt) => __async(null, null, function* () {
6174
- yield update(evt);
6175
- })));
6031
+ // src/@modules/@eas/eas.setAFSK.ts
6032
+ var setAFSK = (bits, sampleRate) => {
6033
+ const baud = 520.83;
6034
+ const markFreq = 2083.3;
6035
+ const spaceFreq = 1562.5;
6036
+ const amplitude = 0.6;
6037
+ const twoPi = Math.PI * 2;
6038
+ const result = [];
6039
+ let phase = 0;
6040
+ let frac = 0;
6041
+ for (let b = 0; b < bits.length; b++) {
6042
+ const bit = bits[b];
6043
+ const freq = bit ? markFreq : spaceFreq;
6044
+ const samplesPerBit = sampleRate / baud + frac;
6045
+ const n = Math.round(samplesPerBit);
6046
+ frac = samplesPerBit - n;
6047
+ const inc = twoPi * freq / sampleRate;
6048
+ for (let i = 0; i < n; i++) {
6049
+ result.push(Math.round(Math.sin(phase) * amplitude * 32767));
6050
+ phase += inc;
6051
+ if (phase > twoPi) phase -= twoPi;
6052
+ }
6176
6053
  }
6177
- if (selectedEvent) {
6178
- yield update(selectedEvent);
6054
+ const fadeSamples = Math.floor(sampleRate * 2e-3);
6055
+ for (let i = 0; i < fadeSamples; i++) {
6056
+ const gain = i / fadeSamples;
6057
+ result[i] = Math.round(result[i] * gain);
6058
+ result[result.length - 1 - i] = Math.round(result[result.length - 1 - i] * gain);
6179
6059
  }
6180
- if (total > 0) {
6181
- setEventEmit({
6182
- event: `onNodeUpdate`,
6183
- metadata: {
6184
- type: `global-update`,
6185
- updated: total
6186
- }
6187
- });
6060
+ return Int16Array.from(result);
6061
+ };
6062
+
6063
+ // src/@modules/@eas/eas.setAsciiToBits.ts
6064
+ var setAsciiToBits = (str) => {
6065
+ const bits = [];
6066
+ for (let i = 0; i < str.length; i++) {
6067
+ const c = str.charCodeAt(i) & 255;
6068
+ bits.push(0);
6069
+ for (let b = 0; b < 8; b++) bits.push(c >> b & 1);
6070
+ bits.push(1, 1);
6188
6071
  }
6189
- });
6072
+ return bits;
6073
+ };
6190
6074
 
6191
- // src/@manager/manager.mkEvent.ts
6192
- var mkEvent = (event) => __async(null, null, function* () {
6193
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w;
6194
- const settings = bootstrap.settings;
6195
- const features = bootstrap.cache.events.features;
6196
- const getHash = event.properties.metadata.hash;
6197
- const getTracking = event.properties.metadata.tracking;
6198
- const isEntry = (_a = bootstrap.cache.hashes) == null ? void 0 : _a.find((hash) => hash.tracking === getTracking);
6199
- const isHashed = (_c = (_b = isEntry == null ? void 0 : isEntry.hashes) == null ? void 0 : _b.includes(getHash)) != null ? _c : false;
6200
- const getFeature = features.find((feature) => feature.properties.metadata.tracking === getTracking);
6201
- if (isHashed || event.properties.status_metadata.is_expired) return;
6202
- setHash(event, isEntry);
6203
- const isFilteredLocation = yield updateNode(event).then(() => event.properties.metadata.filtered_proximity);
6204
- if (!isFilteredLocation && settings.GlobalSettings.EventFiltering.NodeLocationFiltering) {
6205
- return;
6075
+ // src/@modules/@eas/eas.getMergedPCM16.ts
6076
+ var getMergedPCM16 = (arrays) => {
6077
+ let total = 0;
6078
+ for (const a of arrays) total += a.length;
6079
+ const out = new Int16Array(total);
6080
+ let o = 0;
6081
+ for (const a of arrays) {
6082
+ out.set(a, o);
6083
+ o += a.length;
6206
6084
  }
6207
- setEventEmit({
6208
- event: `onEventStatus`,
6209
- metadata: {
6210
- type: getFeature ? `Updated` : `New`,
6211
- event
6212
- },
6213
- message: `[${getFeature ? "Updated" : "New"}] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
6214
- });
6215
- if (settings.GlobalSettings.EventManagement) {
6216
- if (event.properties.status_metadata.is_issued || event.properties.status_metadata.is_updated) {
6217
- if (getFeature) {
6218
- const getIndex = features.indexOf(getFeature);
6219
- const cHistory = (_f = (_e = (_d = getFeature == null ? void 0 : getFeature.properties) == null ? void 0 : _d.metadata) == null ? void 0 : _e.history) != null ? _f : [];
6220
- 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 : [];
6221
- const cUgc = (_l = (_k = (_j = getFeature == null ? void 0 : getFeature.properties) == null ? void 0 : _j.geocode) == null ? void 0 : _k.ugc) != null ? _l : [];
6222
- const iHistory = (_o = (_n = (_m = event.properties) == null ? void 0 : _m.metadata) == null ? void 0 : _n.history) != null ? _o : [];
6223
- const iLocations = (_r = (_q = (_p = event.properties) == null ? void 0 : _p.locations) == null ? void 0 : _q.split(";").map((l) => l.trim())) != null ? _r : [];
6224
- const iUgc = (_u = (_t = (_s = event.properties) == null ? void 0 : _s.geocode) == null ? void 0 : _t.ugc) != null ? _u : [];
6225
- 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);
6226
- const mLocations = [...cLocations, ...iLocations].filter((v, i, a) => a.indexOf(v) === i).join("; ");
6227
- const mUgc = [...cUgc, ...iUgc].filter((v, i, a) => a.indexOf(v) === i);
6228
- bootstrap.cache.events.features[getIndex] = __spreadProps(__spreadValues({}, event), {
6229
- properties: __spreadProps(__spreadValues({}, event.properties), {
6230
- metadata: __spreadProps(__spreadValues({}, (_v = event == null ? void 0 : event.properties) == null ? void 0 : _v.metadata), {
6231
- history: mHistory
6232
- }),
6233
- locations: mLocations,
6234
- geocode: __spreadProps(__spreadValues({}, (_w = event == null ? void 0 : event.properties) == null ? void 0 : _w.geocode), {
6235
- ugc: mUgc
6236
- })
6237
- })
6238
- });
6239
- updateListener(bootstrap.cache.events.features[getIndex]);
6240
- } else {
6241
- features.push(event);
6242
- updateListener(event);
6243
- }
6085
+ return out;
6086
+ };
6087
+
6088
+ // src/@modules/@eas/eas.setSameHeader.ts
6089
+ var setSameHeader = (vtec2, repeats, sampleRate = 8e3, options = {}) => {
6090
+ var _a, _b;
6091
+ const preMarkSec = (_a = options.preMarkSec) != null ? _a : 0.3;
6092
+ const gapSec = (_b = options.gapSec) != null ? _b : 0.1;
6093
+ const bursts = [];
6094
+ const gap = new Int16Array(Math.floor(gapSec * sampleRate));
6095
+ for (let i = 0; i < repeats; i++) {
6096
+ const bodyBits = setAsciiToBits(vtec2);
6097
+ const body = setAFSK(bodyBits, sampleRate);
6098
+ const extendedBodyDuration = Math.round(preMarkSec * sampleRate);
6099
+ const extendedBody = new Int16Array(extendedBodyDuration + gap.length);
6100
+ for (let j2 = 0; j2 < extendedBodyDuration; j2++) {
6101
+ extendedBody[j2] = Math.round(body[j2 % body.length] * 0.2);
6244
6102
  }
6103
+ extendedBody.set(gap, extendedBodyDuration);
6104
+ bursts.push(extendedBody);
6105
+ if (i !== repeats - 1) bursts.push(gap);
6245
6106
  }
6246
- });
6107
+ return getMergedPCM16(bursts);
6108
+ };
6109
+
6110
+ // src/@modules/@eas/eas.setAttentionTone.ts
6111
+ var setAttentionTone = (ms, sampleRate) => {
6112
+ const len = Math.floor(ms * sampleRate);
6113
+ const out = new Int16Array(len);
6114
+ const f1 = 853;
6115
+ const f2 = 960;
6116
+ const twoPi = Math.PI * 2;
6117
+ const amp = 0.1;
6118
+ const fadeLen = Math.floor(sampleRate * 0);
6119
+ for (let i = 0; i < len; i++) {
6120
+ const t = i / sampleRate;
6121
+ const s = Math.sin(twoPi * f1 * t) + Math.sin(twoPi * f2 * t);
6122
+ let gain = 1;
6123
+ if (i < fadeLen) gain = i / fadeLen;
6124
+ else if (i > len - fadeLen) gain = (len - i) / fadeLen;
6125
+ const v = Math.max(-1, Math.min(1, s / 2 * amp * gain));
6126
+ out[i] = Math.round(v * 32767);
6127
+ }
6128
+ return out;
6129
+ };
6130
+
6131
+ // src/@modules/@eas/eas.setNoise.ts
6132
+ var setNoise = (int16, noiseLevel = 0.02) => {
6133
+ const x = getPCMToFloat(int16);
6134
+ for (let i = 0; i < x.length; i++) x[i] += (Math.random() * 2 - 1) * noiseLevel;
6135
+ let peak = 0;
6136
+ for (let i = 0; i < x.length; i++) peak = Math.max(peak, Math.abs(x[i]));
6137
+ if (peak > 1) for (let i = 0; i < x.length; i++) x[i] *= 0.98 / peak;
6138
+ return getFloatPCM16(x);
6139
+ };
6247
6140
 
6248
- // src/@manager/manager.rmEvent.ts
6249
- var rmEvent = (event) => {
6250
- const getEvent = bootstrap.cache.events.features.find((f) => {
6251
- var _a, _b, _c, _d;
6252
- 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);
6253
- });
6254
- const cachedStatus = event.properties.status;
6255
- event.properties.expires = (/* @__PURE__ */ new Date()).toISOString();
6256
- event.properties.status = `Expired`;
6257
- event.properties.status_metadata.is_expired = true;
6258
- if (getEvent) {
6259
- setEventEmit({
6260
- event: `onEventStatus`,
6261
- metadata: {
6262
- type: `Removed`,
6263
- event
6264
- },
6265
- message: `[Removed] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
6266
- });
6267
- setEventEmit({ event: `onExpiredProduct`, metadata: event });
6268
- if (cachedStatus != `Statement`) updateListener(event);
6269
- bootstrap.cache.events.features.splice(bootstrap.cache.events.features.indexOf(getEvent), 1);
6270
- bootstrap.cache.hashes = bootstrap.cache.hashes.filter((hash) => hash.tracking !== event.properties.metadata.tracking);
6141
+ // src/@modules/@eas/eas.getPCM16.ts
6142
+ var getPCM16 = (samples, sampleRate) => {
6143
+ let o = 0;
6144
+ const bytesPerSample = 2;
6145
+ const blockAlign = 1 * bytesPerSample;
6146
+ const byteRate = sampleRate * blockAlign;
6147
+ const subchunk2Size = samples.length * bytesPerSample;
6148
+ const chunkSize = 36 + subchunk2Size;
6149
+ const buffer = Buffer.alloc(44 + subchunk2Size);
6150
+ buffer.write("RIFF", o);
6151
+ o += 4;
6152
+ buffer.writeUInt32LE(chunkSize, o);
6153
+ o += 4;
6154
+ buffer.write("WAVE", o);
6155
+ o += 4;
6156
+ buffer.write("fmt ", o);
6157
+ o += 4;
6158
+ buffer.writeUInt32LE(16, o);
6159
+ o += 4;
6160
+ buffer.writeUInt16LE(1, o);
6161
+ o += 2;
6162
+ buffer.writeUInt16LE(1, o);
6163
+ o += 2;
6164
+ buffer.writeUInt32LE(sampleRate, o);
6165
+ o += 4;
6166
+ buffer.writeUInt32LE(byteRate, o);
6167
+ o += 4;
6168
+ buffer.writeUInt16LE(blockAlign, o);
6169
+ o += 2;
6170
+ buffer.writeUInt16LE(16, o);
6171
+ o += 2;
6172
+ buffer.write("data", o);
6173
+ o += 4;
6174
+ buffer.writeUInt32LE(subchunk2Size, o);
6175
+ o += 4;
6176
+ for (let i = 0; i < samples.length; i++, o += 2) {
6177
+ buffer.writeInt16LE(samples[i].value, o);
6271
6178
  }
6272
- setEventEmit({
6273
- event: `onEventCache`,
6274
- metadata: bootstrap.cache.events,
6275
- limited: true
6276
- });
6179
+ return buffer;
6277
6180
  };
6278
6181
 
6279
- // src/@modules/@utilities/utilities.getLatestIssuance.ts
6280
- var getLatestIssuance = () => {
6281
- const now = /* @__PURE__ */ new Date();
6282
- const current = now.getUTCHours() * 100 + now.getUTCMinutes();
6283
- const issuances = [100, 600, 1300, 1630, 2e3];
6284
- let latest = issuances[0];
6285
- for (const issuance of issuances) {
6286
- if (current >= issuance) {
6287
- latest = issuance;
6182
+ // src/@modules/@eas/eas.getTTS.ts
6183
+ import { platform } from "os";
6184
+ import { writeFileSync } from "fs";
6185
+ import { execSync } from "child_process";
6186
+ var getTTS = (text2, outputPath) => __async(null, null, function* () {
6187
+ const vPlatform = platform();
6188
+ switch (vPlatform) {
6189
+ case "win32": {
6190
+ try {
6191
+ const txtPath = outputPath + ".txt";
6192
+ writeFileSync(txtPath, text2, "utf8");
6193
+ const command = [
6194
+ "Add-Type -AssemblyName System.Speech;",
6195
+ `$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;`,
6196
+ `$text = Get-Content -Raw -LiteralPath '${txtPath}';`,
6197
+ `$speak.SetOutputToWaveFile('${outputPath}');`,
6198
+ `$speak.Speak($text);`,
6199
+ `$speak.Dispose();`
6200
+ ].join(" ");
6201
+ execSync(`powershell -Command "${command}"`, { stdio: "inherit" });
6202
+ } catch (error) {
6203
+ console.error("Error occurred while generating TTS:", error);
6204
+ }
6205
+ break;
6288
6206
  }
6207
+ case "linux":
6208
+ try {
6209
+ execSync(`espeak -w "${outputPath}" "${text2.replace(/"/g, '\\"')}"`);
6210
+ } catch (e) {
6211
+ }
6212
+ break;
6213
+ default:
6214
+ break;
6289
6215
  }
6290
- return latest.toString().padStart(4, "0");
6291
- };
6216
+ });
6292
6217
 
6293
- // src/@dictionaries/dictionaries.states.ts
6294
- var dict_states = {
6295
- "AL": "Alabama",
6296
- "AK": "Alaska",
6297
- "AZ": "Arizona",
6298
- "AR": "Arkansas",
6299
- "CA": "California",
6300
- "CO": "Colorado",
6301
- "CT": "Connecticut",
6302
- "DE": "Delaware",
6303
- "FL": "Florida",
6304
- "GA": "Georgia",
6305
- "HI": "Hawaii",
6306
- "ID": "Idaho",
6307
- "IL": "Illinois",
6308
- "IN": "Indiana",
6309
- "IA": "Iowa",
6310
- "KS": "Kansas",
6311
- "KY": "Kentucky",
6312
- "LA": "Louisiana",
6313
- "ME": "Maine",
6314
- "MD": "Maryland",
6315
- "MA": "Massachusetts",
6316
- "MI": "Michigan",
6317
- "MN": "Minnesota",
6318
- "MS": "Mississippi",
6319
- "MO": "Missouri",
6320
- "MT": "Montana",
6321
- "NE": "Nebraska",
6322
- "NV": "Nevada",
6323
- "NH": "New Hampshire",
6324
- "NJ": "New Jersey",
6325
- "NM": "New Mexico",
6326
- "NY": "New York",
6327
- "NC": "North Carolina",
6328
- "ND": "North Dakota",
6329
- "OH": "Ohio",
6330
- "OK": "Oklahoma",
6331
- "OR": "Oregon",
6332
- "PA": "Pennsylvania",
6333
- "RI": "Rhode Island",
6334
- "SC": "South Carolina",
6335
- "SD": "South Dakota",
6336
- "TN": "Tennessee",
6337
- "TX": "Texas",
6338
- "UT": "Utah",
6339
- "VT": "Vermont",
6340
- "VA": "Virginia",
6341
- "WA": "Washington",
6342
- "WV": "West Virginia",
6343
- "WI": "Wisconsin",
6344
- "WY": "Wyoming",
6345
- "DC": "District of Columbia"
6218
+ // src/@modules/@eas/eas.getCleanDescription.ts
6219
+ var getCleanDescription = (message) => {
6220
+ const patches = [
6221
+ { regex: /\.{3,}/g, replacement: ". " },
6222
+ { regex: /\bUTC\b/g, replacement: "Coordinated Universal Time" },
6223
+ { regex: /\bGMT\b/g, replacement: "Greenwich Mean Time" },
6224
+ { regex: /\bEST\b(?!\w)/g, replacement: "Eastern Standard Time" },
6225
+ { regex: /\bEDT\b(?!\w)/g, replacement: "Eastern Daylight Time" },
6226
+ { regex: /\bCST\b(?!\w)/g, replacement: "Central Standard Time" },
6227
+ { regex: /\bCDT\b(?!\w)/g, replacement: "Central Daylight Time" },
6228
+ { regex: /\bMST\b(?!\w)/g, replacement: "Mountain Standard Time" },
6229
+ { regex: /\bMDT\b(?!\w)/g, replacement: "Mountain Daylight Time" },
6230
+ { regex: /\bPST\b(?!\w)/g, replacement: "Pacific Standard Time" },
6231
+ { regex: /\bPDT\b(?!\w)/g, replacement: "Pacific Daylight Time" },
6232
+ { regex: /\bAKST\b(?!\w)/g, replacement: "Alaska Standard Time" },
6233
+ { regex: /\bAKDT\b(?!\w)/g, replacement: "Alaska Daylight Time" },
6234
+ { regex: /\bHST\b(?!\w)/g, replacement: "Hawaii Standard Time" },
6235
+ { regex: /\bHDT\b(?!\w)/g, replacement: "Hawaii Daylight Time" },
6236
+ { regex: /\bmph\b(?!\w)/g, replacement: "miles per hour" },
6237
+ { regex: /\bkm\/h\b(?!\w)/g, replacement: "kilometers per hour" },
6238
+ { regex: /\bkmh\b(?!\w)/g, replacement: "kilometers per hour" },
6239
+ { regex: /\bkt\b(?!\w)/g, replacement: "knots" },
6240
+ { regex: /\bNE\b(?!\w)/g, replacement: "northeast" },
6241
+ { regex: /\bNW\b(?!\w)/g, replacement: "northwest" },
6242
+ { regex: /\bSE\b(?!\w)/g, replacement: "southeast" },
6243
+ { regex: /\bSW\b(?!\w)/g, replacement: "southwest" },
6244
+ { regex: /\bNM\b(?!\w)/g, replacement: "nautical miles" },
6245
+ { regex: /\bdeg\b(?!\w)/g, replacement: "degrees" },
6246
+ { regex: /\btstm\b(?!\w)/g, replacement: "thunderstorm" },
6247
+ { regex: /\bmm\b(?!\w)/g, replacement: "millimeters" },
6248
+ { regex: /\bcm\b(?!\w)/g, replacement: "centimeters" },
6249
+ { regex: /\bin.\b(?!\w)/g, replacement: "inches" },
6250
+ { regex: /\bft\b(?!\w)/g, replacement: "feet" },
6251
+ { regex: /\bmi\b(?!\w)/g, replacement: "miles" },
6252
+ { regex: /\bhr\b(?!\w)/g, replacement: "hour" },
6253
+ { regex: /\bhourly\b(?!\w)/g, replacement: "per hour" },
6254
+ { regex: /\bkg\b(?!\w)/g, replacement: "kilograms" },
6255
+ { regex: /\bg\/kg\b(?!\w)/g, replacement: "grams per kilogram" },
6256
+ { regex: /\bmb\b(?!\w)/g, replacement: "millibars" },
6257
+ { regex: /\bhPa\b(?!\w)/g, replacement: "hectopascals" },
6258
+ { regex: /\bPa\b(?!\w)/g, replacement: "pascals" },
6259
+ { regex: /\bKPa\b(?!\w)/g, replacement: "kilopascals" },
6260
+ { regex: /\bC\/hr\b(?!\w)/g, replacement: "degrees Celsius per hour" },
6261
+ { regex: /\bF\/hr\b(?!\w)/g, replacement: "degrees Fahrenheit per hour" },
6262
+ { regex: /\bC\/min\b(?!\w)/g, replacement: "degrees Celsius per minute" },
6263
+ { regex: /\bF\/min\b(?!\w)/g, replacement: "degrees Fahrenheit per minute" },
6264
+ { regex: /\bC\b(?!\w)/g, replacement: "degrees Celsius" },
6265
+ { regex: /\bF\b(?!\w)/g, replacement: "degrees Fahrenheit" }
6266
+ ];
6267
+ const hours = {
6268
+ 0: "twelve",
6269
+ 1: "one",
6270
+ 2: "two",
6271
+ 3: "three",
6272
+ 4: "four",
6273
+ 5: "five",
6274
+ 6: "six",
6275
+ 7: "seven",
6276
+ 8: "eight",
6277
+ 9: "nine",
6278
+ 10: "ten",
6279
+ 11: "eleven",
6280
+ 12: "twelve"
6281
+ };
6282
+ const minWord = (m) => m === 0 ? "o'clock" : m < 10 ? `oh ${m}` : `${m}`;
6283
+ const fmt = (h, m, ap) => `${hours[h % 12]} ${minWord(m)} ${ap}`;
6284
+ for (const { regex, replacement } of patches) {
6285
+ message = message.replace(regex, replacement);
6286
+ }
6287
+ return message.replace(/'/g, "''").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(/\b(\d{1,2})\s+(AM|PM)\b/gi, (_, h, ap) => fmt(+h, 0, ap.toUpperCase())).replace(/\*+/g, " ").replace(/-/g, " ").replace(/\n/g, " ").trim();
6346
6288
  };
6347
6289
 
6348
- // src/@building/building.attachments.ts
6349
- var getEventAttachments = (event) => {
6350
- var _a, _b, _c, _d, _e, _f, _g;
6351
- let attachments = [];
6352
- const issuanceTime = getLatestIssuance();
6353
- const spcNumber = (_b = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.discussion_parameters) == null ? void 0 : _b.discussion_number;
6354
- const watchNumber = (_d = (_c = event == null ? void 0 : event.properties) == null ? void 0 : _c.watch_parameters) == null ? void 0 : _d.watch_number;
6355
- const locations = (_e = event == null ? void 0 : event.properties) == null ? void 0 : _e.locations_array;
6356
- const events = [
6357
- { target: "Day 1", attachment: `https://www.spc.noaa.gov/products/outlook/day1otlk_${issuanceTime}.png` },
6358
- { target: "Day 2", attachment: `https://www.spc.noaa.gov/products/outlook/day2otlk.png` },
6359
- { target: "Day 3", attachment: `https://www.spc.noaa.gov/products/outlook/day3otlk.png` },
6360
- { target: "Mesoscale Discussion", attachment: `https://www.spc.noaa.gov/products/md/mcd${spcNumber}.png` },
6361
- { target: "Tornado Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
6362
- { target: "PDS Tornado Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
6363
- { target: "Severe Thunderstorm Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
6364
- { target: "PDS Severe Thunderstorm Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` }
6365
- ];
6366
- if (events.find((e) => e.target === event.properties.event)) {
6367
- attachments.push({ name: `Image: Graphic`, link: events.find((e) => e.target === event.properties.event).attachment });
6290
+ // src/@modules/@eas/eas.setEasTone.ts
6291
+ import { join } from "path";
6292
+ import { existsSync, mkdirSync, readFileSync, writeFileSync as writeFileSync2, unlinkSync } from "fs";
6293
+ import { execSync as execSync2 } from "child_process";
6294
+ import { platform as platform2 } from "os";
6295
+ var setEasTone = (options) => __async(null, null, function* () {
6296
+ var _a;
6297
+ const tick = performance.now();
6298
+ const settings = bootstrap.settings;
6299
+ const directory = settings.GlobalSettings.ArchiveSettings.EasDirectory;
6300
+ const prefix = settings.GlobalSettings.ArchiveSettings.EasToneout;
6301
+ let message = options.message;
6302
+ let header = options.header;
6303
+ let title = ((_a = options.title) != null ? _a : `${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, "")}`).replace(/[\\:*?"<>|]/g, "_").replace(/\s+/g, " ").trim();
6304
+ if (!message || !header) {
6305
+ setWarning({
6306
+ title: `EAS`,
6307
+ message: `Message and header are required to generate an EAS tone.`
6308
+ });
6309
+ return null;
6368
6310
  }
6369
- for (const location of locations) {
6370
- if (dict_expressions.location.test(location)) {
6371
- const lines = [`Northern`, `Southern`, `Eastern`, `Western`, `Inland`, `Costal`, `County`];
6372
- const county = (_f = location == null ? void 0 : location.split(",")[0]) == null ? void 0 : _f.trim().replace(new RegExp(`^(${lines.join("|")}) `), "");
6373
- const state = dict_states[(_g = location == null ? void 0 : location.split(",")[1]) == null ? void 0 : _g.trim()];
6374
- const feeds = bootstrap.database.prepare(`SELECT * FROM broadcastify WHERE state = ? AND county = ?`).all(state, county).sort((a, b) => {
6375
- const typeOrder = ["Other", "Public Safety"];
6376
- const indexA = typeOrder.indexOf(a.type);
6377
- const indexB = typeOrder.indexOf(b.type);
6378
- return indexA - indexB;
6379
- });
6380
- const tags = bootstrap.settings.BroadcastifySettings.BroadcastifyTags;
6381
- const filtered = feeds.filter((feed) => tags.includes(feed.type));
6382
- if (filtered.length > 0) {
6383
- filtered.map((filtered2) => {
6384
- if (!attachments.some((a) => a.link === filtered2.link)) {
6385
- attachments.push({ name: `${filtered2.type}: ${filtered2.feed}`, link: filtered2.link });
6311
+ let buffTTS;
6312
+ let buffRadio;
6313
+ let buffFull = [];
6314
+ if (!existsSync(directory)) {
6315
+ mkdirSync(directory, { recursive: true });
6316
+ }
6317
+ if (!existsSync(join(directory, `/tts`))) {
6318
+ mkdirSync(join(directory, `/tts`), { recursive: true });
6319
+ }
6320
+ if (!existsSync(join(directory, `/encoded`))) {
6321
+ mkdirSync(join(directory, `/encoded`), { recursive: true });
6322
+ }
6323
+ const tmpTTS = join(directory, `/tts/${title}.wav`);
6324
+ const outTTS = join(directory, `/encoded/${title}.wav`);
6325
+ const vPlatform = platform2();
6326
+ if (vPlatform === "darwin") {
6327
+ setWarning({
6328
+ title: `EAS`,
6329
+ message: `EAS tone generation is not supported on macOS.`
6330
+ });
6331
+ return null;
6332
+ }
6333
+ yield new Promise((resolve6, reject) => {
6334
+ const tMsg = getCleanDescription(message);
6335
+ getTTS(tMsg, tmpTTS).then(() => {
6336
+ resolve6();
6337
+ });
6338
+ });
6339
+ if (!existsSync(tmpTTS)) {
6340
+ return null;
6341
+ }
6342
+ buffTTS = readFileSync(tmpTTS);
6343
+ const vWav = getWavPCM16(buffTTS);
6344
+ const vSamples = getSampledPCM16(vWav.samples, vWav.sampleRate, 8e3);
6345
+ const vRadio = setRadioEffect(vSamples, 8e3);
6346
+ if (existsSync(prefix)) {
6347
+ let tBuffer = readFileSync(prefix);
6348
+ let tWav = getWavPCM16(tBuffer);
6349
+ if (tWav == null) {
6350
+ try {
6351
+ const converted = join(directory, `/tts/${title}.converted.wav`);
6352
+ execSync2(`ffmpeg -y -i "${prefix}" -ar 8000 -ac 1 -sample_fmt s16 "${converted}"`, { stdio: "ignore" });
6353
+ if (existsSync(converted)) {
6354
+ tBuffer = readFileSync(converted);
6355
+ tWav = getWavPCM16(tBuffer);
6356
+ try {
6357
+ unlinkSync(converted);
6358
+ } catch (e) {
6386
6359
  }
6387
- });
6360
+ }
6361
+ } catch (e) {
6388
6362
  }
6389
6363
  }
6364
+ if (tWav == null) {
6365
+ 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.` });
6366
+ return null;
6367
+ }
6368
+ const tSamples = tWav.sampleRate != 8e3 ? getSampledPCM16(tWav.samples, tWav.sampleRate, 8e3) : tWav.samples;
6369
+ buffRadio = setRadioEffect(tSamples, 8e3);
6390
6370
  }
6391
- return attachments;
6371
+ buffFull = buffRadio != null ? [buffRadio, new Int16Array(Math.floor(0.5 * 8e3))] : [];
6372
+ buffFull.push(
6373
+ setSameHeader(header, 3, 8e3, {
6374
+ preMarkSec: 1.1,
6375
+ gapSec: 0.5
6376
+ }),
6377
+ new Int16Array(Math.floor(0.5 * 8e3)),
6378
+ setAttentionTone(8, 8e3),
6379
+ new Int16Array(Math.floor(0.5 * 8e3)),
6380
+ vRadio
6381
+ );
6382
+ for (let i = 0; i < 3; i++) {
6383
+ buffFull.push(setSameHeader(header, 1, 8e3, { preMarkSec: 0.5, gapSec: 0.1 }));
6384
+ buffFull.push(new Int16Array(Math.floor(0.5 * 8e3)));
6385
+ }
6386
+ const aSamples = getMergedPCM16(buffFull);
6387
+ const aFinal = setNoise(aSamples, 2e-3);
6388
+ const aBuffer = getPCM16(Array.from(aFinal).map((v) => ({ value: v })), 8e3);
6389
+ writeFileSync2(outTTS, aBuffer);
6390
+ try {
6391
+ unlinkSync(tmpTTS);
6392
+ } catch (e) {
6393
+ }
6394
+ setDebug({ title: `@eas.setEasTone`, message: `EAS tone generation took ${performance.now() - tick} ms` });
6395
+ return outTTS;
6396
+ });
6397
+
6398
+ // src/@parsers/@text/text.getEmbed.ts
6399
+ var getEmebed = (event) => {
6400
+ 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;
6401
+ const line = (label, value, condition = true) => condition && value ? `${label} ${value}` : null;
6402
+ const isStatement = event.properties.status_metadata.is_statement;
6403
+ const isExpired = event.properties.status_metadata.is_expired;
6404
+ return [
6405
+ line(`**Locations:**`, (_b = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.locations) == null ? void 0 : _b.slice(0, 100)),
6406
+ line(`**Issued:**`, `<t:${Math.floor(new Date(event.properties.issued).getTime() / 1e3)}:R>`, !isExpired),
6407
+ line(`**Expires:**`, `<t:${Math.floor(new Date(event.properties.expires).getTime() / 1e3)}:R>`, !isStatement),
6408
+ line(`**Damage Threat:**`, (_d = (_c = event == null ? void 0 : event.properties) == null ? void 0 : _c.parameters) == null ? void 0 : _d.damage_threat, !isExpired),
6409
+ line(`**Flood Threat:**`, (_f = (_e = event == null ? void 0 : event.properties) == null ? void 0 : _e.parameters) == null ? void 0 : _f.flood_threat, !isExpired),
6410
+ line(`**Tornado Threat:**`, (_h = (_g = event == null ? void 0 : event.properties) == null ? void 0 : _g.parameters) == null ? void 0 : _h.tornado_threat, !isExpired),
6411
+ line(`**Estimated Wind Gusts:**`, `${(_j = (_i = event == null ? void 0 : event.properties) == null ? void 0 : _i.parameters) == null ? void 0 : _j.estimated_wind_gusts} ${((_l = (_k = event == null ? void 0 : event.properties) == null ? void 0 : _k.parameters) == null ? void 0 : _l.wind_threat) ? ` (${(_n = (_m = event == null ? void 0 : event.properties) == null ? void 0 : _m.parameters) == null ? void 0 : _n.wind_threat})` : ""}`, !isExpired && ((_p = (_o = event == null ? void 0 : event.properties) == null ? void 0 : _o.parameters) == null ? void 0 : _p.estimated_wind_gusts) != null),
6412
+ line(`**Estimated Hail Size:**`, `${(_r = (_q = event == null ? void 0 : event.properties) == null ? void 0 : _q.parameters) == null ? void 0 : _r.estimated_hail_size} ${((_t = (_s = event == null ? void 0 : event.properties) == null ? void 0 : _s.parameters) == null ? void 0 : _t.hail_threat) ? ` (${(_v = (_u = event == null ? void 0 : event.properties) == null ? void 0 : _u.parameters) == null ? void 0 : _v.hail_threat})` : ""}`, !isExpired && ((_x = (_w = event == null ? void 0 : event.properties) == null ? void 0 : _w.parameters) == null ? void 0 : _x.estimated_hail_size) != null),
6413
+ line(`**Discussion:**`, (_z = (_y = event == null ? void 0 : event.properties) == null ? void 0 : _y.discussion_parameters) == null ? void 0 : _z.discussion_number, !isExpired),
6414
+ line(`**Concern:**`, (_B = (_A = event == null ? void 0 : event.properties) == null ? void 0 : _A.discussion_parameters) == null ? void 0 : _B.discussion_concerning, !isExpired),
6415
+ line(`**SPC Max Tornado Threat:**`, (_D = (_C = event == null ? void 0 : event.properties) == null ? void 0 : _C.discussion_parameters) == null ? void 0 : _D.discussion_max_tornado, !isExpired),
6416
+ line(`**SPC Max Hail Threat:**`, (_F = (_E = event == null ? void 0 : event.properties) == null ? void 0 : _E.discussion_parameters) == null ? void 0 : _F.discussion_max_hail, !isExpired),
6417
+ line(`**SPC Max Wind Threat:**`, (_H = (_G = event == null ? void 0 : event.properties) == null ? void 0 : _G.discussion_parameters) == null ? void 0 : _H.discussion_max_wind, !isExpired),
6418
+ line(`**SPC Watch Issuance Probability:**`, ((_J = (_I = event == null ? void 0 : event.properties) == null ? void 0 : _I.discussion_parameters) == null ? void 0 : _J.discussion_watch_issuance) ? `${(_L = (_K = event == null ? void 0 : event.properties) == null ? void 0 : _K.discussion_parameters) == null ? void 0 : _L.discussion_watch_issuance}%` : null, !isExpired),
6419
+ line(`**Watch Number:**`, (_N = (_M = event == null ? void 0 : event.properties) == null ? void 0 : _M.watch_parameters) == null ? void 0 : _N.watch_number, !isExpired),
6420
+ line(`**Strong Tornadoes Probability:**`, ((_P = (_O = event == null ? void 0 : event.properties) == null ? void 0 : _O.watch_parameters) == null ? void 0 : _P.strong_tornadoes_probability) ? `${(_R = (_Q = event == null ? void 0 : event.properties) == null ? void 0 : _Q.watch_parameters) == null ? void 0 : _R.strong_tornadoes_probability}%` : null, !isExpired),
6421
+ line(`**Additional Tornadoes Probability:**`, ((_T = (_S = event == null ? void 0 : event.properties) == null ? void 0 : _S.watch_parameters) == null ? void 0 : _T.additional_tornadoes_probability) ? `${(_V = (_U = event == null ? void 0 : event.properties) == null ? void 0 : _U.watch_parameters) == null ? void 0 : _V.additional_tornadoes_probability}%` : null, !isExpired),
6422
+ line(`**Combined Hail/Wind Probability:**`, ((_X = (_W = event == null ? void 0 : event.properties) == null ? void 0 : _W.watch_parameters) == null ? void 0 : _X.combined_hail_wind_probability) ? `${(_Z = (_Y = event == null ? void 0 : event.properties) == null ? void 0 : _Y.watch_parameters) == null ? void 0 : _Z.combined_hail_wind_probability}%` : null, !isExpired),
6423
+ line(`**Severe Hail Probability:**`, ((_$ = (__ = event == null ? void 0 : event.properties) == null ? void 0 : __.watch_parameters) == null ? void 0 : _$.severe_hail_probability) ? `${(_ba = (_aa = event == null ? void 0 : event.properties) == null ? void 0 : _aa.watch_parameters) == null ? void 0 : _ba.severe_hail_probability}%` : null, !isExpired),
6424
+ line(`**Hail >2in Probability:**`, ((_da = (_ca = event == null ? void 0 : event.properties) == null ? void 0 : _ca.watch_parameters) == null ? void 0 : _da.hail_2in_probability) ? `${(_fa = (_ea = event == null ? void 0 : event.properties) == null ? void 0 : _ea.watch_parameters) == null ? void 0 : _fa.hail_2in_probability}%` : null, !isExpired),
6425
+ line(`**Max Hail Inches:**`, (_ha = (_ga = event == null ? void 0 : event.properties) == null ? void 0 : _ga.watch_parameters) == null ? void 0 : _ha.max_hail_in, !isExpired),
6426
+ line(`**Severe Wind Probability:**`, ((_ja = (_ia = event == null ? void 0 : event.properties) == null ? void 0 : _ia.watch_parameters) == null ? void 0 : _ja.severe_wind_probability) ? `${(_la = (_ka = event == null ? void 0 : event.properties) == null ? void 0 : _ka.watch_parameters) == null ? void 0 : _la.severe_wind_probability}%` : null, !isExpired),
6427
+ line(`**Max Surface Wind:**`, (_na = (_ma = event == null ? void 0 : event.properties) == null ? void 0 : _ma.watch_parameters) == null ? void 0 : _na.max_wind_surface, !isExpired),
6428
+ line(`**Max Tops (x100 feet):**`, (_pa = (_oa = event == null ? void 0 : event.properties) == null ? void 0 : _oa.watch_parameters) == null ? void 0 : _pa.max_tops_x100feet, !isExpired),
6429
+ line(`**Tags:**`, ((_sa = (_ra = (_qa = event == null ? void 0 : event.properties) == null ? void 0 : _qa.parameters) == null ? void 0 : _ra.tags) == null ? void 0 : _sa.length) > 0 ? (_ua = (_ta = event == null ? void 0 : event.properties) == null ? void 0 : _ta.parameters) == null ? void 0 : _ua.tags.join(", ") : null, !isExpired),
6430
+ line(`**Sender:**`, ((_xa = (_wa = (_va = event == null ? void 0 : event.properties) == null ? void 0 : _va.geocode) == null ? void 0 : _wa.office) == null ? void 0 : _xa.name) ? `${(_Aa = (_za = (_ya = event == null ? void 0 : event.properties) == null ? void 0 : _ya.geocode) == null ? void 0 : _za.office) == null ? void 0 : _Aa.name} (${(_Da = (_Ca = (_Ba = event == null ? void 0 : event.properties) == null ? void 0 : _Ba.geocode) == null ? void 0 : _Ca.office) == null ? void 0 : _Da.office})` : (_Ga = (_Fa = (_Ea = event == null ? void 0 : event.properties) == null ? void 0 : _Ea.geocode) == null ? void 0 : _Fa.office) == null ? void 0 : _Ga.office),
6431
+ line(`**Tracking:**`, (_Ia = (_Ha = event == null ? void 0 : event.properties) == null ? void 0 : _Ha.metadata) == null ? void 0 : _Ia.tracking),
6432
+ line(`**Logs:**`, ((_La = (_Ka = (_Ja = event == null ? void 0 : event.properties) == null ? void 0 : _Ja.metadata) == null ? void 0 : _Ka.history) == null ? void 0 : _La.length) > 0 ? (_Na = (_Ma = event == null ? void 0 : event.properties) == null ? void 0 : _Ma.metadata) == null ? void 0 : _Na.history.length : null)
6433
+ ].filter(Boolean).join("\n");
6392
6434
  };
6393
6435
 
6394
- // src/@building/building.validate.ts
6395
- var validateEvents = (events) => __async(null, null, function* () {
6396
- var _a;
6397
- if (events.length === 0) return;
6398
- const configurations = bootstrap.settings;
6399
- const sets = {};
6400
- const bools = {};
6401
- const megered = __spreadValues(__spreadValues({}, configurations.GlobalSettings), configurations.GlobalSettings.EventFiltering);
6402
- for (const key in megered) {
6403
- const setting = megered[key];
6404
- if (Array.isArray(setting)) {
6405
- sets[key] = new Set(setting.map((item) => item.toLowerCase()));
6406
- }
6407
- if (typeof setting === "boolean") {
6408
- bools[key] = setting;
6409
- }
6436
+ // src/@modules/@utilities/utilities.createHttp.ts
6437
+ var createHttp = (options) => __async(null, null, function* () {
6438
+ var _a, _b, _c, _d;
6439
+ const requestOptions = {
6440
+ method: (_a = options.method) != null ? _a : "GET",
6441
+ headers: (_b = options.headers) != null ? _b : {
6442
+ "User-Agent": "AtmosphericX",
6443
+ "Accept": "application/geo+json, text/plain, */*; q=0.9",
6444
+ "Accept-Language": "en-US,en;q=0.9"
6445
+ },
6446
+ signal: AbortSignal.timeout((_c = options.timeout) != null ? _c : 1e4),
6447
+ redirect: "follow"
6448
+ };
6449
+ const returnHttp = function(error, status, message) {
6450
+ return { error, options: requestOptions, status, message };
6451
+ };
6452
+ if (options == null ? void 0 : options.formData) {
6453
+ requestOptions.body = options.formData;
6454
+ } else if ((options == null ? void 0 : options.body) != void 0) {
6455
+ requestOptions.body = options.body instanceof FormData ? options.body : typeof options.body === "string" ? options.body : JSON.stringify(options.body);
6410
6456
  }
6411
- const filterd = events.filter((event) => {
6412
- var _a2, _b, _c, _d, _e;
6413
- const define2 = getEventSignature(event);
6414
- const properties2 = define2.properties;
6415
- const zones = properties2.geocode.ugc;
6416
- const icao = properties2.geocode.office.office;
6417
- const enhancedEventName = properties2.event = getEventEnhancedName(event);
6418
- const filteredProperties = JSON.parse(JSON.stringify(properties2));
6419
- if ((filteredProperties == null ? void 0 : filteredProperties.metadata) && "ms" in filteredProperties.metadata) {
6420
- delete filteredProperties.metadata.ms;
6421
- }
6422
- filteredProperties.metadata = (_a2 = filteredProperties.metadata) != null ? _a2 : {};
6423
- properties2.metadata.hash = createHash("sha256").update(JSON.stringify(filteredProperties)).digest("hex");
6424
- properties2.metadata.attachments = getEventAttachments(event);
6425
- setEventEmit({ event: `onProductType${enhancedEventName.replace(/\s+/g, "")}`, metadata: define2 });
6426
- if (properties2.status_metadata.is_test) {
6427
- setEventEmit({ event: `onTestProduct`, metadata: define2 });
6428
- if (bools == null ? void 0 : bools.IgnoreTestProducts) return false;
6429
- }
6430
- if (properties2.status_metadata.is_expired) {
6431
- setEventEmit({ event: `onExpiredProduct`, metadata: define2 });
6432
- rmEvent(define2);
6433
- return false;
6457
+ try {
6458
+ const response2 = yield fetch(
6459
+ (_d = options == null ? void 0 : options.url) != null ? _d : `https://api.weather.gov/alerts/active`,
6460
+ requestOptions
6461
+ );
6462
+ const body = yield response2.text();
6463
+ if (!response2.ok) {
6464
+ return returnHttp(true, response2.status, `HTTP Status Code ${response2.status} (${response2.statusText})`);
6434
6465
  }
6435
- if (((_c = (_b = properties2.metadata) == null ? void 0 : _b.vtec) == null ? void 0 : _c.is_watch) && properties2.metadata.source != `events.api`) {
6436
- const isSPC = (_e = (_d = properties2.metadata) == null ? void 0 : _d.vtec) == null ? void 0 : _e.prediction_center;
6437
- setEventEmit({ event: isSPC ? `onStormPredictionWatch` : `onNonStormPredictionWatch`, metadata: define2 });
6438
- if ((bools == null ? void 0 : bools.SPCWatchesOnly) && !isSPC) {
6439
- return false;
6440
- }
6441
- if (!(bools == null ? void 0 : bools.SPCWatchesOnly) && isSPC) {
6442
- return false;
6443
- }
6466
+ return returnHttp(false, response2.status, body);
6467
+ } catch (error) {
6468
+ return returnHttp(true, 500, `Internal Server Error: ${error}`);
6469
+ }
6470
+ });
6471
+
6472
+ // src/@modules/@utilities/utilities.getMatched.ts
6473
+ var getMatched = (strings, string) => {
6474
+ const isMatched = strings.some((pattern) => {
6475
+ if (!pattern) return false;
6476
+ const lowerP = pattern.toLowerCase();
6477
+ const lowerS = string.toLowerCase();
6478
+ if (lowerP === "*" || lowerP === lowerS) return true;
6479
+ if (lowerP.includes("*")) {
6480
+ const regex = "^" + lowerP.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$";
6481
+ return new RegExp(regex).test(lowerS);
6444
6482
  }
6445
- for (const key in sets) {
6446
- const setting = sets[key];
6447
- if (key === "ListeningEvents" && setting.size > 0 && !setting.has(define2.properties.event.toLowerCase())) {
6448
- setEventEmit({
6449
- event: `onFilteredEvent`,
6450
- metadata: define2
6451
- });
6452
- return false;
6453
- }
6454
- if (key === "IgnoredEvents" && setting.size > 0 && setting.has(define2.properties.event.toLowerCase())) {
6455
- setEventEmit({
6456
- event: `onIgnoredEvent`,
6457
- metadata: define2
6458
- });
6459
- return false;
6460
- }
6461
- if (key === "ListeningICAO" && setting.size > 0 && icao != null && !setting.has(icao.toLowerCase())) {
6462
- setEventEmit({
6463
- event: `onFilteredICAO`,
6464
- metadata: define2
6483
+ return false;
6484
+ });
6485
+ return isMatched;
6486
+ };
6487
+
6488
+ // src/@manager/manager.updateListener.ts
6489
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3, readFileSync as readFileSync2, appendFileSync } from "fs";
6490
+ var updateListener = (event) => __async(null, null, function* () {
6491
+ var _a, _b, _c, _d, _e, _f;
6492
+ const tick = performance.now();
6493
+ const settings = bootstrap.settings;
6494
+ const listeners2 = settings.ListenerSettings;
6495
+ const properties2 = event.properties;
6496
+ const metadata = {
6497
+ file: null,
6498
+ eas: null,
6499
+ json: null,
6500
+ name: properties2.event,
6501
+ status: properties2.status,
6502
+ description: properties2.description,
6503
+ tracking: properties2.metadata.tracking,
6504
+ header: properties2.metadata.header,
6505
+ raw: properties2.metadata.raw,
6506
+ expired: properties2.status_metadata.is_expired,
6507
+ attachments: properties2.metadata.attachments
6508
+ };
6509
+ for (const listener2 of listeners2) {
6510
+ const events = listener2 == null ? void 0 : listener2.events;
6511
+ const webhook = listener2 == null ? void 0 : listener2.webhook;
6512
+ const uploads = listener2 == null ? void 0 : listener2.uploads;
6513
+ const isMatched = getMatched(events != null ? events : [], metadata.name);
6514
+ if ((events == null ? void 0 : events.length) == 0 || isMatched) {
6515
+ if (uploads == null ? void 0 : uploads.eas) {
6516
+ metadata.eas = yield setEasTone({
6517
+ title: `${metadata.name}_${metadata.status}_${metadata.tracking}`,
6518
+ message: metadata.description,
6519
+ header: metadata.header
6465
6520
  });
6466
- return false;
6467
6521
  }
6468
- if (key === "IgnoredICAO" && setting.size > 0 && icao != null && setting.has(icao.toLowerCase())) {
6469
- setEventEmit({
6470
- event: `onIgnoredICAO`,
6471
- metadata: define2
6472
- });
6473
- return false;
6522
+ if (uploads == null ? void 0 : uploads.file) {
6523
+ const fDestination = settings.GlobalSettings.ArchiveSettings.TextDirectory;
6524
+ if (fDestination) {
6525
+ const file = `${fDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.txt`.replace(/[\\:*?"<>|]/g, "_").replace(/\s+/g, " ").trim();
6526
+ if (!existsSync2(fDestination)) {
6527
+ mkdirSync2(fDestination, { recursive: true });
6528
+ }
6529
+ if (existsSync2(file)) {
6530
+ appendFileSync(file, metadata.raw);
6531
+ } else {
6532
+ writeFileSync3(file, metadata.raw);
6533
+ }
6534
+ }
6535
+ metadata.file = metadata.raw;
6474
6536
  }
6475
- if (key === "ListeningUGC" && setting.size > 0 && zones.length > 0 && !zones.some((ugc2) => setting.has(ugc2.toLowerCase()))) {
6476
- setEventEmit({
6477
- event: `onFilteredUGC`,
6478
- metadata: define2
6479
- });
6480
- return false;
6537
+ if (uploads == null ? void 0 : uploads.event) {
6538
+ const eDestination = settings.GlobalSettings.ArchiveSettings.EventDirectory;
6539
+ if (eDestination) {
6540
+ const file = `${eDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.json`.replace(/[\\:*?"<>|]/g, "_").replace(/\s+/g, " ").trim();
6541
+ if (!existsSync2(eDestination)) {
6542
+ mkdirSync2(eDestination, { recursive: true });
6543
+ }
6544
+ writeFileSync3(file, JSON.stringify(getCleanedEvent(event), null, 2));
6545
+ }
6546
+ metadata.json = JSON.stringify(getCleanedEvent(event), null, 2);
6481
6547
  }
6482
- if (key === "ListeningStates" && setting.size > 0 && zones.length > 0 && !zones.some((ugc2) => setting.has(ugc2.substring(0, 2).toLowerCase()))) {
6483
- setEventEmit({
6484
- event: `onFilteredState`,
6485
- metadata: define2
6548
+ if ((webhook == null ? void 0 : webhook.enabled) && (webhook == null ? void 0 : webhook.destination)) {
6549
+ const isRatelimited = setTimeoutAction({ identifier: webhook.destination, interval: ((_a = webhook.ratelimit) != null ? _a : 2) * 2, max: (_b = webhook.ratelimit) != null ? _b : 2, addTime: true });
6550
+ const form = new FormData();
6551
+ const embed = {
6552
+ title: `${metadata.name} (${metadata.status})`,
6553
+ description: getEmebed(event),
6554
+ fields: [],
6555
+ color: 16711680,
6556
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6557
+ footer: { text: (_c = webhook.title) != null ? _c : `AtmosphericX` }
6558
+ };
6559
+ if (isRatelimited.limited) {
6560
+ return;
6561
+ }
6562
+ if (metadata.description && !metadata.expired) {
6563
+ if (metadata.description.length > 900) {
6564
+ metadata.description = metadata.description.substring(0, 900) + "\n\n[Message truncated due to length]";
6565
+ }
6566
+ embed.fields.push({
6567
+ name: "Description",
6568
+ value: metadata.description ? "```\n" + metadata.description.split("\n").map((l) => l.trim()).filter(Boolean).join("\n") + "\n```" : ""
6569
+ });
6570
+ }
6571
+ if (((_d = metadata.attachments) == null ? void 0 : _d.length) > 0) {
6572
+ metadata.attachments = metadata.attachments.slice(0, 5);
6573
+ embed.fields.push({
6574
+ name: "Attachments",
6575
+ value: metadata.attachments.map((attachment) => `- [${attachment.name.length > 45 ? attachment.name.substring(0, 45) + "..." : attachment.name}](${attachment.link})`).join("\n")
6576
+ });
6577
+ }
6578
+ if (uploads == null ? void 0 : uploads.file) {
6579
+ form.append("fUpload", new Blob([Buffer.from(metadata.file)], { type: "application/text" }), `${properties2.event}_${properties2.status}_${properties2.metadata.tracking}.txt`);
6580
+ }
6581
+ if (uploads == null ? void 0 : uploads.event) {
6582
+ form.append("fUpload2", new Blob([Buffer.from(metadata.json)], { type: "application/json" }), `${properties2.event}_${properties2.status}_${properties2.metadata.tracking}.json`);
6583
+ }
6584
+ if (uploads == null ? void 0 : uploads.eas) {
6585
+ if (metadata.eas) {
6586
+ const file = readFileSync2(metadata.eas);
6587
+ form.append("fEas", new Blob([Buffer.from(file)], { type: "audio/mpeg" }), `${properties2.event}_${properties2.status}_${properties2.metadata.tracking}_eas.mp3`);
6588
+ }
6589
+ }
6590
+ form.append("payload_json", JSON.stringify({
6591
+ username: (_e = webhook.title) != null ? _e : "AtmosphericX",
6592
+ content: (_f = webhook.message) != null ? _f : "",
6593
+ embeds: [embed]
6594
+ }));
6595
+ yield createHttp({
6596
+ url: webhook.destination,
6597
+ timeout: 15e3,
6598
+ method: `POST`,
6599
+ body: form
6486
6600
  });
6487
- return false;
6488
6601
  }
6489
6602
  }
6490
- return true;
6491
- });
6492
- if (!((_a = configurations == null ? void 0 : configurations.GlobalSettings) == null ? void 0 : _a.DisableGeometryParsing)) {
6493
- for (const event of filterd) {
6494
- event.geometry = yield getEventGeometry(event);
6495
- }
6496
- }
6497
- if (filterd.length > 0) {
6498
- for (const event of filterd) {
6499
- yield mkEvent(event);
6500
- }
6501
6603
  }
6502
- yield updateNode();
6503
- setEventEmit({
6504
- event: `onEventCache`,
6505
- metadata: bootstrap.cache.events,
6506
- limited: true
6507
- });
6604
+ setDebug({ title: `@manager.updateListener`, message: `Listener took ${performance.now() - tick} ms` });
6508
6605
  });
6509
6606
 
6510
- // src/@events/events.text.ts
6511
- var text = (stanza) => __async(null, null, function* () {
6512
- var _a, _b, _c;
6513
- let processed = [];
6514
- 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 !== "$$");
6515
- if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
6516
- for (const message of getMessages) {
6517
- const tick = performance.now();
6518
- const attributes = stanza == null ? void 0 : stanza.attributes;
6519
- const props = properties({ message, attributes });
6520
- const header = getEventHeader({ properties: props, getType: stanza.getType });
6521
- const issued = new Date(attributes.issue);
6522
- const expires = new Date(issued.getTime() + 12 * 60 * 60 * 1e3);
6523
- let event = Object.keys(dict_matches).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
6524
- let isStatement = false;
6525
- if (!event) {
6526
- event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
6527
- isStatement = true;
6528
- }
6529
- processed.push({
6530
- type: `Feature`,
6531
- geometry: {
6532
- type: `Point`,
6533
- coordinates: []
6534
- },
6535
- properties: __spreadProps(__spreadValues({
6536
- event,
6537
- parent: event,
6538
- status: isStatement ? `Statement` : `Issued`,
6539
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
6540
- expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
6541
- }, props), {
6542
- metadata: {
6543
- ms: performance.now() - tick,
6544
- source: `events.text`,
6545
- tracking: getEventTracking({ type: `RAW`, stanza, attributes, properties: props }),
6546
- header,
6547
- vtec: null,
6548
- hvtec: null,
6549
- raw: message,
6550
- history: [
6551
- {
6552
- description: props.description,
6553
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
6554
- status: `Issued`
6555
- }
6556
- ]
6557
- }
6558
- })
6559
- });
6607
+ // src/@modules/@utilities/utilities.getShapeNearestPoint.ts
6608
+ var getShapeNearestPoint = (coordinates, point) => {
6609
+ if (!coordinates || !point) {
6610
+ return { proximity: false, point: [0, 0], distance: null };
6560
6611
  }
6561
- validateEvents(processed);
6562
- });
6563
-
6564
- // src/@parsers/@ugc/ugc.header.ts
6565
- var getUGCHeader = (message) => {
6566
- const start = message.search(dict_expressions.ugc1);
6567
- const sub = message.substring(start);
6568
- const end = sub.search(dict_expressions.ugc2);
6569
- const fin = sub.substring(0, end).replace(/\s+/g, "").slice(0, -1);
6570
- return fin != null ? fin : null;
6571
- };
6572
-
6573
- // src/@parsers/@ugc/ugc.zones.ts
6574
- var getZones = (header) => {
6575
- const splits = header.split("-");
6576
- const zones = [];
6577
- let state = splits[0].substring(0, 2);
6578
- const format = splits[0].substring(2, 3);
6579
- for (const part of splits) {
6580
- if (/^[A-Z]/.test(part)) {
6581
- state = part.substring(0, 2);
6582
- if (part.includes(">")) {
6583
- const [start, end] = part.split(">");
6584
- const startNum = parseInt(start.substring(3), 10);
6585
- const endNum = parseInt(end, 10);
6586
- for (let j2 = startNum; j2 <= endNum; j2++) {
6587
- zones.push(`${state}${format}${j2.toString().padStart(3, "0")}`);
6612
+ const normalize = (coords) => {
6613
+ if (!Array.isArray(coords)) return [];
6614
+ if (typeof coords[0] === "number" && typeof coords[1] === "number") return [];
6615
+ if (Array.isArray(coords[0]) && typeof coords[0][0] === "number") {
6616
+ return [[coords]];
6617
+ }
6618
+ if (Array.isArray(coords[0]) && Array.isArray(coords[0][0]) && typeof coords[0][0][0] === "number") {
6619
+ return [coords];
6620
+ }
6621
+ if (Array.isArray(coords[0]) && Array.isArray(coords[0][0]) && Array.isArray(coords[0][0][0]) && typeof coords[0][0][0][0] === "number") {
6622
+ return coords;
6623
+ }
6624
+ return [];
6625
+ };
6626
+ const polys = normalize(coordinates);
6627
+ if (polys.length === 0) return { proximity: false, point: [0, 0], distance: null };
6628
+ const lon = point[0];
6629
+ const lat = point[1];
6630
+ const pointInRing = (pt, ring) => {
6631
+ let x = pt[0], y = pt[1];
6632
+ let inside = false;
6633
+ for (let i = 0, j2 = ring.length - 1; i < ring.length; j2 = i++) {
6634
+ const xi = ring[i][0], yi = ring[i][1];
6635
+ const xj = ring[j2][0], yj = ring[j2][1];
6636
+ const intersect = yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi + 0) + xi;
6637
+ if (intersect) inside = !inside;
6638
+ }
6639
+ return inside;
6640
+ };
6641
+ const toRadians = (deg) => deg * Math.PI / 180;
6642
+ const haversineMiles = (a, b) => {
6643
+ const R = 3958.8;
6644
+ const dLat = toRadians(b[1] - a[1]);
6645
+ const dLon = toRadians(b[0] - a[0]);
6646
+ const lat1 = toRadians(a[1]);
6647
+ const lat2 = toRadians(b[1]);
6648
+ const sinDLat = Math.sin(dLat / 2);
6649
+ const sinDLon = Math.sin(dLon / 2);
6650
+ const c = 2 * Math.asin(Math.sqrt(sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon));
6651
+ return R * c;
6652
+ };
6653
+ let minDistance = Infinity;
6654
+ let closestPoint = null;
6655
+ for (const poly of polys) {
6656
+ const outer = poly[0];
6657
+ const holes = poly.slice(1);
6658
+ if (pointInRing(point, outer)) {
6659
+ let inHole = false;
6660
+ for (const hole of holes) {
6661
+ if (pointInRing(point, hole)) {
6662
+ inHole = true;
6663
+ break;
6588
6664
  }
6589
- } else {
6590
- zones.push(part);
6591
6665
  }
6592
- continue;
6666
+ if (!inHole) {
6667
+ return { proximity: true, point, distance: 0 };
6668
+ }
6593
6669
  }
6594
- if (part.includes(">")) {
6595
- const [start, end] = part.split(">");
6596
- const startNum = parseInt(start, 10);
6597
- const endNum = parseInt(end, 10);
6598
- for (let j2 = startNum; j2 <= endNum; j2++) {
6599
- zones.push(`${state}${format}${j2.toString().padStart(3, "0")}`);
6670
+ for (const ring of poly) {
6671
+ for (let i = 0; i < ring.length - 1; i++) {
6672
+ const start = [ring[i][0], ring[i][1]];
6673
+ const end = [ring[i + 1][0], ring[i + 1][1]];
6674
+ const A = lon - start[0];
6675
+ const B = lat - start[1];
6676
+ const C = end[0] - start[0];
6677
+ const D = end[1] - start[1];
6678
+ const lenSq = C * C + D * D;
6679
+ const t = lenSq === 0 ? 0 : Math.max(0, Math.min(1, (A * C + B * D) / lenSq));
6680
+ const candidate = [start[0] + t * C, start[1] + t * D];
6681
+ const dist = haversineMiles([lon, lat], candidate);
6682
+ if (!isNaN(dist) && dist < minDistance) {
6683
+ minDistance = Number(dist.toFixed(3));
6684
+ closestPoint = candidate;
6685
+ }
6600
6686
  }
6601
- } else {
6602
- zones.push(`${state}${format}${part}`);
6603
6687
  }
6604
6688
  }
6605
- return zones.filter((item) => item !== "");
6606
- };
6607
-
6608
- // src/@parsers/@ugc/ugc.expiry.ts
6609
- var getExpiry = (message) => {
6610
- const match = message.match(/\b(\d{6})-/);
6611
- if (!match) {
6612
- return null;
6689
+ if (!isFinite(minDistance) || closestPoint == null) {
6690
+ return { proximity: false, point: [0, 0], distance: null };
6613
6691
  }
6614
- const date = match == null ? void 0 : match[1];
6615
- const day = parseInt(date == null ? void 0 : date.slice(0, 2), 10);
6616
- const hour = parseInt(date == null ? void 0 : date.slice(2, 4), 10);
6617
- const minute = parseInt(date == null ? void 0 : date.slice(4, 6), 10);
6618
- const now = /* @__PURE__ */ new Date();
6619
- const expires = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), day, hour, minute));
6620
- return expires.toISOString();
6692
+ const distanceMiles = minDistance;
6693
+ const distanceKm = Number((distanceMiles * 1.609344).toFixed(3));
6694
+ const distanceMeters = Math.round(distanceKm * 1e3);
6695
+ return { proximity: distanceMiles === 0, point: closestPoint, distance: distanceMiles, distanceKm, distanceMeters };
6621
6696
  };
6622
6697
 
6623
- // src/@parsers/@ugc/ugc.locations.ts
6624
- var getLocations = (zones) => __async(null, null, function* () {
6625
- const sites = Array.from(new Set(zones));
6626
- const placeholders = sites.map(() => "?").join(",");
6627
- const rows = yield bootstrap.database.prepare(`SELECT id, location FROM shapefiles WHERE id IN (${placeholders})`).all(...sites);
6628
- return rows.map((row) => row.location).sort();
6629
- });
6630
-
6631
- // src/@parsers/@ugc/ugc.extract.ts
6632
- var ugcExtract = (message) => __async(null, null, function* () {
6633
- const head = getUGCHeader(message);
6634
- const ugcs = getZones(head);
6635
- const expires = getExpiry(message);
6636
- const areas = yield getLocations(ugcs);
6637
- if (!head || (ugcs == null ? void 0 : ugcs.length) == 0) return;
6698
+ // src/@building/building.polygon.ts
6699
+ var getEventNodes = (event) => __async(null, null, function* () {
6700
+ var _a, _b;
6701
+ const metadata = { nodes: [], proximity: false, filtered: false };
6702
+ const geometry = yield getEventGeometry(event);
6703
+ if (!geometry || !geometry.coordinates) {
6704
+ return { nodes: [], filtered: false, updated: Date.now() };
6705
+ }
6706
+ const nodes = bootstrap.cache.nodes.features;
6707
+ for (const node of nodes) {
6708
+ const [longitude, latitude] = node.geometry.coordinates;
6709
+ const getPoint = getShapeNearestPoint(geometry.coordinates, [longitude, latitude]);
6710
+ const miles = (_a = getPoint.distance) != null ? _a : null;
6711
+ const kilometers = Number((miles * 1.609344).toFixed(3));
6712
+ const info = {
6713
+ id: (_b = node.properties) == null ? void 0 : _b.identifier,
6714
+ coordinates: [longitude, latitude],
6715
+ nearest: getPoint.point,
6716
+ miles,
6717
+ kilometers,
6718
+ proximity: getPoint.proximity
6719
+ };
6720
+ metadata.nodes.push(info);
6721
+ if (bootstrap.settings.GlobalSettings.EventFiltering.NodeLocationFiltering && miles < bootstrap.settings.GlobalSettings.NodeMinDistance) {
6722
+ metadata.proximity = true;
6723
+ info.proximity = true;
6724
+ }
6725
+ }
6638
6726
  return {
6639
- zones: ugcs,
6640
- locations: areas,
6641
- expires
6727
+ nodes: metadata.nodes,
6728
+ filtered: metadata.proximity,
6729
+ updated: Date.now()
6642
6730
  };
6643
6731
  });
6644
6732
 
6645
- // src/@events/events.ugc.ts
6646
- var ugc = (stanza) => __async(null, null, function* () {
6647
- var _a, _b, _c;
6648
- let processed = [];
6649
- 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 !== "$$");
6650
- if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
6651
- for (const message of getMessages) {
6652
- const tick = performance.now();
6653
- const attributes = stanza == null ? void 0 : stanza.attributes;
6654
- const ugc2 = yield ugcExtract(message);
6655
- if (ugc2 != null) {
6656
- const props = properties({ message, attributes, ugc: ugc2 });
6657
- const issued = new Date(attributes.issue);
6658
- const expires = new Date(ugc2.expires);
6659
- const header = getEventHeader({ properties: props, getType: stanza.getType });
6660
- let event = Object.keys(dict_matches).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
6661
- let isStatement = false;
6662
- if (!event) {
6663
- event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
6664
- isStatement = true;
6733
+ // src/@manager/manager.updateNodes.ts
6734
+ var updateNode = (selectedEvent) => __async(null, null, function* () {
6735
+ const events = bootstrap.cache.events.features;
6736
+ const ttl = bootstrap.settings.GlobalSettings.NodeTTL * 1e3;
6737
+ let total = 0;
6738
+ function update(evt) {
6739
+ return __async(this, null, function* () {
6740
+ var _a, _b, _c;
6741
+ const lastUpdate = (_c = (_b = (_a = evt == null ? void 0 : evt.properties) == null ? void 0 : _a.metadata) == null ? void 0 : _b.updated) != null ? _c : null;
6742
+ if (lastUpdate != null && Date.now() - lastUpdate < ttl) {
6743
+ return evt;
6665
6744
  }
6666
- processed.push({
6667
- type: `Feature`,
6668
- geometry: {
6669
- type: `Point`,
6670
- coordinates: []
6671
- },
6672
- properties: __spreadProps(__spreadValues({
6673
- event,
6674
- parent: event,
6675
- status: isStatement ? `Statement` : `Issued`,
6676
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
6677
- expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
6678
- }, props), {
6679
- metadata: {
6680
- ms: performance.now() - tick,
6681
- source: `events.ugc`,
6682
- tracking: getEventTracking({ type: `RAW`, stanza, attributes, properties: props }),
6683
- header,
6684
- vtec: null,
6685
- hvtec: null,
6686
- raw: message,
6687
- history: [
6688
- {
6689
- description: props.description,
6690
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
6691
- status: `Issued`
6692
- }
6693
- ]
6694
- }
6695
- })
6696
- });
6697
- }
6745
+ const node = yield getEventNodes(evt);
6746
+ if (node.nodes.length > 0) {
6747
+ total++;
6748
+ }
6749
+ evt.properties.metadata.nodes = node.nodes;
6750
+ evt.properties.metadata.filtered_proximity = node.filtered;
6751
+ evt.properties.metadata.updated = node.updated;
6752
+ });
6698
6753
  }
6699
- validateEvents(processed);
6700
- });
6701
-
6702
- // src/@dictionaries/dictionaries.events.ts
6703
- var dict_events = {
6704
- "AF": "Ashfall",
6705
- "AS": "Air Stagnation",
6706
- "BH": "Beach Hazard",
6707
- "BW": "Brisk Wind",
6708
- "BZ": "Blizzard",
6709
- "CF": "Coastal Flood",
6710
- "DF": "Debris Flow",
6711
- "DS": "Dust Storm",
6712
- "EC": "Extreme Cold",
6713
- "EH": "Excessive Heat",
6714
- "XH": "Extreme Heat",
6715
- "EW": "Extreme Wind",
6716
- "FA": "Areal Flood",
6717
- "FF": "Flash Flood",
6718
- "FG": "Dense Fog",
6719
- "FL": "Flood",
6720
- "FR": "Frost",
6721
- "FW": "Fire Weather",
6722
- "FZ": "Freeze",
6723
- "GL": "Gale",
6724
- "HF": "Hurricane Force Wind",
6725
- "HT": "Heat",
6726
- "HU": "Hurricane",
6727
- "HW": "High Wind",
6728
- "HY": "Hydrologic",
6729
- "HZ": "Hard Freeze",
6730
- "IS": "Ice Storm",
6731
- "LE": "Lake Effect Snow",
6732
- "LO": "Low Water",
6733
- "LS": "Lakeshore Flood",
6734
- "LW": "Lake Wind",
6735
- "MA": "Special Marine",
6736
- "EQ": "Earthquake",
6737
- "MF": "Dense Fog",
6738
- "MH": "Ashfall",
6739
- "MS": "Dense Smoke",
6740
- "RB": "Small Craft for Rough Bar",
6741
- "RP": "Rip Current Risk",
6742
- "SC": "Small Craft",
6743
- "SE": "Hazardous Seas",
6744
- "SI": "Small Craft for Winds",
6745
- "SM": "Dense Smoke",
6746
- "SQ": "Snow Squall",
6747
- "SR": "Storm",
6748
- "SS": "Storm Surge",
6749
- "SU": "High Surf",
6750
- "SV": "Severe Thunderstorm",
6751
- "SW": "Small Craft for Hazardous Seas",
6752
- "TO": "Tornado",
6753
- "TR": "Tropical Storm",
6754
- "TS": "Tsunami",
6755
- "TY": "Typhoon",
6756
- "SP": "Special Weather",
6757
- "UP": "Heavy Freezing Spray",
6758
- "WC": "Wind Chill",
6759
- "WI": "Wind",
6760
- "WS": "Winter Storm",
6761
- "WW": "Winter Weather",
6762
- "ZF": "Freezing Fog",
6763
- "ZR": "Freezing Rain",
6764
- "ZY": "Freezing Spray"
6765
- };
6766
-
6767
- // src/@dictionaries/dictionaries.actions.ts
6768
- var dict_actions = {
6769
- "W": "Warning",
6770
- "F": "Forecast",
6771
- "A": "Watch",
6772
- "O": "Outlook",
6773
- "Y": "Advisory",
6774
- "N": "Synopsis",
6775
- "S": "Statement"
6776
- };
6777
-
6778
- // src/@dictionaries/dictionaries.status.ts
6779
- var dict_status = {
6780
- "NEW": "Issued",
6781
- "CON": "Updated",
6782
- "EXT": "Extended",
6783
- "EXA": "Extended",
6784
- "EXB": "Extended",
6785
- "UPG": "Upgraded",
6786
- "COR": "Correction",
6787
- "ROU": "Routine",
6788
- "CAN": "Cancelled",
6789
- "EXP": "Expired"
6790
- };
6791
-
6792
- // src/@parsers/@pvtec/pvtec.expires.ts
6793
- var getExpiry2 = (dates) => {
6794
- if ((dates == null ? void 0 : dates[1]) == `000000T0000Z`) return "Invalid Date Format";
6795
- 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`;
6796
- const local = new Date(new Date(expires).getTime() - 4 * 60 * 6e4);
6797
- const pad = (n) => n.toString().padStart(2, "0");
6798
- return `${local.getFullYear()}-${pad(local.getMonth() + 1)}-${pad(local.getDate())}T${pad(local.getHours())}:${pad(local.getMinutes())}:00.000-04:00`;
6799
- };
6800
-
6801
- // src/@parsers/@pvtec/pvtec.extract.ts
6802
- var pvExtract = (message) => {
6803
- var _a, _b, _c, _d;
6804
- if (!message) return null;
6805
- const getVTECs = (_a = message.match(dict_expressions.pvtec)) != null ? _a : [];
6806
- const vtecs = [];
6807
- for (const vtec2 of getVTECs) {
6808
- const sub = vtec2.split(`.`);
6809
- if ((sub == null ? void 0 : sub.length) < 7) continue;
6810
- const dates = (_b = sub[6]) == null ? void 0 : _b.split(`-`);
6811
- vtecs.push({
6812
- vtec: vtec2,
6813
- product: dict_products[sub[0]],
6814
- tracking: `${sub[2]}.${sub[3]}.${sub[4]}.${sub[5]}`,
6815
- event: `${dict_events[sub[3]]} ${dict_actions[sub[4]]}`,
6816
- status: dict_status[sub[1]],
6817
- organization: (_d = (_c = message.match(dict_expressions.wmo)) == null ? void 0 : _c[0]) != null ? _d : null,
6818
- expires: getExpiry2(dates),
6819
- is_watch: (sub[4] == `A` || sub[4] == `Y`) && (sub[3] == `TO` || sub[3] == `SV`),
6820
- prediction_center: sub[2] == `KWNS` ? true : false
6754
+ if (!selectedEvent) {
6755
+ yield Promise.all(events.map((evt) => __async(null, null, function* () {
6756
+ yield update(evt);
6757
+ })));
6758
+ }
6759
+ if (selectedEvent) {
6760
+ yield update(selectedEvent);
6761
+ }
6762
+ if (total > 0) {
6763
+ setEventEmit({
6764
+ event: `onNodeUpdate`,
6765
+ metadata: {
6766
+ type: `global-update`,
6767
+ updated: total
6768
+ }
6821
6769
  });
6822
6770
  }
6823
- return vtecs.length > 0 ? vtecs : null;
6824
- };
6771
+ });
6825
6772
 
6826
- // src/@dictionaries/dictionaries.causes.ts
6827
- var dict_causes = {
6828
- "SM": "Snow Melt",
6829
- "RS": "Rain/Snow Melt",
6830
- "ER": "Excessive Rain",
6831
- "DM": "Dam/Levee Failure",
6832
- "IJ": "Ice Jam",
6833
- "GO": "Glacier Lake Outburst",
6834
- "IC": "Ice",
6835
- "FS": "Flash Flood / Storm Surge",
6836
- "FT": "Tidal Effects",
6837
- "ET": "Elevated Upstream Flow",
6838
- "MC": "Other Multiple Causes",
6839
- "WT": "Wind and/or Tidal Effects",
6840
- "DR": "Reservoir Release",
6841
- "UU": "Unknown",
6842
- "OT": "Other Effects"
6843
- };
6773
+ // src/@manager/manager.mkEvent.ts
6774
+ var mkEvent = (event) => __async(null, null, function* () {
6775
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w;
6776
+ const settings = bootstrap.settings;
6777
+ const features = bootstrap.cache.events.features;
6778
+ const getHash = event.properties.metadata.hash;
6779
+ const getTracking = event.properties.metadata.tracking;
6780
+ const isEntry = (_a = bootstrap.cache.hashes) == null ? void 0 : _a.find((hash) => hash.tracking === getTracking);
6781
+ const isHashed = (_c = (_b = isEntry == null ? void 0 : isEntry.hashes) == null ? void 0 : _b.includes(getHash)) != null ? _c : false;
6782
+ const getFeature = features.find((feature) => feature.properties.metadata.tracking === getTracking);
6783
+ if (isHashed || event.properties.status_metadata.is_expired) return;
6784
+ setHash(event, isEntry);
6785
+ const isFilteredLocation = yield updateNode(event).then(() => event.properties.metadata.filtered_proximity);
6786
+ if (!isFilteredLocation && !dict_global.includes(event.properties.event.toLowerCase()) && settings.GlobalSettings.EventFiltering.NodeLocationFiltering) {
6787
+ return;
6788
+ }
6789
+ const isRatelimited = setTimeoutAction({ identifier: getTracking, interval: 1, max: 1, addTime: true });
6790
+ if (!isRatelimited.limited) {
6791
+ setEventEmit({
6792
+ event: `onEventStatus`,
6793
+ metadata: {
6794
+ type: getFeature ? `Updated` : `New`,
6795
+ event
6796
+ },
6797
+ message: `[${getFeature ? "Updated" : "New"}] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
6798
+ });
6799
+ }
6800
+ if (settings.GlobalSettings.EventManagement) {
6801
+ if (event.properties.status_metadata.is_issued || event.properties.status_metadata.is_updated) {
6802
+ if (getFeature) {
6803
+ const getIndex = features.indexOf(getFeature);
6804
+ const cHistory = (_f = (_e = (_d = getFeature == null ? void 0 : getFeature.properties) == null ? void 0 : _d.metadata) == null ? void 0 : _e.history) != null ? _f : [];
6805
+ 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 : [];
6806
+ const cUgc = (_l = (_k = (_j = getFeature == null ? void 0 : getFeature.properties) == null ? void 0 : _j.geocode) == null ? void 0 : _k.ugc) != null ? _l : [];
6807
+ const iHistory = (_o = (_n = (_m = event.properties) == null ? void 0 : _m.metadata) == null ? void 0 : _n.history) != null ? _o : [];
6808
+ const iLocations = (_r = (_q = (_p = event.properties) == null ? void 0 : _p.locations) == null ? void 0 : _q.split(";").map((l) => l.trim())) != null ? _r : [];
6809
+ const iUgc = (_u = (_t = (_s = event.properties) == null ? void 0 : _s.geocode) == null ? void 0 : _t.ugc) != null ? _u : [];
6810
+ 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);
6811
+ const mLocations = [...cLocations, ...iLocations].filter((v, i, a) => a.indexOf(v) === i).join("; ");
6812
+ const mUgc = [...cUgc, ...iUgc].filter((v, i, a) => a.indexOf(v) === i);
6813
+ bootstrap.cache.events.features[getIndex] = __spreadProps(__spreadValues({}, event), {
6814
+ properties: __spreadProps(__spreadValues({}, event.properties), {
6815
+ metadata: __spreadProps(__spreadValues({}, (_v = event == null ? void 0 : event.properties) == null ? void 0 : _v.metadata), {
6816
+ history: mHistory
6817
+ }),
6818
+ locations: mLocations,
6819
+ geocode: __spreadProps(__spreadValues({}, (_w = event == null ? void 0 : event.properties) == null ? void 0 : _w.geocode), {
6820
+ ugc: mUgc
6821
+ })
6822
+ })
6823
+ });
6824
+ yield updateListener(bootstrap.cache.events.features[getIndex]);
6825
+ } else {
6826
+ features.push(event);
6827
+ yield updateListener(event);
6828
+ }
6829
+ }
6830
+ }
6831
+ });
6844
6832
 
6845
- // src/@dictionaries/dictionaries.records.ts
6846
- var dict_records = {
6847
- "NO": "No Record Expected",
6848
- "NR": "Near Record or possible record",
6849
- "UU": "Unknown history of records",
6850
- "OO": "Other"
6851
- };
6833
+ // src/@manager/manager.rmEvent.ts
6834
+ var rmEvent = (event) => __async(null, null, function* () {
6835
+ const getEvent = bootstrap.cache.events.features.find((f) => {
6836
+ var _a, _b, _c, _d;
6837
+ 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);
6838
+ });
6839
+ const cachedStatus = event.properties.status;
6840
+ event.properties.expires = (/* @__PURE__ */ new Date()).toISOString();
6841
+ event.properties.status = `Expired`;
6842
+ event.properties.status_metadata.is_expired = true;
6843
+ if (getEvent) {
6844
+ if (!event.properties.status_metadata.is_statement) {
6845
+ setEventEmit({
6846
+ event: `onEventStatus`,
6847
+ metadata: {
6848
+ type: `Removed`,
6849
+ event
6850
+ },
6851
+ message: `[Removed] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
6852
+ });
6853
+ setEventEmit({ event: `onExpiredProduct`, metadata: event });
6854
+ }
6855
+ if (cachedStatus != `Statement`) yield updateListener(event);
6856
+ bootstrap.cache.events.features.splice(bootstrap.cache.events.features.indexOf(getEvent), 1);
6857
+ bootstrap.cache.hashes = bootstrap.cache.hashes.filter((hash) => hash.tracking !== event.properties.metadata.tracking);
6858
+ setTimeoutAction({ identifier: event.properties.metadata.tracking, expire: true });
6859
+ }
6860
+ setEventEmit({
6861
+ event: `onEventCache`,
6862
+ metadata: bootstrap.cache.events,
6863
+ limited: true
6864
+ });
6865
+ });
6852
6866
 
6853
- // src/@dictionaries/dictionaries.severity.ts
6854
- var dict_severity = {
6855
- N: "Not Expected",
6856
- 0: "Areal Flood or FF Product",
6857
- 1: "Minor",
6858
- 2: "Moderate",
6859
- 3: "Major",
6860
- U: "Unknown"
6867
+ // src/@dictionaries/dictionaries.states.ts
6868
+ var dict_states = {
6869
+ "AL": "Alabama",
6870
+ "AK": "Alaska",
6871
+ "AZ": "Arizona",
6872
+ "AR": "Arkansas",
6873
+ "CA": "California",
6874
+ "CO": "Colorado",
6875
+ "CT": "Connecticut",
6876
+ "DE": "Delaware",
6877
+ "FL": "Florida",
6878
+ "GA": "Georgia",
6879
+ "HI": "Hawaii",
6880
+ "ID": "Idaho",
6881
+ "IL": "Illinois",
6882
+ "IN": "Indiana",
6883
+ "IA": "Iowa",
6884
+ "KS": "Kansas",
6885
+ "KY": "Kentucky",
6886
+ "LA": "Louisiana",
6887
+ "ME": "Maine",
6888
+ "MD": "Maryland",
6889
+ "MA": "Massachusetts",
6890
+ "MI": "Michigan",
6891
+ "MN": "Minnesota",
6892
+ "MS": "Mississippi",
6893
+ "MO": "Missouri",
6894
+ "MT": "Montana",
6895
+ "NE": "Nebraska",
6896
+ "NV": "Nevada",
6897
+ "NH": "New Hampshire",
6898
+ "NJ": "New Jersey",
6899
+ "NM": "New Mexico",
6900
+ "NY": "New York",
6901
+ "NC": "North Carolina",
6902
+ "ND": "North Dakota",
6903
+ "OH": "Ohio",
6904
+ "OK": "Oklahoma",
6905
+ "OR": "Oregon",
6906
+ "PA": "Pennsylvania",
6907
+ "RI": "Rhode Island",
6908
+ "SC": "South Carolina",
6909
+ "SD": "South Dakota",
6910
+ "TN": "Tennessee",
6911
+ "TX": "Texas",
6912
+ "UT": "Utah",
6913
+ "VT": "Vermont",
6914
+ "VA": "Virginia",
6915
+ "WA": "Washington",
6916
+ "WV": "West Virginia",
6917
+ "WI": "Wisconsin",
6918
+ "WY": "Wyoming",
6919
+ "DC": "District of Columbia"
6861
6920
  };
6862
6921
 
6863
- // src/@parsers/@hvtec/hvtec.extract.ts
6864
- var hvExtract = (message) => {
6865
- var _a;
6866
- const getHVTECs = (_a = message.match(dict_expressions.hvtec)) != null ? _a : [];
6867
- const vtecs = [];
6868
- for (const vtec2 of getHVTECs) {
6869
- const sub = vtec2.split(`.`);
6870
- if (sub.length < 7) continue;
6871
- vtecs.push({
6872
- hvtec: vtec2,
6873
- severity: dict_severity[sub[1]],
6874
- cause: dict_causes[sub[2]],
6875
- record: dict_records[sub[6]]
6876
- });
6922
+ // src/@modules/@utilities/utilities.getLatestIssuance.ts
6923
+ var getLatestIssuance = () => {
6924
+ const now = /* @__PURE__ */ new Date();
6925
+ const current = now.getUTCHours() * 100 + now.getUTCMinutes();
6926
+ const issuances = [100, 600, 1300, 1630, 2e3];
6927
+ let latest = issuances[0];
6928
+ for (const issuance of issuances) {
6929
+ if (current >= issuance) {
6930
+ latest = issuance;
6931
+ }
6877
6932
  }
6878
- return vtecs.length > 0 ? vtecs : null;
6933
+ return latest.toString().padStart(4, "0");
6879
6934
  };
6880
6935
 
6881
- // src/@events/events.vtec.ts
6882
- var vtec = (stanza) => __async(null, null, function* () {
6883
- var _a, _b, _c, _d, _e;
6884
- let processed = [];
6885
- 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 !== "$$");
6886
- if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
6887
- for (const message of getMessages) {
6888
- const tick = performance.now();
6889
- const attributes = stanza == null ? void 0 : stanza.attributes;
6890
- const pVtec = pvExtract(message);
6891
- const hVtec = hvExtract(message);
6892
- const ugc2 = yield ugcExtract(message);
6893
- if (pVtec != null && ugc2 != null) {
6894
- for (const pv of pVtec) {
6895
- const vtec2 = pv;
6896
- const props = properties({ message, attributes, ugc: ugc2, pVtec: vtec2 });
6897
- const header = getEventHeader({ properties: props, getType: stanza.getType, vtec: vtec2 });
6898
- const issued = (_d = new Date(attributes.issue)) != null ? _d : /* @__PURE__ */ new Date();
6899
- const expires = new Date(vtec2.expires);
6900
- processed.push({
6901
- type: `Feature`,
6902
- geometry: {
6903
- type: `Point`,
6904
- coordinates: []
6905
- },
6906
- properties: __spreadProps(__spreadValues({
6907
- event: pv.event,
6908
- parent: pv.event,
6909
- status: pv.status,
6910
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
6911
- expires: !isNaN(expires.getTime()) ? expires.toISOString() : (_e = ugc2.expires) != null ? _e : new Date(issued.getTime() + 60 * 60 * 1e3).toISOString()
6912
- }, props), {
6913
- metadata: {
6914
- ms: performance.now() - tick,
6915
- source: `events.vtec`,
6916
- tracking: getEventTracking({ type: `VTEC`, stanza, attributes, properties: props, vtec: vtec2 }),
6917
- header,
6918
- vtec: pv,
6919
- hvtec: hVtec,
6920
- raw: message,
6921
- history: [
6922
- {
6923
- description: props.description,
6924
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
6925
- status: pv.status
6926
- }
6927
- ]
6928
- }
6929
- })
6936
+ // src/@building/building.attachments.ts
6937
+ var getEventAttachments = (event) => {
6938
+ var _a, _b, _c, _d, _e, _f, _g;
6939
+ let attachments = [];
6940
+ const issuanceTime = getLatestIssuance();
6941
+ const spcNumber = (_b = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.discussion_parameters) == null ? void 0 : _b.discussion_number;
6942
+ const watchNumber = (_d = (_c = event == null ? void 0 : event.properties) == null ? void 0 : _c.watch_parameters) == null ? void 0 : _d.watch_number;
6943
+ const locations = (_e = event == null ? void 0 : event.properties) == null ? void 0 : _e.locations_array;
6944
+ const events = [
6945
+ { target: "SPC Day 1 Outlook", attachment: `https://www.spc.noaa.gov/products/outlook/day1otlk_${issuanceTime}.png` },
6946
+ { target: "SPC Day 2 Outlook", attachment: `https://www.spc.noaa.gov/products/outlook/day2otlk.png` },
6947
+ { target: "SPC Day 3 Outlook", attachment: `https://www.spc.noaa.gov/products/outlook/day3otlk.png` },
6948
+ { target: "Mesoscale Discussion", attachment: `https://www.spc.noaa.gov/products/md/mcd${spcNumber}.png` },
6949
+ { target: "Tornado Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
6950
+ { target: "PDS Tornado Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
6951
+ { target: "Severe Thunderstorm Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
6952
+ { target: "PDS Severe Thunderstorm Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` }
6953
+ ];
6954
+ if (events.find((e) => e.target === event.properties.event)) {
6955
+ attachments.push({ name: `Image: Graphic`, link: events.find((e) => e.target.toLowerCase() === event.properties.event.toLowerCase()).attachment });
6956
+ }
6957
+ for (const location of locations) {
6958
+ if (dict_expressions.location.test(location)) {
6959
+ const lines = [`Northern`, `Southern`, `Eastern`, `Western`, `Inland`, `Costal`, `County`];
6960
+ const county = (_f = location == null ? void 0 : location.split(",")[0]) == null ? void 0 : _f.trim().replace(new RegExp(`^(${lines.join("|")}) `), "");
6961
+ const state = dict_states[(_g = location == null ? void 0 : location.split(",")[1]) == null ? void 0 : _g.trim()];
6962
+ const feeds = bootstrap.database.prepare(`SELECT * FROM broadcastify WHERE state = ? AND county = ?`).all(state, county).sort((a, b) => {
6963
+ const typeOrder = ["Other", "Public Safety"];
6964
+ const indexA = typeOrder.indexOf(a.type);
6965
+ const indexB = typeOrder.indexOf(b.type);
6966
+ return indexA - indexB;
6967
+ });
6968
+ const tags = bootstrap.settings.BroadcastifySettings.BroadcastifyTags;
6969
+ const filtered = feeds.filter((feed) => tags.includes(feed.type));
6970
+ if (filtered.length > 0) {
6971
+ filtered.map((filtered2) => {
6972
+ if (!attachments.some((a) => a.link === filtered2.link)) {
6973
+ attachments.push({ name: `${filtered2.type}: ${filtered2.feed}`, link: filtered2.link });
6974
+ }
6930
6975
  });
6931
6976
  }
6932
6977
  }
6933
6978
  }
6934
- validateEvents(processed);
6935
- });
6979
+ return attachments;
6980
+ };
6936
6981
 
6937
- // src/@events/events.api.ts
6938
- var api = (stanza) => __async(null, null, function* () {
6939
- 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, _hb, _ib, _jb, _kb, _lb, _mb, _nb, _ob, _pb, _qb, _rb, _sb, _tb, _ub;
6940
- let processed = [];
6941
- const messages = Object.values(JSON.parse(stanza.message).features);
6942
- for (const feature of messages) {
6943
- const tick = performance.now();
6944
- const pVtec = (_d = pvExtract((_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;
6945
- processed.push({
6946
- type: `Feature`,
6947
- geometry: {
6948
- type: `Point`,
6949
- coordinates: []
6950
- },
6951
- properties: {
6952
- event: (_f = (_e = feature == null ? void 0 : feature.properties) == null ? void 0 : _e.event) != null ? _f : null,
6953
- parent: (_h = (_g = feature == null ? void 0 : feature.properties) == null ? void 0 : _g.event) != null ? _h : null,
6954
- status: (_j = (_i = feature == null ? void 0 : feature.properties) == null ? void 0 : _i.messageType) != null ? _j : null,
6955
- 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,
6956
- 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,
6957
- locations: (_p = (_o = feature == null ? void 0 : feature.properties) == null ? void 0 : _o.areaDesc) != null ? _p : null,
6958
- locations_array: ((_q = feature == null ? void 0 : feature.properties) == null ? void 0 : _q.areaDesc) ? (_r = feature == null ? void 0 : feature.properties) == null ? void 0 : _r.areaDesc.split(";") : [],
6959
- description: (_t = (_s = feature == null ? void 0 : feature.properties) == null ? void 0 : _s.description) != null ? _t : null,
6960
- attributes: (_v = (_u = feature == null ? void 0 : feature.properties) == null ? void 0 : _u.attributes) != null ? _v : {},
6961
- geocode: {
6962
- office: {
6963
- office: pVtec ? (_w = pVtec == null ? void 0 : pVtec[0]) == null ? void 0 : _w.tracking.split(`.`)[0] : null,
6964
- name: (_y = dict_icao[pVtec ? (_x = pVtec == null ? void 0 : pVtec[0]) == null ? void 0 : _x.tracking.split(`.`)[0] : null]) != null ? _y : null
6965
- },
6966
- organization: (_B = (_A = (_z = feature == null ? void 0 : feature.properties) == null ? void 0 : _z.parameters) == null ? void 0 : _A.WMOidentifier) == null ? void 0 : _B[0],
6967
- ugc: (_E = (_D = (_C = feature == null ? void 0 : feature.properties) == null ? void 0 : _C.geocode) == null ? void 0 : _D.UGC) != null ? _E : [],
6968
- polygon: ((_F = feature == null ? void 0 : feature.geometry) == null ? void 0 : _F.coordinates.length) > 0 ? Buffer.from(JSON.stringify([(_G = feature == null ? void 0 : feature.geometry) == null ? void 0 : _G.coordinates[0]])).toString("base64") : null,
6969
- polygon_generated: ((_H = feature == null ? void 0 : feature.geometry) == null ? void 0 : _H.coordinates.length) > 0 ? true : false
6970
- },
6971
- parameters: {
6972
- tags: getEventTags((_I = feature == null ? void 0 : feature.properties) == null ? void 0 : _I.description),
6973
- instructions: (_K = (_J = feature == null ? void 0 : feature.properties) == null ? void 0 : _J.instruction) != null ? _K : null,
6974
- source: (_M = getTextFromProduct({ message: (_L = feature == null ? void 0 : feature.properties) == null ? void 0 : _L.description, find: [`SOURCE...`], removal: [`.`] })) != null ? _M : null,
6975
- hazards: (_O = getTextFromProduct({ message: (_N = feature == null ? void 0 : feature.properties) == null ? void 0 : _N.description, find: [`HAZARD...`], removal: [`.`] })) != null ? _O : null,
6976
- impacts: (_Q = getTextFromProduct({ message: (_P = feature == null ? void 0 : feature.properties) == null ? void 0 : _P.description, find: [`IMPACT...`], removal: [`.`] })) != null ? _Q : null,
6977
- estimated_hail_size: (_U = (_T = (_S = (_R = feature == null ? void 0 : feature.properties) == null ? void 0 : _R.parameters) == null ? void 0 : _S.maxHailSize) == null ? void 0 : _T[0]) != null ? _U : null,
6978
- estimated_wind_gusts: (_Y = (_X = (_W = (_V = feature == null ? void 0 : feature.properties) == null ? void 0 : _V.parameters) == null ? void 0 : _W.maxWindGust) == null ? void 0 : _X[0]) != null ? _Y : null,
6979
- damage_threat: (_aa = (_$ = (__ = (_Z = feature == null ? void 0 : feature.properties) == null ? void 0 : _Z.parameters) == null ? void 0 : __.thunderstormDamageThreat) == null ? void 0 : _$[0]) != null ? _aa : null,
6980
- tornado_threat: (_ea = (_da = (_ca = (_ba = feature == null ? void 0 : feature.properties) == null ? void 0 : _ba.parameters) == null ? void 0 : _ca.tornadoDetection) == null ? void 0 : _da[0]) != null ? _ea : null,
6981
- flood_threat: (_ia = (_ha = (_ga = (_fa = feature == null ? void 0 : feature.properties) == null ? void 0 : _fa.parameters) == null ? void 0 : _ga.floodDetection) == null ? void 0 : _ha[0]) != null ? _ia : null,
6982
- wind_threat: (_ma = (_la = (_ka = (_ja = feature == null ? void 0 : feature.properties) == null ? void 0 : _ja.parameters) == null ? void 0 : _ka.windThreat) == null ? void 0 : _la[0]) != null ? _ma : null,
6983
- hail_threat: (_qa = (_pa = (_oa = (_na = feature == null ? void 0 : feature.properties) == null ? void 0 : _na.parameters) == null ? void 0 : _oa.hailThreat) == null ? void 0 : _pa[0]) != null ? _qa : null
6984
- },
6985
- discussion_parameters: {
6986
- discussion_number: (_ua = (_ta = (_sa = getTextFromProduct({ message: (_ra = feature == null ? void 0 : feature.properties) == null ? void 0 : _ra.description, find: [`Mesoscale Discussion `], removal: [`Mesoscale Discussion`, `Number`, `...`] })) == null ? void 0 : _sa.toString()) == null ? void 0 : _ta.padStart(4, "0")) != null ? _ua : null,
6987
- discussion_concerning: (_wa = getTextFromProduct({ message: (_va = feature == null ? void 0 : feature.properties) == null ? void 0 : _va.description, find: [`Concerning...`] })) != null ? _wa : null,
6988
- discussion_max_tornado: (_ya = getTextFromProduct({ message: (_xa = feature == null ? void 0 : feature.properties) == null ? void 0 : _xa.description, find: [`MOST PROBABLE PEAK TORNADO INTENSITY...`] })) != null ? _ya : null,
6989
- discussion_max_hail: (_Aa = getTextFromProduct({ message: (_za = feature == null ? void 0 : feature.properties) == null ? void 0 : _za.description, find: [`MOST PROBABLE PEAK HAIL SIZE...`] })) != null ? _Aa : null,
6990
- discussion_max_wind: (_Ca = getTextFromProduct({ message: (_Ba = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ba.description, find: [`MOST PROBABLE PEAK WIND GUST...`] })) != null ? _Ca : null,
6991
- discussion_watch_issuance: (_Ea = getTextFromProduct({ message: (_Da = feature == null ? void 0 : feature.properties) == null ? void 0 : _Da.description, find: [`Probability of Watch Issuance...`], removal: [`percent`] })) != null ? _Ea : null
6992
- },
6993
- watch_parameters: {
6994
- watch_number: ((_Fa = pVtec == null ? void 0 : pVtec[0]) == null ? void 0 : _Fa.is_watch) && ((_Qa = (_Pa = (_Ka = (_Ja = (_Ia = (_Ha = getTextFromProduct({ message: (_Ga = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ga.description, find: [`ITIES FOR`, `UPDATE FOR`, `Watch Number `], removal: [`%`, `<`, `:`] })) == null ? void 0 : _Ha.replace(/(WT|WS|)/g, "")) == null ? void 0 : _Ia.trim()) == null ? void 0 : _Ja.toString()) == null ? void 0 : _Ka.padStart(4, "0")) != null ? _Pa : (_Oa = (_Na = (_Ma = (_La = pVtec == null ? void 0 : pVtec[0]) == null ? void 0 : _La.tracking) == null ? void 0 : _Ma.slice(-4)) == null ? void 0 : _Na.toString()) == null ? void 0 : _Oa.padStart(4, "0")) != null ? _Qa : null),
6995
- watch_type: ((_Ra = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ra.description.includes(`TORNADO WATCH`)) ? `Tornado` : ((_Sa = feature == null ? void 0 : feature.properties) == null ? void 0 : _Sa.description.includes(`SEVERE`)) ? `Severe` : null,
6996
- additional_tornadoes_probability: (_Ua = getTextFromProduct({ message: (_Ta = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ta.description, find: [`PROB OF 2 OR MORE TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _Ua : null,
6997
- strong_tornadoes_probability: (_Wa = getTextFromProduct({ message: (_Va = feature == null ? void 0 : feature.properties) == null ? void 0 : _Va.description, find: [`PROB OF 1 OR MORE STRONG /EF2-EF5/ TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _Wa : null,
6998
- severe_wind_probability: (_Ya = getTextFromProduct({ message: (_Xa = feature == null ? void 0 : feature.properties) == null ? void 0 : _Xa.description, find: [`PROB OF 10 OR MORE SEVERE WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _Ya : null,
6999
- severe_hail_probability: (__a = getTextFromProduct({ message: (_Za = feature == null ? void 0 : feature.properties) == null ? void 0 : _Za.description, find: [`PROB OF 10 OR MORE SEVERE HAIL EVENTS`], removal: [`%`, `<`, `:`] })) != null ? __a : null,
7000
- hail_2in_probability: (_ab = getTextFromProduct({ message: (_$a = feature == null ? void 0 : feature.properties) == null ? void 0 : _$a.description, find: [`PROB OF 1 OR MORE HAIL EVENTS >= 2 INCHES`], removal: [`%`, `<`, `:`] })) != null ? _ab : null,
7001
- combined_hail_wind_probability: (_cb = getTextFromProduct({ message: (_bb = feature == null ? void 0 : feature.properties) == null ? void 0 : _bb.description, find: [`PROB OF 6 OR MORE COMBINED SEVERE HAIL/WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _cb : null,
7002
- max_hail_in: (_eb = getTextFromProduct({ message: (_db = feature == null ? void 0 : feature.properties) == null ? void 0 : _db.description, find: [`MAX HAIL /INCHES/`], removal: [`%`, `<`, `:`] })) != null ? _eb : null,
7003
- max_wind_surface: (_gb = getTextFromProduct({ message: (_fb = feature == null ? void 0 : feature.properties) == null ? void 0 : _fb.description, find: [`MAX WIND GUSTS SURFACE /KNOTS/`], removal: [`%`, `<`, `:`] })) != null ? _gb : null,
7004
- max_tops_x100feet: (_ib = getTextFromProduct({ message: (_hb = feature == null ? void 0 : feature.properties) == null ? void 0 : _hb.description, find: [`MAX TOPS /X 100 FEET/`], removal: [`%`, `<`, `:`] })) != null ? _ib : null,
7005
- pds_watch: getTextFromProduct({ message: (_jb = feature == null ? void 0 : feature.properties) == null ? void 0 : _jb.description, find: [`PARTICULARLY DANGEROUS SITUATION`], removal: [`%`, `<`, `:`] }) === `YES`
7006
- },
7007
- metadata: {
7008
- ms: performance.now() - tick,
7009
- source: `events.api`,
7010
- tracking: getEventTracking({ type: `API`, organization: { wmoidentifier: (_mb = (_lb = (_kb = feature == null ? void 0 : feature.properties) == null ? void 0 : _kb.parameters) == null ? void 0 : _lb.WMOidentifier) == null ? void 0 : _mb[0], featureId: feature == null ? void 0 : feature.id }, vtec: pVtec == null ? void 0 : pVtec[0] }),
7011
- header: `ZCZC-ATMOSX-${(_ob = (_nb = feature == null ? void 0 : feature.properties) == null ? void 0 : _nb.parameters) == null ? void 0 : _ob.WMOidentifier}`,
7012
- vtec: pVtec == null ? void 0 : pVtec[0],
7013
- hvtec: null,
7014
- raw: (_pb = feature == null ? void 0 : feature.properties) == null ? void 0 : _pb.description,
7015
- history: [
7016
- {
7017
- description: (_qb = feature == null ? void 0 : feature.properties) == null ? void 0 : _qb.description,
7018
- issued: ((_rb = feature == null ? void 0 : feature.properties) == null ? void 0 : _rb.sent) ? new Date((_sb = feature == null ? void 0 : feature.properties) == null ? void 0 : _sb.sent).toISOString() : null,
7019
- status: (_ub = (_tb = feature == null ? void 0 : feature.properties) == null ? void 0 : _tb.messageType) != null ? _ub : null
7020
- }
7021
- ]
7022
- }
6982
+ // src/@building/building.validate.ts
6983
+ import { createHash } from "crypto";
6984
+ var validateEvents = (events) => __async(null, null, function* () {
6985
+ const tick = performance.now();
6986
+ if (events.length === 0) return;
6987
+ const configurations = bootstrap.settings;
6988
+ const sets = {};
6989
+ const bools = {};
6990
+ const megered = __spreadValues(__spreadValues({}, configurations.GlobalSettings), configurations.GlobalSettings.EventFiltering);
6991
+ for (const key in megered) {
6992
+ const setting = megered[key];
6993
+ if (Array.isArray(setting)) {
6994
+ sets[key] = new Set(setting.map((item) => item.toLowerCase()));
6995
+ }
6996
+ if (typeof setting === "boolean") {
6997
+ bools[key] = setting;
6998
+ }
6999
+ }
7000
+ const isFiltered = (define2) => {
7001
+ var _a, _b, _c, _d;
7002
+ const properties2 = define2.properties;
7003
+ const zones = properties2.geocode.ugc;
7004
+ const icao = properties2.geocode.office.office;
7005
+ if (properties2.status_metadata.is_test) {
7006
+ setEventEmit({ event: `onTestProduct`, metadata: define2 });
7007
+ if (bools == null ? void 0 : bools.IgnoreTestProducts) return true;
7008
+ }
7009
+ if (properties2.status_metadata.is_expired) {
7010
+ setEventEmit({ event: `onExpiredProduct`, metadata: define2 });
7011
+ rmEvent(define2);
7012
+ return true;
7013
+ }
7014
+ if (((_b = (_a = properties2.metadata) == null ? void 0 : _a.vtec) == null ? void 0 : _b.is_watch) && properties2.metadata.source != `events.api`) {
7015
+ const isSPC = (_d = (_c = properties2.metadata) == null ? void 0 : _c.vtec) == null ? void 0 : _d.prediction_center;
7016
+ setEventEmit({ event: isSPC ? `onStormPredictionWatch` : `onNonStormPredictionWatch`, metadata: define2 });
7017
+ if ((bools == null ? void 0 : bools.SPCWatchesOnly) && !isSPC) {
7018
+ return true;
7023
7019
  }
7024
- });
7020
+ if (!(bools == null ? void 0 : bools.SPCWatchesOnly) && isSPC) {
7021
+ return true;
7022
+ }
7023
+ }
7024
+ for (const key in sets) {
7025
+ const setting = sets[key];
7026
+ const values = [...setting];
7027
+ if (key === "ListeningEvents" && setting.size > 0 && !getMatched(values, define2.properties.event)) {
7028
+ setEventEmit({
7029
+ event: `onFilteredEvent`,
7030
+ metadata: define2
7031
+ });
7032
+ return true;
7033
+ }
7034
+ if (key === "IgnoredEvents" && setting.size > 0 && getMatched(values, define2.properties.event)) {
7035
+ setEventEmit({
7036
+ event: `onIgnoredEvent`,
7037
+ metadata: define2
7038
+ });
7039
+ return true;
7040
+ }
7041
+ if (key === "ListeningICAO" && setting.size > 0 && icao != null && !setting.has(icao.toLowerCase())) {
7042
+ setEventEmit({
7043
+ event: `onFilteredICAO`,
7044
+ metadata: define2
7045
+ });
7046
+ return true;
7047
+ }
7048
+ if (key === "IgnoredICAO" && setting.size > 0 && icao != null && setting.has(icao.toLowerCase())) {
7049
+ setEventEmit({
7050
+ event: `onIgnoredICAO`,
7051
+ metadata: define2
7052
+ });
7053
+ return true;
7054
+ }
7055
+ if (key === "ListeningUGC" && setting.size > 0 && zones.length > 0 && !zones.some((ugc2) => setting.has(ugc2.toLowerCase()))) {
7056
+ setEventEmit({
7057
+ event: `onFilteredUGC`,
7058
+ metadata: define2
7059
+ });
7060
+ return true;
7061
+ }
7062
+ if (key === "ListeningStates" && setting.size > 0 && zones.length > 0 && !zones.some((ugc2) => setting.has(ugc2.substring(0, 2).toLowerCase()))) {
7063
+ setEventEmit({
7064
+ event: `onFilteredState`,
7065
+ metadata: define2
7066
+ });
7067
+ return true;
7068
+ }
7069
+ }
7070
+ return false;
7071
+ };
7072
+ const filtering = events.filter((event) => {
7073
+ var _a;
7074
+ bootstrap.cache.processed = bootstrap.cache.processed.filter((e) => e !== event);
7075
+ const define2 = getEventSignature(event);
7076
+ const properties2 = define2.properties;
7077
+ (_a = properties2 == null ? void 0 : properties2.metadata) == null ? true : delete _a.ms;
7078
+ const enhanced = properties2.event = getEventEnhancedName(event);
7079
+ const filtered = isFiltered(define2);
7080
+ if (!filtered) {
7081
+ event.geometry = !(bools == null ? void 0 : bools.DisableGeometryParsing) ? getEventGeometry(event) : null;
7082
+ properties2.metadata.attachments = getEventAttachments(event);
7083
+ }
7084
+ properties2.metadata.hash = createHash("sha256").update(JSON.stringify(properties2)).digest("hex");
7085
+ setEventEmit({ event: `onProductType${enhanced.replace(/\s+/g, "")}`, metadata: define2 });
7086
+ return !filtered;
7087
+ });
7088
+ if (filtering.length > 0) {
7089
+ for (const event of filtering) {
7090
+ yield mkEvent(event);
7091
+ }
7025
7092
  }
7026
- validateEvents(processed);
7093
+ yield updateNode();
7094
+ setEventEmit({
7095
+ event: `onEventCache`,
7096
+ metadata: bootstrap.cache.events,
7097
+ limited: true
7098
+ });
7099
+ setDebug({ title: `@building.validate`, message: `Filtered ${filtering.length} events which took ${performance.now() - tick} ms` });
7027
7100
  });
7028
7101
 
7029
7102
  // src/@building/building.create.ts
7030
- var createEvent = (stanza) => __async(null, null, function* () {
7103
+ var createEvent = (stanza, ignorePushing) => __async(null, null, function* () {
7031
7104
  const settings = bootstrap.settings;
7032
7105
  const StanzaSettings = settings.NOAAWeatherWireServiceSettings.StanzaSettings;
7033
7106
  const isVtecEvent = stanza.isVTEC && stanza.isUGC;
7034
7107
  const isUgcEvent = !stanza.isVTEC && stanza.isUGC;
7035
7108
  const isTextEvent = !stanza.isVTEC && !stanza.isUGC;
7036
7109
  const isNWWS = stanza.isNWWS;
7037
- if (!isNWWS) return yield api(stanza);
7038
- if (!StanzaSettings.DisableVTEC && isVtecEvent) return yield vtec(stanza);
7039
- if (!StanzaSettings.DisableUGC && isUgcEvent) return yield ugc(stanza);
7040
- if (!StanzaSettings.DisableText && isTextEvent) return yield text(stanza);
7110
+ switch (true) {
7111
+ case !isNWWS:
7112
+ yield api(stanza);
7113
+ break;
7114
+ case (isNWWS && !StanzaSettings.DisableVTEC && isVtecEvent):
7115
+ yield vtec(stanza);
7116
+ break;
7117
+ case (isNWWS && !StanzaSettings.DisableUGC && isUgcEvent):
7118
+ yield ugc(stanza);
7119
+ break;
7120
+ case (isNWWS && !StanzaSettings.DisableText && isTextEvent):
7121
+ yield text(stanza);
7122
+ break;
7123
+ }
7124
+ if (!ignorePushing) {
7125
+ validateEvents(bootstrap.cache.processed);
7126
+ }
7041
7127
  return "nothing picked";
7042
7128
  });
7043
7129
 
@@ -7133,25 +7219,6 @@ var xDeploy = () => __async(null, null, function* () {
7133
7219
  }
7134
7220
  });
7135
7221
 
7136
- // src/@modules/@database/database.init.ts
7137
- import fs2 from "fs";
7138
- import sqlite3 from "better-sqlite3";
7139
-
7140
- // src/@modules/@database/database.shapefiles.ts
7141
- import fs from "fs";
7142
- import { resolve as resolve5, extname } from "path";
7143
- import { loadAsync } from "jszip";
7144
- import { read } from "shapefile";
7145
-
7146
- // src/@modules/@utilities/utilities.setSleep.ts
7147
- var setSleep = (options) => __async(null, null, function* () {
7148
- return new Promise((resolve6) => {
7149
- setTimeout(() => {
7150
- resolve6();
7151
- }, options.timeout);
7152
- });
7153
- });
7154
-
7155
7222
  // src/@dictionaries/dictionaries.shapefiles.ts
7156
7223
  var dict_shapefiles = [
7157
7224
  { name: "us_counties", id: "C", link: "https://www.weather.gov/source/gis/Shapefiles/County/c_16ap26.zip" },
@@ -7165,7 +7232,20 @@ var dict_shapefiles = [
7165
7232
  { name: "high_seas_marine_zones", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/WSOM/hz17fe26.zip" }
7166
7233
  ];
7167
7234
 
7235
+ // src/@modules/@utilities/utilities.setSleep.ts
7236
+ var setSleep = (options) => __async(null, null, function* () {
7237
+ return new Promise((resolve6) => {
7238
+ setTimeout(() => {
7239
+ resolve6();
7240
+ }, options.timeout);
7241
+ });
7242
+ });
7243
+
7168
7244
  // src/@modules/@database/database.shapefiles.ts
7245
+ import { existsSync as existsSync3, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4, unlinkSync as unlinkSync2, rm } from "fs";
7246
+ import { resolve as resolve5, extname } from "path";
7247
+ import { loadAsync } from "jszip";
7248
+ import { read } from "shapefile";
7169
7249
  var importShapefiles = () => __async(null, null, function* () {
7170
7250
  var _a, _b;
7171
7251
  const settings = bootstrap.settings;
@@ -7178,14 +7258,14 @@ var importShapefiles = () => __async(null, null, function* () {
7178
7258
  const arrayBuff = yield response2.arrayBuffer();
7179
7259
  const content = yield loadAsync(arrayBuff);
7180
7260
  const directory = resolve5(__dirname, `../../shapefiles`);
7181
- if (!fs.existsSync(directory)) {
7182
- fs.mkdirSync(directory, { recursive: true });
7261
+ if (!existsSync3(directory)) {
7262
+ mkdirSync3(directory, { recursive: true });
7183
7263
  }
7184
7264
  for (const file of Object.keys(content.files)) {
7185
7265
  if (file.endsWith(".shp") || file.endsWith(".dbf")) {
7186
7266
  const data = yield content.files[file].async(`nodebuffer`);
7187
7267
  const output = resolve5(directory, `${(_a = shapefile == null ? void 0 : shapefile.name) != null ? _a : ``}_${(_b = shapefile == null ? void 0 : shapefile.id) != null ? _b : ``}${extname(file)}`);
7188
- fs.writeFileSync(output, data);
7268
+ writeFileSync4(output, data);
7189
7269
  }
7190
7270
  }
7191
7271
  const filepath = resolve5(__dirname, "../../shapefiles", shapefile.name + "_" + shapefile.id);
@@ -7216,11 +7296,11 @@ var importShapefiles = () => __async(null, null, function* () {
7216
7296
  insert.run(final2, location, JSON.stringify(geometry));
7217
7297
  }
7218
7298
  });
7219
- fs.unlinkSync(`${filepath}.shp`);
7220
- fs.unlinkSync(`${filepath}.dbf`);
7299
+ unlinkSync2(`${filepath}.shp`);
7300
+ unlinkSync2(`${filepath}.dbf`);
7221
7301
  transaction(features);
7222
7302
  }
7223
- fs.rm(resolve5(__dirname, "../../shapefiles"), { recursive: true, force: true }, () => {
7303
+ rm(resolve5(__dirname, "../../shapefiles"), { recursive: true, force: true }, () => {
7224
7304
  });
7225
7305
  }
7226
7306
  } catch (error) {
@@ -7272,11 +7352,13 @@ var importBroadcastify = () => __async(null, null, function* () {
7272
7352
  });
7273
7353
 
7274
7354
  // src/@modules/@database/database.init.ts
7355
+ import { existsSync as existsSync4, writeFileSync as writeFileSync5 } from "fs";
7356
+ import sqlite3 from "better-sqlite3";
7275
7357
  var initializeDatabase = () => __async(null, null, function* () {
7276
7358
  const settings = bootstrap.settings;
7277
7359
  try {
7278
- if (!fs2.existsSync(settings.Database)) {
7279
- fs2.writeFileSync(settings.Database, "");
7360
+ if (!existsSync4(settings.Database)) {
7361
+ writeFileSync5(settings.Database, "");
7280
7362
  setWarning({ message: `Creating new database at ${settings.Database}` });
7281
7363
  }
7282
7364
  bootstrap.database = new sqlite3(settings.Database);
@@ -7304,7 +7386,7 @@ var getCachedEvents = () => __async(null, null, function* () {
7304
7386
  if (settings.NOAAWeatherWireServiceSettings.CacheSettings.Enabled) {
7305
7387
  const max = (_a = settings.NOAAWeatherWireServiceSettings.CacheSettings.MaxRetentionHistory) != null ? _a : 500;
7306
7388
  const get = yield bootstrap.database.prepare(`SELECT * FROM stanzas ORDER BY rowid DESC LIMIT ?`).all(max);
7307
- setWarning({ message: `Fetched ${get.length} cached events from the database in ${Math.floor(performance.now() - tick)} ms` });
7389
+ setWarning({ message: `Fetched ${get.length} cached stanzas from the database in ${Math.floor(performance.now() - tick)} ms` });
7308
7390
  let events = get.map((row) => JSON.parse(row.stanza)).filter((stanza) => {
7309
7391
  if (!stanza) {
7310
7392
  return;
@@ -7313,11 +7395,12 @@ var getCachedEvents = () => __async(null, null, function* () {
7313
7395
  return !isSkippable;
7314
7396
  });
7315
7397
  events = events.sort((a, b) => b.issued - a.issued);
7316
- yield Promise.all(events.map((event) => createEvent(event)));
7317
- setWarning({ message: `Processed ${events.length} cached events in ${Math.floor(performance.now() - tick)} ms` });
7398
+ yield Promise.all(events.map((event) => createEvent(event, true)));
7399
+ setWarning({ message: `Processed ${events.length} cached stanzas in ${Math.floor(performance.now() - tick)} ms` });
7400
+ validateEvents(bootstrap.cache.processed);
7318
7401
  }
7319
7402
  } catch (error) {
7320
- setWarning({ message: `An error occurred while fetching cached events: ${error.message} -> ${error.stack}` });
7403
+ setWarning({ message: `An error occurred while fetching cached stanzas: ${error.message} -> ${error.stack}` });
7321
7404
  }
7322
7405
  });
7323
7406
 
@@ -7367,14 +7450,14 @@ var xReconnect = (interval) => __async(null, null, function* () {
7367
7450
  });
7368
7451
 
7369
7452
  // src/@modules/@utilities/utilities.setCronSchedule.ts
7370
- import { readdirSync, unlinkSync as unlinkSync2, statSync, existsSync as existsSync3 } from "fs";
7453
+ import { readdirSync, unlinkSync as unlinkSync3, statSync, existsSync as existsSync5 } from "fs";
7371
7454
  import { join as join2 } from "path";
7372
7455
  var setCronSchedule = () => __async(null, null, function* () {
7373
7456
  const settings = bootstrap.settings;
7374
7457
  const TTL = settings.GlobalSettings.ArchiveSettings.TTL;
7375
7458
  const TTLCUT = Date.now() - TTL * 1e3;
7376
7459
  const walk = (dir) => {
7377
- if (existsSync3(dir)) {
7460
+ if (existsSync5(dir)) {
7378
7461
  const entries = readdirSync(dir, { withFileTypes: true });
7379
7462
  for (const entry of entries) {
7380
7463
  const fullPath = join2(dir, entry.name);
@@ -7385,7 +7468,7 @@ var setCronSchedule = () => __async(null, null, function* () {
7385
7468
  const stats = statSync(fullPath);
7386
7469
  if (stats.mtime.getTime() < TTLCUT) {
7387
7470
  try {
7388
- unlinkSync2(fullPath);
7471
+ unlinkSync3(fullPath);
7389
7472
  } catch (err) {
7390
7473
  console.error(`Failed to delete ${fullPath}:`, err);
7391
7474
  }
@@ -7437,7 +7520,7 @@ var updateEvents = (selectedEvent) => __async(null, null, function* () {
7437
7520
  function update(evt) {
7438
7521
  return __async(this, null, function* () {
7439
7522
  if (new Date(evt.properties.expires) < /* @__PURE__ */ new Date()) {
7440
- rmEvent(evt);
7523
+ yield rmEvent(evt);
7441
7524
  }
7442
7525
  });
7443
7526
  }
@@ -7563,59 +7646,16 @@ var getNodes = () => {
7563
7646
  return bootstrap.cache.nodes;
7564
7647
  };
7565
7648
 
7566
- // src/@core/core.createEvent.ts
7567
- var createEvent2 = (options) => {
7568
- var _a;
7569
- const tick = performance.now();
7570
- validateEvents([{
7571
- type: `Feature`,
7572
- geometry: {
7573
- type: `Point`,
7574
- coordinates: options.coordinates
7575
- },
7576
- properties: {
7577
- event: options.event,
7578
- parent: options.event,
7579
- status: options.status,
7580
- issued: options.issued.toISOString(),
7581
- expires: options.expires.toISOString(),
7582
- locations: options.locations,
7583
- locations_array: options.locations ? options.locations.split(";") : [],
7584
- description: options.description,
7585
- geocode: {
7586
- office: {
7587
- office: `ATMX`,
7588
- name: `AtmosphericX Manual Event`
7589
- },
7590
- organization: `AtmosphericX`,
7591
- ugc: [],
7592
- polygon: options.coordinates.length > 0 ? Buffer.from(JSON.stringify([options.coordinates[0]])).toString("base64") : null,
7593
- polygon_generated: options.coordinates.length > 0 ? true : false
7594
- },
7595
- status_metadata: {
7596
- is_issued: options.status == `Issued`,
7597
- is_updated: options.status == `Updated`,
7598
- is_expired: options.status == `Expired`,
7599
- is_test: options.status == `Test`,
7600
- is_statement: options.status == `Statement`
7601
- },
7602
- metadata: {
7603
- ms: performance.now() - tick,
7604
- source: `events.manual`,
7605
- tracking: `ATMX-M-W-01`,
7606
- header: `ZCZC-ATMOSX-ATMX-M-W-01`,
7607
- raw: options.description,
7608
- history: [
7609
- {
7610
- description: options.description,
7611
- issued: options.issued.toISOString(),
7612
- status: (_a = options.status) != null ? _a : null
7613
- }
7614
- ]
7615
- }
7616
- }
7617
- }]);
7618
- };
7649
+ // src/@core/core.manualEvent.ts
7650
+ var manualEvent = (options) => __async(null, null, function* () {
7651
+ const isCapEvent = options.message.includes(`<?xml`);
7652
+ const isCapAreaDescription = options.message.includes(`<areaDesc>`);
7653
+ const isVTEC = options.message.match(dict_expressions.pvtec) != null;
7654
+ const isUGC = options.message.match(dict_expressions.ugc1) != null;
7655
+ const getType = getAwipsType({ attributes: options.attributes });
7656
+ const result = { message: options.message, attributes: options.attributes, isCapEvent, isVTEC, isUGC, isCapAreaDescription, isIgnored: false, isNWWS: true, getType };
7657
+ yield createEvent(result);
7658
+ });
7619
7659
 
7620
7660
  // src/@core/core.getRandomEvent.ts
7621
7661
  var getRandomEvent = () => {
@@ -7676,13 +7716,13 @@ var index_default = Manager;
7676
7716
  export {
7677
7717
  Manager,
7678
7718
  clearEvents,
7679
- createEvent2 as createEvent,
7680
7719
  index_default as default,
7681
7720
  getCleanedEvent,
7682
7721
  getEventGeometry,
7683
7722
  getEvents,
7684
7723
  getNodes,
7685
7724
  getRandomEvent,
7725
+ manualEvent,
7686
7726
  query,
7687
7727
  setEasTone,
7688
7728
  setNode,