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