@atmosx/event-product-parser 3.0.48 → 3.0.51

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 (57) hide show
  1. package/README.md +48 -21
  2. package/dist/cjs/index.cjs +1895 -1812
  3. package/dist/esm/index.mjs +1898 -1815
  4. package/package.json +2 -2
  5. package/src/@building/building.attachments.ts +5 -5
  6. package/src/@building/building.create.ts +19 -5
  7. package/src/@building/building.enhance.ts +1 -1
  8. package/src/@building/building.geometry.ts +1 -1
  9. package/src/@building/building.polygon.ts +1 -2
  10. package/src/@building/building.signature.ts +0 -1
  11. package/src/@building/building.tracking.ts +4 -4
  12. package/src/@building/building.validate.ts +11 -6
  13. package/src/@core/core.clearEvents.ts +0 -1
  14. package/src/@core/core.createEvent.ts +0 -1
  15. package/src/@core/core.getEvents.ts +0 -1
  16. package/src/@core/core.getNodes.ts +0 -1
  17. package/src/@core/core.getRandomEvent.ts +0 -1
  18. package/src/@core/core.getVersion.ts +0 -1
  19. package/src/@dictionaries/dictionaries.awips.ts +3 -3
  20. package/src/@events/events.api.ts +7 -9
  21. package/src/@events/events.text.ts +5 -6
  22. package/src/@events/events.ugc.ts +5 -5
  23. package/src/@events/events.vtec.ts +4 -5
  24. package/src/@manager/manager.mkEvent.ts +17 -12
  25. package/src/@manager/manager.rmEvent.ts +5 -3
  26. package/src/@manager/manager.setHash.ts +0 -1
  27. package/src/@manager/manager.updateEvents.ts +1 -3
  28. package/src/@manager/manager.updateListener.ts +22 -27
  29. package/src/@manager/manager.updateNodes.ts +2 -3
  30. package/src/@modules/@database/database.cache.ts +6 -4
  31. package/src/@modules/@database/database.init.ts +5 -4
  32. package/src/@modules/@database/database.shapefiles.ts +11 -11
  33. package/src/@modules/@database/database.stanza.ts +2 -3
  34. package/src/@modules/@eas/eas.setAFSK.ts +0 -1
  35. package/src/@modules/@eas/eas.setAsciiToBits.ts +0 -1
  36. package/src/@modules/@eas/eas.setEasTone.ts +6 -2
  37. package/src/@modules/@eas/eas.setNoise.ts +1 -0
  38. package/src/@modules/@eas/eas.setRadioEffect.ts +1 -0
  39. package/src/@modules/@eas/eas.setSameHeader.ts +0 -1
  40. package/src/@modules/@utilities/utilities.getMatched.ts +33 -0
  41. package/src/@modules/@utilities/utilities.setDebug.ts +38 -0
  42. package/src/@modules/@utilities/utilities.setTimeoutAction.ts +5 -1
  43. package/src/@modules/@xmpp/xmpp.xDeploy.ts +1 -2
  44. package/src/@modules/@xmpp/xmpp.xError.ts +0 -2
  45. package/src/@modules/@xmpp/xmpp.xOffline.ts +0 -1
  46. package/src/@modules/@xmpp/xmpp.xOnline.ts +2 -2
  47. package/src/@parsers/@text/text.getEmbed.ts +0 -2
  48. package/src/@parsers/@ugc/ugc.coordinates.ts +2 -1
  49. package/src/@parsers/@ugc/ugc.getCache.ts +24 -0
  50. package/src/@parsers/@ugc/ugc.locations.ts +35 -7
  51. package/src/@parsers/@ugc/ugc.setCache.ts +28 -0
  52. package/src/@types/type.settings.ts +1 -0
  53. package/src/bootstrap.ts +4 -1
  54. package/test.js +15 -21
  55. package/tsup.config.ts +1 -1
  56. package/dist/index.d.mts +0 -299
  57. package/dist/index.d.ts +0 -299
@@ -1124,7 +1124,7 @@ module.exports = __toCommonJS(index_exports);
1124
1124
  var import_path = __toESM(require("path"));
1125
1125
  var import_node_events = require("events");
1126
1126
  var bootstrap = {
1127
- version: `3.0.48`,
1127
+ version: `3.0.51`,
1128
1128
  isReady: true,
1129
1129
  ratelimits: {},
1130
1130
  session_xmpp: null,
@@ -1149,11 +1149,14 @@ var bootstrap = {
1149
1149
  sigHault: false,
1150
1150
  events: { type: "FeatureCollection", features: [] },
1151
1151
  nodes: { type: "FeatureCollection", features: [] },
1152
- hashes: []
1152
+ hashes: [],
1153
+ processed: [],
1154
+ ugc: /* @__PURE__ */ new Map()
1153
1155
  },
1154
1156
  settings: {
1155
1157
  Database: import_path.default.join(process.cwd(), "shapefiles.db"),
1156
1158
  EnableWireService: true,
1159
+ EnableDebugging: false,
1157
1160
  EnableJournal: true,
1158
1161
  NOAAWeatherWireServiceSettings: {
1159
1162
  ReconnectionSettings: {
@@ -1364,6 +1367,9 @@ var setTimeoutAction = (options) => {
1364
1367
  bootstrap.ratelimits[options == null ? void 0 : options.identifier] = [];
1365
1368
  target = bootstrap.ratelimits[options == null ? void 0 : options.identifier];
1366
1369
  }
1370
+ if (options == null ? void 0 : options.expire) {
1371
+ delete bootstrap.ratelimits[options == null ? void 0 : options.identifier];
1372
+ }
1367
1373
  if ((target == null ? void 0 : target.length) > 0) {
1368
1374
  bootstrap.ratelimits[options == null ? void 0 : options.identifier] = target.filter((ts) => Date.now() - ts < (options == null ? void 0 : options.interval) * 1e3);
1369
1375
  target = bootstrap.ratelimits[options == null ? void 0 : options.identifier];
@@ -4516,9 +4522,9 @@ var dict_awips = {
4516
4522
  SVR: `severe-thunderstorm-warning`,
4517
4523
  SVS: `severe-weather-statement`,
4518
4524
  SWOMCD: `mesoscale-discussion`,
4519
- SWODY1: `day-1`,
4520
- SWODY2: `day-2`,
4521
- SWODY3: `day-3`,
4525
+ SWODY1: `spc-day-1-outlook`,
4526
+ SWODY2: `spc-day-2-outlook`,
4527
+ SWODY3: `spc-day-3-outlook`,
4522
4528
  SWS: `state-weather-summary`,
4523
4529
  SYN: `regional-weather-synopsis`,
4524
4530
  TAF: `terminal-aerodrome-forecast`,
@@ -4632,6 +4638,25 @@ var validate = (options) => {
4632
4638
  return { isIgnored: true };
4633
4639
  };
4634
4640
 
4641
+ // src/@dictionaries/dictionaries.matches.ts
4642
+ var dict_matches = {
4643
+ "Special Weather Statement": "Special Weather Statement",
4644
+ "Hurricane Warning": "Hurricane Warning",
4645
+ "Hurricane Force Wind Warning": "Hurricane Force Wind Warning",
4646
+ "Hurricane Watch": "Hurricane Watch",
4647
+ "Tropical Storm Warning": "Tropical Storm Warning",
4648
+ "Tropical Storm Watch": "Tropical Storm Watch",
4649
+ "High Wind Warning": "High Wind Warning",
4650
+ "Gale Warning": "Gale Warning",
4651
+ "Small Craft Advisory": "Small Craft Advisory",
4652
+ "Small Craft Warning": "Small Craft Warning",
4653
+ "Tsunami Warning": "Tsunami Warning",
4654
+ "Tsunami Watch": "Tsunami Watch",
4655
+ "Tsunami Advisory": "Tsunami Advisory",
4656
+ "Tsunami Information Statement": "Tsunami Information Statement",
4657
+ "Subscribers:": "National Weather Service Policy"
4658
+ };
4659
+
4635
4660
  // src/@parsers/@text/text.getDescriptionFromProduct.ts
4636
4661
  var getDescriptionFromProduct = (options) => {
4637
4662
  let message = options.message;
@@ -5101,25 +5126,6 @@ var getEventHeader = (options) => {
5101
5126
  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`}`;
5102
5127
  };
5103
5128
 
5104
- // src/@dictionaries/dictionaries.matches.ts
5105
- var dict_matches = {
5106
- "Special Weather Statement": "Special Weather Statement",
5107
- "Hurricane Warning": "Hurricane Warning",
5108
- "Hurricane Force Wind Warning": "Hurricane Force Wind Warning",
5109
- "Hurricane Watch": "Hurricane Watch",
5110
- "Tropical Storm Warning": "Tropical Storm Warning",
5111
- "Tropical Storm Watch": "Tropical Storm Watch",
5112
- "High Wind Warning": "High Wind Warning",
5113
- "Gale Warning": "Gale Warning",
5114
- "Small Craft Advisory": "Small Craft Advisory",
5115
- "Small Craft Warning": "Small Craft Warning",
5116
- "Tsunami Warning": "Tsunami Warning",
5117
- "Tsunami Watch": "Tsunami Watch",
5118
- "Tsunami Advisory": "Tsunami Advisory",
5119
- "Tsunami Information Statement": "Tsunami Information Statement",
5120
- "Subscribers:": "National Weather Service Policy"
5121
- };
5122
-
5123
5129
  // src/@building/building.tracking.ts
5124
5130
  var getEventTracking = (options) => {
5125
5131
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
@@ -5144,178 +5150,254 @@ var getEventTracking = (options) => {
5144
5150
  return `${splitPVTEC[2]}.${splitPVTEC[3]}.${splitPVTEC[4]}.${splitPVTEC[5]}`;
5145
5151
  }
5146
5152
  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})/);
5147
- const station = (_f = wmoMatch == null ? void 0 : wmoMatch[2]) != null ? _f : "N/A";
5153
+ const station = (_f = wmoMatch == null ? void 0 : wmoMatch[2]) != null ? _f : "---";
5148
5154
  if (options.organization.featureId) {
5149
5155
  const idMatch = options.organization.featureId.match(/([a-f0-9]+)\.(\d+)\.(\d+)$/);
5150
- return `${station}.${(_h = (_g = idMatch == null ? void 0 : idMatch[0]) == null ? void 0 : _g.replace(/\./g, "")) != null ? _h : "N/A"}`;
5156
+ return `${station}.${(_h = (_g = idMatch == null ? void 0 : idMatch[0]) == null ? void 0 : _g.replace(/\./g, "")) != null ? _h : "---"}`;
5151
5157
  }
5152
- const id2 = (_i = wmoMatch == null ? void 0 : wmoMatch[1]) != null ? _i : "N/A";
5153
- return `${station}.${(_j = id2 == null ? void 0 : id2.replace(/\./g, "")) != null ? _j : "N/A"}`;
5158
+ const id2 = (_i = wmoMatch == null ? void 0 : wmoMatch[1]) != null ? _i : "---";
5159
+ return `${station}.${(_j = id2 == null ? void 0 : id2.replace(/\./g, "")) != null ? _j : "---"}`;
5154
5160
  }
5155
5161
  };
5156
5162
 
5157
- // src/@building/building.validate.ts
5158
- var import_crypto = require("crypto");
5163
+ // src/@modules/@utilities/utilities.setDebug.ts
5164
+ var setDebug = (options) => {
5165
+ var _a, _b, _c, _d;
5166
+ const settings = bootstrap.settings;
5167
+ bootstrap.listener.emit(`debug`, {
5168
+ message: options.message,
5169
+ parent: (_b = (_a = options == null ? void 0 : options.title) == null ? void 0 : _a.split(`.`)[0]) == null ? void 0 : _b.replace(`@`, ``),
5170
+ function: (_c = options == null ? void 0 : options.title) == null ? void 0 : _c.split(`.`)[1]
5171
+ });
5172
+ if (settings.EnableDebugging) {
5173
+ console.log(`[${bootstrap.ansi_colors.BLUE}${(_d = options.title) != null ? _d : `debug`}${bootstrap.ansi_colors.RESET}] ${options.message}`);
5174
+ }
5175
+ };
5159
5176
 
5160
- // src/@dictionaries/dictionaries.enhanced.ts
5161
- var dict_enhanced = {
5162
- "Tornado Warning": {
5163
- "Tornado Emergency": {
5164
- description: "tornado emergency"
5165
- },
5166
- "PDS Tornado Warning": {
5167
- description: "particularly dangerous situation",
5168
- damage: `CONSIDERABLE`
5169
- },
5170
- "Radar Confirmed Tornado Warning": {
5171
- description: "source...radar confirmed tornado.",
5172
- tornado: `OBSERVED`
5173
- },
5174
- "Confirmed Tornado Warning": {
5175
- tornado: `OBSERVED`
5176
- },
5177
- "Radar Indicated Tornado Warning": {}
5178
- },
5179
- "Fire Weather Warning": {
5180
- "PDS Fire Weather Warning": {
5181
- description: "particularly dangerous situation"
5182
- }
5183
- },
5184
- "Blizzard Warning": {
5185
- "PDS Blizzard Warning": {
5186
- description: "particularly dangerous situation"
5187
- }
5188
- },
5189
- "Ice Storm Warning": {
5190
- "PDS Ice Storm Warning": {
5191
- description: "particularly dangerous situation"
5192
- }
5193
- },
5194
- "Special Marine Warning": {
5195
- "Special Marine Warning (TPROB)": {
5196
- tornado: `POSSIBLE`
5197
- }
5198
- },
5199
- "Tornado Watch": {
5200
- "PDS Tornado Watch": {
5201
- pdswatch: true
5202
- }
5203
- },
5204
- "Severe Thunderstorm Watch": {
5205
- "PDS Severe Thunderstorm Watch": {
5206
- pdswatch: true
5207
- }
5208
- },
5209
- "Flash Flood Warning": {
5210
- "Flash Flood Emergency": {
5211
- description: "flash flood emergency"
5212
- },
5213
- "Considerable Flash Flood Warning": {
5214
- damage: `CONSIDERABLE`
5215
- }
5216
- },
5217
- "Severe Thunderstorm Warning": {
5218
- "EDS Severe Thunderstorm Warning (TPROB)": {
5219
- description: "extremely dangerous situation",
5220
- tornado: "POSSIBLE"
5221
- },
5222
- "EDS Severe Thunderstorm Warning": {
5223
- description: "extremely dangerous situation"
5224
- },
5225
- "Destructive Severe Thunderstorm Warning (TPROB)": {
5226
- damage: `DESTRUCTIVE`,
5227
- tornado: `POSSIBLE`
5228
- },
5229
- "Destructive Severe Thunderstorm Warning": {
5230
- damage: `DESTRUCTIVE`
5231
- },
5232
- "Considerable Severe Thunderstorm Warning (TPROB)": {
5233
- damage: `CONSIDERABLE`,
5234
- tornado: `POSSIBLE`
5235
- },
5236
- "Considerable Severe Thunderstorm Warning": {
5237
- damage: `CONSIDERABLE`
5238
- },
5239
- "Severe Thunderstorm Warning (TPROB)": {
5240
- tornado: `POSSIBLE`
5177
+ // src/@events/events.text.ts
5178
+ var text = (stanza) => __async(null, null, function* () {
5179
+ var _a, _b, _c;
5180
+ 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 !== "$$");
5181
+ if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
5182
+ for (const message of getMessages) {
5183
+ const tick = performance.now();
5184
+ const attributes = stanza == null ? void 0 : stanza.attributes;
5185
+ const props = properties({ message, attributes });
5186
+ const header = getEventHeader({ properties: props, getType: stanza.getType });
5187
+ const issued = new Date(attributes.issue);
5188
+ const expires = new Date(issued.getTime() + 12 * 60 * 60 * 1e3);
5189
+ let event = Object.keys(dict_matches).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
5190
+ let isStatement = false;
5191
+ if (!event) {
5192
+ event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
5193
+ isStatement = true;
5241
5194
  }
5195
+ bootstrap.cache.processed.push({
5196
+ type: `Feature`,
5197
+ geometry: {
5198
+ type: `Point`,
5199
+ coordinates: []
5200
+ },
5201
+ properties: __spreadProps(__spreadValues({
5202
+ event,
5203
+ parent: event,
5204
+ status: isStatement ? `Statement` : `Issued`,
5205
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
5206
+ expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
5207
+ }, props), {
5208
+ metadata: {
5209
+ ms: performance.now() - tick,
5210
+ source: `events.text`,
5211
+ tracking: getEventTracking({ type: `RAW`, stanza, attributes, properties: props }),
5212
+ header,
5213
+ vtec: null,
5214
+ hvtec: null,
5215
+ raw: message,
5216
+ history: [
5217
+ {
5218
+ description: props.description,
5219
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
5220
+ status: `Issued`
5221
+ }
5222
+ ]
5223
+ }
5224
+ })
5225
+ });
5226
+ setDebug({ title: `@events.text`, message: `Event process took ${performance.now() - tick} ms` });
5242
5227
  }
5228
+ });
5229
+
5230
+ // src/@parsers/@ugc/ugc.header.ts
5231
+ var getUGCHeader = (message) => {
5232
+ const start = message.search(dict_expressions.ugc1);
5233
+ const sub = message.substring(start);
5234
+ const end = sub.search(dict_expressions.ugc2);
5235
+ const fin = sub.substring(0, end).replace(/\s+/g, "").slice(0, -1);
5236
+ return fin != null ? fin : null;
5243
5237
  };
5244
5238
 
5245
- // src/@building/building.enhance.ts
5246
- var getEventEnhancedName = (event) => {
5247
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5248
- const configurations = bootstrap.settings;
5249
- let name = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.event;
5250
- if (!((_b = configurations == null ? void 0 : configurations.GlobalSettings) == null ? void 0 : _b.BetterEventNames)) {
5251
- return name;
5252
- }
5253
- const damage = (_d = (_c = event == null ? void 0 : event.properties) == null ? void 0 : _c.parameters) == null ? void 0 : _d.damage_threat;
5254
- const tornado = (_f = (_e = event == null ? void 0 : event.properties) == null ? void 0 : _e.parameters) == null ? void 0 : _f.tornado_threat;
5255
- const pdswatch = (_h = (_g = event == null ? void 0 : event.properties) == null ? void 0 : _g.watch_parameters) == null ? void 0 : _h.pds_watch;
5256
- const description = (_j = (_i = event == null ? void 0 : event.properties) == null ? void 0 : _i.description) == null ? void 0 : _j.toLowerCase();
5257
- for (const [eventKey, eventConfig] of Object.entries(dict_enhanced)) {
5258
- if (eventKey !== name) continue;
5259
- for (const [paramKey, paramValue] of Object.entries(eventConfig)) {
5260
- let matches = true;
5261
- if (paramValue == null ? void 0 : paramValue.description) {
5262
- if (!description.includes(paramValue.description.toLowerCase())) matches = false;
5263
- }
5264
- if (paramValue == null ? void 0 : paramValue.damage) {
5265
- if (paramValue.damage !== damage) matches = false;
5266
- }
5267
- if (paramValue == null ? void 0 : paramValue.tornado) {
5268
- if (paramValue.tornado !== tornado) matches = false;
5269
- }
5270
- if (paramValue == null ? void 0 : paramValue.pdswatch) {
5271
- if (paramValue.pdswatch !== pdswatch) matches = false;
5239
+ // src/@parsers/@ugc/ugc.zones.ts
5240
+ var getZones = (header) => {
5241
+ const splits = header.split("-");
5242
+ const zones = [];
5243
+ let state = splits[0].substring(0, 2);
5244
+ const format = splits[0].substring(2, 3);
5245
+ for (const part of splits) {
5246
+ if (/^[A-Z]/.test(part)) {
5247
+ state = part.substring(0, 2);
5248
+ if (part.includes(">")) {
5249
+ const [start, end] = part.split(">");
5250
+ const startNum = parseInt(start.substring(3), 10);
5251
+ const endNum = parseInt(end, 10);
5252
+ for (let j2 = startNum; j2 <= endNum; j2++) {
5253
+ zones.push(`${state}${format}${j2.toString().padStart(3, "0")}`);
5254
+ }
5255
+ } else {
5256
+ zones.push(part);
5272
5257
  }
5273
- if (matches) {
5274
- name = paramKey;
5275
- break;
5258
+ continue;
5259
+ }
5260
+ if (part.includes(">")) {
5261
+ const [start, end] = part.split(">");
5262
+ const startNum = parseInt(start, 10);
5263
+ const endNum = parseInt(end, 10);
5264
+ for (let j2 = startNum; j2 <= endNum; j2++) {
5265
+ zones.push(`${state}${format}${j2.toString().padStart(3, "0")}`);
5276
5266
  }
5267
+ } else {
5268
+ zones.push(`${state}${format}${part}`);
5277
5269
  }
5278
5270
  }
5279
- return name;
5271
+ return zones.filter((item) => item !== "");
5280
5272
  };
5281
5273
 
5282
- // src/@dictionaries/dictionaries.correlations.ts
5283
- var dict_correlations = [
5284
- { type: "Statement", name: "Statement", isCancel: false, isUpdate: false, isIssued: true, isStatement: true },
5285
- { type: "Update", name: "Updated", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5286
- { type: "Cancel", name: "Cancelled", isCancel: true, isUpdate: false, isIssued: false, isStatement: false },
5287
- { type: "Alert", name: "Issued", isCancel: false, isUpdate: false, isIssued: true, isStatement: false },
5288
- { type: "Updated", name: "Updated", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5289
- { type: "Expired", name: "Expired", isCancel: true, isUpdate: false, isIssued: false, isStatement: false },
5290
- { type: "Issued", name: "Issued", isCancel: false, isUpdate: false, isIssued: true, isStatement: false },
5291
- { type: "Extended", name: "Extended", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5292
- { type: "Correction", name: "Correction", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5293
- { type: "Upgraded", name: "Upgraded", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5294
- { type: "Cancelled", name: "Cancelled", isCancel: true, isUpdate: false, isIssued: false, isStatement: false },
5295
- { type: "Routine", name: "Routine", isCancel: false, isUpdate: true, isIssued: false, isStatement: false }
5296
- ];
5274
+ // src/@parsers/@ugc/ugc.expiry.ts
5275
+ var getExpiry = (message) => {
5276
+ const match = message.match(/\b(\d{6})-/);
5277
+ if (!match) {
5278
+ return null;
5279
+ }
5280
+ const date = match == null ? void 0 : match[1];
5281
+ const day = parseInt(date == null ? void 0 : date.slice(0, 2), 10);
5282
+ const hour = parseInt(date == null ? void 0 : date.slice(2, 4), 10);
5283
+ const minute = parseInt(date == null ? void 0 : date.slice(4, 6), 10);
5284
+ const now = /* @__PURE__ */ new Date();
5285
+ const expires = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), day, hour, minute));
5286
+ return expires.toISOString();
5287
+ };
5297
5288
 
5298
- // src/@dictionaries/dictionaries.cancellation.ts
5299
- var dict_cancellation = [
5300
- "has been cancelled",
5301
- "subsided sufficiently for the advisory to be cancelled",
5302
- "has been cancelled",
5303
- "no tsunami threat from a nearby earthquake",
5304
- "will be allowed to expire",
5305
- "has diminished",
5306
- "and no longer",
5307
- "has been replaced",
5308
- "The threat has ended",
5309
- "has weakened below severe"
5310
- ];
5289
+ // src/@parsers/@ugc/ugc.getCache.ts
5290
+ var getCache = (key) => {
5291
+ return bootstrap.cache.ugc.get(key);
5292
+ };
5311
5293
 
5312
- // src/@dictionaries/dictionaries.testing.ts
5313
- var dict_testing = [
5314
- `This is a test message`,
5315
- `Monitoring message only.`,
5316
- `THIS_MESSAGE_IS_FOR_TEST_PURPOSES_ONLY`,
5317
- "TEST MESSAGE"
5318
- ];
5294
+ // src/@parsers/@ugc/ugc.setCache.ts
5295
+ var setCache = (key, value) => {
5296
+ if (bootstrap.cache.ugc.size >= 5e3) {
5297
+ const firstKey = bootstrap.cache.ugc.keys().next().value;
5298
+ bootstrap.cache.ugc.delete(firstKey);
5299
+ }
5300
+ bootstrap.cache.ugc.set(key, value);
5301
+ };
5302
+
5303
+ // src/@parsers/@ugc/ugc.locations.ts
5304
+ var getLocations = (zones) => __async(null, null, function* () {
5305
+ const uniqueZones = Array.from(new Set(zones));
5306
+ const results = [];
5307
+ const missing = [];
5308
+ for (let i = 0; i < uniqueZones.length; i++) {
5309
+ const zone = uniqueZones[i];
5310
+ const cached = getCache(zone);
5311
+ if (cached) {
5312
+ for (let j2 = 0; j2 < cached.length; j2++) {
5313
+ results.push(cached[j2]);
5314
+ }
5315
+ } else {
5316
+ missing.push(zone);
5317
+ }
5318
+ }
5319
+ if (missing.length > 0) {
5320
+ const rows = yield bootstrap.database.prepare(
5321
+ `SELECT id, location FROM shapefiles WHERE id IN (${missing.map(() => "?").join(",")})`
5322
+ ).all(...missing);
5323
+ for (let i = 0; i < rows.length; i++) {
5324
+ const r = rows[i];
5325
+ setCache(r.id, [r.location]);
5326
+ results.push(r.location);
5327
+ }
5328
+ }
5329
+ return results;
5330
+ });
5331
+
5332
+ // src/@parsers/@ugc/ugc.extract.ts
5333
+ var ugcExtract = (message) => __async(null, null, function* () {
5334
+ const head = getUGCHeader(message);
5335
+ const ugcs = getZones(head);
5336
+ const expires = getExpiry(message);
5337
+ const areas = yield getLocations(ugcs);
5338
+ if (!head || (ugcs == null ? void 0 : ugcs.length) == 0) return;
5339
+ return {
5340
+ zones: ugcs,
5341
+ locations: areas,
5342
+ expires
5343
+ };
5344
+ });
5345
+
5346
+ // src/@events/events.ugc.ts
5347
+ var ugc = (stanza) => __async(null, null, function* () {
5348
+ var _a, _b, _c;
5349
+ 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 !== "$$");
5350
+ if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
5351
+ for (const message of getMessages) {
5352
+ const tick = performance.now();
5353
+ const attributes = stanza == null ? void 0 : stanza.attributes;
5354
+ const ugc2 = yield ugcExtract(message);
5355
+ if (ugc2 != null) {
5356
+ const props = properties({ message, attributes, ugc: ugc2 });
5357
+ const issued = new Date(attributes.issue);
5358
+ const expires = new Date(ugc2.expires);
5359
+ const header = getEventHeader({ properties: props, getType: stanza.getType });
5360
+ let event = Object.keys(dict_matches).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
5361
+ let isStatement = false;
5362
+ if (!event) {
5363
+ event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
5364
+ isStatement = true;
5365
+ }
5366
+ bootstrap.cache.processed.push({
5367
+ type: `Feature`,
5368
+ geometry: {
5369
+ type: `Point`,
5370
+ coordinates: []
5371
+ },
5372
+ properties: __spreadProps(__spreadValues({
5373
+ event,
5374
+ parent: event,
5375
+ status: isStatement ? `Statement` : `Issued`,
5376
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
5377
+ expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
5378
+ }, props), {
5379
+ metadata: {
5380
+ ms: performance.now() - tick,
5381
+ source: `events.ugc`,
5382
+ tracking: getEventTracking({ type: `RAW`, stanza, attributes, properties: props }),
5383
+ header,
5384
+ vtec: null,
5385
+ hvtec: null,
5386
+ raw: message,
5387
+ history: [
5388
+ {
5389
+ description: props.description,
5390
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
5391
+ status: `Issued`
5392
+ }
5393
+ ]
5394
+ }
5395
+ })
5396
+ });
5397
+ setDebug({ title: `@events.ugc`, message: `Event process took ${performance.now() - tick} ms` });
5398
+ }
5399
+ }
5400
+ });
5319
5401
 
5320
5402
  // src/@dictionaries/dictionaries.products.ts
5321
5403
  var dict_products = {
@@ -5325,1739 +5407,1743 @@ var dict_products = {
5325
5407
  "X": "Experimental Product (Non-Operational)"
5326
5408
  };
5327
5409
 
5328
- // src/@dictionaries/dictionaries.hail.ts
5329
- var dict_hail = {
5330
- ".25": "Pea",
5331
- ".50": "Penny",
5332
- ".75": "Penny",
5333
- "Up to .75": "Penny",
5334
- ".88": "Nickel",
5335
- "0.75": "Penny",
5336
- "0.88": "Nickel",
5337
- "1.00": "Quarter",
5338
- "1.25": "Half Dollar",
5339
- "1.50": "Ping Pong Ball",
5340
- "1.75": "Golf Ball",
5341
- "2.00": "Hen Egg",
5342
- "2.50": "Tennis Ball",
5343
- "2.75": "Baseball",
5344
- "4.00": "CD/DVD"
5345
- };
5346
-
5347
- // src/@building/building.signature.ts
5348
- var getEventSignature = (event) => {
5349
- var _a, _b, _c, _d, _e, _f, _g, _h;
5350
- const properties2 = event == null ? void 0 : event.properties;
5351
- const vtec2 = (_b = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.metadata) == null ? void 0 : _b.vtec;
5352
- const status = dict_correlations.find((c) => c.type === (properties2 == null ? void 0 : properties2.status));
5353
- const csig = dict_cancellation.find((sig) => properties2.description.toLowerCase().includes(sig.toLowerCase()));
5354
- properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_issued: true, is_test: false });
5355
- if ((_c = properties2 == null ? void 0 : properties2.parameters) == null ? void 0 : _c.estimated_hail_size) {
5356
- properties2.parameters.estimated_hail_size += ` (${(_e = dict_hail[(_d = properties2 == null ? void 0 : properties2.parameters) == null ? void 0 : _d.estimated_hail_size]) != null ? _e : "--"})`;
5357
- }
5358
- if (status) {
5359
- properties2.status = (_f = status.name) != null ? _f : properties2.status;
5360
- properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_updated: !!status.isUpdate, is_issued: !!status.isIssued, is_expired: !!status.isCancel, is_statement: !!status.isStatement });
5361
- }
5362
- if (csig) {
5363
- properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_expired: true });
5364
- }
5365
- const getProduct = (_h = (_g = vtec2 == null ? void 0 : vtec2.vtec) == null ? void 0 : _g.split(`.`)[0]) == null ? void 0 : _h.replace(`/`, ``);
5366
- const isTestProduct = dict_products[getProduct] == `Test Product`;
5367
- if (isTestProduct || dict_testing.some((sig) => {
5368
- var _a2, _b2, _c2, _d2;
5369
- 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());
5370
- })) {
5371
- properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_test: true });
5372
- }
5373
- if (new Date(properties2.expires).getTime() < Date.now()) {
5374
- properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_expired: true });
5375
- }
5376
- properties2.status_metadata = __spreadValues({}, properties2.status_metadata);
5377
- return event;
5410
+ // src/@dictionaries/dictionaries.events.ts
5411
+ var dict_events = {
5412
+ "AF": "Ashfall",
5413
+ "AS": "Air Stagnation",
5414
+ "BH": "Beach Hazard",
5415
+ "BW": "Brisk Wind",
5416
+ "BZ": "Blizzard",
5417
+ "CF": "Coastal Flood",
5418
+ "DF": "Debris Flow",
5419
+ "DS": "Dust Storm",
5420
+ "EC": "Extreme Cold",
5421
+ "EH": "Excessive Heat",
5422
+ "XH": "Extreme Heat",
5423
+ "EW": "Extreme Wind",
5424
+ "FA": "Areal Flood",
5425
+ "FF": "Flash Flood",
5426
+ "FG": "Dense Fog",
5427
+ "FL": "Flood",
5428
+ "FR": "Frost",
5429
+ "FW": "Fire Weather",
5430
+ "FZ": "Freeze",
5431
+ "GL": "Gale",
5432
+ "HF": "Hurricane Force Wind",
5433
+ "HT": "Heat",
5434
+ "HU": "Hurricane",
5435
+ "HW": "High Wind",
5436
+ "HY": "Hydrologic",
5437
+ "HZ": "Hard Freeze",
5438
+ "IS": "Ice Storm",
5439
+ "LE": "Lake Effect Snow",
5440
+ "LO": "Low Water",
5441
+ "LS": "Lakeshore Flood",
5442
+ "LW": "Lake Wind",
5443
+ "MA": "Special Marine",
5444
+ "EQ": "Earthquake",
5445
+ "MF": "Dense Fog",
5446
+ "MH": "Ashfall",
5447
+ "MS": "Dense Smoke",
5448
+ "RB": "Small Craft for Rough Bar",
5449
+ "RP": "Rip Current Risk",
5450
+ "SC": "Small Craft",
5451
+ "SE": "Hazardous Seas",
5452
+ "SI": "Small Craft for Winds",
5453
+ "SM": "Dense Smoke",
5454
+ "SQ": "Snow Squall",
5455
+ "SR": "Storm",
5456
+ "SS": "Storm Surge",
5457
+ "SU": "High Surf",
5458
+ "SV": "Severe Thunderstorm",
5459
+ "SW": "Small Craft for Hazardous Seas",
5460
+ "TO": "Tornado",
5461
+ "TR": "Tropical Storm",
5462
+ "TS": "Tsunami",
5463
+ "TY": "Typhoon",
5464
+ "SP": "Special Weather",
5465
+ "UP": "Heavy Freezing Spray",
5466
+ "WC": "Wind Chill",
5467
+ "WI": "Wind",
5468
+ "WS": "Winter Storm",
5469
+ "WW": "Winter Weather",
5470
+ "ZF": "Freezing Fog",
5471
+ "ZR": "Freezing Rain",
5472
+ "ZY": "Freezing Spray"
5378
5473
  };
5379
5474
 
5380
- // src/@manager/manager.setHash.ts
5381
- var setHash = (event, entry) => {
5382
- if (entry) {
5383
- entry.hashes.push(event.properties.metadata.hash);
5384
- entry.expires = event.properties.expires;
5385
- } else {
5386
- bootstrap.cache.hashes.push({
5387
- tracking: event.properties.metadata.tracking,
5388
- hashes: [event.properties.metadata.hash],
5389
- expires: event.properties.expires
5390
- });
5391
- }
5475
+ // src/@dictionaries/dictionaries.actions.ts
5476
+ var dict_actions = {
5477
+ "W": "Warning",
5478
+ "F": "Forecast",
5479
+ "A": "Watch",
5480
+ "O": "Outlook",
5481
+ "Y": "Advisory",
5482
+ "N": "Synopsis",
5483
+ "S": "Statement"
5392
5484
  };
5393
5485
 
5394
- // src/@modules/@eas/eas.getWavPCM16.ts
5395
- var getWavPCM16 = (buffer) => {
5396
- if (buffer.toString("ascii", 0, 4) !== "RIFF" || buffer.toString("ascii", 8, 12) !== "WAVE") {
5397
- return null;
5398
- }
5399
- let fmt = null;
5400
- let data = null;
5401
- let i = 12;
5402
- while (i + 8 <= buffer.length) {
5403
- const id2 = buffer.toString("ascii", i, i + 4);
5404
- const size = buffer.readUInt32LE(i + 4);
5405
- const start = i + 8;
5406
- const end = start + size;
5407
- if (id2 === "fmt ") fmt = buffer.slice(start, end);
5408
- if (id2 === "data") data = buffer.slice(start, end);
5409
- i = end + size % 2;
5410
- }
5411
- if (!fmt || !data) return null;
5412
- const audioFormat = fmt.readUInt16LE(0);
5413
- const channels = fmt.readUInt16LE(2);
5414
- const sampleRate = fmt.readUInt32LE(4);
5415
- const bitsPerSample = fmt.readUInt16LE(14);
5416
- if (audioFormat !== 1 || bitsPerSample !== 16 || channels !== 1) {
5417
- return null;
5418
- }
5419
- const samples = new Int16Array(data.buffer, data.byteOffset, data.length / 2);
5420
- return { samples: new Int16Array(samples), sampleRate, channels, bitsPerSample };
5421
- };
5422
-
5423
- // src/@modules/@eas/eas.getSampledPCM16.ts
5424
- var getSampledPCM16 = (int16, originalRate, targetRate) => {
5425
- if (originalRate === targetRate) return int16;
5426
- const ratio = targetRate / originalRate;
5427
- const outLen = Math.max(1, Math.round(int16.length * ratio));
5428
- const out = new Int16Array(outLen);
5429
- for (let i = 0; i < outLen; i++) {
5430
- const pos = i / ratio;
5431
- const i0 = Math.floor(pos);
5432
- const i1 = Math.min(i0 + 1, int16.length - 1);
5433
- const frac = pos - i0;
5434
- const v = int16[i0] * (1 - frac) + int16[i1] * frac;
5435
- out[i] = Math.round(v);
5436
- }
5437
- return out;
5438
- };
5439
-
5440
- // src/@modules/@eas/eas.getPCMToFloat.ts
5441
- var getPCMToFloat = (int16) => {
5442
- const out = new Float32Array(int16.length);
5443
- for (let i = 0; i < int16.length; i++) out[i] = int16[i] / 32768;
5444
- return out;
5486
+ // src/@dictionaries/dictionaries.status.ts
5487
+ var dict_status = {
5488
+ "NEW": "Issued",
5489
+ "CON": "Updated",
5490
+ "EXT": "Extended",
5491
+ "EXA": "Extended",
5492
+ "EXB": "Extended",
5493
+ "UPG": "Upgraded",
5494
+ "COR": "Correction",
5495
+ "ROU": "Routine",
5496
+ "CAN": "Cancelled",
5497
+ "EXP": "Expired"
5445
5498
  };
5446
5499
 
5447
- // src/@modules/@eas/eas.getFloatPCM16.ts
5448
- var getFloatPCM16 = (float32) => {
5449
- const out = new Int16Array(float32.length);
5450
- for (let i = 0; i < float32.length; i++) {
5451
- let v = Math.max(-1, Math.min(1, float32[i]));
5452
- out[i] = Math.round(v * 32767);
5453
- }
5454
- return out;
5500
+ // src/@parsers/@pvtec/pvtec.expires.ts
5501
+ var getExpiry2 = (dates) => {
5502
+ if ((dates == null ? void 0 : dates[1]) == `000000T0000Z`) return "Invalid Date Format";
5503
+ 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`;
5504
+ const local = new Date(new Date(expires).getTime() - 4 * 60 * 6e4);
5505
+ const pad = (n) => n.toString().padStart(2, "0");
5506
+ return `${local.getFullYear()}-${pad(local.getMonth() + 1)}-${pad(local.getDate())}T${pad(local.getHours())}:${pad(local.getMinutes())}:00.000-04:00`;
5455
5507
  };
5456
5508
 
5457
- // src/@modules/@eas/eas.setRadioEffect.ts
5458
- var setRadioEffect = (int16, sampleRate) => {
5459
- const hpCut = 3555;
5460
- const lpCut = 1600;
5461
- const x = getPCMToFloat(int16);
5462
- const dt = 1 / sampleRate;
5463
- const rcHP = 1 / (2 * Math.PI * hpCut);
5464
- const aHP = rcHP / (rcHP + dt);
5465
- let yHP = 0, xPrev = 0;
5466
- for (let i = 0; i < x.length; i++) {
5467
- const xi = x[i];
5468
- yHP = aHP * (yHP + xi - xPrev);
5469
- xPrev = xi;
5470
- x[i] = yHP;
5471
- }
5472
- const rcLP = 1 / (2 * Math.PI * lpCut);
5473
- const aLP = dt / (rcLP + dt);
5474
- let yLP = 0;
5475
- for (let i = 0; i < x.length; i++) {
5476
- yLP = yLP + aLP * (x[i] - yLP);
5477
- x[i] = yLP;
5509
+ // src/@parsers/@pvtec/pvtec.extract.ts
5510
+ var pvExtract = (message) => {
5511
+ var _a, _b, _c, _d;
5512
+ if (!message) return null;
5513
+ const getVTECs = (_a = message.match(dict_expressions.pvtec)) != null ? _a : [];
5514
+ const vtecs = [];
5515
+ for (const vtec2 of getVTECs) {
5516
+ const sub = vtec2.split(`.`);
5517
+ if ((sub == null ? void 0 : sub.length) < 7) continue;
5518
+ const dates = (_b = sub[6]) == null ? void 0 : _b.split(`-`);
5519
+ vtecs.push({
5520
+ vtec: vtec2,
5521
+ product: dict_products[sub[0]],
5522
+ tracking: `${sub[2]}.${sub[3]}.${sub[4]}.${sub[5]}`,
5523
+ event: `${dict_events[sub[3]]} ${dict_actions[sub[4]]}`,
5524
+ status: dict_status[sub[1]],
5525
+ organization: (_d = (_c = message.match(dict_expressions.wmo)) == null ? void 0 : _c[0]) != null ? _d : null,
5526
+ expires: getExpiry2(dates),
5527
+ is_watch: (sub[4] == `A` || sub[4] == `Y`) && (sub[3] == `TO` || sub[3] == `SV`),
5528
+ prediction_center: sub[2] == `KWNS` ? true : false
5529
+ });
5478
5530
  }
5479
- const compGain = 2;
5480
- const norm = Math.tanh(compGain);
5481
- for (let i = 0; i < x.length; i++) x[i] = Math.tanh(x[i] * compGain) / norm;
5482
- return getFloatPCM16(x);
5531
+ return vtecs.length > 0 ? vtecs : null;
5483
5532
  };
5484
5533
 
5485
- // src/@modules/@eas/eas.setAFSK.ts
5486
- var setAFSK = (bits, sampleRate) => {
5487
- const baud = 520.83;
5488
- const markFreq = 2083.3;
5489
- const spaceFreq = 1562.5;
5490
- const amplitude = 0.6;
5491
- const twoPi = Math.PI * 2;
5492
- const result = [];
5493
- let phase = 0;
5494
- let frac = 0;
5495
- for (let b = 0; b < bits.length; b++) {
5496
- const bit = bits[b];
5497
- const freq = bit ? markFreq : spaceFreq;
5498
- const samplesPerBit = sampleRate / baud + frac;
5499
- const n = Math.round(samplesPerBit);
5500
- frac = samplesPerBit - n;
5501
- const inc = twoPi * freq / sampleRate;
5502
- for (let i = 0; i < n; i++) {
5503
- result.push(Math.round(Math.sin(phase) * amplitude * 32767));
5504
- phase += inc;
5505
- if (phase > twoPi) phase -= twoPi;
5506
- }
5507
- }
5508
- const fadeSamples = Math.floor(sampleRate * 2e-3);
5509
- for (let i = 0; i < fadeSamples; i++) {
5510
- const gain = i / fadeSamples;
5511
- result[i] = Math.round(result[i] * gain);
5512
- result[result.length - 1 - i] = Math.round(result[result.length - 1 - i] * gain);
5513
- }
5514
- return Int16Array.from(result);
5534
+ // src/@dictionaries/dictionaries.causes.ts
5535
+ var dict_causes = {
5536
+ "SM": "Snow Melt",
5537
+ "RS": "Rain/Snow Melt",
5538
+ "ER": "Excessive Rain",
5539
+ "DM": "Dam/Levee Failure",
5540
+ "IJ": "Ice Jam",
5541
+ "GO": "Glacier Lake Outburst",
5542
+ "IC": "Ice",
5543
+ "FS": "Flash Flood / Storm Surge",
5544
+ "FT": "Tidal Effects",
5545
+ "ET": "Elevated Upstream Flow",
5546
+ "MC": "Other Multiple Causes",
5547
+ "WT": "Wind and/or Tidal Effects",
5548
+ "DR": "Reservoir Release",
5549
+ "UU": "Unknown",
5550
+ "OT": "Other Effects"
5515
5551
  };
5516
5552
 
5517
- // src/@modules/@eas/eas.setAsciiToBits.ts
5518
- var setAsciiToBits = (str) => {
5519
- const bits = [];
5520
- for (let i = 0; i < str.length; i++) {
5521
- const c = str.charCodeAt(i) & 255;
5522
- bits.push(0);
5523
- for (let b = 0; b < 8; b++) bits.push(c >> b & 1);
5524
- bits.push(1, 1);
5525
- }
5526
- return bits;
5553
+ // src/@dictionaries/dictionaries.records.ts
5554
+ var dict_records = {
5555
+ "NO": "No Record Expected",
5556
+ "NR": "Near Record or possible record",
5557
+ "UU": "Unknown history of records",
5558
+ "OO": "Other"
5527
5559
  };
5528
5560
 
5529
- // src/@modules/@eas/eas.getMergedPCM16.ts
5530
- var getMergedPCM16 = (arrays) => {
5531
- let total = 0;
5532
- for (const a of arrays) total += a.length;
5533
- const out = new Int16Array(total);
5534
- let o = 0;
5535
- for (const a of arrays) {
5536
- out.set(a, o);
5537
- o += a.length;
5538
- }
5539
- return out;
5561
+ // src/@dictionaries/dictionaries.severity.ts
5562
+ var dict_severity = {
5563
+ N: "Not Expected",
5564
+ 0: "Areal Flood or FF Product",
5565
+ 1: "Minor",
5566
+ 2: "Moderate",
5567
+ 3: "Major",
5568
+ U: "Unknown"
5540
5569
  };
5541
5570
 
5542
- // src/@modules/@eas/eas.setSameHeader.ts
5543
- var setSameHeader = (vtec2, repeats, sampleRate = 8e3, options = {}) => {
5544
- var _a, _b;
5545
- const preMarkSec = (_a = options.preMarkSec) != null ? _a : 0.3;
5546
- const gapSec = (_b = options.gapSec) != null ? _b : 0.1;
5547
- const bursts = [];
5548
- const gap = new Int16Array(Math.floor(gapSec * sampleRate));
5549
- for (let i = 0; i < repeats; i++) {
5550
- const bodyBits = setAsciiToBits(vtec2);
5551
- const body = setAFSK(bodyBits, sampleRate);
5552
- const extendedBodyDuration = Math.round(preMarkSec * sampleRate);
5553
- const extendedBody = new Int16Array(extendedBodyDuration + gap.length);
5554
- for (let j2 = 0; j2 < extendedBodyDuration; j2++) {
5555
- extendedBody[j2] = Math.round(body[j2 % body.length] * 0.2);
5556
- }
5557
- extendedBody.set(gap, extendedBodyDuration);
5558
- bursts.push(extendedBody);
5559
- if (i !== repeats - 1) bursts.push(gap);
5571
+ // src/@parsers/@hvtec/hvtec.extract.ts
5572
+ var hvExtract = (message) => {
5573
+ var _a;
5574
+ const getHVTECs = (_a = message.match(dict_expressions.hvtec)) != null ? _a : [];
5575
+ const vtecs = [];
5576
+ for (const vtec2 of getHVTECs) {
5577
+ const sub = vtec2.split(`.`);
5578
+ if (sub.length < 7) continue;
5579
+ vtecs.push({
5580
+ hvtec: vtec2,
5581
+ severity: dict_severity[sub[1]],
5582
+ cause: dict_causes[sub[2]],
5583
+ record: dict_records[sub[6]]
5584
+ });
5560
5585
  }
5561
- return getMergedPCM16(bursts);
5586
+ return vtecs.length > 0 ? vtecs : null;
5562
5587
  };
5563
5588
 
5564
- // src/@modules/@eas/eas.setAttentionTone.ts
5565
- var setAttentionTone = (ms, sampleRate) => {
5566
- const len = Math.floor(ms * sampleRate);
5567
- const out = new Int16Array(len);
5568
- const f1 = 853;
5569
- const f2 = 960;
5570
- const twoPi = Math.PI * 2;
5571
- const amp = 0.1;
5572
- const fadeLen = Math.floor(sampleRate * 0);
5573
- for (let i = 0; i < len; i++) {
5574
- const t = i / sampleRate;
5575
- const s = Math.sin(twoPi * f1 * t) + Math.sin(twoPi * f2 * t);
5576
- let gain = 1;
5577
- if (i < fadeLen) gain = i / fadeLen;
5578
- else if (i > len - fadeLen) gain = (len - i) / fadeLen;
5579
- const v = Math.max(-1, Math.min(1, s / 2 * amp * gain));
5580
- out[i] = Math.round(v * 32767);
5581
- }
5582
- return out;
5583
- };
5589
+ // src/@events/events.vtec.ts
5590
+ var vtec = (stanza) => __async(null, null, function* () {
5591
+ var _a, _b, _c, _d, _e;
5592
+ 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 !== "$$");
5593
+ if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
5594
+ for (const message of getMessages) {
5595
+ const tick = performance.now();
5596
+ const attributes = stanza == null ? void 0 : stanza.attributes;
5597
+ const pVtec = pvExtract(message);
5598
+ const hVtec = hvExtract(message);
5599
+ const ugc2 = yield ugcExtract(message);
5600
+ if (pVtec != null && ugc2 != null) {
5601
+ for (const pv of pVtec) {
5602
+ const vtec2 = pv;
5603
+ const props = properties({ message, attributes, ugc: ugc2, pVtec: vtec2 });
5604
+ const header = getEventHeader({ properties: props, getType: stanza.getType, vtec: vtec2 });
5605
+ const issued = (_d = new Date(attributes.issue)) != null ? _d : /* @__PURE__ */ new Date();
5606
+ const expires = new Date(vtec2.expires);
5607
+ bootstrap.cache.processed.push({
5608
+ type: `Feature`,
5609
+ geometry: {
5610
+ type: `Point`,
5611
+ coordinates: []
5612
+ },
5613
+ properties: __spreadProps(__spreadValues({
5614
+ event: pv.event,
5615
+ parent: pv.event,
5616
+ status: pv.status,
5617
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
5618
+ expires: !isNaN(expires.getTime()) ? expires.toISOString() : (_e = ugc2.expires) != null ? _e : new Date(issued.getTime() + 60 * 60 * 1e3).toISOString()
5619
+ }, props), {
5620
+ metadata: {
5621
+ ms: performance.now() - tick,
5622
+ source: `events.vtec`,
5623
+ tracking: getEventTracking({ type: `VTEC`, stanza, attributes, properties: props, vtec: vtec2 }),
5624
+ header,
5625
+ vtec: pv,
5626
+ hvtec: hVtec,
5627
+ raw: message,
5628
+ history: [
5629
+ {
5630
+ description: props.description,
5631
+ issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
5632
+ status: pv.status
5633
+ }
5634
+ ]
5635
+ }
5636
+ })
5637
+ });
5638
+ setDebug({ title: `@events.vtec`, message: `Event process took ${performance.now() - tick} ms` });
5639
+ }
5640
+ }
5641
+ }
5642
+ });
5584
5643
 
5585
- // src/@modules/@eas/eas.setNoise.ts
5586
- var setNoise = (int16, noiseLevel = 0.02) => {
5587
- const x = getPCMToFloat(int16);
5588
- for (let i = 0; i < x.length; i++) x[i] += (Math.random() * 2 - 1) * noiseLevel;
5589
- let peak = 0;
5590
- for (let i = 0; i < x.length; i++) peak = Math.max(peak, Math.abs(x[i]));
5591
- if (peak > 1) for (let i = 0; i < x.length; i++) x[i] *= 0.98 / peak;
5592
- return getFloatPCM16(x);
5593
- };
5644
+ // src/@events/events.api.ts
5645
+ var api = (stanza) => __async(null, null, function* () {
5646
+ 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;
5647
+ const messages = Object.values(JSON.parse(stanza.message).features);
5648
+ for (const feature of messages) {
5649
+ const tick = performance.now();
5650
+ 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;
5651
+ bootstrap.cache.processed.push({
5652
+ type: `Feature`,
5653
+ geometry: {
5654
+ type: `Point`,
5655
+ coordinates: []
5656
+ },
5657
+ properties: {
5658
+ event: (_f = (_e = feature == null ? void 0 : feature.properties) == null ? void 0 : _e.event) != null ? _f : null,
5659
+ parent: (_h = (_g = feature == null ? void 0 : feature.properties) == null ? void 0 : _g.event) != null ? _h : null,
5660
+ status: (_j = (_i = feature == null ? void 0 : feature.properties) == null ? void 0 : _i.messageType) != null ? _j : null,
5661
+ 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,
5662
+ 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,
5663
+ locations: (_p = (_o = feature == null ? void 0 : feature.properties) == null ? void 0 : _o.areaDesc) != null ? _p : null,
5664
+ 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(";") : [],
5665
+ description: (_t = (_s = feature == null ? void 0 : feature.properties) == null ? void 0 : _s.description) != null ? _t : null,
5666
+ attributes: (_v = (_u = feature == null ? void 0 : feature.properties) == null ? void 0 : _u.attributes) != null ? _v : {},
5667
+ geocode: {
5668
+ office: {
5669
+ office: pVtec ? (_w = pVtec == null ? void 0 : pVtec[0]) == null ? void 0 : _w.tracking.split(`.`)[0] : null,
5670
+ name: (_y = dict_icao[pVtec ? (_x = pVtec == null ? void 0 : pVtec[0]) == null ? void 0 : _x.tracking.split(`.`)[0] : null]) != null ? _y : null
5671
+ },
5672
+ 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],
5673
+ ugc: (_E = (_D = (_C = feature == null ? void 0 : feature.properties) == null ? void 0 : _C.geocode) == null ? void 0 : _D.UGC) != null ? _E : [],
5674
+ 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,
5675
+ polygon_generated: ((_H = feature == null ? void 0 : feature.geometry) == null ? void 0 : _H.coordinates.length) > 0 ? true : false
5676
+ },
5677
+ parameters: {
5678
+ tags: getEventTags((_I = feature == null ? void 0 : feature.properties) == null ? void 0 : _I.description),
5679
+ instructions: (_K = (_J = feature == null ? void 0 : feature.properties) == null ? void 0 : _J.instruction) != null ? _K : null,
5680
+ source: (_M = getTextFromProduct({ message: (_L = feature == null ? void 0 : feature.properties) == null ? void 0 : _L.description, find: [`SOURCE...`], removal: [`.`] })) != null ? _M : null,
5681
+ hazards: (_O = getTextFromProduct({ message: (_N = feature == null ? void 0 : feature.properties) == null ? void 0 : _N.description, find: [`HAZARD...`], removal: [`.`] })) != null ? _O : null,
5682
+ impacts: (_Q = getTextFromProduct({ message: (_P = feature == null ? void 0 : feature.properties) == null ? void 0 : _P.description, find: [`IMPACT...`], removal: [`.`] })) != null ? _Q : null,
5683
+ 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,
5684
+ 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,
5685
+ 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,
5686
+ 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,
5687
+ 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,
5688
+ 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,
5689
+ 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
5690
+ },
5691
+ discussion_parameters: {
5692
+ 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,
5693
+ discussion_concerning: (_wa = getTextFromProduct({ message: (_va = feature == null ? void 0 : feature.properties) == null ? void 0 : _va.description, find: [`Concerning...`] })) != null ? _wa : null,
5694
+ 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,
5695
+ 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,
5696
+ 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,
5697
+ 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
5698
+ },
5699
+ watch_parameters: {
5700
+ 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),
5701
+ 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,
5702
+ 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,
5703
+ 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,
5704
+ 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,
5705
+ 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,
5706
+ 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,
5707
+ 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,
5708
+ 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,
5709
+ 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,
5710
+ 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,
5711
+ pds_watch: getTextFromProduct({ message: (_jb = feature == null ? void 0 : feature.properties) == null ? void 0 : _jb.description, find: [`PARTICULARLY DANGEROUS SITUATION`], removal: [`%`, `<`, `:`] }) === `YES`
5712
+ },
5713
+ metadata: {
5714
+ ms: performance.now() - tick,
5715
+ source: `events.api`,
5716
+ 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] }),
5717
+ header: `ZCZC-ATMOSX-${(_ob = (_nb = feature == null ? void 0 : feature.properties) == null ? void 0 : _nb.parameters) == null ? void 0 : _ob.WMOidentifier}`,
5718
+ vtec: pVtec == null ? void 0 : pVtec[0],
5719
+ hvtec: null,
5720
+ raw: (_pb = feature == null ? void 0 : feature.properties) == null ? void 0 : _pb.description,
5721
+ history: [
5722
+ {
5723
+ description: (_qb = feature == null ? void 0 : feature.properties) == null ? void 0 : _qb.description,
5724
+ 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,
5725
+ status: (_ub = (_tb = feature == null ? void 0 : feature.properties) == null ? void 0 : _tb.messageType) != null ? _ub : null
5726
+ }
5727
+ ]
5728
+ }
5729
+ }
5730
+ });
5731
+ setDebug({ title: `@events.api`, message: `Event process took ${performance.now() - tick} ms` });
5732
+ }
5733
+ });
5594
5734
 
5595
- // src/@modules/@eas/eas.getPCM16.ts
5596
- var getPCM16 = (samples, sampleRate) => {
5597
- let o = 0;
5598
- const bytesPerSample = 2;
5599
- const blockAlign = 1 * bytesPerSample;
5600
- const byteRate = sampleRate * blockAlign;
5601
- const subchunk2Size = samples.length * bytesPerSample;
5602
- const chunkSize = 36 + subchunk2Size;
5603
- const buffer = Buffer.alloc(44 + subchunk2Size);
5604
- buffer.write("RIFF", o);
5605
- o += 4;
5606
- buffer.writeUInt32LE(chunkSize, o);
5607
- o += 4;
5608
- buffer.write("WAVE", o);
5609
- o += 4;
5610
- buffer.write("fmt ", o);
5611
- o += 4;
5612
- buffer.writeUInt32LE(16, o);
5613
- o += 4;
5614
- buffer.writeUInt16LE(1, o);
5615
- o += 2;
5616
- buffer.writeUInt16LE(1, o);
5617
- o += 2;
5618
- buffer.writeUInt32LE(sampleRate, o);
5619
- o += 4;
5620
- buffer.writeUInt32LE(byteRate, o);
5621
- o += 4;
5622
- buffer.writeUInt16LE(blockAlign, o);
5623
- o += 2;
5624
- buffer.writeUInt16LE(16, o);
5625
- o += 2;
5626
- buffer.write("data", o);
5627
- o += 4;
5628
- buffer.writeUInt32LE(subchunk2Size, o);
5629
- o += 4;
5630
- for (let i = 0; i < samples.length; i++, o += 2) {
5631
- buffer.writeInt16LE(samples[i].value, o);
5735
+ // src/@dictionaries/dictionaries.enhanced.ts
5736
+ var dict_enhanced = {
5737
+ "Tornado Warning": {
5738
+ "Tornado Emergency": {
5739
+ description: "tornado emergency"
5740
+ },
5741
+ "PDS Tornado Warning": {
5742
+ description: "particularly dangerous situation",
5743
+ damage: `CONSIDERABLE`
5744
+ },
5745
+ "Radar Confirmed Tornado Warning": {
5746
+ description: "source...radar confirmed tornado.",
5747
+ tornado: `OBSERVED`
5748
+ },
5749
+ "Confirmed Tornado Warning": {
5750
+ tornado: `OBSERVED`
5751
+ },
5752
+ "Radar Indicated Tornado Warning": {}
5753
+ },
5754
+ "Fire Weather Warning": {
5755
+ "PDS Fire Weather Warning": {
5756
+ description: "particularly dangerous situation"
5757
+ }
5758
+ },
5759
+ "Blizzard Warning": {
5760
+ "PDS Blizzard Warning": {
5761
+ description: "particularly dangerous situation"
5762
+ }
5763
+ },
5764
+ "Ice Storm Warning": {
5765
+ "PDS Ice Storm Warning": {
5766
+ description: "particularly dangerous situation"
5767
+ }
5768
+ },
5769
+ "Special Marine Warning": {
5770
+ "Special Marine Warning (TPROB)": {
5771
+ tornado: `POSSIBLE`
5772
+ }
5773
+ },
5774
+ "Tornado Watch": {
5775
+ "PDS Tornado Watch": {
5776
+ pdswatch: true
5777
+ }
5778
+ },
5779
+ "Severe Thunderstorm Watch": {
5780
+ "PDS Severe Thunderstorm Watch": {
5781
+ pdswatch: true
5782
+ }
5783
+ },
5784
+ "Flash Flood Warning": {
5785
+ "Flash Flood Emergency": {
5786
+ description: "flash flood emergency"
5787
+ },
5788
+ "Considerable Flash Flood Warning": {
5789
+ damage: `CONSIDERABLE`
5790
+ }
5791
+ },
5792
+ "Severe Thunderstorm Warning": {
5793
+ "EDS Severe Thunderstorm Warning (TPROB)": {
5794
+ description: "extremely dangerous situation",
5795
+ tornado: "POSSIBLE"
5796
+ },
5797
+ "EDS Severe Thunderstorm Warning": {
5798
+ description: "extremely dangerous situation"
5799
+ },
5800
+ "Destructive Severe Thunderstorm Warning (TPROB)": {
5801
+ damage: `DESTRUCTIVE`,
5802
+ tornado: `POSSIBLE`
5803
+ },
5804
+ "Destructive Severe Thunderstorm Warning": {
5805
+ damage: `DESTRUCTIVE`
5806
+ },
5807
+ "Considerable Severe Thunderstorm Warning (TPROB)": {
5808
+ damage: `CONSIDERABLE`,
5809
+ tornado: `POSSIBLE`
5810
+ },
5811
+ "Considerable Severe Thunderstorm Warning": {
5812
+ damage: `CONSIDERABLE`
5813
+ },
5814
+ "Severe Thunderstorm Warning (TPROB)": {
5815
+ tornado: `POSSIBLE`
5816
+ }
5632
5817
  }
5633
- return buffer;
5634
5818
  };
5635
5819
 
5636
- // src/@modules/@eas/eas.getTTS.ts
5637
- var import_os = require("os");
5638
- var import_fs = require("fs");
5639
- var import_child_process = require("child_process");
5640
- var getTTS = (text2, outputPath) => __async(null, null, function* () {
5641
- const vPlatform = (0, import_os.platform)();
5642
- switch (vPlatform) {
5643
- case "win32": {
5644
- try {
5645
- const txtPath = outputPath + ".txt";
5646
- (0, import_fs.writeFileSync)(txtPath, text2, "utf8");
5647
- const command = [
5648
- "Add-Type -AssemblyName System.Speech;",
5649
- `$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;`,
5650
- `$text = Get-Content -Raw -LiteralPath '${txtPath}';`,
5651
- `$speak.SetOutputToWaveFile('${outputPath}');`,
5652
- `$speak.Speak($text);`,
5653
- `$speak.Dispose();`
5654
- ].join(" ");
5655
- (0, import_child_process.execSync)(`powershell -Command "${command}"`, { stdio: "inherit" });
5656
- } catch (error) {
5657
- console.error("Error occurred while generating TTS:", error);
5820
+ // src/@building/building.enhance.ts
5821
+ var getEventEnhancedName = (event) => {
5822
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
5823
+ const configurations = bootstrap.settings;
5824
+ let name = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.event;
5825
+ if (!((_b = configurations == null ? void 0 : configurations.GlobalSettings) == null ? void 0 : _b.BetterEventNames)) {
5826
+ return name;
5827
+ }
5828
+ const damage = (_d = (_c = event == null ? void 0 : event.properties) == null ? void 0 : _c.parameters) == null ? void 0 : _d.damage_threat;
5829
+ const tornado = (_f = (_e = event == null ? void 0 : event.properties) == null ? void 0 : _e.parameters) == null ? void 0 : _f.tornado_threat;
5830
+ const pdswatch = (_h = (_g = event == null ? void 0 : event.properties) == null ? void 0 : _g.watch_parameters) == null ? void 0 : _h.pds_watch;
5831
+ const description = (_j = (_i = event == null ? void 0 : event.properties) == null ? void 0 : _i.description) == null ? void 0 : _j.toLowerCase();
5832
+ for (const [eventKey, eventConfig] of Object.entries(dict_enhanced)) {
5833
+ if (eventKey !== name) continue;
5834
+ for (const [paramKey, paramValue] of Object.entries(eventConfig)) {
5835
+ let matches = true;
5836
+ if (paramValue == null ? void 0 : paramValue.description) {
5837
+ if (!description.includes(paramValue.description.toLowerCase())) matches = false;
5658
5838
  }
5659
- break;
5660
- }
5661
- case "linux":
5662
- try {
5663
- (0, import_child_process.execSync)(`espeak -w "${outputPath}" "${text2.replace(/"/g, '\\"')}"`);
5664
- } catch (e) {
5839
+ if (paramValue == null ? void 0 : paramValue.damage) {
5840
+ if (paramValue.damage !== damage) matches = false;
5665
5841
  }
5666
- break;
5667
- default:
5668
- break;
5842
+ if (paramValue == null ? void 0 : paramValue.tornado) {
5843
+ if (paramValue.tornado !== tornado) matches = false;
5844
+ }
5845
+ if (paramValue == null ? void 0 : paramValue.pdswatch) {
5846
+ if (paramValue.pdswatch !== pdswatch) matches = false;
5847
+ }
5848
+ if (matches) {
5849
+ name = paramKey;
5850
+ break;
5851
+ }
5852
+ }
5669
5853
  }
5670
- });
5854
+ return name;
5855
+ };
5671
5856
 
5672
- // src/@modules/@eas/eas.getCleanDescription.ts
5673
- var getCleanDescription = (message) => {
5674
- const patches = [
5675
- { regex: /\.{3,}/g, replacement: ". " },
5676
- { regex: /\bUTC\b/g, replacement: "Coordinated Universal Time" },
5677
- { regex: /\bGMT\b/g, replacement: "Greenwich Mean Time" },
5678
- { regex: /\bEST\b(?!\w)/g, replacement: "Eastern Standard Time" },
5679
- { regex: /\bEDT\b(?!\w)/g, replacement: "Eastern Daylight Time" },
5680
- { regex: /\bCST\b(?!\w)/g, replacement: "Central Standard Time" },
5681
- { regex: /\bCDT\b(?!\w)/g, replacement: "Central Daylight Time" },
5682
- { regex: /\bMST\b(?!\w)/g, replacement: "Mountain Standard Time" },
5683
- { regex: /\bMDT\b(?!\w)/g, replacement: "Mountain Daylight Time" },
5684
- { regex: /\bPST\b(?!\w)/g, replacement: "Pacific Standard Time" },
5685
- { regex: /\bPDT\b(?!\w)/g, replacement: "Pacific Daylight Time" },
5686
- { regex: /\bAKST\b(?!\w)/g, replacement: "Alaska Standard Time" },
5687
- { regex: /\bAKDT\b(?!\w)/g, replacement: "Alaska Daylight Time" },
5688
- { regex: /\bHST\b(?!\w)/g, replacement: "Hawaii Standard Time" },
5689
- { regex: /\bHDT\b(?!\w)/g, replacement: "Hawaii Daylight Time" },
5690
- { regex: /\bmph\b(?!\w)/g, replacement: "miles per hour" },
5691
- { regex: /\bkm\/h\b(?!\w)/g, replacement: "kilometers per hour" },
5692
- { regex: /\bkmh\b(?!\w)/g, replacement: "kilometers per hour" },
5693
- { regex: /\bkt\b(?!\w)/g, replacement: "knots" },
5694
- { regex: /\bNE\b(?!\w)/g, replacement: "northeast" },
5695
- { regex: /\bNW\b(?!\w)/g, replacement: "northwest" },
5696
- { regex: /\bSE\b(?!\w)/g, replacement: "southeast" },
5697
- { regex: /\bSW\b(?!\w)/g, replacement: "southwest" },
5698
- { regex: /\bNM\b(?!\w)/g, replacement: "nautical miles" },
5699
- { regex: /\bdeg\b(?!\w)/g, replacement: "degrees" },
5700
- { regex: /\btstm\b(?!\w)/g, replacement: "thunderstorm" },
5701
- { regex: /\bmm\b(?!\w)/g, replacement: "millimeters" },
5702
- { regex: /\bcm\b(?!\w)/g, replacement: "centimeters" },
5703
- { regex: /\bin.\b(?!\w)/g, replacement: "inches" },
5704
- { regex: /\bft\b(?!\w)/g, replacement: "feet" },
5705
- { regex: /\bmi\b(?!\w)/g, replacement: "miles" },
5706
- { regex: /\bhr\b(?!\w)/g, replacement: "hour" },
5707
- { regex: /\bhourly\b(?!\w)/g, replacement: "per hour" },
5708
- { regex: /\bkg\b(?!\w)/g, replacement: "kilograms" },
5709
- { regex: /\bg\/kg\b(?!\w)/g, replacement: "grams per kilogram" },
5710
- { regex: /\bmb\b(?!\w)/g, replacement: "millibars" },
5711
- { regex: /\bhPa\b(?!\w)/g, replacement: "hectopascals" },
5712
- { regex: /\bPa\b(?!\w)/g, replacement: "pascals" },
5713
- { regex: /\bKPa\b(?!\w)/g, replacement: "kilopascals" },
5714
- { regex: /\bC\/hr\b(?!\w)/g, replacement: "degrees Celsius per hour" },
5715
- { regex: /\bF\/hr\b(?!\w)/g, replacement: "degrees Fahrenheit per hour" },
5716
- { regex: /\bC\/min\b(?!\w)/g, replacement: "degrees Celsius per minute" },
5717
- { regex: /\bF\/min\b(?!\w)/g, replacement: "degrees Fahrenheit per minute" },
5718
- { regex: /\bC\b(?!\w)/g, replacement: "degrees Celsius" },
5719
- { regex: /\bF\b(?!\w)/g, replacement: "degrees Fahrenheit" }
5720
- ];
5721
- const hours = {
5722
- 0: "twelve",
5723
- 1: "one",
5724
- 2: "two",
5725
- 3: "three",
5726
- 4: "four",
5727
- 5: "five",
5728
- 6: "six",
5729
- 7: "seven",
5730
- 8: "eight",
5731
- 9: "nine",
5732
- 10: "ten",
5733
- 11: "eleven",
5734
- 12: "twelve"
5735
- };
5736
- const minWord = (m) => m === 0 ? "o'clock" : m < 10 ? `oh ${m}` : `${m}`;
5737
- const fmt = (h, m, ap) => `${hours[h % 12]} ${minWord(m)} ${ap}`;
5738
- for (const { regex, replacement } of patches) {
5739
- message = message.replace(regex, replacement);
5740
- }
5741
- 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();
5857
+ // src/@dictionaries/dictionaries.correlations.ts
5858
+ var dict_correlations = [
5859
+ { type: "Statement", name: "Statement", isCancel: false, isUpdate: false, isIssued: true, isStatement: true },
5860
+ { type: "Update", name: "Updated", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5861
+ { type: "Cancel", name: "Cancelled", isCancel: true, isUpdate: false, isIssued: false, isStatement: false },
5862
+ { type: "Alert", name: "Issued", isCancel: false, isUpdate: false, isIssued: true, isStatement: false },
5863
+ { type: "Updated", name: "Updated", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5864
+ { type: "Expired", name: "Expired", isCancel: true, isUpdate: false, isIssued: false, isStatement: false },
5865
+ { type: "Issued", name: "Issued", isCancel: false, isUpdate: false, isIssued: true, isStatement: false },
5866
+ { type: "Extended", name: "Extended", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5867
+ { type: "Correction", name: "Correction", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5868
+ { type: "Upgraded", name: "Upgraded", isCancel: false, isUpdate: true, isIssued: false, isStatement: false },
5869
+ { type: "Cancelled", name: "Cancelled", isCancel: true, isUpdate: false, isIssued: false, isStatement: false },
5870
+ { type: "Routine", name: "Routine", isCancel: false, isUpdate: true, isIssued: false, isStatement: false }
5871
+ ];
5872
+
5873
+ // src/@dictionaries/dictionaries.cancellation.ts
5874
+ var dict_cancellation = [
5875
+ "has been cancelled",
5876
+ "subsided sufficiently for the advisory to be cancelled",
5877
+ "has been cancelled",
5878
+ "no tsunami threat from a nearby earthquake",
5879
+ "will be allowed to expire",
5880
+ "has diminished",
5881
+ "and no longer",
5882
+ "has been replaced",
5883
+ "The threat has ended",
5884
+ "has weakened below severe"
5885
+ ];
5886
+
5887
+ // src/@dictionaries/dictionaries.testing.ts
5888
+ var dict_testing = [
5889
+ `This is a test message`,
5890
+ `Monitoring message only.`,
5891
+ `THIS_MESSAGE_IS_FOR_TEST_PURPOSES_ONLY`,
5892
+ "TEST MESSAGE"
5893
+ ];
5894
+
5895
+ // src/@dictionaries/dictionaries.hail.ts
5896
+ var dict_hail = {
5897
+ ".25": "Pea",
5898
+ ".50": "Penny",
5899
+ ".75": "Penny",
5900
+ "Up to .75": "Penny",
5901
+ ".88": "Nickel",
5902
+ "0.75": "Penny",
5903
+ "0.88": "Nickel",
5904
+ "1.00": "Quarter",
5905
+ "1.25": "Half Dollar",
5906
+ "1.50": "Ping Pong Ball",
5907
+ "1.75": "Golf Ball",
5908
+ "2.00": "Hen Egg",
5909
+ "2.50": "Tennis Ball",
5910
+ "2.75": "Baseball",
5911
+ "4.00": "CD/DVD"
5742
5912
  };
5743
5913
 
5744
- // src/@modules/@eas/eas.setEasTone.ts
5745
- var import_path2 = require("path");
5746
- var import_fs2 = require("fs");
5747
- var import_child_process2 = require("child_process");
5748
- var import_os2 = require("os");
5749
- var setEasTone = (options) => __async(null, null, function* () {
5750
- var _a;
5751
- const settings = bootstrap.settings;
5752
- const directory = settings.GlobalSettings.ArchiveSettings.EasDirectory;
5753
- const prefix = settings.GlobalSettings.ArchiveSettings.EasToneout;
5754
- let message = options.message;
5755
- let header = options.header;
5756
- let title = (_a = options.title) != null ? _a : `${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, "")}`;
5757
- if (!message || !header) {
5758
- setWarning({
5759
- title: `EAS`,
5760
- message: `Message and header are required to generate an EAS tone.`
5761
- });
5762
- return null;
5914
+ // src/@building/building.signature.ts
5915
+ var getEventSignature = (event) => {
5916
+ var _a, _b, _c, _d, _e, _f, _g, _h;
5917
+ const properties2 = event == null ? void 0 : event.properties;
5918
+ const vtec2 = (_b = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.metadata) == null ? void 0 : _b.vtec;
5919
+ const status = dict_correlations.find((c) => c.type === (properties2 == null ? void 0 : properties2.status));
5920
+ const csig = dict_cancellation.find((sig) => properties2.description.toLowerCase().includes(sig.toLowerCase()));
5921
+ properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_issued: true, is_test: false });
5922
+ if ((_c = properties2 == null ? void 0 : properties2.parameters) == null ? void 0 : _c.estimated_hail_size) {
5923
+ properties2.parameters.estimated_hail_size += ` (${(_e = dict_hail[(_d = properties2 == null ? void 0 : properties2.parameters) == null ? void 0 : _d.estimated_hail_size]) != null ? _e : "--"})`;
5763
5924
  }
5764
- let buffTTS;
5765
- let buffRadio;
5766
- let buffFull = [];
5767
- if (!(0, import_fs2.existsSync)(directory)) {
5768
- (0, import_fs2.mkdirSync)(directory, { recursive: true });
5925
+ if (status) {
5926
+ properties2.status = (_f = status.name) != null ? _f : properties2.status;
5927
+ properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_updated: !!status.isUpdate, is_issued: !!status.isIssued, is_expired: !!status.isCancel, is_statement: !!status.isStatement });
5769
5928
  }
5770
- if (!(0, import_fs2.existsSync)((0, import_path2.join)(directory, `/tts`))) {
5771
- (0, import_fs2.mkdirSync)((0, import_path2.join)(directory, `/tts`), { recursive: true });
5929
+ if (csig) {
5930
+ properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_expired: true });
5772
5931
  }
5773
- if (!(0, import_fs2.existsSync)((0, import_path2.join)(directory, `/encoded`))) {
5774
- (0, import_fs2.mkdirSync)((0, import_path2.join)(directory, `/encoded`), { recursive: true });
5932
+ const getProduct = (_h = (_g = vtec2 == null ? void 0 : vtec2.vtec) == null ? void 0 : _g.split(`.`)[0]) == null ? void 0 : _h.replace(`/`, ``);
5933
+ const isTestProduct = dict_products[getProduct] == `Test Product`;
5934
+ if (isTestProduct || dict_testing.some((sig) => {
5935
+ var _a2, _b2, _c2, _d2;
5936
+ 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());
5937
+ })) {
5938
+ properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_test: true });
5775
5939
  }
5776
- const tmpTTS = (0, import_path2.join)(directory, `/tts/${title}.wav`);
5777
- const outTTS = (0, import_path2.join)(directory, `/encoded/${title}.wav`);
5778
- const vPlatform = (0, import_os2.platform)();
5779
- if (vPlatform === "darwin") {
5780
- setWarning({
5781
- title: `EAS`,
5782
- message: `EAS tone generation is not supported on macOS.`
5783
- });
5784
- return null;
5940
+ if (new Date(properties2.expires).getTime() < Date.now()) {
5941
+ properties2.status_metadata = __spreadProps(__spreadValues({}, properties2.status_metadata), { is_expired: true });
5785
5942
  }
5786
- yield new Promise((resolve6, reject) => {
5787
- const tMsg = getCleanDescription(message);
5788
- getTTS(tMsg, tmpTTS).then(() => {
5789
- resolve6();
5943
+ properties2.status_metadata = __spreadValues({}, properties2.status_metadata);
5944
+ return event;
5945
+ };
5946
+
5947
+ // src/@manager/manager.setHash.ts
5948
+ var setHash = (event, entry) => {
5949
+ if (entry) {
5950
+ entry.hashes.push(event.properties.metadata.hash);
5951
+ entry.expires = event.properties.expires;
5952
+ } else {
5953
+ bootstrap.cache.hashes.push({
5954
+ tracking: event.properties.metadata.tracking,
5955
+ hashes: [event.properties.metadata.hash],
5956
+ expires: event.properties.expires
5790
5957
  });
5791
- });
5792
- if (!(0, import_fs2.existsSync)(tmpTTS)) {
5958
+ }
5959
+ };
5960
+
5961
+ // src/@modules/@eas/eas.getWavPCM16.ts
5962
+ var getWavPCM16 = (buffer) => {
5963
+ if (buffer.toString("ascii", 0, 4) !== "RIFF" || buffer.toString("ascii", 8, 12) !== "WAVE") {
5793
5964
  return null;
5794
5965
  }
5795
- buffTTS = (0, import_fs2.readFileSync)(tmpTTS);
5796
- const vWav = getWavPCM16(buffTTS);
5797
- const vSamples = getSampledPCM16(vWav.samples, vWav.sampleRate, 8e3);
5798
- const vRadio = setRadioEffect(vSamples, 8e3);
5799
- if ((0, import_fs2.existsSync)(prefix)) {
5800
- let tBuffer = (0, import_fs2.readFileSync)(prefix);
5801
- let tWav = getWavPCM16(tBuffer);
5802
- if (tWav == null) {
5803
- try {
5804
- const converted = (0, import_path2.join)(directory, `/tts/${title}.converted.wav`);
5805
- (0, import_child_process2.execSync)(`ffmpeg -y -i "${prefix}" -ar 8000 -ac 1 -sample_fmt s16 "${converted}"`, { stdio: "ignore" });
5806
- if ((0, import_fs2.existsSync)(converted)) {
5807
- tBuffer = (0, import_fs2.readFileSync)(converted);
5808
- tWav = getWavPCM16(tBuffer);
5809
- try {
5810
- (0, import_fs2.unlinkSync)(converted);
5811
- } catch (e) {
5812
- }
5813
- }
5814
- } catch (e) {
5815
- }
5816
- }
5817
- if (tWav == null) {
5818
- 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.` });
5819
- return null;
5820
- }
5821
- const tSamples = tWav.sampleRate != 8e3 ? getSampledPCM16(tWav.samples, tWav.sampleRate, 8e3) : tWav.samples;
5822
- buffRadio = setRadioEffect(tSamples, 8e3);
5966
+ let fmt = null;
5967
+ let data = null;
5968
+ let i = 12;
5969
+ while (i + 8 <= buffer.length) {
5970
+ const id2 = buffer.toString("ascii", i, i + 4);
5971
+ const size = buffer.readUInt32LE(i + 4);
5972
+ const start = i + 8;
5973
+ const end = start + size;
5974
+ if (id2 === "fmt ") fmt = buffer.slice(start, end);
5975
+ if (id2 === "data") data = buffer.slice(start, end);
5976
+ i = end + size % 2;
5823
5977
  }
5824
- buffFull = buffRadio != null ? [buffRadio, new Int16Array(Math.floor(0.5 * 8e3))] : [];
5825
- buffFull.push(
5826
- setSameHeader(header, 3, 8e3, {
5827
- preMarkSec: 1.1,
5828
- gapSec: 0.5
5829
- }),
5830
- new Int16Array(Math.floor(0.5 * 8e3)),
5831
- setAttentionTone(8, 8e3),
5832
- new Int16Array(Math.floor(0.5 * 8e3)),
5833
- vRadio
5834
- );
5835
- for (let i = 0; i < 3; i++) {
5836
- buffFull.push(setSameHeader(header, 1, 8e3, { preMarkSec: 0.5, gapSec: 0.1 }));
5837
- buffFull.push(new Int16Array(Math.floor(0.5 * 8e3)));
5978
+ if (!fmt || !data) return null;
5979
+ const audioFormat = fmt.readUInt16LE(0);
5980
+ const channels = fmt.readUInt16LE(2);
5981
+ const sampleRate = fmt.readUInt32LE(4);
5982
+ const bitsPerSample = fmt.readUInt16LE(14);
5983
+ if (audioFormat !== 1 || bitsPerSample !== 16 || channels !== 1) {
5984
+ return null;
5838
5985
  }
5839
- const aSamples = getMergedPCM16(buffFull);
5840
- const aFinal = setNoise(aSamples, 2e-3);
5841
- const aBuffer = getPCM16(Array.from(aFinal).map((v) => ({ value: v })), 8e3);
5842
- (0, import_fs2.writeFileSync)(outTTS, aBuffer);
5843
- try {
5844
- (0, import_fs2.unlinkSync)(tmpTTS);
5845
- } catch (e) {
5986
+ const samples = new Int16Array(data.buffer, data.byteOffset, data.length / 2);
5987
+ return { samples: new Int16Array(samples), sampleRate, channels, bitsPerSample };
5988
+ };
5989
+
5990
+ // src/@modules/@eas/eas.getSampledPCM16.ts
5991
+ var getSampledPCM16 = (int16, originalRate, targetRate) => {
5992
+ if (originalRate === targetRate) return int16;
5993
+ const ratio = targetRate / originalRate;
5994
+ const outLen = Math.max(1, Math.round(int16.length * ratio));
5995
+ const out = new Int16Array(outLen);
5996
+ for (let i = 0; i < outLen; i++) {
5997
+ const pos = i / ratio;
5998
+ const i0 = Math.floor(pos);
5999
+ const i1 = Math.min(i0 + 1, int16.length - 1);
6000
+ const frac = pos - i0;
6001
+ const v = int16[i0] * (1 - frac) + int16[i1] * frac;
6002
+ out[i] = Math.round(v);
5846
6003
  }
5847
- return outTTS;
5848
- });
6004
+ return out;
6005
+ };
5849
6006
 
5850
- // src/@parsers/@text/text.getEmbed.ts
5851
- var getEmebed = (event) => {
5852
- 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;
5853
- const line = (label, value, condition = true) => condition && value ? `${label} ${value}` : null;
5854
- const isStatement = event.properties.status_metadata.is_statement;
5855
- const isExpired = event.properties.status_metadata.is_expired;
5856
- return [
5857
- line(`**Locations:**`, (_b = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.locations) == null ? void 0 : _b.slice(0, 100)),
5858
- line(`**Issued:**`, `<t:${Math.floor(new Date(event.properties.issued).getTime() / 1e3)}:R>`, !isExpired),
5859
- line(`**Expires:**`, `<t:${Math.floor(new Date(event.properties.expires).getTime() / 1e3)}:R>`, !isStatement),
5860
- line(`**Damage Threat:**`, (_d = (_c = event == null ? void 0 : event.properties) == null ? void 0 : _c.parameters) == null ? void 0 : _d.damage_threat, !isExpired),
5861
- line(`**Flood Threat:**`, (_f = (_e = event == null ? void 0 : event.properties) == null ? void 0 : _e.parameters) == null ? void 0 : _f.flood_threat, !isExpired),
5862
- line(`**Tornado Threat:**`, (_h = (_g = event == null ? void 0 : event.properties) == null ? void 0 : _g.parameters) == null ? void 0 : _h.tornado_threat, !isExpired),
5863
- 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),
5864
- 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),
5865
- line(`**Discussion:**`, (_z = (_y = event == null ? void 0 : event.properties) == null ? void 0 : _y.discussion_parameters) == null ? void 0 : _z.discussion_number, !isExpired),
5866
- line(`**Concern:**`, (_B = (_A = event == null ? void 0 : event.properties) == null ? void 0 : _A.discussion_parameters) == null ? void 0 : _B.discussion_concerning, !isExpired),
5867
- 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),
5868
- 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),
5869
- 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),
5870
- 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),
5871
- line(`**Watch Number:**`, (_N = (_M = event == null ? void 0 : event.properties) == null ? void 0 : _M.watch_parameters) == null ? void 0 : _N.watch_number, !isExpired),
5872
- 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),
5873
- 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),
5874
- 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),
5875
- 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),
5876
- 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),
5877
- 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),
5878
- 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),
5879
- 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),
5880
- 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),
5881
- 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),
5882
- 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),
5883
- line(`**Tracking:**`, (_Ia = (_Ha = event == null ? void 0 : event.properties) == null ? void 0 : _Ha.metadata) == null ? void 0 : _Ia.tracking),
5884
- 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)
5885
- ].filter(Boolean).join("\n");
6007
+ // src/@modules/@eas/eas.getPCMToFloat.ts
6008
+ var getPCMToFloat = (int16) => {
6009
+ const out = new Float32Array(int16.length);
6010
+ for (let i = 0; i < int16.length; i++) out[i] = int16[i] / 32768;
6011
+ return out;
5886
6012
  };
5887
6013
 
5888
- // src/@modules/@utilities/utilities.createHttp.ts
5889
- var createHttp = (options) => __async(null, null, function* () {
5890
- var _a, _b, _c, _d;
5891
- const requestOptions = {
5892
- method: (_a = options.method) != null ? _a : "GET",
5893
- headers: (_b = options.headers) != null ? _b : {
5894
- "User-Agent": "AtmosphericX",
5895
- "Accept": "application/geo+json, text/plain, */*; q=0.9",
5896
- "Accept-Language": "en-US,en;q=0.9"
5897
- },
5898
- signal: AbortSignal.timeout((_c = options.timeout) != null ? _c : 1e4),
5899
- redirect: "follow"
5900
- };
5901
- const returnHttp = function(error, status, message) {
5902
- return { error, options: requestOptions, status, message };
5903
- };
5904
- if (options == null ? void 0 : options.formData) {
5905
- requestOptions.body = options.formData;
5906
- } else if ((options == null ? void 0 : options.body) != void 0) {
5907
- requestOptions.body = options.body instanceof FormData ? options.body : typeof options.body === "string" ? options.body : JSON.stringify(options.body);
5908
- }
5909
- try {
5910
- const response2 = yield fetch(
5911
- (_d = options == null ? void 0 : options.url) != null ? _d : `https://api.weather.gov/alerts/active`,
5912
- requestOptions
5913
- );
5914
- const body = yield response2.text();
5915
- if (!response2.ok) {
5916
- return returnHttp(true, response2.status, `HTTP Status Code ${response2.status} (${response2.statusText})`);
5917
- }
5918
- return returnHttp(false, response2.status, body);
5919
- } catch (error) {
5920
- return returnHttp(true, 500, `Internal Server Error: ${error}`);
6014
+ // src/@modules/@eas/eas.getFloatPCM16.ts
6015
+ var getFloatPCM16 = (float32) => {
6016
+ const out = new Int16Array(float32.length);
6017
+ for (let i = 0; i < float32.length; i++) {
6018
+ let v = Math.max(-1, Math.min(1, float32[i]));
6019
+ out[i] = Math.round(v * 32767);
5921
6020
  }
5922
- });
6021
+ return out;
6022
+ };
5923
6023
 
5924
- // src/@manager/manager.updateListener.ts
5925
- var import_fs3 = require("fs");
5926
- var updateListener = (event) => __async(null, null, function* () {
5927
- var _a, _b, _c, _d;
5928
- const settings = bootstrap.settings;
5929
- const listeners2 = settings.ListenerSettings;
5930
- const properties2 = event.properties;
5931
- const metadata = {
5932
- file: null,
5933
- eas: null,
5934
- name: properties2.event,
5935
- status: properties2.status,
5936
- description: properties2.description,
5937
- tracking: properties2.metadata.tracking,
5938
- header: properties2.metadata.header,
5939
- raw: properties2.metadata.raw,
5940
- expired: properties2.status_metadata.is_expired,
5941
- attachments: properties2.metadata.attachments
5942
- };
5943
- for (const listener2 of listeners2) {
5944
- const events = listener2 == null ? void 0 : listener2.events;
5945
- const webhook = listener2 == null ? void 0 : listener2.webhook;
5946
- const uploads = listener2 == null ? void 0 : listener2.uploads;
5947
- const isMatched = events.some((pattern) => {
5948
- if (!pattern) return false;
5949
- if (pattern === "*" || pattern === metadata.name) return true;
5950
- if (pattern.includes("*")) {
5951
- const regex = "^" + pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$";
5952
- return new RegExp(regex).test(metadata.name);
5953
- }
5954
- return false;
5955
- });
5956
- if ((events == null ? void 0 : events.length) == 0 || isMatched) {
5957
- if (uploads == null ? void 0 : uploads.eas) {
5958
- metadata.eas = yield setEasTone({
5959
- title: `${metadata.name}_${metadata.status}_${metadata.tracking}`,
5960
- message: metadata.description,
5961
- header: metadata.header
5962
- });
5963
- }
5964
- if (uploads == null ? void 0 : uploads.file) {
5965
- const fDestination = settings.GlobalSettings.ArchiveSettings.TextDirectory;
5966
- if (fDestination) {
5967
- if (!(0, import_fs3.existsSync)(fDestination)) {
5968
- (0, import_fs3.mkdirSync)(fDestination, { recursive: true });
5969
- }
5970
- if ((0, import_fs3.existsSync)(`${fDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.txt`)) {
5971
- (0, import_fs3.appendFileSync)(`${fDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.txt`, metadata.raw);
5972
- } else {
5973
- (0, import_fs3.writeFileSync)(`${fDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.txt`, metadata.raw);
5974
- }
5975
- }
5976
- metadata.file = metadata.raw;
5977
- }
5978
- if (uploads == null ? void 0 : uploads.event) {
5979
- const eDestination = settings.GlobalSettings.ArchiveSettings.EventDirectory;
5980
- if (eDestination) {
5981
- if (!(0, import_fs3.existsSync)(eDestination)) {
5982
- (0, import_fs3.mkdirSync)(eDestination, { recursive: true });
5983
- }
5984
- (0, import_fs3.writeFileSync)(`${eDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.json`, JSON.stringify(getCleanedEvent(event), null, 2));
5985
- }
5986
- }
5987
- if (webhook.enabled && webhook.destination) {
5988
- const ratelimit = setTimeoutAction({ identifier: webhook.destination, interval: webhook.ratelimit * 2, max: webhook.ratelimit, addTime: true });
5989
- const form = new FormData();
5990
- const embed = {
5991
- title: `${metadata.name} (${metadata.status})`,
5992
- description: getEmebed(event),
5993
- fields: [],
5994
- color: 16711680,
5995
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5996
- footer: { text: (_a = webhook.title) != null ? _a : `AtmosphericX` }
5997
- };
5998
- if (ratelimit.limited) {
5999
- return;
6000
- }
6001
- if (metadata.description && !metadata.expired) {
6002
- if (metadata.description.length > 900) {
6003
- metadata.description = metadata.description.substring(0, 900) + "\n\n[Message truncated due to length]";
6004
- }
6005
- embed.fields.push({
6006
- name: "Description",
6007
- value: metadata.description ? "```\n" + metadata.description.split("\n").map((l) => l.trim()).filter(Boolean).join("\n") + "\n```" : ""
6008
- });
6009
- }
6010
- if (((_b = metadata.attachments) == null ? void 0 : _b.length) > 0) {
6011
- metadata.attachments = metadata.attachments.slice(0, 5);
6012
- embed.fields.push({
6013
- name: "Attachments",
6014
- value: metadata.attachments.map((attachment) => `- [${attachment.name.length > 45 ? attachment.name.substring(0, 45) + "..." : attachment.name}](${attachment.link})`).join("\n")
6015
- });
6016
- }
6017
- if (uploads == null ? void 0 : uploads.file) {
6018
- form.append("fUpload", new Blob([Buffer.from(metadata.file)], { type: "application/text" }), `${properties2.event}_${properties2.status}_${properties2.metadata.tracking}.txt`);
6019
- }
6020
- if (uploads == null ? void 0 : uploads.eas) {
6021
- if (metadata.eas) {
6022
- const file = (0, import_fs3.readFileSync)(metadata.eas);
6023
- form.append("fEas", new Blob([Buffer.from(file)], { type: "audio/mpeg" }), `${properties2.event}_${properties2.status}_${properties2.metadata.tracking}_eas.mp3`);
6024
- }
6025
- }
6026
- form.append("payload_json", JSON.stringify({
6027
- username: (_c = webhook.title) != null ? _c : "AtmosphericX",
6028
- content: (_d = webhook.message) != null ? _d : "",
6029
- embeds: [embed]
6030
- }));
6031
- const a = yield createHttp({
6032
- url: webhook.destination,
6033
- timeout: 5e3,
6034
- method: `POST`,
6035
- body: form
6036
- });
6037
- if (a.error) {
6038
- setWarning({ message: `Failed to send webhook: ${a.error.message}` });
6039
- }
6040
- }
6041
- }
6024
+ // src/@modules/@eas/eas.setRadioEffect.ts
6025
+ var setRadioEffect = (int16, sampleRate) => {
6026
+ const hpCut = 3555;
6027
+ const lpCut = 1600;
6028
+ const x = getPCMToFloat(int16);
6029
+ const dt = 1 / sampleRate;
6030
+ const rcHP = 1 / (2 * Math.PI * hpCut);
6031
+ const aHP = rcHP / (rcHP + dt);
6032
+ let yHP = 0, xPrev = 0;
6033
+ for (let i = 0; i < x.length; i++) {
6034
+ const xi = x[i];
6035
+ yHP = aHP * (yHP + xi - xPrev);
6036
+ xPrev = xi;
6037
+ x[i] = yHP;
6042
6038
  }
6043
- });
6044
-
6045
- // src/@modules/@utilities/utilities.getShapeNearestPoint.ts
6046
- var getShapeNearestPoint = (coordinates, point) => {
6047
- if (!coordinates || !point) {
6048
- return { proximity: false, point: [0, 0], distance: null };
6039
+ const rcLP = 1 / (2 * Math.PI * lpCut);
6040
+ const aLP = dt / (rcLP + dt);
6041
+ let yLP = 0;
6042
+ for (let i = 0; i < x.length; i++) {
6043
+ yLP = yLP + aLP * (x[i] - yLP);
6044
+ x[i] = yLP;
6049
6045
  }
6050
- const normalize = (coords) => {
6051
- if (!Array.isArray(coords)) return [];
6052
- if (typeof coords[0] === "number" && typeof coords[1] === "number") return [];
6053
- if (Array.isArray(coords[0]) && typeof coords[0][0] === "number") {
6054
- return [[coords]];
6055
- }
6056
- if (Array.isArray(coords[0]) && Array.isArray(coords[0][0]) && typeof coords[0][0][0] === "number") {
6057
- return [coords];
6058
- }
6059
- if (Array.isArray(coords[0]) && Array.isArray(coords[0][0]) && Array.isArray(coords[0][0][0]) && typeof coords[0][0][0][0] === "number") {
6060
- return coords;
6061
- }
6062
- return [];
6063
- };
6064
- const polys = normalize(coordinates);
6065
- if (polys.length === 0) return { proximity: false, point: [0, 0], distance: null };
6066
- const lon = point[0];
6067
- const lat = point[1];
6068
- const pointInRing = (pt, ring) => {
6069
- let x = pt[0], y = pt[1];
6070
- let inside = false;
6071
- for (let i = 0, j2 = ring.length - 1; i < ring.length; j2 = i++) {
6072
- const xi = ring[i][0], yi = ring[i][1];
6073
- const xj = ring[j2][0], yj = ring[j2][1];
6074
- const intersect = yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi + 0) + xi;
6075
- if (intersect) inside = !inside;
6076
- }
6077
- return inside;
6078
- };
6079
- const toRadians = (deg) => deg * Math.PI / 180;
6080
- const haversineMiles = (a, b) => {
6081
- const R = 3958.8;
6082
- const dLat = toRadians(b[1] - a[1]);
6083
- const dLon = toRadians(b[0] - a[0]);
6084
- const lat1 = toRadians(a[1]);
6085
- const lat2 = toRadians(b[1]);
6086
- const sinDLat = Math.sin(dLat / 2);
6087
- const sinDLon = Math.sin(dLon / 2);
6088
- const c = 2 * Math.asin(Math.sqrt(sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon));
6089
- return R * c;
6090
- };
6091
- let minDistance = Infinity;
6092
- let closestPoint = null;
6093
- for (const poly of polys) {
6094
- const outer = poly[0];
6095
- const holes = poly.slice(1);
6096
- if (pointInRing(point, outer)) {
6097
- let inHole = false;
6098
- for (const hole of holes) {
6099
- if (pointInRing(point, hole)) {
6100
- inHole = true;
6101
- break;
6102
- }
6103
- }
6104
- if (!inHole) {
6105
- return { proximity: true, point, distance: 0 };
6106
- }
6107
- }
6108
- for (const ring of poly) {
6109
- for (let i = 0; i < ring.length - 1; i++) {
6110
- const start = [ring[i][0], ring[i][1]];
6111
- const end = [ring[i + 1][0], ring[i + 1][1]];
6112
- const A = lon - start[0];
6113
- const B = lat - start[1];
6114
- const C = end[0] - start[0];
6115
- const D = end[1] - start[1];
6116
- const lenSq = C * C + D * D;
6117
- const t = lenSq === 0 ? 0 : Math.max(0, Math.min(1, (A * C + B * D) / lenSq));
6118
- const candidate = [start[0] + t * C, start[1] + t * D];
6119
- const dist = haversineMiles([lon, lat], candidate);
6120
- if (!isNaN(dist) && dist < minDistance) {
6121
- minDistance = Number(dist.toFixed(3));
6122
- closestPoint = candidate;
6123
- }
6124
- }
6046
+ const compGain = 2;
6047
+ const norm = Math.tanh(compGain);
6048
+ for (let i = 0; i < x.length; i++) x[i] = Math.tanh(x[i] * compGain) / norm;
6049
+ return getFloatPCM16(x);
6050
+ };
6051
+
6052
+ // src/@modules/@eas/eas.setAFSK.ts
6053
+ var setAFSK = (bits, sampleRate) => {
6054
+ const baud = 520.83;
6055
+ const markFreq = 2083.3;
6056
+ const spaceFreq = 1562.5;
6057
+ const amplitude = 0.6;
6058
+ const twoPi = Math.PI * 2;
6059
+ const result = [];
6060
+ let phase = 0;
6061
+ let frac = 0;
6062
+ for (let b = 0; b < bits.length; b++) {
6063
+ const bit = bits[b];
6064
+ const freq = bit ? markFreq : spaceFreq;
6065
+ const samplesPerBit = sampleRate / baud + frac;
6066
+ const n = Math.round(samplesPerBit);
6067
+ frac = samplesPerBit - n;
6068
+ const inc = twoPi * freq / sampleRate;
6069
+ for (let i = 0; i < n; i++) {
6070
+ result.push(Math.round(Math.sin(phase) * amplitude * 32767));
6071
+ phase += inc;
6072
+ if (phase > twoPi) phase -= twoPi;
6125
6073
  }
6126
6074
  }
6127
- if (!isFinite(minDistance) || closestPoint == null) {
6128
- return { proximity: false, point: [0, 0], distance: null };
6075
+ const fadeSamples = Math.floor(sampleRate * 2e-3);
6076
+ for (let i = 0; i < fadeSamples; i++) {
6077
+ const gain = i / fadeSamples;
6078
+ result[i] = Math.round(result[i] * gain);
6079
+ result[result.length - 1 - i] = Math.round(result[result.length - 1 - i] * gain);
6129
6080
  }
6130
- const distanceMiles = minDistance;
6131
- const distanceKm = Number((distanceMiles * 1.609344).toFixed(3));
6132
- const distanceMeters = Math.round(distanceKm * 1e3);
6133
- return { proximity: distanceMiles === 0, point: closestPoint, distance: distanceMiles, distanceKm, distanceMeters };
6081
+ return Int16Array.from(result);
6134
6082
  };
6135
6083
 
6136
- // src/@building/building.polygon.ts
6137
- var getEventNodes = (event) => __async(null, null, function* () {
6084
+ // src/@modules/@eas/eas.setAsciiToBits.ts
6085
+ var setAsciiToBits = (str) => {
6086
+ const bits = [];
6087
+ for (let i = 0; i < str.length; i++) {
6088
+ const c = str.charCodeAt(i) & 255;
6089
+ bits.push(0);
6090
+ for (let b = 0; b < 8; b++) bits.push(c >> b & 1);
6091
+ bits.push(1, 1);
6092
+ }
6093
+ return bits;
6094
+ };
6095
+
6096
+ // src/@modules/@eas/eas.getMergedPCM16.ts
6097
+ var getMergedPCM16 = (arrays) => {
6098
+ let total = 0;
6099
+ for (const a of arrays) total += a.length;
6100
+ const out = new Int16Array(total);
6101
+ let o = 0;
6102
+ for (const a of arrays) {
6103
+ out.set(a, o);
6104
+ o += a.length;
6105
+ }
6106
+ return out;
6107
+ };
6108
+
6109
+ // src/@modules/@eas/eas.setSameHeader.ts
6110
+ var setSameHeader = (vtec2, repeats, sampleRate = 8e3, options = {}) => {
6138
6111
  var _a, _b;
6139
- const metadata = { nodes: [], proximity: false, filtered: false };
6140
- const geometry = yield getEventGeometry(event);
6141
- if (!geometry || !geometry.coordinates) {
6142
- return { nodes: [], filtered: false, updated: Date.now() };
6112
+ const preMarkSec = (_a = options.preMarkSec) != null ? _a : 0.3;
6113
+ const gapSec = (_b = options.gapSec) != null ? _b : 0.1;
6114
+ const bursts = [];
6115
+ const gap = new Int16Array(Math.floor(gapSec * sampleRate));
6116
+ for (let i = 0; i < repeats; i++) {
6117
+ const bodyBits = setAsciiToBits(vtec2);
6118
+ const body = setAFSK(bodyBits, sampleRate);
6119
+ const extendedBodyDuration = Math.round(preMarkSec * sampleRate);
6120
+ const extendedBody = new Int16Array(extendedBodyDuration + gap.length);
6121
+ for (let j2 = 0; j2 < extendedBodyDuration; j2++) {
6122
+ extendedBody[j2] = Math.round(body[j2 % body.length] * 0.2);
6123
+ }
6124
+ extendedBody.set(gap, extendedBodyDuration);
6125
+ bursts.push(extendedBody);
6126
+ if (i !== repeats - 1) bursts.push(gap);
6143
6127
  }
6144
- const nodes = bootstrap.cache.nodes.features;
6145
- for (const node of nodes) {
6146
- const [longitude, latitude] = node.geometry.coordinates;
6147
- const getPoint = getShapeNearestPoint(geometry.coordinates, [longitude, latitude]);
6148
- const miles = (_a = getPoint.distance) != null ? _a : null;
6149
- const kilometers = Number((miles * 1.609344).toFixed(3));
6150
- const info = {
6151
- id: (_b = node.properties) == null ? void 0 : _b.identifier,
6152
- coordinates: [longitude, latitude],
6153
- nearest: getPoint.point,
6154
- miles,
6155
- kilometers,
6156
- proximity: getPoint.proximity
6157
- };
6158
- metadata.nodes.push(info);
6159
- if (bootstrap.settings.GlobalSettings.EventFiltering.NodeLocationFiltering && miles < bootstrap.settings.GlobalSettings.NodeMinDistance) {
6160
- metadata.proximity = true;
6161
- info.proximity = true;
6128
+ return getMergedPCM16(bursts);
6129
+ };
6130
+
6131
+ // src/@modules/@eas/eas.setAttentionTone.ts
6132
+ var setAttentionTone = (ms, sampleRate) => {
6133
+ const len = Math.floor(ms * sampleRate);
6134
+ const out = new Int16Array(len);
6135
+ const f1 = 853;
6136
+ const f2 = 960;
6137
+ const twoPi = Math.PI * 2;
6138
+ const amp = 0.1;
6139
+ const fadeLen = Math.floor(sampleRate * 0);
6140
+ for (let i = 0; i < len; i++) {
6141
+ const t = i / sampleRate;
6142
+ const s = Math.sin(twoPi * f1 * t) + Math.sin(twoPi * f2 * t);
6143
+ let gain = 1;
6144
+ if (i < fadeLen) gain = i / fadeLen;
6145
+ else if (i > len - fadeLen) gain = (len - i) / fadeLen;
6146
+ const v = Math.max(-1, Math.min(1, s / 2 * amp * gain));
6147
+ out[i] = Math.round(v * 32767);
6148
+ }
6149
+ return out;
6150
+ };
6151
+
6152
+ // src/@modules/@eas/eas.setNoise.ts
6153
+ var setNoise = (int16, noiseLevel = 0.02) => {
6154
+ const x = getPCMToFloat(int16);
6155
+ for (let i = 0; i < x.length; i++) x[i] += (Math.random() * 2 - 1) * noiseLevel;
6156
+ let peak = 0;
6157
+ for (let i = 0; i < x.length; i++) peak = Math.max(peak, Math.abs(x[i]));
6158
+ if (peak > 1) for (let i = 0; i < x.length; i++) x[i] *= 0.98 / peak;
6159
+ return getFloatPCM16(x);
6160
+ };
6161
+
6162
+ // src/@modules/@eas/eas.getPCM16.ts
6163
+ var getPCM16 = (samples, sampleRate) => {
6164
+ let o = 0;
6165
+ const bytesPerSample = 2;
6166
+ const blockAlign = 1 * bytesPerSample;
6167
+ const byteRate = sampleRate * blockAlign;
6168
+ const subchunk2Size = samples.length * bytesPerSample;
6169
+ const chunkSize = 36 + subchunk2Size;
6170
+ const buffer = Buffer.alloc(44 + subchunk2Size);
6171
+ buffer.write("RIFF", o);
6172
+ o += 4;
6173
+ buffer.writeUInt32LE(chunkSize, o);
6174
+ o += 4;
6175
+ buffer.write("WAVE", o);
6176
+ o += 4;
6177
+ buffer.write("fmt ", o);
6178
+ o += 4;
6179
+ buffer.writeUInt32LE(16, o);
6180
+ o += 4;
6181
+ buffer.writeUInt16LE(1, o);
6182
+ o += 2;
6183
+ buffer.writeUInt16LE(1, o);
6184
+ o += 2;
6185
+ buffer.writeUInt32LE(sampleRate, o);
6186
+ o += 4;
6187
+ buffer.writeUInt32LE(byteRate, o);
6188
+ o += 4;
6189
+ buffer.writeUInt16LE(blockAlign, o);
6190
+ o += 2;
6191
+ buffer.writeUInt16LE(16, o);
6192
+ o += 2;
6193
+ buffer.write("data", o);
6194
+ o += 4;
6195
+ buffer.writeUInt32LE(subchunk2Size, o);
6196
+ o += 4;
6197
+ for (let i = 0; i < samples.length; i++, o += 2) {
6198
+ buffer.writeInt16LE(samples[i].value, o);
6199
+ }
6200
+ return buffer;
6201
+ };
6202
+
6203
+ // src/@modules/@eas/eas.getTTS.ts
6204
+ var import_os = require("os");
6205
+ var import_fs = require("fs");
6206
+ var import_child_process = require("child_process");
6207
+ var getTTS = (text2, outputPath) => __async(null, null, function* () {
6208
+ const vPlatform = (0, import_os.platform)();
6209
+ switch (vPlatform) {
6210
+ case "win32": {
6211
+ try {
6212
+ const txtPath = outputPath + ".txt";
6213
+ (0, import_fs.writeFileSync)(txtPath, text2, "utf8");
6214
+ const command = [
6215
+ "Add-Type -AssemblyName System.Speech;",
6216
+ `$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;`,
6217
+ `$text = Get-Content -Raw -LiteralPath '${txtPath}';`,
6218
+ `$speak.SetOutputToWaveFile('${outputPath}');`,
6219
+ `$speak.Speak($text);`,
6220
+ `$speak.Dispose();`
6221
+ ].join(" ");
6222
+ (0, import_child_process.execSync)(`powershell -Command "${command}"`, { stdio: "inherit" });
6223
+ } catch (error) {
6224
+ console.error("Error occurred while generating TTS:", error);
6225
+ }
6226
+ break;
6162
6227
  }
6228
+ case "linux":
6229
+ try {
6230
+ (0, import_child_process.execSync)(`espeak -w "${outputPath}" "${text2.replace(/"/g, '\\"')}"`);
6231
+ } catch (e) {
6232
+ }
6233
+ break;
6234
+ default:
6235
+ break;
6163
6236
  }
6164
- return {
6165
- nodes: metadata.nodes,
6166
- filtered: metadata.proximity,
6167
- updated: Date.now()
6237
+ });
6238
+
6239
+ // src/@modules/@eas/eas.getCleanDescription.ts
6240
+ var getCleanDescription = (message) => {
6241
+ const patches = [
6242
+ { regex: /\.{3,}/g, replacement: ". " },
6243
+ { regex: /\bUTC\b/g, replacement: "Coordinated Universal Time" },
6244
+ { regex: /\bGMT\b/g, replacement: "Greenwich Mean Time" },
6245
+ { regex: /\bEST\b(?!\w)/g, replacement: "Eastern Standard Time" },
6246
+ { regex: /\bEDT\b(?!\w)/g, replacement: "Eastern Daylight Time" },
6247
+ { regex: /\bCST\b(?!\w)/g, replacement: "Central Standard Time" },
6248
+ { regex: /\bCDT\b(?!\w)/g, replacement: "Central Daylight Time" },
6249
+ { regex: /\bMST\b(?!\w)/g, replacement: "Mountain Standard Time" },
6250
+ { regex: /\bMDT\b(?!\w)/g, replacement: "Mountain Daylight Time" },
6251
+ { regex: /\bPST\b(?!\w)/g, replacement: "Pacific Standard Time" },
6252
+ { regex: /\bPDT\b(?!\w)/g, replacement: "Pacific Daylight Time" },
6253
+ { regex: /\bAKST\b(?!\w)/g, replacement: "Alaska Standard Time" },
6254
+ { regex: /\bAKDT\b(?!\w)/g, replacement: "Alaska Daylight Time" },
6255
+ { regex: /\bHST\b(?!\w)/g, replacement: "Hawaii Standard Time" },
6256
+ { regex: /\bHDT\b(?!\w)/g, replacement: "Hawaii Daylight Time" },
6257
+ { regex: /\bmph\b(?!\w)/g, replacement: "miles per hour" },
6258
+ { regex: /\bkm\/h\b(?!\w)/g, replacement: "kilometers per hour" },
6259
+ { regex: /\bkmh\b(?!\w)/g, replacement: "kilometers per hour" },
6260
+ { regex: /\bkt\b(?!\w)/g, replacement: "knots" },
6261
+ { regex: /\bNE\b(?!\w)/g, replacement: "northeast" },
6262
+ { regex: /\bNW\b(?!\w)/g, replacement: "northwest" },
6263
+ { regex: /\bSE\b(?!\w)/g, replacement: "southeast" },
6264
+ { regex: /\bSW\b(?!\w)/g, replacement: "southwest" },
6265
+ { regex: /\bNM\b(?!\w)/g, replacement: "nautical miles" },
6266
+ { regex: /\bdeg\b(?!\w)/g, replacement: "degrees" },
6267
+ { regex: /\btstm\b(?!\w)/g, replacement: "thunderstorm" },
6268
+ { regex: /\bmm\b(?!\w)/g, replacement: "millimeters" },
6269
+ { regex: /\bcm\b(?!\w)/g, replacement: "centimeters" },
6270
+ { regex: /\bin.\b(?!\w)/g, replacement: "inches" },
6271
+ { regex: /\bft\b(?!\w)/g, replacement: "feet" },
6272
+ { regex: /\bmi\b(?!\w)/g, replacement: "miles" },
6273
+ { regex: /\bhr\b(?!\w)/g, replacement: "hour" },
6274
+ { regex: /\bhourly\b(?!\w)/g, replacement: "per hour" },
6275
+ { regex: /\bkg\b(?!\w)/g, replacement: "kilograms" },
6276
+ { regex: /\bg\/kg\b(?!\w)/g, replacement: "grams per kilogram" },
6277
+ { regex: /\bmb\b(?!\w)/g, replacement: "millibars" },
6278
+ { regex: /\bhPa\b(?!\w)/g, replacement: "hectopascals" },
6279
+ { regex: /\bPa\b(?!\w)/g, replacement: "pascals" },
6280
+ { regex: /\bKPa\b(?!\w)/g, replacement: "kilopascals" },
6281
+ { regex: /\bC\/hr\b(?!\w)/g, replacement: "degrees Celsius per hour" },
6282
+ { regex: /\bF\/hr\b(?!\w)/g, replacement: "degrees Fahrenheit per hour" },
6283
+ { regex: /\bC\/min\b(?!\w)/g, replacement: "degrees Celsius per minute" },
6284
+ { regex: /\bF\/min\b(?!\w)/g, replacement: "degrees Fahrenheit per minute" },
6285
+ { regex: /\bC\b(?!\w)/g, replacement: "degrees Celsius" },
6286
+ { regex: /\bF\b(?!\w)/g, replacement: "degrees Fahrenheit" }
6287
+ ];
6288
+ const hours = {
6289
+ 0: "twelve",
6290
+ 1: "one",
6291
+ 2: "two",
6292
+ 3: "three",
6293
+ 4: "four",
6294
+ 5: "five",
6295
+ 6: "six",
6296
+ 7: "seven",
6297
+ 8: "eight",
6298
+ 9: "nine",
6299
+ 10: "ten",
6300
+ 11: "eleven",
6301
+ 12: "twelve"
6168
6302
  };
6169
- });
6303
+ const minWord = (m) => m === 0 ? "o'clock" : m < 10 ? `oh ${m}` : `${m}`;
6304
+ const fmt = (h, m, ap) => `${hours[h % 12]} ${minWord(m)} ${ap}`;
6305
+ for (const { regex, replacement } of patches) {
6306
+ message = message.replace(regex, replacement);
6307
+ }
6308
+ 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();
6309
+ };
6170
6310
 
6171
- // src/@manager/manager.updateNodes.ts
6172
- var updateNode = (selectedEvent) => __async(null, null, function* () {
6173
- const events = bootstrap.cache.events.features;
6174
- const ttl = bootstrap.settings.GlobalSettings.NodeTTL * 1e3;
6175
- let total = 0;
6176
- function update(evt) {
6177
- return __async(this, null, function* () {
6178
- var _a, _b, _c;
6179
- const lastUpdate = (_c = (_b = (_a = evt == null ? void 0 : evt.properties) == null ? void 0 : _a.metadata) == null ? void 0 : _b.updated) != null ? _c : null;
6180
- if (lastUpdate != null && Date.now() - lastUpdate < ttl) {
6181
- return evt;
6182
- }
6183
- const node = yield getEventNodes(evt);
6184
- if (node.nodes.length > 0) {
6185
- total++;
6186
- }
6187
- evt.properties.metadata.nodes = node.nodes;
6188
- evt.properties.metadata.filtered_proximity = node.filtered;
6189
- evt.properties.metadata.updated = node.updated;
6311
+ // src/@modules/@eas/eas.setEasTone.ts
6312
+ var import_path2 = require("path");
6313
+ var import_fs2 = require("fs");
6314
+ var import_child_process2 = require("child_process");
6315
+ var import_os2 = require("os");
6316
+ var setEasTone = (options) => __async(null, null, function* () {
6317
+ var _a;
6318
+ const tick = performance.now();
6319
+ const settings = bootstrap.settings;
6320
+ const directory = settings.GlobalSettings.ArchiveSettings.EasDirectory;
6321
+ const prefix = settings.GlobalSettings.ArchiveSettings.EasToneout;
6322
+ let message = options.message;
6323
+ let header = options.header;
6324
+ 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();
6325
+ if (!message || !header) {
6326
+ setWarning({
6327
+ title: `EAS`,
6328
+ message: `Message and header are required to generate an EAS tone.`
6190
6329
  });
6330
+ return null;
6191
6331
  }
6192
- if (!selectedEvent) {
6193
- yield Promise.all(events.map((evt) => __async(null, null, function* () {
6194
- yield update(evt);
6195
- })));
6196
- }
6197
- if (selectedEvent) {
6198
- yield update(selectedEvent);
6199
- }
6200
- if (total > 0) {
6201
- setEventEmit({
6202
- event: `onNodeUpdate`,
6203
- metadata: {
6204
- type: `global-update`,
6205
- updated: total
6206
- }
6207
- });
6332
+ let buffTTS;
6333
+ let buffRadio;
6334
+ let buffFull = [];
6335
+ if (!(0, import_fs2.existsSync)(directory)) {
6336
+ (0, import_fs2.mkdirSync)(directory, { recursive: true });
6208
6337
  }
6209
- });
6210
-
6211
- // src/@manager/manager.mkEvent.ts
6212
- var mkEvent = (event) => __async(null, null, function* () {
6213
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w;
6214
- const settings = bootstrap.settings;
6215
- const features = bootstrap.cache.events.features;
6216
- const getHash = event.properties.metadata.hash;
6217
- const getTracking = event.properties.metadata.tracking;
6218
- const isEntry = (_a = bootstrap.cache.hashes) == null ? void 0 : _a.find((hash) => hash.tracking === getTracking);
6219
- const isHashed = (_c = (_b = isEntry == null ? void 0 : isEntry.hashes) == null ? void 0 : _b.includes(getHash)) != null ? _c : false;
6220
- const getFeature = features.find((feature) => feature.properties.metadata.tracking === getTracking);
6221
- if (isHashed || event.properties.status_metadata.is_expired) return;
6222
- setHash(event, isEntry);
6223
- const isFilteredLocation = yield updateNode(event).then(() => event.properties.metadata.filtered_proximity);
6224
- if (!isFilteredLocation && settings.GlobalSettings.EventFiltering.NodeLocationFiltering) {
6225
- return;
6338
+ if (!(0, import_fs2.existsSync)((0, import_path2.join)(directory, `/tts`))) {
6339
+ (0, import_fs2.mkdirSync)((0, import_path2.join)(directory, `/tts`), { recursive: true });
6226
6340
  }
6227
- setEventEmit({
6228
- event: `onEventStatus`,
6229
- metadata: {
6230
- type: getFeature ? `Updated` : `New`,
6231
- event
6232
- },
6233
- message: `[${getFeature ? "Updated" : "New"}] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
6234
- });
6235
- if (settings.GlobalSettings.EventManagement) {
6236
- if (event.properties.status_metadata.is_issued || event.properties.status_metadata.is_updated) {
6237
- if (getFeature) {
6238
- const getIndex = features.indexOf(getFeature);
6239
- const cHistory = (_f = (_e = (_d = getFeature == null ? void 0 : getFeature.properties) == null ? void 0 : _d.metadata) == null ? void 0 : _e.history) != null ? _f : [];
6240
- 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 : [];
6241
- const cUgc = (_l = (_k = (_j = getFeature == null ? void 0 : getFeature.properties) == null ? void 0 : _j.geocode) == null ? void 0 : _k.ugc) != null ? _l : [];
6242
- const iHistory = (_o = (_n = (_m = event.properties) == null ? void 0 : _m.metadata) == null ? void 0 : _n.history) != null ? _o : [];
6243
- const iLocations = (_r = (_q = (_p = event.properties) == null ? void 0 : _p.locations) == null ? void 0 : _q.split(";").map((l) => l.trim())) != null ? _r : [];
6244
- const iUgc = (_u = (_t = (_s = event.properties) == null ? void 0 : _s.geocode) == null ? void 0 : _t.ugc) != null ? _u : [];
6245
- 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);
6246
- const mLocations = [...cLocations, ...iLocations].filter((v, i, a) => a.indexOf(v) === i).join("; ");
6247
- const mUgc = [...cUgc, ...iUgc].filter((v, i, a) => a.indexOf(v) === i);
6248
- bootstrap.cache.events.features[getIndex] = __spreadProps(__spreadValues({}, event), {
6249
- properties: __spreadProps(__spreadValues({}, event.properties), {
6250
- metadata: __spreadProps(__spreadValues({}, (_v = event == null ? void 0 : event.properties) == null ? void 0 : _v.metadata), {
6251
- history: mHistory
6252
- }),
6253
- locations: mLocations,
6254
- geocode: __spreadProps(__spreadValues({}, (_w = event == null ? void 0 : event.properties) == null ? void 0 : _w.geocode), {
6255
- ugc: mUgc
6256
- })
6257
- })
6258
- });
6259
- updateListener(bootstrap.cache.events.features[getIndex]);
6260
- } else {
6261
- features.push(event);
6262
- updateListener(event);
6263
- }
6264
- }
6341
+ if (!(0, import_fs2.existsSync)((0, import_path2.join)(directory, `/encoded`))) {
6342
+ (0, import_fs2.mkdirSync)((0, import_path2.join)(directory, `/encoded`), { recursive: true });
6265
6343
  }
6266
- });
6267
-
6268
- // src/@manager/manager.rmEvent.ts
6269
- var rmEvent = (event) => {
6270
- const getEvent = bootstrap.cache.events.features.find((f) => {
6271
- var _a, _b, _c, _d;
6272
- 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);
6273
- });
6274
- const cachedStatus = event.properties.status;
6275
- event.properties.expires = (/* @__PURE__ */ new Date()).toISOString();
6276
- event.properties.status = `Expired`;
6277
- event.properties.status_metadata.is_expired = true;
6278
- if (getEvent) {
6279
- setEventEmit({
6280
- event: `onEventStatus`,
6281
- metadata: {
6282
- type: `Removed`,
6283
- event
6284
- },
6285
- message: `[Removed] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
6344
+ const tmpTTS = (0, import_path2.join)(directory, `/tts/${title}.wav`);
6345
+ const outTTS = (0, import_path2.join)(directory, `/encoded/${title}.wav`);
6346
+ const vPlatform = (0, import_os2.platform)();
6347
+ if (vPlatform === "darwin") {
6348
+ setWarning({
6349
+ title: `EAS`,
6350
+ message: `EAS tone generation is not supported on macOS.`
6286
6351
  });
6287
- setEventEmit({ event: `onExpiredProduct`, metadata: event });
6288
- if (cachedStatus != `Statement`) updateListener(event);
6289
- bootstrap.cache.events.features.splice(bootstrap.cache.events.features.indexOf(getEvent), 1);
6290
- bootstrap.cache.hashes = bootstrap.cache.hashes.filter((hash) => hash.tracking !== event.properties.metadata.tracking);
6352
+ return null;
6291
6353
  }
6292
- setEventEmit({
6293
- event: `onEventCache`,
6294
- metadata: bootstrap.cache.events,
6295
- limited: true
6354
+ yield new Promise((resolve6, reject) => {
6355
+ const tMsg = getCleanDescription(message);
6356
+ getTTS(tMsg, tmpTTS).then(() => {
6357
+ resolve6();
6358
+ });
6296
6359
  });
6297
- };
6298
-
6299
- // src/@modules/@utilities/utilities.getLatestIssuance.ts
6300
- var getLatestIssuance = () => {
6301
- const now = /* @__PURE__ */ new Date();
6302
- const current = now.getUTCHours() * 100 + now.getUTCMinutes();
6303
- const issuances = [100, 600, 1300, 1630, 2e3];
6304
- let latest = issuances[0];
6305
- for (const issuance of issuances) {
6306
- if (current >= issuance) {
6307
- latest = issuance;
6308
- }
6309
- }
6310
- return latest.toString().padStart(4, "0");
6311
- };
6312
-
6313
- // src/@dictionaries/dictionaries.states.ts
6314
- var dict_states = {
6315
- "AL": "Alabama",
6316
- "AK": "Alaska",
6317
- "AZ": "Arizona",
6318
- "AR": "Arkansas",
6319
- "CA": "California",
6320
- "CO": "Colorado",
6321
- "CT": "Connecticut",
6322
- "DE": "Delaware",
6323
- "FL": "Florida",
6324
- "GA": "Georgia",
6325
- "HI": "Hawaii",
6326
- "ID": "Idaho",
6327
- "IL": "Illinois",
6328
- "IN": "Indiana",
6329
- "IA": "Iowa",
6330
- "KS": "Kansas",
6331
- "KY": "Kentucky",
6332
- "LA": "Louisiana",
6333
- "ME": "Maine",
6334
- "MD": "Maryland",
6335
- "MA": "Massachusetts",
6336
- "MI": "Michigan",
6337
- "MN": "Minnesota",
6338
- "MS": "Mississippi",
6339
- "MO": "Missouri",
6340
- "MT": "Montana",
6341
- "NE": "Nebraska",
6342
- "NV": "Nevada",
6343
- "NH": "New Hampshire",
6344
- "NJ": "New Jersey",
6345
- "NM": "New Mexico",
6346
- "NY": "New York",
6347
- "NC": "North Carolina",
6348
- "ND": "North Dakota",
6349
- "OH": "Ohio",
6350
- "OK": "Oklahoma",
6351
- "OR": "Oregon",
6352
- "PA": "Pennsylvania",
6353
- "RI": "Rhode Island",
6354
- "SC": "South Carolina",
6355
- "SD": "South Dakota",
6356
- "TN": "Tennessee",
6357
- "TX": "Texas",
6358
- "UT": "Utah",
6359
- "VT": "Vermont",
6360
- "VA": "Virginia",
6361
- "WA": "Washington",
6362
- "WV": "West Virginia",
6363
- "WI": "Wisconsin",
6364
- "WY": "Wyoming",
6365
- "DC": "District of Columbia"
6366
- };
6367
-
6368
- // src/@building/building.attachments.ts
6369
- var getEventAttachments = (event) => {
6370
- var _a, _b, _c, _d, _e, _f, _g;
6371
- let attachments = [];
6372
- const issuanceTime = getLatestIssuance();
6373
- const spcNumber = (_b = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.discussion_parameters) == null ? void 0 : _b.discussion_number;
6374
- const watchNumber = (_d = (_c = event == null ? void 0 : event.properties) == null ? void 0 : _c.watch_parameters) == null ? void 0 : _d.watch_number;
6375
- const locations = (_e = event == null ? void 0 : event.properties) == null ? void 0 : _e.locations_array;
6376
- const events = [
6377
- { target: "Day 1", attachment: `https://www.spc.noaa.gov/products/outlook/day1otlk_${issuanceTime}.png` },
6378
- { target: "Day 2", attachment: `https://www.spc.noaa.gov/products/outlook/day2otlk.png` },
6379
- { target: "Day 3", attachment: `https://www.spc.noaa.gov/products/outlook/day3otlk.png` },
6380
- { target: "Mesoscale Discussion", attachment: `https://www.spc.noaa.gov/products/md/mcd${spcNumber}.png` },
6381
- { target: "Tornado Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
6382
- { target: "PDS Tornado Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
6383
- { target: "Severe Thunderstorm Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
6384
- { target: "PDS Severe Thunderstorm Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` }
6385
- ];
6386
- if (events.find((e) => e.target === event.properties.event)) {
6387
- attachments.push({ name: `Image: Graphic`, link: events.find((e) => e.target === event.properties.event).attachment });
6360
+ if (!(0, import_fs2.existsSync)(tmpTTS)) {
6361
+ return null;
6388
6362
  }
6389
- for (const location of locations) {
6390
- if (dict_expressions.location.test(location)) {
6391
- const lines = [`Northern`, `Southern`, `Eastern`, `Western`, `Inland`, `Costal`, `County`];
6392
- const county = (_f = location == null ? void 0 : location.split(",")[0]) == null ? void 0 : _f.trim().replace(new RegExp(`^(${lines.join("|")}) `), "");
6393
- const state = dict_states[(_g = location == null ? void 0 : location.split(",")[1]) == null ? void 0 : _g.trim()];
6394
- const feeds = bootstrap.database.prepare(`SELECT * FROM broadcastify WHERE state = ? AND county = ?`).all(state, county).sort((a, b) => {
6395
- const typeOrder = ["Other", "Public Safety"];
6396
- const indexA = typeOrder.indexOf(a.type);
6397
- const indexB = typeOrder.indexOf(b.type);
6398
- return indexA - indexB;
6399
- });
6400
- const tags = bootstrap.settings.BroadcastifySettings.BroadcastifyTags;
6401
- const filtered = feeds.filter((feed) => tags.includes(feed.type));
6402
- if (filtered.length > 0) {
6403
- filtered.map((filtered2) => {
6404
- if (!attachments.some((a) => a.link === filtered2.link)) {
6405
- attachments.push({ name: `${filtered2.type}: ${filtered2.feed}`, link: filtered2.link });
6363
+ buffTTS = (0, import_fs2.readFileSync)(tmpTTS);
6364
+ const vWav = getWavPCM16(buffTTS);
6365
+ const vSamples = getSampledPCM16(vWav.samples, vWav.sampleRate, 8e3);
6366
+ const vRadio = setRadioEffect(vSamples, 8e3);
6367
+ if ((0, import_fs2.existsSync)(prefix)) {
6368
+ let tBuffer = (0, import_fs2.readFileSync)(prefix);
6369
+ let tWav = getWavPCM16(tBuffer);
6370
+ if (tWav == null) {
6371
+ try {
6372
+ const converted = (0, import_path2.join)(directory, `/tts/${title}.converted.wav`);
6373
+ (0, import_child_process2.execSync)(`ffmpeg -y -i "${prefix}" -ar 8000 -ac 1 -sample_fmt s16 "${converted}"`, { stdio: "ignore" });
6374
+ if ((0, import_fs2.existsSync)(converted)) {
6375
+ tBuffer = (0, import_fs2.readFileSync)(converted);
6376
+ tWav = getWavPCM16(tBuffer);
6377
+ try {
6378
+ (0, import_fs2.unlinkSync)(converted);
6379
+ } catch (e) {
6406
6380
  }
6407
- });
6381
+ }
6382
+ } catch (e) {
6408
6383
  }
6409
6384
  }
6385
+ if (tWav == null) {
6386
+ 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.` });
6387
+ return null;
6388
+ }
6389
+ const tSamples = tWav.sampleRate != 8e3 ? getSampledPCM16(tWav.samples, tWav.sampleRate, 8e3) : tWav.samples;
6390
+ buffRadio = setRadioEffect(tSamples, 8e3);
6410
6391
  }
6411
- return attachments;
6392
+ buffFull = buffRadio != null ? [buffRadio, new Int16Array(Math.floor(0.5 * 8e3))] : [];
6393
+ buffFull.push(
6394
+ setSameHeader(header, 3, 8e3, {
6395
+ preMarkSec: 1.1,
6396
+ gapSec: 0.5
6397
+ }),
6398
+ new Int16Array(Math.floor(0.5 * 8e3)),
6399
+ setAttentionTone(8, 8e3),
6400
+ new Int16Array(Math.floor(0.5 * 8e3)),
6401
+ vRadio
6402
+ );
6403
+ for (let i = 0; i < 3; i++) {
6404
+ buffFull.push(setSameHeader(header, 1, 8e3, { preMarkSec: 0.5, gapSec: 0.1 }));
6405
+ buffFull.push(new Int16Array(Math.floor(0.5 * 8e3)));
6406
+ }
6407
+ const aSamples = getMergedPCM16(buffFull);
6408
+ const aFinal = setNoise(aSamples, 2e-3);
6409
+ const aBuffer = getPCM16(Array.from(aFinal).map((v) => ({ value: v })), 8e3);
6410
+ (0, import_fs2.writeFileSync)(outTTS, aBuffer);
6411
+ try {
6412
+ (0, import_fs2.unlinkSync)(tmpTTS);
6413
+ } catch (e) {
6414
+ }
6415
+ setDebug({ title: `@eas.setEasTone`, message: `EAS tone generation took ${performance.now() - tick} ms` });
6416
+ return outTTS;
6417
+ });
6418
+
6419
+ // src/@parsers/@text/text.getEmbed.ts
6420
+ var getEmebed = (event) => {
6421
+ 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;
6422
+ const line = (label, value, condition = true) => condition && value ? `${label} ${value}` : null;
6423
+ const isStatement = event.properties.status_metadata.is_statement;
6424
+ const isExpired = event.properties.status_metadata.is_expired;
6425
+ return [
6426
+ line(`**Locations:**`, (_b = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.locations) == null ? void 0 : _b.slice(0, 100)),
6427
+ line(`**Issued:**`, `<t:${Math.floor(new Date(event.properties.issued).getTime() / 1e3)}:R>`, !isExpired),
6428
+ line(`**Expires:**`, `<t:${Math.floor(new Date(event.properties.expires).getTime() / 1e3)}:R>`, !isStatement),
6429
+ line(`**Damage Threat:**`, (_d = (_c = event == null ? void 0 : event.properties) == null ? void 0 : _c.parameters) == null ? void 0 : _d.damage_threat, !isExpired),
6430
+ line(`**Flood Threat:**`, (_f = (_e = event == null ? void 0 : event.properties) == null ? void 0 : _e.parameters) == null ? void 0 : _f.flood_threat, !isExpired),
6431
+ line(`**Tornado Threat:**`, (_h = (_g = event == null ? void 0 : event.properties) == null ? void 0 : _g.parameters) == null ? void 0 : _h.tornado_threat, !isExpired),
6432
+ 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),
6433
+ 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),
6434
+ line(`**Discussion:**`, (_z = (_y = event == null ? void 0 : event.properties) == null ? void 0 : _y.discussion_parameters) == null ? void 0 : _z.discussion_number, !isExpired),
6435
+ line(`**Concern:**`, (_B = (_A = event == null ? void 0 : event.properties) == null ? void 0 : _A.discussion_parameters) == null ? void 0 : _B.discussion_concerning, !isExpired),
6436
+ 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),
6437
+ 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),
6438
+ 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),
6439
+ 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),
6440
+ line(`**Watch Number:**`, (_N = (_M = event == null ? void 0 : event.properties) == null ? void 0 : _M.watch_parameters) == null ? void 0 : _N.watch_number, !isExpired),
6441
+ 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),
6442
+ 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),
6443
+ 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),
6444
+ 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),
6445
+ 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),
6446
+ 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),
6447
+ 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),
6448
+ 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),
6449
+ 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),
6450
+ 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),
6451
+ 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),
6452
+ line(`**Tracking:**`, (_Ia = (_Ha = event == null ? void 0 : event.properties) == null ? void 0 : _Ha.metadata) == null ? void 0 : _Ia.tracking),
6453
+ 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)
6454
+ ].filter(Boolean).join("\n");
6412
6455
  };
6413
6456
 
6414
- // src/@building/building.validate.ts
6415
- var validateEvents = (events) => __async(null, null, function* () {
6416
- var _a;
6417
- if (events.length === 0) return;
6418
- const configurations = bootstrap.settings;
6419
- const sets = {};
6420
- const bools = {};
6421
- const megered = __spreadValues(__spreadValues({}, configurations.GlobalSettings), configurations.GlobalSettings.EventFiltering);
6422
- for (const key in megered) {
6423
- const setting = megered[key];
6424
- if (Array.isArray(setting)) {
6425
- sets[key] = new Set(setting.map((item) => item.toLowerCase()));
6426
- }
6427
- if (typeof setting === "boolean") {
6428
- bools[key] = setting;
6429
- }
6457
+ // src/@modules/@utilities/utilities.createHttp.ts
6458
+ var createHttp = (options) => __async(null, null, function* () {
6459
+ var _a, _b, _c, _d;
6460
+ const requestOptions = {
6461
+ method: (_a = options.method) != null ? _a : "GET",
6462
+ headers: (_b = options.headers) != null ? _b : {
6463
+ "User-Agent": "AtmosphericX",
6464
+ "Accept": "application/geo+json, text/plain, */*; q=0.9",
6465
+ "Accept-Language": "en-US,en;q=0.9"
6466
+ },
6467
+ signal: AbortSignal.timeout((_c = options.timeout) != null ? _c : 1e4),
6468
+ redirect: "follow"
6469
+ };
6470
+ const returnHttp = function(error, status, message) {
6471
+ return { error, options: requestOptions, status, message };
6472
+ };
6473
+ if (options == null ? void 0 : options.formData) {
6474
+ requestOptions.body = options.formData;
6475
+ } else if ((options == null ? void 0 : options.body) != void 0) {
6476
+ requestOptions.body = options.body instanceof FormData ? options.body : typeof options.body === "string" ? options.body : JSON.stringify(options.body);
6430
6477
  }
6431
- const filterd = events.filter((event) => {
6432
- var _a2, _b, _c, _d, _e;
6433
- const define2 = getEventSignature(event);
6434
- const properties2 = define2.properties;
6435
- const zones = properties2.geocode.ugc;
6436
- const icao = properties2.geocode.office.office;
6437
- const enhancedEventName = properties2.event = getEventEnhancedName(event);
6438
- const filteredProperties = JSON.parse(JSON.stringify(properties2));
6439
- if ((filteredProperties == null ? void 0 : filteredProperties.metadata) && "ms" in filteredProperties.metadata) {
6440
- delete filteredProperties.metadata.ms;
6441
- }
6442
- filteredProperties.metadata = (_a2 = filteredProperties.metadata) != null ? _a2 : {};
6443
- properties2.metadata.hash = (0, import_crypto.createHash)("sha256").update(JSON.stringify(filteredProperties)).digest("hex");
6444
- properties2.metadata.attachments = getEventAttachments(event);
6445
- setEventEmit({ event: `onProductType${enhancedEventName.replace(/\s+/g, "")}`, metadata: define2 });
6446
- if (properties2.status_metadata.is_test) {
6447
- setEventEmit({ event: `onTestProduct`, metadata: define2 });
6448
- if (bools == null ? void 0 : bools.IgnoreTestProducts) return false;
6449
- }
6450
- if (properties2.status_metadata.is_expired) {
6451
- setEventEmit({ event: `onExpiredProduct`, metadata: define2 });
6452
- rmEvent(define2);
6453
- return false;
6478
+ try {
6479
+ const response2 = yield fetch(
6480
+ (_d = options == null ? void 0 : options.url) != null ? _d : `https://api.weather.gov/alerts/active`,
6481
+ requestOptions
6482
+ );
6483
+ const body = yield response2.text();
6484
+ if (!response2.ok) {
6485
+ return returnHttp(true, response2.status, `HTTP Status Code ${response2.status} (${response2.statusText})`);
6454
6486
  }
6455
- if (((_c = (_b = properties2.metadata) == null ? void 0 : _b.vtec) == null ? void 0 : _c.is_watch) && properties2.metadata.source != `events.api`) {
6456
- const isSPC = (_e = (_d = properties2.metadata) == null ? void 0 : _d.vtec) == null ? void 0 : _e.prediction_center;
6457
- setEventEmit({ event: isSPC ? `onStormPredictionWatch` : `onNonStormPredictionWatch`, metadata: define2 });
6458
- if ((bools == null ? void 0 : bools.SPCWatchesOnly) && !isSPC) {
6459
- return false;
6460
- }
6461
- if (!(bools == null ? void 0 : bools.SPCWatchesOnly) && isSPC) {
6462
- return false;
6463
- }
6487
+ return returnHttp(false, response2.status, body);
6488
+ } catch (error) {
6489
+ return returnHttp(true, 500, `Internal Server Error: ${error}`);
6490
+ }
6491
+ });
6492
+
6493
+ // src/@modules/@utilities/utilities.getMatched.ts
6494
+ var getMatched = (strings, string) => {
6495
+ const isMatched = strings.some((pattern) => {
6496
+ if (!pattern) return false;
6497
+ const lowerP = pattern.toLowerCase();
6498
+ const lowerS = string.toLowerCase();
6499
+ if (lowerP === "*" || lowerP === lowerS) return true;
6500
+ if (lowerP.includes("*")) {
6501
+ const regex = "^" + lowerP.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$";
6502
+ return new RegExp(regex).test(lowerS);
6464
6503
  }
6465
- for (const key in sets) {
6466
- const setting = sets[key];
6467
- if (key === "ListeningEvents" && setting.size > 0 && !setting.has(define2.properties.event.toLowerCase())) {
6468
- setEventEmit({
6469
- event: `onFilteredEvent`,
6470
- metadata: define2
6471
- });
6472
- return false;
6473
- }
6474
- if (key === "IgnoredEvents" && setting.size > 0 && setting.has(define2.properties.event.toLowerCase())) {
6475
- setEventEmit({
6476
- event: `onIgnoredEvent`,
6477
- metadata: define2
6478
- });
6479
- return false;
6480
- }
6481
- if (key === "ListeningICAO" && setting.size > 0 && icao != null && !setting.has(icao.toLowerCase())) {
6482
- setEventEmit({
6483
- event: `onFilteredICAO`,
6484
- metadata: define2
6504
+ return false;
6505
+ });
6506
+ return isMatched;
6507
+ };
6508
+
6509
+ // src/@manager/manager.updateListener.ts
6510
+ var import_fs3 = require("fs");
6511
+ var updateListener = (event) => __async(null, null, function* () {
6512
+ var _a, _b, _c, _d, _e, _f;
6513
+ const tick = performance.now();
6514
+ const settings = bootstrap.settings;
6515
+ const listeners2 = settings.ListenerSettings;
6516
+ const properties2 = event.properties;
6517
+ const metadata = {
6518
+ file: null,
6519
+ eas: null,
6520
+ json: null,
6521
+ name: properties2.event,
6522
+ status: properties2.status,
6523
+ description: properties2.description,
6524
+ tracking: properties2.metadata.tracking,
6525
+ header: properties2.metadata.header,
6526
+ raw: properties2.metadata.raw,
6527
+ expired: properties2.status_metadata.is_expired,
6528
+ attachments: properties2.metadata.attachments
6529
+ };
6530
+ for (const listener2 of listeners2) {
6531
+ const events = listener2 == null ? void 0 : listener2.events;
6532
+ const webhook = listener2 == null ? void 0 : listener2.webhook;
6533
+ const uploads = listener2 == null ? void 0 : listener2.uploads;
6534
+ const isMatched = getMatched(events != null ? events : [], metadata.name);
6535
+ if ((events == null ? void 0 : events.length) == 0 || isMatched) {
6536
+ if (uploads == null ? void 0 : uploads.eas) {
6537
+ metadata.eas = yield setEasTone({
6538
+ title: `${metadata.name}_${metadata.status}_${metadata.tracking}`,
6539
+ message: metadata.description,
6540
+ header: metadata.header
6485
6541
  });
6486
- return false;
6487
6542
  }
6488
- if (key === "IgnoredICAO" && setting.size > 0 && icao != null && setting.has(icao.toLowerCase())) {
6489
- setEventEmit({
6490
- event: `onIgnoredICAO`,
6491
- metadata: define2
6492
- });
6493
- return false;
6543
+ if (uploads == null ? void 0 : uploads.file) {
6544
+ const fDestination = settings.GlobalSettings.ArchiveSettings.TextDirectory;
6545
+ if (fDestination) {
6546
+ const file = `${fDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.txt`.replace(/[\\:*?"<>|]/g, "_").replace(/\s+/g, " ").trim();
6547
+ if (!(0, import_fs3.existsSync)(fDestination)) {
6548
+ (0, import_fs3.mkdirSync)(fDestination, { recursive: true });
6549
+ }
6550
+ if ((0, import_fs3.existsSync)(file)) {
6551
+ (0, import_fs3.appendFileSync)(file, metadata.raw);
6552
+ } else {
6553
+ (0, import_fs3.writeFileSync)(file, metadata.raw);
6554
+ }
6555
+ }
6556
+ metadata.file = metadata.raw;
6494
6557
  }
6495
- if (key === "ListeningUGC" && setting.size > 0 && zones.length > 0 && !zones.some((ugc2) => setting.has(ugc2.toLowerCase()))) {
6496
- setEventEmit({
6497
- event: `onFilteredUGC`,
6498
- metadata: define2
6499
- });
6500
- return false;
6558
+ if (uploads == null ? void 0 : uploads.event) {
6559
+ const eDestination = settings.GlobalSettings.ArchiveSettings.EventDirectory;
6560
+ if (eDestination) {
6561
+ const file = `${eDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.json`.replace(/[\\:*?"<>|]/g, "_").replace(/\s+/g, " ").trim();
6562
+ if (!(0, import_fs3.existsSync)(eDestination)) {
6563
+ (0, import_fs3.mkdirSync)(eDestination, { recursive: true });
6564
+ }
6565
+ (0, import_fs3.writeFileSync)(file, JSON.stringify(getCleanedEvent(event), null, 2));
6566
+ }
6567
+ metadata.json = JSON.stringify(getCleanedEvent(event), null, 2);
6501
6568
  }
6502
- if (key === "ListeningStates" && setting.size > 0 && zones.length > 0 && !zones.some((ugc2) => setting.has(ugc2.substring(0, 2).toLowerCase()))) {
6503
- setEventEmit({
6504
- event: `onFilteredState`,
6505
- metadata: define2
6569
+ if ((webhook == null ? void 0 : webhook.enabled) && (webhook == null ? void 0 : webhook.destination)) {
6570
+ const isRatelimited = setTimeoutAction({ identifier: webhook.destination, interval: ((_a = webhook.ratelimit) != null ? _a : 2) * 2, max: (_b = webhook.ratelimit) != null ? _b : 2, addTime: true });
6571
+ const form = new FormData();
6572
+ const embed = {
6573
+ title: `${metadata.name} (${metadata.status})`,
6574
+ description: getEmebed(event),
6575
+ fields: [],
6576
+ color: 16711680,
6577
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6578
+ footer: { text: (_c = webhook.title) != null ? _c : `AtmosphericX` }
6579
+ };
6580
+ if (isRatelimited.limited) {
6581
+ return;
6582
+ }
6583
+ if (metadata.description && !metadata.expired) {
6584
+ if (metadata.description.length > 900) {
6585
+ metadata.description = metadata.description.substring(0, 900) + "\n\n[Message truncated due to length]";
6586
+ }
6587
+ embed.fields.push({
6588
+ name: "Description",
6589
+ value: metadata.description ? "```\n" + metadata.description.split("\n").map((l) => l.trim()).filter(Boolean).join("\n") + "\n```" : ""
6590
+ });
6591
+ }
6592
+ if (((_d = metadata.attachments) == null ? void 0 : _d.length) > 0) {
6593
+ metadata.attachments = metadata.attachments.slice(0, 5);
6594
+ embed.fields.push({
6595
+ name: "Attachments",
6596
+ value: metadata.attachments.map((attachment) => `- [${attachment.name.length > 45 ? attachment.name.substring(0, 45) + "..." : attachment.name}](${attachment.link})`).join("\n")
6597
+ });
6598
+ }
6599
+ if (uploads == null ? void 0 : uploads.file) {
6600
+ form.append("fUpload", new Blob([Buffer.from(metadata.file)], { type: "application/text" }), `${properties2.event}_${properties2.status}_${properties2.metadata.tracking}.txt`);
6601
+ }
6602
+ if (uploads == null ? void 0 : uploads.event) {
6603
+ form.append("fUpload2", new Blob([Buffer.from(metadata.json)], { type: "application/json" }), `${properties2.event}_${properties2.status}_${properties2.metadata.tracking}.json`);
6604
+ }
6605
+ if (uploads == null ? void 0 : uploads.eas) {
6606
+ if (metadata.eas) {
6607
+ const file = (0, import_fs3.readFileSync)(metadata.eas);
6608
+ form.append("fEas", new Blob([Buffer.from(file)], { type: "audio/mpeg" }), `${properties2.event}_${properties2.status}_${properties2.metadata.tracking}_eas.mp3`);
6609
+ }
6610
+ }
6611
+ form.append("payload_json", JSON.stringify({
6612
+ username: (_e = webhook.title) != null ? _e : "AtmosphericX",
6613
+ content: (_f = webhook.message) != null ? _f : "",
6614
+ embeds: [embed]
6615
+ }));
6616
+ yield createHttp({
6617
+ url: webhook.destination,
6618
+ timeout: 15e3,
6619
+ method: `POST`,
6620
+ body: form
6506
6621
  });
6507
- return false;
6508
6622
  }
6509
6623
  }
6510
- return true;
6511
- });
6512
- if (!((_a = configurations == null ? void 0 : configurations.GlobalSettings) == null ? void 0 : _a.DisableGeometryParsing)) {
6513
- for (const event of filterd) {
6514
- event.geometry = yield getEventGeometry(event);
6515
- }
6516
- }
6517
- if (filterd.length > 0) {
6518
- for (const event of filterd) {
6519
- yield mkEvent(event);
6520
- }
6521
6624
  }
6522
- yield updateNode();
6523
- setEventEmit({
6524
- event: `onEventCache`,
6525
- metadata: bootstrap.cache.events,
6526
- limited: true
6527
- });
6625
+ setDebug({ title: `@manager.updateListener`, message: `Listener took ${performance.now() - tick} ms` });
6528
6626
  });
6529
6627
 
6530
- // src/@events/events.text.ts
6531
- var text = (stanza) => __async(null, null, function* () {
6532
- var _a, _b, _c;
6533
- let processed = [];
6534
- 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 !== "$$");
6535
- if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
6536
- for (const message of getMessages) {
6537
- const tick = performance.now();
6538
- const attributes = stanza == null ? void 0 : stanza.attributes;
6539
- const props = properties({ message, attributes });
6540
- const header = getEventHeader({ properties: props, getType: stanza.getType });
6541
- const issued = new Date(attributes.issue);
6542
- const expires = new Date(issued.getTime() + 12 * 60 * 60 * 1e3);
6543
- let event = Object.keys(dict_matches).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
6544
- let isStatement = false;
6545
- if (!event) {
6546
- event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
6547
- isStatement = true;
6548
- }
6549
- processed.push({
6550
- type: `Feature`,
6551
- geometry: {
6552
- type: `Point`,
6553
- coordinates: []
6554
- },
6555
- properties: __spreadProps(__spreadValues({
6556
- event,
6557
- parent: event,
6558
- status: isStatement ? `Statement` : `Issued`,
6559
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
6560
- expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
6561
- }, props), {
6562
- metadata: {
6563
- ms: performance.now() - tick,
6564
- source: `events.text`,
6565
- tracking: getEventTracking({ type: `RAW`, stanza, attributes, properties: props }),
6566
- header,
6567
- vtec: null,
6568
- hvtec: null,
6569
- raw: message,
6570
- history: [
6571
- {
6572
- description: props.description,
6573
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
6574
- status: `Issued`
6575
- }
6576
- ]
6577
- }
6578
- })
6579
- });
6628
+ // src/@modules/@utilities/utilities.getShapeNearestPoint.ts
6629
+ var getShapeNearestPoint = (coordinates, point) => {
6630
+ if (!coordinates || !point) {
6631
+ return { proximity: false, point: [0, 0], distance: null };
6580
6632
  }
6581
- validateEvents(processed);
6582
- });
6583
-
6584
- // src/@parsers/@ugc/ugc.header.ts
6585
- var getUGCHeader = (message) => {
6586
- const start = message.search(dict_expressions.ugc1);
6587
- const sub = message.substring(start);
6588
- const end = sub.search(dict_expressions.ugc2);
6589
- const fin = sub.substring(0, end).replace(/\s+/g, "").slice(0, -1);
6590
- return fin != null ? fin : null;
6591
- };
6592
-
6593
- // src/@parsers/@ugc/ugc.zones.ts
6594
- var getZones = (header) => {
6595
- const splits = header.split("-");
6596
- const zones = [];
6597
- let state = splits[0].substring(0, 2);
6598
- const format = splits[0].substring(2, 3);
6599
- for (const part of splits) {
6600
- if (/^[A-Z]/.test(part)) {
6601
- state = part.substring(0, 2);
6602
- if (part.includes(">")) {
6603
- const [start, end] = part.split(">");
6604
- const startNum = parseInt(start.substring(3), 10);
6605
- const endNum = parseInt(end, 10);
6606
- for (let j2 = startNum; j2 <= endNum; j2++) {
6607
- zones.push(`${state}${format}${j2.toString().padStart(3, "0")}`);
6633
+ const normalize = (coords) => {
6634
+ if (!Array.isArray(coords)) return [];
6635
+ if (typeof coords[0] === "number" && typeof coords[1] === "number") return [];
6636
+ if (Array.isArray(coords[0]) && typeof coords[0][0] === "number") {
6637
+ return [[coords]];
6638
+ }
6639
+ if (Array.isArray(coords[0]) && Array.isArray(coords[0][0]) && typeof coords[0][0][0] === "number") {
6640
+ return [coords];
6641
+ }
6642
+ if (Array.isArray(coords[0]) && Array.isArray(coords[0][0]) && Array.isArray(coords[0][0][0]) && typeof coords[0][0][0][0] === "number") {
6643
+ return coords;
6644
+ }
6645
+ return [];
6646
+ };
6647
+ const polys = normalize(coordinates);
6648
+ if (polys.length === 0) return { proximity: false, point: [0, 0], distance: null };
6649
+ const lon = point[0];
6650
+ const lat = point[1];
6651
+ const pointInRing = (pt, ring) => {
6652
+ let x = pt[0], y = pt[1];
6653
+ let inside = false;
6654
+ for (let i = 0, j2 = ring.length - 1; i < ring.length; j2 = i++) {
6655
+ const xi = ring[i][0], yi = ring[i][1];
6656
+ const xj = ring[j2][0], yj = ring[j2][1];
6657
+ const intersect = yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi + 0) + xi;
6658
+ if (intersect) inside = !inside;
6659
+ }
6660
+ return inside;
6661
+ };
6662
+ const toRadians = (deg) => deg * Math.PI / 180;
6663
+ const haversineMiles = (a, b) => {
6664
+ const R = 3958.8;
6665
+ const dLat = toRadians(b[1] - a[1]);
6666
+ const dLon = toRadians(b[0] - a[0]);
6667
+ const lat1 = toRadians(a[1]);
6668
+ const lat2 = toRadians(b[1]);
6669
+ const sinDLat = Math.sin(dLat / 2);
6670
+ const sinDLon = Math.sin(dLon / 2);
6671
+ const c = 2 * Math.asin(Math.sqrt(sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon));
6672
+ return R * c;
6673
+ };
6674
+ let minDistance = Infinity;
6675
+ let closestPoint = null;
6676
+ for (const poly of polys) {
6677
+ const outer = poly[0];
6678
+ const holes = poly.slice(1);
6679
+ if (pointInRing(point, outer)) {
6680
+ let inHole = false;
6681
+ for (const hole of holes) {
6682
+ if (pointInRing(point, hole)) {
6683
+ inHole = true;
6684
+ break;
6608
6685
  }
6609
- } else {
6610
- zones.push(part);
6611
6686
  }
6612
- continue;
6687
+ if (!inHole) {
6688
+ return { proximity: true, point, distance: 0 };
6689
+ }
6613
6690
  }
6614
- if (part.includes(">")) {
6615
- const [start, end] = part.split(">");
6616
- const startNum = parseInt(start, 10);
6617
- const endNum = parseInt(end, 10);
6618
- for (let j2 = startNum; j2 <= endNum; j2++) {
6619
- zones.push(`${state}${format}${j2.toString().padStart(3, "0")}`);
6691
+ for (const ring of poly) {
6692
+ for (let i = 0; i < ring.length - 1; i++) {
6693
+ const start = [ring[i][0], ring[i][1]];
6694
+ const end = [ring[i + 1][0], ring[i + 1][1]];
6695
+ const A = lon - start[0];
6696
+ const B = lat - start[1];
6697
+ const C = end[0] - start[0];
6698
+ const D = end[1] - start[1];
6699
+ const lenSq = C * C + D * D;
6700
+ const t = lenSq === 0 ? 0 : Math.max(0, Math.min(1, (A * C + B * D) / lenSq));
6701
+ const candidate = [start[0] + t * C, start[1] + t * D];
6702
+ const dist = haversineMiles([lon, lat], candidate);
6703
+ if (!isNaN(dist) && dist < minDistance) {
6704
+ minDistance = Number(dist.toFixed(3));
6705
+ closestPoint = candidate;
6706
+ }
6620
6707
  }
6621
- } else {
6622
- zones.push(`${state}${format}${part}`);
6623
6708
  }
6624
6709
  }
6625
- return zones.filter((item) => item !== "");
6626
- };
6627
-
6628
- // src/@parsers/@ugc/ugc.expiry.ts
6629
- var getExpiry = (message) => {
6630
- const match = message.match(/\b(\d{6})-/);
6631
- if (!match) {
6632
- return null;
6633
- }
6634
- const date = match == null ? void 0 : match[1];
6635
- const day = parseInt(date == null ? void 0 : date.slice(0, 2), 10);
6636
- const hour = parseInt(date == null ? void 0 : date.slice(2, 4), 10);
6637
- const minute = parseInt(date == null ? void 0 : date.slice(4, 6), 10);
6638
- const now = /* @__PURE__ */ new Date();
6639
- const expires = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), day, hour, minute));
6640
- return expires.toISOString();
6710
+ if (!isFinite(minDistance) || closestPoint == null) {
6711
+ return { proximity: false, point: [0, 0], distance: null };
6712
+ }
6713
+ const distanceMiles = minDistance;
6714
+ const distanceKm = Number((distanceMiles * 1.609344).toFixed(3));
6715
+ const distanceMeters = Math.round(distanceKm * 1e3);
6716
+ return { proximity: distanceMiles === 0, point: closestPoint, distance: distanceMiles, distanceKm, distanceMeters };
6641
6717
  };
6642
6718
 
6643
- // src/@parsers/@ugc/ugc.locations.ts
6644
- var getLocations = (zones) => __async(null, null, function* () {
6645
- const sites = Array.from(new Set(zones));
6646
- const placeholders = sites.map(() => "?").join(",");
6647
- const rows = yield bootstrap.database.prepare(`SELECT id, location FROM shapefiles WHERE id IN (${placeholders})`).all(...sites);
6648
- return rows.map((row) => row.location).sort();
6649
- });
6650
-
6651
- // src/@parsers/@ugc/ugc.extract.ts
6652
- var ugcExtract = (message) => __async(null, null, function* () {
6653
- const head = getUGCHeader(message);
6654
- const ugcs = getZones(head);
6655
- const expires = getExpiry(message);
6656
- const areas = yield getLocations(ugcs);
6657
- if (!head || (ugcs == null ? void 0 : ugcs.length) == 0) return;
6719
+ // src/@building/building.polygon.ts
6720
+ var getEventNodes = (event) => __async(null, null, function* () {
6721
+ var _a, _b;
6722
+ const metadata = { nodes: [], proximity: false, filtered: false };
6723
+ const geometry = yield getEventGeometry(event);
6724
+ if (!geometry || !geometry.coordinates) {
6725
+ return { nodes: [], filtered: false, updated: Date.now() };
6726
+ }
6727
+ const nodes = bootstrap.cache.nodes.features;
6728
+ for (const node of nodes) {
6729
+ const [longitude, latitude] = node.geometry.coordinates;
6730
+ const getPoint = getShapeNearestPoint(geometry.coordinates, [longitude, latitude]);
6731
+ const miles = (_a = getPoint.distance) != null ? _a : null;
6732
+ const kilometers = Number((miles * 1.609344).toFixed(3));
6733
+ const info = {
6734
+ id: (_b = node.properties) == null ? void 0 : _b.identifier,
6735
+ coordinates: [longitude, latitude],
6736
+ nearest: getPoint.point,
6737
+ miles,
6738
+ kilometers,
6739
+ proximity: getPoint.proximity
6740
+ };
6741
+ metadata.nodes.push(info);
6742
+ if (bootstrap.settings.GlobalSettings.EventFiltering.NodeLocationFiltering && miles < bootstrap.settings.GlobalSettings.NodeMinDistance) {
6743
+ metadata.proximity = true;
6744
+ info.proximity = true;
6745
+ }
6746
+ }
6658
6747
  return {
6659
- zones: ugcs,
6660
- locations: areas,
6661
- expires
6748
+ nodes: metadata.nodes,
6749
+ filtered: metadata.proximity,
6750
+ updated: Date.now()
6662
6751
  };
6663
6752
  });
6664
6753
 
6665
- // src/@events/events.ugc.ts
6666
- var ugc = (stanza) => __async(null, null, function* () {
6667
- var _a, _b, _c;
6668
- let processed = [];
6669
- 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 !== "$$");
6670
- if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
6671
- for (const message of getMessages) {
6672
- const tick = performance.now();
6673
- const attributes = stanza == null ? void 0 : stanza.attributes;
6674
- const ugc2 = yield ugcExtract(message);
6675
- if (ugc2 != null) {
6676
- const props = properties({ message, attributes, ugc: ugc2 });
6677
- const issued = new Date(attributes.issue);
6678
- const expires = new Date(ugc2.expires);
6679
- const header = getEventHeader({ properties: props, getType: stanza.getType });
6680
- let event = Object.keys(dict_matches).find((event2) => message.toLowerCase().includes(event2.toLowerCase()));
6681
- let isStatement = false;
6682
- if (!event) {
6683
- event = stanza.getType.type.split(`-`).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `);
6684
- isStatement = true;
6754
+ // src/@manager/manager.updateNodes.ts
6755
+ var updateNode = (selectedEvent) => __async(null, null, function* () {
6756
+ const events = bootstrap.cache.events.features;
6757
+ const ttl = bootstrap.settings.GlobalSettings.NodeTTL * 1e3;
6758
+ let total = 0;
6759
+ function update(evt) {
6760
+ return __async(this, null, function* () {
6761
+ var _a, _b, _c;
6762
+ const lastUpdate = (_c = (_b = (_a = evt == null ? void 0 : evt.properties) == null ? void 0 : _a.metadata) == null ? void 0 : _b.updated) != null ? _c : null;
6763
+ if (lastUpdate != null && Date.now() - lastUpdate < ttl) {
6764
+ return evt;
6685
6765
  }
6686
- processed.push({
6687
- type: `Feature`,
6688
- geometry: {
6689
- type: `Point`,
6690
- coordinates: []
6691
- },
6692
- properties: __spreadProps(__spreadValues({
6693
- event,
6694
- parent: event,
6695
- status: isStatement ? `Statement` : `Issued`,
6696
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
6697
- expires: isStatement ? new Date(issued.getTime() + 120 * 1e3).toISOString() : !isNaN(expires.getTime()) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1e3).toISOString()
6698
- }, props), {
6699
- metadata: {
6700
- ms: performance.now() - tick,
6701
- source: `events.ugc`,
6702
- tracking: getEventTracking({ type: `RAW`, stanza, attributes, properties: props }),
6703
- header,
6704
- vtec: null,
6705
- hvtec: null,
6706
- raw: message,
6707
- history: [
6708
- {
6709
- description: props.description,
6710
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
6711
- status: `Issued`
6712
- }
6713
- ]
6714
- }
6715
- })
6716
- });
6717
- }
6766
+ const node = yield getEventNodes(evt);
6767
+ if (node.nodes.length > 0) {
6768
+ total++;
6769
+ }
6770
+ evt.properties.metadata.nodes = node.nodes;
6771
+ evt.properties.metadata.filtered_proximity = node.filtered;
6772
+ evt.properties.metadata.updated = node.updated;
6773
+ });
6774
+ }
6775
+ if (!selectedEvent) {
6776
+ yield Promise.all(events.map((evt) => __async(null, null, function* () {
6777
+ yield update(evt);
6778
+ })));
6779
+ }
6780
+ if (selectedEvent) {
6781
+ yield update(selectedEvent);
6782
+ }
6783
+ if (total > 0) {
6784
+ setEventEmit({
6785
+ event: `onNodeUpdate`,
6786
+ metadata: {
6787
+ type: `global-update`,
6788
+ updated: total
6789
+ }
6790
+ });
6718
6791
  }
6719
- validateEvents(processed);
6720
6792
  });
6721
6793
 
6722
- // src/@dictionaries/dictionaries.events.ts
6723
- var dict_events = {
6724
- "AF": "Ashfall",
6725
- "AS": "Air Stagnation",
6726
- "BH": "Beach Hazard",
6727
- "BW": "Brisk Wind",
6728
- "BZ": "Blizzard",
6729
- "CF": "Coastal Flood",
6730
- "DF": "Debris Flow",
6731
- "DS": "Dust Storm",
6732
- "EC": "Extreme Cold",
6733
- "EH": "Excessive Heat",
6734
- "XH": "Extreme Heat",
6735
- "EW": "Extreme Wind",
6736
- "FA": "Areal Flood",
6737
- "FF": "Flash Flood",
6738
- "FG": "Dense Fog",
6739
- "FL": "Flood",
6740
- "FR": "Frost",
6741
- "FW": "Fire Weather",
6742
- "FZ": "Freeze",
6743
- "GL": "Gale",
6744
- "HF": "Hurricane Force Wind",
6745
- "HT": "Heat",
6746
- "HU": "Hurricane",
6747
- "HW": "High Wind",
6748
- "HY": "Hydrologic",
6749
- "HZ": "Hard Freeze",
6750
- "IS": "Ice Storm",
6751
- "LE": "Lake Effect Snow",
6752
- "LO": "Low Water",
6753
- "LS": "Lakeshore Flood",
6754
- "LW": "Lake Wind",
6755
- "MA": "Special Marine",
6756
- "EQ": "Earthquake",
6757
- "MF": "Dense Fog",
6758
- "MH": "Ashfall",
6759
- "MS": "Dense Smoke",
6760
- "RB": "Small Craft for Rough Bar",
6761
- "RP": "Rip Current Risk",
6762
- "SC": "Small Craft",
6763
- "SE": "Hazardous Seas",
6764
- "SI": "Small Craft for Winds",
6765
- "SM": "Dense Smoke",
6766
- "SQ": "Snow Squall",
6767
- "SR": "Storm",
6768
- "SS": "Storm Surge",
6769
- "SU": "High Surf",
6770
- "SV": "Severe Thunderstorm",
6771
- "SW": "Small Craft for Hazardous Seas",
6772
- "TO": "Tornado",
6773
- "TR": "Tropical Storm",
6774
- "TS": "Tsunami",
6775
- "TY": "Typhoon",
6776
- "SP": "Special Weather",
6777
- "UP": "Heavy Freezing Spray",
6778
- "WC": "Wind Chill",
6779
- "WI": "Wind",
6780
- "WS": "Winter Storm",
6781
- "WW": "Winter Weather",
6782
- "ZF": "Freezing Fog",
6783
- "ZR": "Freezing Rain",
6784
- "ZY": "Freezing Spray"
6785
- };
6786
-
6787
- // src/@dictionaries/dictionaries.actions.ts
6788
- var dict_actions = {
6789
- "W": "Warning",
6790
- "F": "Forecast",
6791
- "A": "Watch",
6792
- "O": "Outlook",
6793
- "Y": "Advisory",
6794
- "N": "Synopsis",
6795
- "S": "Statement"
6796
- };
6797
-
6798
- // src/@dictionaries/dictionaries.status.ts
6799
- var dict_status = {
6800
- "NEW": "Issued",
6801
- "CON": "Updated",
6802
- "EXT": "Extended",
6803
- "EXA": "Extended",
6804
- "EXB": "Extended",
6805
- "UPG": "Upgraded",
6806
- "COR": "Correction",
6807
- "ROU": "Routine",
6808
- "CAN": "Cancelled",
6809
- "EXP": "Expired"
6810
- };
6811
-
6812
- // src/@parsers/@pvtec/pvtec.expires.ts
6813
- var getExpiry2 = (dates) => {
6814
- if ((dates == null ? void 0 : dates[1]) == `000000T0000Z`) return "Invalid Date Format";
6815
- 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`;
6816
- const local = new Date(new Date(expires).getTime() - 4 * 60 * 6e4);
6817
- const pad = (n) => n.toString().padStart(2, "0");
6818
- return `${local.getFullYear()}-${pad(local.getMonth() + 1)}-${pad(local.getDate())}T${pad(local.getHours())}:${pad(local.getMinutes())}:00.000-04:00`;
6819
- };
6820
-
6821
- // src/@parsers/@pvtec/pvtec.extract.ts
6822
- var pvExtract = (message) => {
6823
- var _a, _b, _c, _d;
6824
- if (!message) return null;
6825
- const getVTECs = (_a = message.match(dict_expressions.pvtec)) != null ? _a : [];
6826
- const vtecs = [];
6827
- for (const vtec2 of getVTECs) {
6828
- const sub = vtec2.split(`.`);
6829
- if ((sub == null ? void 0 : sub.length) < 7) continue;
6830
- const dates = (_b = sub[6]) == null ? void 0 : _b.split(`-`);
6831
- vtecs.push({
6832
- vtec: vtec2,
6833
- product: dict_products[sub[0]],
6834
- tracking: `${sub[2]}.${sub[3]}.${sub[4]}.${sub[5]}`,
6835
- event: `${dict_events[sub[3]]} ${dict_actions[sub[4]]}`,
6836
- status: dict_status[sub[1]],
6837
- organization: (_d = (_c = message.match(dict_expressions.wmo)) == null ? void 0 : _c[0]) != null ? _d : null,
6838
- expires: getExpiry2(dates),
6839
- is_watch: (sub[4] == `A` || sub[4] == `Y`) && (sub[3] == `TO` || sub[3] == `SV`),
6840
- prediction_center: sub[2] == `KWNS` ? true : false
6794
+ // src/@manager/manager.mkEvent.ts
6795
+ var mkEvent = (event) => __async(null, null, function* () {
6796
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w;
6797
+ const settings = bootstrap.settings;
6798
+ const features = bootstrap.cache.events.features;
6799
+ const getHash = event.properties.metadata.hash;
6800
+ const getTracking = event.properties.metadata.tracking;
6801
+ const isEntry = (_a = bootstrap.cache.hashes) == null ? void 0 : _a.find((hash) => hash.tracking === getTracking);
6802
+ const isHashed = (_c = (_b = isEntry == null ? void 0 : isEntry.hashes) == null ? void 0 : _b.includes(getHash)) != null ? _c : false;
6803
+ const getFeature = features.find((feature) => feature.properties.metadata.tracking === getTracking);
6804
+ if (isHashed || event.properties.status_metadata.is_expired) return;
6805
+ setHash(event, isEntry);
6806
+ const isFilteredLocation = yield updateNode(event).then(() => event.properties.metadata.filtered_proximity);
6807
+ if (!isFilteredLocation && settings.GlobalSettings.EventFiltering.NodeLocationFiltering) {
6808
+ return;
6809
+ }
6810
+ const isRatelimited = setTimeoutAction({ identifier: getTracking, interval: 1, max: 1, addTime: true });
6811
+ if (!isRatelimited.limited) {
6812
+ setEventEmit({
6813
+ event: `onEventStatus`,
6814
+ metadata: {
6815
+ type: getFeature ? `Updated` : `New`,
6816
+ event
6817
+ },
6818
+ message: `[${getFeature ? "Updated" : "New"}] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
6841
6819
  });
6842
6820
  }
6843
- return vtecs.length > 0 ? vtecs : null;
6844
- };
6845
-
6846
- // src/@dictionaries/dictionaries.causes.ts
6847
- var dict_causes = {
6848
- "SM": "Snow Melt",
6849
- "RS": "Rain/Snow Melt",
6850
- "ER": "Excessive Rain",
6851
- "DM": "Dam/Levee Failure",
6852
- "IJ": "Ice Jam",
6853
- "GO": "Glacier Lake Outburst",
6854
- "IC": "Ice",
6855
- "FS": "Flash Flood / Storm Surge",
6856
- "FT": "Tidal Effects",
6857
- "ET": "Elevated Upstream Flow",
6858
- "MC": "Other Multiple Causes",
6859
- "WT": "Wind and/or Tidal Effects",
6860
- "DR": "Reservoir Release",
6861
- "UU": "Unknown",
6862
- "OT": "Other Effects"
6863
- };
6821
+ if (settings.GlobalSettings.EventManagement) {
6822
+ if (event.properties.status_metadata.is_issued || event.properties.status_metadata.is_updated) {
6823
+ if (getFeature) {
6824
+ const getIndex = features.indexOf(getFeature);
6825
+ const cHistory = (_f = (_e = (_d = getFeature == null ? void 0 : getFeature.properties) == null ? void 0 : _d.metadata) == null ? void 0 : _e.history) != null ? _f : [];
6826
+ 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 : [];
6827
+ const cUgc = (_l = (_k = (_j = getFeature == null ? void 0 : getFeature.properties) == null ? void 0 : _j.geocode) == null ? void 0 : _k.ugc) != null ? _l : [];
6828
+ const iHistory = (_o = (_n = (_m = event.properties) == null ? void 0 : _m.metadata) == null ? void 0 : _n.history) != null ? _o : [];
6829
+ const iLocations = (_r = (_q = (_p = event.properties) == null ? void 0 : _p.locations) == null ? void 0 : _q.split(";").map((l) => l.trim())) != null ? _r : [];
6830
+ const iUgc = (_u = (_t = (_s = event.properties) == null ? void 0 : _s.geocode) == null ? void 0 : _t.ugc) != null ? _u : [];
6831
+ 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);
6832
+ const mLocations = [...cLocations, ...iLocations].filter((v, i, a) => a.indexOf(v) === i).join("; ");
6833
+ const mUgc = [...cUgc, ...iUgc].filter((v, i, a) => a.indexOf(v) === i);
6834
+ bootstrap.cache.events.features[getIndex] = __spreadProps(__spreadValues({}, event), {
6835
+ properties: __spreadProps(__spreadValues({}, event.properties), {
6836
+ metadata: __spreadProps(__spreadValues({}, (_v = event == null ? void 0 : event.properties) == null ? void 0 : _v.metadata), {
6837
+ history: mHistory
6838
+ }),
6839
+ locations: mLocations,
6840
+ geocode: __spreadProps(__spreadValues({}, (_w = event == null ? void 0 : event.properties) == null ? void 0 : _w.geocode), {
6841
+ ugc: mUgc
6842
+ })
6843
+ })
6844
+ });
6845
+ yield updateListener(bootstrap.cache.events.features[getIndex]);
6846
+ } else {
6847
+ features.push(event);
6848
+ yield updateListener(event);
6849
+ }
6850
+ }
6851
+ }
6852
+ });
6864
6853
 
6865
- // src/@dictionaries/dictionaries.records.ts
6866
- var dict_records = {
6867
- "NO": "No Record Expected",
6868
- "NR": "Near Record or possible record",
6869
- "UU": "Unknown history of records",
6870
- "OO": "Other"
6871
- };
6854
+ // src/@manager/manager.rmEvent.ts
6855
+ var rmEvent = (event) => __async(null, null, function* () {
6856
+ const getEvent = bootstrap.cache.events.features.find((f) => {
6857
+ var _a, _b, _c, _d;
6858
+ 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);
6859
+ });
6860
+ const cachedStatus = event.properties.status;
6861
+ event.properties.expires = (/* @__PURE__ */ new Date()).toISOString();
6862
+ event.properties.status = `Expired`;
6863
+ event.properties.status_metadata.is_expired = true;
6864
+ if (getEvent) {
6865
+ setEventEmit({
6866
+ event: `onEventStatus`,
6867
+ metadata: {
6868
+ type: `Removed`,
6869
+ event
6870
+ },
6871
+ message: `[Removed] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
6872
+ });
6873
+ setEventEmit({ event: `onExpiredProduct`, metadata: event });
6874
+ if (cachedStatus != `Statement`) yield updateListener(event);
6875
+ bootstrap.cache.events.features.splice(bootstrap.cache.events.features.indexOf(getEvent), 1);
6876
+ bootstrap.cache.hashes = bootstrap.cache.hashes.filter((hash) => hash.tracking !== event.properties.metadata.tracking);
6877
+ setTimeoutAction({ identifier: event.properties.metadata.tracking, expire: true });
6878
+ }
6879
+ setEventEmit({
6880
+ event: `onEventCache`,
6881
+ metadata: bootstrap.cache.events,
6882
+ limited: true
6883
+ });
6884
+ });
6872
6885
 
6873
- // src/@dictionaries/dictionaries.severity.ts
6874
- var dict_severity = {
6875
- N: "Not Expected",
6876
- 0: "Areal Flood or FF Product",
6877
- 1: "Minor",
6878
- 2: "Moderate",
6879
- 3: "Major",
6880
- U: "Unknown"
6886
+ // src/@dictionaries/dictionaries.states.ts
6887
+ var dict_states = {
6888
+ "AL": "Alabama",
6889
+ "AK": "Alaska",
6890
+ "AZ": "Arizona",
6891
+ "AR": "Arkansas",
6892
+ "CA": "California",
6893
+ "CO": "Colorado",
6894
+ "CT": "Connecticut",
6895
+ "DE": "Delaware",
6896
+ "FL": "Florida",
6897
+ "GA": "Georgia",
6898
+ "HI": "Hawaii",
6899
+ "ID": "Idaho",
6900
+ "IL": "Illinois",
6901
+ "IN": "Indiana",
6902
+ "IA": "Iowa",
6903
+ "KS": "Kansas",
6904
+ "KY": "Kentucky",
6905
+ "LA": "Louisiana",
6906
+ "ME": "Maine",
6907
+ "MD": "Maryland",
6908
+ "MA": "Massachusetts",
6909
+ "MI": "Michigan",
6910
+ "MN": "Minnesota",
6911
+ "MS": "Mississippi",
6912
+ "MO": "Missouri",
6913
+ "MT": "Montana",
6914
+ "NE": "Nebraska",
6915
+ "NV": "Nevada",
6916
+ "NH": "New Hampshire",
6917
+ "NJ": "New Jersey",
6918
+ "NM": "New Mexico",
6919
+ "NY": "New York",
6920
+ "NC": "North Carolina",
6921
+ "ND": "North Dakota",
6922
+ "OH": "Ohio",
6923
+ "OK": "Oklahoma",
6924
+ "OR": "Oregon",
6925
+ "PA": "Pennsylvania",
6926
+ "RI": "Rhode Island",
6927
+ "SC": "South Carolina",
6928
+ "SD": "South Dakota",
6929
+ "TN": "Tennessee",
6930
+ "TX": "Texas",
6931
+ "UT": "Utah",
6932
+ "VT": "Vermont",
6933
+ "VA": "Virginia",
6934
+ "WA": "Washington",
6935
+ "WV": "West Virginia",
6936
+ "WI": "Wisconsin",
6937
+ "WY": "Wyoming",
6938
+ "DC": "District of Columbia"
6881
6939
  };
6882
6940
 
6883
- // src/@parsers/@hvtec/hvtec.extract.ts
6884
- var hvExtract = (message) => {
6885
- var _a;
6886
- const getHVTECs = (_a = message.match(dict_expressions.hvtec)) != null ? _a : [];
6887
- const vtecs = [];
6888
- for (const vtec2 of getHVTECs) {
6889
- const sub = vtec2.split(`.`);
6890
- if (sub.length < 7) continue;
6891
- vtecs.push({
6892
- hvtec: vtec2,
6893
- severity: dict_severity[sub[1]],
6894
- cause: dict_causes[sub[2]],
6895
- record: dict_records[sub[6]]
6896
- });
6941
+ // src/@modules/@utilities/utilities.getLatestIssuance.ts
6942
+ var getLatestIssuance = () => {
6943
+ const now = /* @__PURE__ */ new Date();
6944
+ const current = now.getUTCHours() * 100 + now.getUTCMinutes();
6945
+ const issuances = [100, 600, 1300, 1630, 2e3];
6946
+ let latest = issuances[0];
6947
+ for (const issuance of issuances) {
6948
+ if (current >= issuance) {
6949
+ latest = issuance;
6950
+ }
6897
6951
  }
6898
- return vtecs.length > 0 ? vtecs : null;
6952
+ return latest.toString().padStart(4, "0");
6899
6953
  };
6900
6954
 
6901
- // src/@events/events.vtec.ts
6902
- var vtec = (stanza) => __async(null, null, function* () {
6903
- var _a, _b, _c, _d, _e;
6904
- let processed = [];
6905
- 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 !== "$$");
6906
- if (!getMessages || (getMessages == null ? void 0 : getMessages.length) == 0) return;
6907
- for (const message of getMessages) {
6908
- const tick = performance.now();
6909
- const attributes = stanza == null ? void 0 : stanza.attributes;
6910
- const pVtec = pvExtract(message);
6911
- const hVtec = hvExtract(message);
6912
- const ugc2 = yield ugcExtract(message);
6913
- if (pVtec != null && ugc2 != null) {
6914
- for (const pv of pVtec) {
6915
- const vtec2 = pv;
6916
- const props = properties({ message, attributes, ugc: ugc2, pVtec: vtec2 });
6917
- const header = getEventHeader({ properties: props, getType: stanza.getType, vtec: vtec2 });
6918
- const issued = (_d = new Date(attributes.issue)) != null ? _d : /* @__PURE__ */ new Date();
6919
- const expires = new Date(vtec2.expires);
6920
- processed.push({
6921
- type: `Feature`,
6922
- geometry: {
6923
- type: `Point`,
6924
- coordinates: []
6925
- },
6926
- properties: __spreadProps(__spreadValues({
6927
- event: pv.event,
6928
- parent: pv.event,
6929
- status: pv.status,
6930
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
6931
- expires: !isNaN(expires.getTime()) ? expires.toISOString() : (_e = ugc2.expires) != null ? _e : new Date(issued.getTime() + 60 * 60 * 1e3).toISOString()
6932
- }, props), {
6933
- metadata: {
6934
- ms: performance.now() - tick,
6935
- source: `events.vtec`,
6936
- tracking: getEventTracking({ type: `VTEC`, stanza, attributes, properties: props, vtec: vtec2 }),
6937
- header,
6938
- vtec: pv,
6939
- hvtec: hVtec,
6940
- raw: message,
6941
- history: [
6942
- {
6943
- description: props.description,
6944
- issued: !isNaN(issued.getTime()) ? issued.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
6945
- status: pv.status
6946
- }
6947
- ]
6948
- }
6949
- })
6955
+ // src/@building/building.attachments.ts
6956
+ var getEventAttachments = (event) => {
6957
+ var _a, _b, _c, _d, _e, _f, _g;
6958
+ let attachments = [];
6959
+ const issuanceTime = getLatestIssuance();
6960
+ const spcNumber = (_b = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.discussion_parameters) == null ? void 0 : _b.discussion_number;
6961
+ const watchNumber = (_d = (_c = event == null ? void 0 : event.properties) == null ? void 0 : _c.watch_parameters) == null ? void 0 : _d.watch_number;
6962
+ const locations = (_e = event == null ? void 0 : event.properties) == null ? void 0 : _e.locations_array;
6963
+ const events = [
6964
+ { target: "SPC Day 1 Outlook", attachment: `https://www.spc.noaa.gov/products/outlook/day1otlk_${issuanceTime}.png` },
6965
+ { target: "SPC Day 2 Outlook", attachment: `https://www.spc.noaa.gov/products/outlook/day2otlk.png` },
6966
+ { target: "SPC Day 3 Outlook", attachment: `https://www.spc.noaa.gov/products/outlook/day3otlk.png` },
6967
+ { target: "Mesoscale Discussion", attachment: `https://www.spc.noaa.gov/products/md/mcd${spcNumber}.png` },
6968
+ { target: "Tornado Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
6969
+ { target: "PDS Tornado Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
6970
+ { target: "Severe Thunderstorm Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
6971
+ { target: "PDS Severe Thunderstorm Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` }
6972
+ ];
6973
+ if (events.find((e) => e.target === event.properties.event)) {
6974
+ attachments.push({ name: `Image: Graphic`, link: events.find((e) => e.target === event.properties.event).attachment });
6975
+ }
6976
+ for (const location of locations) {
6977
+ if (dict_expressions.location.test(location)) {
6978
+ const lines = [`Northern`, `Southern`, `Eastern`, `Western`, `Inland`, `Costal`, `County`];
6979
+ const county = (_f = location == null ? void 0 : location.split(",")[0]) == null ? void 0 : _f.trim().replace(new RegExp(`^(${lines.join("|")}) `), "");
6980
+ const state = dict_states[(_g = location == null ? void 0 : location.split(",")[1]) == null ? void 0 : _g.trim()];
6981
+ const feeds = bootstrap.database.prepare(`SELECT * FROM broadcastify WHERE state = ? AND county = ?`).all(state, county).sort((a, b) => {
6982
+ const typeOrder = ["Other", "Public Safety"];
6983
+ const indexA = typeOrder.indexOf(a.type);
6984
+ const indexB = typeOrder.indexOf(b.type);
6985
+ return indexA - indexB;
6986
+ });
6987
+ const tags = bootstrap.settings.BroadcastifySettings.BroadcastifyTags;
6988
+ const filtered = feeds.filter((feed) => tags.includes(feed.type));
6989
+ if (filtered.length > 0) {
6990
+ filtered.map((filtered2) => {
6991
+ if (!attachments.some((a) => a.link === filtered2.link)) {
6992
+ attachments.push({ name: `${filtered2.type}: ${filtered2.feed}`, link: filtered2.link });
6993
+ }
6950
6994
  });
6951
6995
  }
6952
6996
  }
6953
6997
  }
6954
- validateEvents(processed);
6955
- });
6998
+ return attachments;
6999
+ };
6956
7000
 
6957
- // src/@events/events.api.ts
6958
- var api = (stanza) => __async(null, null, function* () {
6959
- 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;
6960
- let processed = [];
6961
- const messages = Object.values(JSON.parse(stanza.message).features);
6962
- for (const feature of messages) {
6963
- const tick = performance.now();
6964
- 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;
6965
- processed.push({
6966
- type: `Feature`,
6967
- geometry: {
6968
- type: `Point`,
6969
- coordinates: []
6970
- },
6971
- properties: {
6972
- event: (_f = (_e = feature == null ? void 0 : feature.properties) == null ? void 0 : _e.event) != null ? _f : null,
6973
- parent: (_h = (_g = feature == null ? void 0 : feature.properties) == null ? void 0 : _g.event) != null ? _h : null,
6974
- status: (_j = (_i = feature == null ? void 0 : feature.properties) == null ? void 0 : _i.messageType) != null ? _j : null,
6975
- 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,
6976
- 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,
6977
- locations: (_p = (_o = feature == null ? void 0 : feature.properties) == null ? void 0 : _o.areaDesc) != null ? _p : null,
6978
- 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(";") : [],
6979
- description: (_t = (_s = feature == null ? void 0 : feature.properties) == null ? void 0 : _s.description) != null ? _t : null,
6980
- attributes: (_v = (_u = feature == null ? void 0 : feature.properties) == null ? void 0 : _u.attributes) != null ? _v : {},
6981
- geocode: {
6982
- office: {
6983
- office: pVtec ? (_w = pVtec == null ? void 0 : pVtec[0]) == null ? void 0 : _w.tracking.split(`.`)[0] : null,
6984
- name: (_y = dict_icao[pVtec ? (_x = pVtec == null ? void 0 : pVtec[0]) == null ? void 0 : _x.tracking.split(`.`)[0] : null]) != null ? _y : null
6985
- },
6986
- 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],
6987
- ugc: (_E = (_D = (_C = feature == null ? void 0 : feature.properties) == null ? void 0 : _C.geocode) == null ? void 0 : _D.UGC) != null ? _E : [],
6988
- 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,
6989
- polygon_generated: ((_H = feature == null ? void 0 : feature.geometry) == null ? void 0 : _H.coordinates.length) > 0 ? true : false
6990
- },
6991
- parameters: {
6992
- tags: getEventTags((_I = feature == null ? void 0 : feature.properties) == null ? void 0 : _I.description),
6993
- instructions: (_K = (_J = feature == null ? void 0 : feature.properties) == null ? void 0 : _J.instruction) != null ? _K : null,
6994
- source: (_M = getTextFromProduct({ message: (_L = feature == null ? void 0 : feature.properties) == null ? void 0 : _L.description, find: [`SOURCE...`], removal: [`.`] })) != null ? _M : null,
6995
- hazards: (_O = getTextFromProduct({ message: (_N = feature == null ? void 0 : feature.properties) == null ? void 0 : _N.description, find: [`HAZARD...`], removal: [`.`] })) != null ? _O : null,
6996
- impacts: (_Q = getTextFromProduct({ message: (_P = feature == null ? void 0 : feature.properties) == null ? void 0 : _P.description, find: [`IMPACT...`], removal: [`.`] })) != null ? _Q : null,
6997
- 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,
6998
- 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,
6999
- 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,
7000
- 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,
7001
- 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,
7002
- 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,
7003
- 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
7004
- },
7005
- discussion_parameters: {
7006
- 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,
7007
- discussion_concerning: (_wa = getTextFromProduct({ message: (_va = feature == null ? void 0 : feature.properties) == null ? void 0 : _va.description, find: [`Concerning...`] })) != null ? _wa : null,
7008
- 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,
7009
- 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,
7010
- 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,
7011
- 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
7012
- },
7013
- watch_parameters: {
7014
- 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),
7015
- 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,
7016
- 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,
7017
- 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,
7018
- 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,
7019
- 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,
7020
- 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,
7021
- 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,
7022
- 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,
7023
- 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,
7024
- 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,
7025
- pds_watch: getTextFromProduct({ message: (_jb = feature == null ? void 0 : feature.properties) == null ? void 0 : _jb.description, find: [`PARTICULARLY DANGEROUS SITUATION`], removal: [`%`, `<`, `:`] }) === `YES`
7026
- },
7027
- metadata: {
7028
- ms: performance.now() - tick,
7029
- source: `events.api`,
7030
- 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] }),
7031
- header: `ZCZC-ATMOSX-${(_ob = (_nb = feature == null ? void 0 : feature.properties) == null ? void 0 : _nb.parameters) == null ? void 0 : _ob.WMOidentifier}`,
7032
- vtec: pVtec == null ? void 0 : pVtec[0],
7033
- hvtec: null,
7034
- raw: (_pb = feature == null ? void 0 : feature.properties) == null ? void 0 : _pb.description,
7035
- history: [
7036
- {
7037
- description: (_qb = feature == null ? void 0 : feature.properties) == null ? void 0 : _qb.description,
7038
- 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,
7039
- status: (_ub = (_tb = feature == null ? void 0 : feature.properties) == null ? void 0 : _tb.messageType) != null ? _ub : null
7040
- }
7041
- ]
7042
- }
7001
+ // src/@building/building.validate.ts
7002
+ var import_crypto = require("crypto");
7003
+ var validateEvents = (events) => __async(null, null, function* () {
7004
+ var _a;
7005
+ const tick = performance.now();
7006
+ if (events.length === 0) return;
7007
+ const configurations = bootstrap.settings;
7008
+ const sets = {};
7009
+ const bools = {};
7010
+ const megered = __spreadValues(__spreadValues({}, configurations.GlobalSettings), configurations.GlobalSettings.EventFiltering);
7011
+ for (const key in megered) {
7012
+ const setting = megered[key];
7013
+ if (Array.isArray(setting)) {
7014
+ sets[key] = new Set(setting.map((item) => item.toLowerCase()));
7015
+ }
7016
+ if (typeof setting === "boolean") {
7017
+ bools[key] = setting;
7018
+ }
7019
+ }
7020
+ const filterd = events.filter((event) => {
7021
+ var _a2, _b, _c, _d, _e;
7022
+ bootstrap.cache.processed = bootstrap.cache.processed.filter((e) => e !== event);
7023
+ const define2 = getEventSignature(event);
7024
+ const properties2 = define2.properties;
7025
+ const zones = properties2.geocode.ugc;
7026
+ const icao = properties2.geocode.office.office;
7027
+ const enhancedEventName = properties2.event = getEventEnhancedName(event);
7028
+ const filteredProperties = JSON.parse(JSON.stringify(properties2));
7029
+ if ((filteredProperties == null ? void 0 : filteredProperties.metadata) && "ms" in filteredProperties.metadata) {
7030
+ delete filteredProperties.metadata.ms;
7031
+ }
7032
+ filteredProperties.metadata = (_a2 = filteredProperties.metadata) != null ? _a2 : {};
7033
+ properties2.metadata.hash = (0, import_crypto.createHash)("sha256").update(JSON.stringify(filteredProperties)).digest("hex");
7034
+ properties2.metadata.attachments = getEventAttachments(event);
7035
+ setEventEmit({ event: `onProductType${enhancedEventName.replace(/\s+/g, "")}`, metadata: define2 });
7036
+ if (properties2.status_metadata.is_test) {
7037
+ setEventEmit({ event: `onTestProduct`, metadata: define2 });
7038
+ if (bools == null ? void 0 : bools.IgnoreTestProducts) return false;
7039
+ }
7040
+ if (properties2.status_metadata.is_expired) {
7041
+ setEventEmit({ event: `onExpiredProduct`, metadata: define2 });
7042
+ rmEvent(define2);
7043
+ return false;
7044
+ }
7045
+ if (((_c = (_b = properties2.metadata) == null ? void 0 : _b.vtec) == null ? void 0 : _c.is_watch) && properties2.metadata.source != `events.api`) {
7046
+ const isSPC = (_e = (_d = properties2.metadata) == null ? void 0 : _d.vtec) == null ? void 0 : _e.prediction_center;
7047
+ setEventEmit({ event: isSPC ? `onStormPredictionWatch` : `onNonStormPredictionWatch`, metadata: define2 });
7048
+ if ((bools == null ? void 0 : bools.SPCWatchesOnly) && !isSPC) {
7049
+ return false;
7043
7050
  }
7044
- });
7051
+ if (!(bools == null ? void 0 : bools.SPCWatchesOnly) && isSPC) {
7052
+ return false;
7053
+ }
7054
+ }
7055
+ for (const key in sets) {
7056
+ const setting = sets[key];
7057
+ const values = [...setting];
7058
+ if (key === "ListeningEvents" && setting.size > 0 && !getMatched(values, define2.properties.event)) {
7059
+ setEventEmit({
7060
+ event: `onFilteredEvent`,
7061
+ metadata: define2
7062
+ });
7063
+ return false;
7064
+ }
7065
+ if (key === "IgnoredEvents" && setting.size > 0 && getMatched(values, define2.properties.event)) {
7066
+ setEventEmit({
7067
+ event: `onIgnoredEvent`,
7068
+ metadata: define2
7069
+ });
7070
+ return false;
7071
+ }
7072
+ if (key === "ListeningICAO" && setting.size > 0 && icao != null && !setting.has(icao.toLowerCase())) {
7073
+ setEventEmit({
7074
+ event: `onFilteredICAO`,
7075
+ metadata: define2
7076
+ });
7077
+ return false;
7078
+ }
7079
+ if (key === "IgnoredICAO" && setting.size > 0 && icao != null && setting.has(icao.toLowerCase())) {
7080
+ setEventEmit({
7081
+ event: `onIgnoredICAO`,
7082
+ metadata: define2
7083
+ });
7084
+ return false;
7085
+ }
7086
+ if (key === "ListeningUGC" && setting.size > 0 && zones.length > 0 && !zones.some((ugc2) => setting.has(ugc2.toLowerCase()))) {
7087
+ setEventEmit({
7088
+ event: `onFilteredUGC`,
7089
+ metadata: define2
7090
+ });
7091
+ return false;
7092
+ }
7093
+ if (key === "ListeningStates" && setting.size > 0 && zones.length > 0 && !zones.some((ugc2) => setting.has(ugc2.substring(0, 2).toLowerCase()))) {
7094
+ setEventEmit({
7095
+ event: `onFilteredState`,
7096
+ metadata: define2
7097
+ });
7098
+ return false;
7099
+ }
7100
+ }
7101
+ return true;
7102
+ });
7103
+ if (!((_a = configurations == null ? void 0 : configurations.GlobalSettings) == null ? void 0 : _a.DisableGeometryParsing)) {
7104
+ for (const event of filterd) {
7105
+ event.geometry = yield getEventGeometry(event);
7106
+ }
7107
+ }
7108
+ if (filterd.length > 0) {
7109
+ for (const event of filterd) {
7110
+ yield mkEvent(event);
7111
+ }
7045
7112
  }
7046
- validateEvents(processed);
7113
+ yield updateNode();
7114
+ setEventEmit({
7115
+ event: `onEventCache`,
7116
+ metadata: bootstrap.cache.events,
7117
+ limited: true
7118
+ });
7119
+ setDebug({ title: `@building.validate`, message: `Filtered ${filterd.length} events which took ${performance.now() - tick} ms` });
7047
7120
  });
7048
7121
 
7049
7122
  // src/@building/building.create.ts
7050
- var createEvent = (stanza) => __async(null, null, function* () {
7123
+ var createEvent = (stanza, ignorePushing) => __async(null, null, function* () {
7051
7124
  const settings = bootstrap.settings;
7052
7125
  const StanzaSettings = settings.NOAAWeatherWireServiceSettings.StanzaSettings;
7053
7126
  const isVtecEvent = stanza.isVTEC && stanza.isUGC;
7054
7127
  const isUgcEvent = !stanza.isVTEC && stanza.isUGC;
7055
7128
  const isTextEvent = !stanza.isVTEC && !stanza.isUGC;
7056
7129
  const isNWWS = stanza.isNWWS;
7057
- if (!isNWWS) return yield api(stanza);
7058
- if (!StanzaSettings.DisableVTEC && isVtecEvent) return yield vtec(stanza);
7059
- if (!StanzaSettings.DisableUGC && isUgcEvent) return yield ugc(stanza);
7060
- if (!StanzaSettings.DisableText && isTextEvent) return yield text(stanza);
7130
+ switch (true) {
7131
+ case !isNWWS:
7132
+ yield api(stanza);
7133
+ break;
7134
+ case (isNWWS && !StanzaSettings.DisableVTEC && isVtecEvent):
7135
+ yield vtec(stanza);
7136
+ break;
7137
+ case (isNWWS && !StanzaSettings.DisableUGC && isUgcEvent):
7138
+ yield ugc(stanza);
7139
+ break;
7140
+ case (isNWWS && !StanzaSettings.DisableText && isTextEvent):
7141
+ yield text(stanza);
7142
+ break;
7143
+ }
7144
+ if (!ignorePushing) {
7145
+ validateEvents(bootstrap.cache.processed);
7146
+ }
7061
7147
  return "nothing picked";
7062
7148
  });
7063
7149
 
@@ -7153,25 +7239,6 @@ var xDeploy = () => __async(null, null, function* () {
7153
7239
  }
7154
7240
  });
7155
7241
 
7156
- // src/@modules/@database/database.init.ts
7157
- var import_fs5 = __toESM(require("fs"));
7158
- var import_better_sqlite3 = __toESM(require("better-sqlite3"));
7159
-
7160
- // src/@modules/@database/database.shapefiles.ts
7161
- var import_fs4 = __toESM(require("fs"));
7162
- var import_path3 = require("path");
7163
- var import_jszip = require("jszip");
7164
- var import_shapefile = require("shapefile");
7165
-
7166
- // src/@modules/@utilities/utilities.setSleep.ts
7167
- var setSleep = (options) => __async(null, null, function* () {
7168
- return new Promise((resolve6) => {
7169
- setTimeout(() => {
7170
- resolve6();
7171
- }, options.timeout);
7172
- });
7173
- });
7174
-
7175
7242
  // src/@dictionaries/dictionaries.shapefiles.ts
7176
7243
  var dict_shapefiles = [
7177
7244
  { name: "us_counties", id: "C", link: "https://www.weather.gov/source/gis/Shapefiles/County/c_16ap26.zip" },
@@ -7185,7 +7252,20 @@ var dict_shapefiles = [
7185
7252
  { name: "high_seas_marine_zones", id: "Z", link: "https://www.weather.gov/source/gis/Shapefiles/WSOM/hz17fe26.zip" }
7186
7253
  ];
7187
7254
 
7255
+ // src/@modules/@utilities/utilities.setSleep.ts
7256
+ var setSleep = (options) => __async(null, null, function* () {
7257
+ return new Promise((resolve6) => {
7258
+ setTimeout(() => {
7259
+ resolve6();
7260
+ }, options.timeout);
7261
+ });
7262
+ });
7263
+
7188
7264
  // src/@modules/@database/database.shapefiles.ts
7265
+ var import_fs4 = require("fs");
7266
+ var import_path3 = require("path");
7267
+ var import_jszip = require("jszip");
7268
+ var import_shapefile = require("shapefile");
7189
7269
  var importShapefiles = () => __async(null, null, function* () {
7190
7270
  var _a, _b;
7191
7271
  const settings = bootstrap.settings;
@@ -7198,14 +7278,14 @@ var importShapefiles = () => __async(null, null, function* () {
7198
7278
  const arrayBuff = yield response2.arrayBuffer();
7199
7279
  const content = yield (0, import_jszip.loadAsync)(arrayBuff);
7200
7280
  const directory = (0, import_path3.resolve)(__dirname, `../../shapefiles`);
7201
- if (!import_fs4.default.existsSync(directory)) {
7202
- import_fs4.default.mkdirSync(directory, { recursive: true });
7281
+ if (!(0, import_fs4.existsSync)(directory)) {
7282
+ (0, import_fs4.mkdirSync)(directory, { recursive: true });
7203
7283
  }
7204
7284
  for (const file of Object.keys(content.files)) {
7205
7285
  if (file.endsWith(".shp") || file.endsWith(".dbf")) {
7206
7286
  const data = yield content.files[file].async(`nodebuffer`);
7207
7287
  const output = (0, import_path3.resolve)(directory, `${(_a = shapefile == null ? void 0 : shapefile.name) != null ? _a : ``}_${(_b = shapefile == null ? void 0 : shapefile.id) != null ? _b : ``}${(0, import_path3.extname)(file)}`);
7208
- import_fs4.default.writeFileSync(output, data);
7288
+ (0, import_fs4.writeFileSync)(output, data);
7209
7289
  }
7210
7290
  }
7211
7291
  const filepath = (0, import_path3.resolve)(__dirname, "../../shapefiles", shapefile.name + "_" + shapefile.id);
@@ -7236,11 +7316,11 @@ var importShapefiles = () => __async(null, null, function* () {
7236
7316
  insert.run(final2, location, JSON.stringify(geometry));
7237
7317
  }
7238
7318
  });
7239
- import_fs4.default.unlinkSync(`${filepath}.shp`);
7240
- import_fs4.default.unlinkSync(`${filepath}.dbf`);
7319
+ (0, import_fs4.unlinkSync)(`${filepath}.shp`);
7320
+ (0, import_fs4.unlinkSync)(`${filepath}.dbf`);
7241
7321
  transaction(features);
7242
7322
  }
7243
- import_fs4.default.rm((0, import_path3.resolve)(__dirname, "../../shapefiles"), { recursive: true, force: true }, () => {
7323
+ (0, import_fs4.rm)((0, import_path3.resolve)(__dirname, "../../shapefiles"), { recursive: true, force: true }, () => {
7244
7324
  });
7245
7325
  }
7246
7326
  } catch (error) {
@@ -7292,11 +7372,13 @@ var importBroadcastify = () => __async(null, null, function* () {
7292
7372
  });
7293
7373
 
7294
7374
  // src/@modules/@database/database.init.ts
7375
+ var import_fs5 = require("fs");
7376
+ var import_better_sqlite3 = __toESM(require("better-sqlite3"));
7295
7377
  var initializeDatabase = () => __async(null, null, function* () {
7296
7378
  const settings = bootstrap.settings;
7297
7379
  try {
7298
- if (!import_fs5.default.existsSync(settings.Database)) {
7299
- import_fs5.default.writeFileSync(settings.Database, "");
7380
+ if (!(0, import_fs5.existsSync)(settings.Database)) {
7381
+ (0, import_fs5.writeFileSync)(settings.Database, "");
7300
7382
  setWarning({ message: `Creating new database at ${settings.Database}` });
7301
7383
  }
7302
7384
  bootstrap.database = new import_better_sqlite3.default(settings.Database);
@@ -7324,7 +7406,7 @@ var getCachedEvents = () => __async(null, null, function* () {
7324
7406
  if (settings.NOAAWeatherWireServiceSettings.CacheSettings.Enabled) {
7325
7407
  const max = (_a = settings.NOAAWeatherWireServiceSettings.CacheSettings.MaxRetentionHistory) != null ? _a : 500;
7326
7408
  const get = yield bootstrap.database.prepare(`SELECT * FROM stanzas ORDER BY rowid DESC LIMIT ?`).all(max);
7327
- setWarning({ message: `Fetched ${get.length} cached events from the database in ${Math.floor(performance.now() - tick)} ms` });
7409
+ setWarning({ message: `Fetched ${get.length} cached stanzas from the database in ${Math.floor(performance.now() - tick)} ms` });
7328
7410
  let events = get.map((row) => JSON.parse(row.stanza)).filter((stanza) => {
7329
7411
  if (!stanza) {
7330
7412
  return;
@@ -7333,11 +7415,12 @@ var getCachedEvents = () => __async(null, null, function* () {
7333
7415
  return !isSkippable;
7334
7416
  });
7335
7417
  events = events.sort((a, b) => b.issued - a.issued);
7336
- yield Promise.all(events.map((event) => createEvent(event)));
7337
- setWarning({ message: `Processed ${events.length} cached events in ${Math.floor(performance.now() - tick)} ms` });
7418
+ yield Promise.all(events.map((event) => createEvent(event, true)));
7419
+ setWarning({ message: `Processed ${events.length} cached stanzas in ${Math.floor(performance.now() - tick)} ms` });
7420
+ validateEvents(bootstrap.cache.processed);
7338
7421
  }
7339
7422
  } catch (error) {
7340
- setWarning({ message: `An error occurred while fetching cached events: ${error.message} -> ${error.stack}` });
7423
+ setWarning({ message: `An error occurred while fetching cached stanzas: ${error.message} -> ${error.stack}` });
7341
7424
  }
7342
7425
  });
7343
7426
 
@@ -7457,7 +7540,7 @@ var updateEvents = (selectedEvent) => __async(null, null, function* () {
7457
7540
  function update(evt) {
7458
7541
  return __async(this, null, function* () {
7459
7542
  if (new Date(evt.properties.expires) < /* @__PURE__ */ new Date()) {
7460
- rmEvent(evt);
7543
+ yield rmEvent(evt);
7461
7544
  }
7462
7545
  });
7463
7546
  }