@atmosx/event-product-parser 3.0.41 → 3.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/dist/cjs/index.cjs +1791 -1646
- package/dist/esm/index.mjs +1026 -882
- package/dist/index.d.mts +34 -3
- package/dist/index.d.ts +34 -3
- package/package.json +1 -1
- package/src/@building/building.create.ts +2 -2
- package/src/@building/building.enhance.ts +1 -1
- package/src/@building/building.geometry.ts +1 -1
- package/src/@building/building.headers.ts +1 -1
- package/src/@building/building.office.ts +3 -3
- package/src/@building/building.outlooks.ts +36 -0
- package/src/@building/building.properties.ts +11 -5
- package/src/@building/building.tracking.ts +7 -7
- package/src/@building/building.validate.ts +4 -2
- package/src/@core/core.query.ts +39 -0
- package/src/@core/core.setNode.ts +2 -2
- package/src/@core/core.start.ts +1 -1
- package/src/@events/events.api.ts +4 -1
- package/src/@events/events.text.ts +3 -2
- package/src/@events/events.ugc.ts +3 -2
- package/src/@events/events.vtec.ts +5 -4
- package/src/@manager/manager.createWebhook.ts +93 -81
- package/src/@manager/manager.mkEvent.ts +3 -2
- package/src/@manager/manager.setHash.ts +1 -1
- package/src/@manager/manager.updateWebhooks.ts +1 -2
- package/src/@modules/@database/database.cache.ts +1 -1
- package/src/@modules/@database/database.init.ts +1 -1
- package/src/@modules/@database/database.shapefiles.ts +1 -1
- package/src/@modules/@database/database.stanza.ts +2 -2
- package/src/@modules/@eas/eas.getCleanDescription.ts +89 -0
- package/src/@modules/@eas/eas.getTTS.ts +43 -0
- package/src/@modules/@eas/eas.setEasTone.ts +29 -24
- package/src/@modules/@stanza/stanza.getAwipsType.ts +1 -1
- package/src/@modules/@stanza/stanza.validate.ts +2 -2
- package/src/@modules/@utilities/utilities.getLatestIssuance.ts +32 -0
- package/src/@modules/@utilities/utilities.getSettings.ts +1 -1
- package/src/@modules/@utilities/utilities.isImageReady.ts +27 -0
- package/src/@modules/@utilities/utilities.setCronSchedule.ts +28 -2
- package/src/@modules/@utilities/utilities.setSettings.ts +1 -1
- package/src/@modules/@utilities/utilities.setWarning.ts +1 -1
- package/src/@modules/@xmpp/xmpp.xDeploy.ts +1 -1
- package/src/@modules/@xmpp/xmpp.xReconnect.ts +1 -1
- package/src/@modules/@xmpp/xmpp.xStanza.ts +1 -1
- package/src/@parsers/@hvtec/hvtec.extract.ts +1 -1
- package/src/@parsers/@pvtec/pvtec.extract.ts +1 -1
- package/src/@parsers/@ugc/ugc.extract.ts +1 -1
- package/src/@types/{types.compiled.ts → type.compiled.ts} +1 -1
- package/src/@types/type.event.ts +4 -2
- package/src/@types/type.properties.ts +3 -1
- package/src/@types/{types.settings.ts → type.settings.ts} +3 -2
- package/src/@types/{types.webhook.ts → type.webhook.ts} +1 -0
- package/src/bootstrap.ts +2 -1
- package/src/index.ts +3 -2
- package/src/@dictionaries/dictionaries.transcribedMessageReplacements.ts +0 -68
- /package/src/@types/{types.attributes.ts → type.attributes.ts} +0 -0
- /package/src/@types/{types.hash.ts → type.hash.ts} +0 -0
- /package/src/@types/{types.hvtec.ts → type.hvtec.ts} +0 -0
- /package/src/@types/{types.pvtec.ts → type.pvtec.ts} +0 -0
- /package/src/@types/{types.stanza.ts → type.stanza.ts} +0 -0
- /package/src/@types/{types.ugc.ts → type.ugc.ts} +0 -0
package/dist/esm/index.mjs
CHANGED
|
@@ -10491,7 +10491,7 @@ var require_form_data = __commonJS({
|
|
|
10491
10491
|
import path from "path";
|
|
10492
10492
|
import { EventEmitter } from "events";
|
|
10493
10493
|
var bootstrap = {
|
|
10494
|
-
version: `3.0.
|
|
10494
|
+
version: `3.0.44`,
|
|
10495
10495
|
isReady: true,
|
|
10496
10496
|
ratelimits: {},
|
|
10497
10497
|
session_xmpp: null,
|
|
@@ -10568,6 +10568,7 @@ var bootstrap = {
|
|
|
10568
10568
|
IgnoreTestProducts: true
|
|
10569
10569
|
},
|
|
10570
10570
|
EASSettings: {
|
|
10571
|
+
ArchiveTTL: 60,
|
|
10571
10572
|
ArchiveDirectory: null,
|
|
10572
10573
|
IntroWavFile: null
|
|
10573
10574
|
}
|
|
@@ -14304,7 +14305,7 @@ var officeICAOs = {
|
|
|
14304
14305
|
// src/@building/building.office.ts
|
|
14305
14306
|
var getEventOffice = (options) => {
|
|
14306
14307
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
14307
|
-
const office = options.pVtec != null ? (_b = (_a = options.pVtec) == null ? void 0 : _a.tracking) == null ? void 0 : _b.split(
|
|
14308
|
+
const office = options.pVtec != null ? (_b = (_a = options.pVtec) == null ? void 0 : _a.tracking) == null ? void 0 : _b.split(`.`)[0] : (_e = (_c = options.attributes) == null ? void 0 : _c.cccc) != null ? _e : options.organization != null ? Array.isArray(options.organization) ? (_d = options.organization) == null ? void 0 : _d[0] : options.organization : null;
|
|
14308
14309
|
const name = (_g = (_f = officeICAOs) == null ? void 0 : _f[office]) != null ? _g : null;
|
|
14309
14310
|
return { office, name };
|
|
14310
14311
|
};
|
|
@@ -14392,10 +14393,10 @@ var getEventTags = (message) => {
|
|
|
14392
14393
|
|
|
14393
14394
|
// src/@building/building.properties.ts
|
|
14394
14395
|
var properties = (options) => {
|
|
14395
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J;
|
|
14396
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L;
|
|
14396
14397
|
const organization = (_b = (_a = options.message.match(regExp.wmo)) == null ? void 0 : _a[0]) != null ? _b : null;
|
|
14397
14398
|
const polygons = getPolygonFromProduct(options.message);
|
|
14398
|
-
|
|
14399
|
+
const properties2 = {
|
|
14399
14400
|
locations: (_e = (_d = (_c = options == null ? void 0 : options.ugc) == null ? void 0 : _c.locations) == null ? void 0 : _d.join(`; `)) != null ? _e : null,
|
|
14400
14401
|
description: getDescriptionFromProduct({ message: options.message, handle: (_g = (_f = options == null ? void 0 : options.pVtec) == null ? void 0 : _f.vtec) != null ? _g : null }),
|
|
14401
14402
|
attributes: options.attributes,
|
|
@@ -14421,26 +14422,32 @@ var properties = (options) => {
|
|
|
14421
14422
|
hail_threat: (_t = getTextFromProduct({ message: options.message, find: [`HAIL THREAT...`], removal: [] })) != null ? _t : null
|
|
14422
14423
|
},
|
|
14423
14424
|
spc_parameters: {
|
|
14424
|
-
|
|
14425
|
-
|
|
14426
|
-
|
|
14427
|
-
|
|
14425
|
+
spc_number: (_u = getTextFromProduct({ message: options.message, find: [`Mesoscale Discussion `], removal: [`Mesoscale Discussion`, `Number`, `...`] })) != null ? _u : null,
|
|
14426
|
+
spc_concerning: (_v = getTextFromProduct({ message: options.message, find: [`Concerning...`] })) != null ? _v : null,
|
|
14427
|
+
spc_max_tornado: (_w = getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK TORNADO INTENSITY...`] })) != null ? _w : null,
|
|
14428
|
+
spc_max_hail: (_x = getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK HAIL SIZE...`] })) != null ? _x : null,
|
|
14429
|
+
spc_max_wind: (_y = getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK WIND GUST...`] })) != null ? _y : null,
|
|
14430
|
+
spc_watch_issuance: (_z = getTextFromProduct({ message: options.message, find: [`Probability of Watch Issuance...`], removal: [`percent`] })) != null ? _z : null
|
|
14428
14431
|
},
|
|
14429
14432
|
watch_parameters: {
|
|
14430
|
-
watch_number: (
|
|
14433
|
+
watch_number: (_C = (_B = (_A = getTextFromProduct({ message: options.message, find: [`ITIES FOR`, `UPDATE FOR`, `Watch Number `], removal: [`%`, `<`, `:`] })) == null ? void 0 : _A.replace(/(WT|WS|)/g, "")) == null ? void 0 : _B.trim()) != null ? _C : null,
|
|
14431
14434
|
watch_type: options.message.includes(`TORNADO WATCH`) ? `Tornado` : (options == null ? void 0 : options.message.includes(`SEVERE`)) ? `Severe` : null,
|
|
14432
|
-
additional_tornadoes_probability: (
|
|
14433
|
-
strong_tornadoes_probability: (
|
|
14434
|
-
severe_wind_probability: (
|
|
14435
|
-
severe_hail_probability: (
|
|
14436
|
-
hail_2in_probability: (
|
|
14437
|
-
combined_hail_wind_probability: (
|
|
14438
|
-
max_hail_in: (
|
|
14439
|
-
max_wind_surface: (
|
|
14440
|
-
max_tops_x100feet: (
|
|
14435
|
+
additional_tornadoes_probability: (_D = getTextFromProduct({ message: options.message, find: [`PROB OF 2 OR MORE TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _D : null,
|
|
14436
|
+
strong_tornadoes_probability: (_E = getTextFromProduct({ message: options.message, find: [`PROB OF 1 OR MORE STRONG /EF2-EF5/ TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _E : null,
|
|
14437
|
+
severe_wind_probability: (_F = getTextFromProduct({ message: options.message, find: [`PROB OF 10 OR MORE SEVERE WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _F : null,
|
|
14438
|
+
severe_hail_probability: (_G = getTextFromProduct({ message: options.message, find: [`PROB OF 10 OR MORE SEVERE HAIL EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _G : null,
|
|
14439
|
+
hail_2in_probability: (_H = getTextFromProduct({ message: options.message, find: [`PROB OF 1 OR MORE HAIL EVENTS >= 2 INCHES`], removal: [`%`, `<`, `:`] })) != null ? _H : null,
|
|
14440
|
+
combined_hail_wind_probability: (_I = getTextFromProduct({ message: options.message, find: [`PROB OF 6 OR MORE COMBINED SEVERE HAIL/WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _I : null,
|
|
14441
|
+
max_hail_in: (_J = getTextFromProduct({ message: options.message, find: [`MAX HAIL /INCHES/`], removal: [`%`, `<`, `:`] })) != null ? _J : null,
|
|
14442
|
+
max_wind_surface: (_K = getTextFromProduct({ message: options.message, find: [`MAX WIND GUSTS SURFACE /KNOTS/`], removal: [`%`, `<`, `:`] })) != null ? _K : null,
|
|
14443
|
+
max_tops_x100feet: (_L = getTextFromProduct({ message: options.message, find: [`MAX TOPS /X 100 FEET/`], removal: [`%`, `<`, `:`] })) != null ? _L : null,
|
|
14441
14444
|
pds_watch: getTextFromProduct({ message: options.message, find: [`PARTICULARLY DANGEROUS SITUATION`], removal: [`%`, `<`, `:`] }) === `YES`
|
|
14442
14445
|
}
|
|
14443
14446
|
};
|
|
14447
|
+
if (isNaN(Number(properties2.watch_parameters.watch_number))) {
|
|
14448
|
+
properties2.watch_parameters.watch_number = null;
|
|
14449
|
+
}
|
|
14450
|
+
return properties2;
|
|
14444
14451
|
};
|
|
14445
14452
|
|
|
14446
14453
|
// src/@building/building.headers.ts
|
|
@@ -14474,16 +14481,16 @@ var eventsMatchText = {
|
|
|
14474
14481
|
// src/@building/building.tracking.ts
|
|
14475
14482
|
var getEventTracking = (options) => {
|
|
14476
14483
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
14477
|
-
const
|
|
14484
|
+
const properties2 = options.properties;
|
|
14478
14485
|
const attributes = options.attributes;
|
|
14479
14486
|
const stanza = options.stanza;
|
|
14480
14487
|
const vtec2 = options.vtec;
|
|
14481
14488
|
if (options.type === `RAW`) {
|
|
14482
|
-
const getWatchNumber = (_a =
|
|
14489
|
+
const getWatchNumber = (_a = properties2.watch_parameters.watch_number) != null ? _a : null;
|
|
14483
14490
|
if (getWatchNumber) {
|
|
14484
|
-
return `${
|
|
14491
|
+
return `${properties2.geocode.office.office}.${stanza.getType.prefix}.A.${getWatchNumber}`;
|
|
14485
14492
|
}
|
|
14486
|
-
return `${
|
|
14493
|
+
return `${properties2.geocode.office.office}.${attributes.ttaaii}.${(_b = attributes.id.slice(-4).replace(`.`, ``)) != null ? _b : "0"}`;
|
|
14487
14494
|
}
|
|
14488
14495
|
if (options.type === `VTEC`) {
|
|
14489
14496
|
return vtec2.tracking;
|
|
@@ -14781,276 +14788,727 @@ var createHttp = (options) => __async(null, null, function* () {
|
|
|
14781
14788
|
});
|
|
14782
14789
|
});
|
|
14783
14790
|
|
|
14784
|
-
// src/@
|
|
14785
|
-
var
|
|
14786
|
-
|
|
14787
|
-
|
|
14788
|
-
|
|
14789
|
-
|
|
14790
|
-
|
|
14791
|
-
event.locations ? `**Locations**: ${event.locations.slice(0, 100)}` : null,
|
|
14792
|
-
event.issued ? `**Issued**: <t:${Math.floor(new Date(event.issued).getTime() / 1e3)}:R>` : null,
|
|
14793
|
-
event.expires && event.status != `Statement` ? `**Expires**: <t:${Math.floor(new Date(event.expires).getTime() / 1e3)}:R>` : null,
|
|
14794
|
-
(() => {
|
|
14795
|
-
var _a2, _b2;
|
|
14796
|
-
const val = (_a2 = event.parameters.estimated_wind_gusts) != null ? _a2 : null;
|
|
14797
|
-
const th = (_b2 = event.parameters.wind_threat) != null ? _b2 : null;
|
|
14798
|
-
const combined = [val, th].filter(Boolean).join(" ");
|
|
14799
|
-
return combined ? `**Wind Gusts**: ${val} ${th ? `(${th})` : ""}` : null;
|
|
14800
|
-
})(),
|
|
14801
|
-
(() => {
|
|
14802
|
-
var _a2, _b2;
|
|
14803
|
-
const val = (_a2 = event.parameters.estimated_hail_size) != null ? _a2 : null;
|
|
14804
|
-
const th = (_b2 = event.parameters.hail_threat) != null ? _b2 : null;
|
|
14805
|
-
return (val != null ? val : th) ? `**Hail Threat**: ${val} ${th ? `(${th})` : ""}` : null;
|
|
14806
|
-
})(),
|
|
14807
|
-
event.parameters.damage_threat ? `**Damage Threat**: ${event.parameters.damage_threat}` : null,
|
|
14808
|
-
event.parameters.flood_threat ? `**Flood Threat**: ${event.parameters.flood_threat}` : null,
|
|
14809
|
-
event.parameters.tornado_threat ? `**Tornado Threat**: ${event.parameters.tornado_threat}` : null,
|
|
14810
|
-
event.spc_parameters.spc_max_tornado ? `**Max Tornado Threat**: ${event.spc_parameters.spc_max_tornado}` : null,
|
|
14811
|
-
event.spc_parameters.spc_max_hail ? `**Max Hail Threat**: ${event.spc_parameters.spc_max_hail}` : null,
|
|
14812
|
-
event.spc_parameters.spc_max_wind ? `**Max Wind Threat**: ${event.spc_parameters.spc_max_wind}` : null,
|
|
14813
|
-
event.spc_parameters.spc_watch_issuance ? `**Watch Issuance**: ${event.spc_parameters.spc_watch_issuance}%` : null,
|
|
14814
|
-
event.watch_parameters.watch_number ? `**Watch Number**: ${event.watch_parameters.watch_number}` : null,
|
|
14815
|
-
event.watch_parameters.strong_tornadoes_probability ? `**Strong Tornadoes Probability**: ${event.watch_parameters.strong_tornadoes_probability}%` : null,
|
|
14816
|
-
event.watch_parameters.additional_tornadoes_probability ? `**Additional Tornadoes Probability**: ${event.watch_parameters.additional_tornadoes_probability}%` : null,
|
|
14817
|
-
event.watch_parameters.combined_hail_wind_probability ? `**Combined Hail/Wind Probability**: ${event.watch_parameters.combined_hail_wind_probability}%` : null,
|
|
14818
|
-
event.watch_parameters.severe_hail_probability ? `**Severe Hail Probability**: ${event.watch_parameters.severe_hail_probability}%` : null,
|
|
14819
|
-
event.watch_parameters.hail_2in_probability ? `**Hail \u22652in Probability**: ${event.watch_parameters.hail_2in_probability}%` : null,
|
|
14820
|
-
event.watch_parameters.max_hail_in ? `**Max Hail Inches**: ${event.watch_parameters.max_hail_in}` : null,
|
|
14821
|
-
event.watch_parameters.severe_wind_probability ? `**Severe Wind Probability**: ${event.watch_parameters.severe_wind_probability}%` : null,
|
|
14822
|
-
event.watch_parameters.max_wind_surface ? `**Max Surface Wind**: ${event.watch_parameters.max_wind_surface}` : null,
|
|
14823
|
-
event.watch_parameters.max_tops_x100feet ? `**Max Tops (x100 feet)**: ${event.watch_parameters.max_tops_x100feet}` : null,
|
|
14824
|
-
((_a = event.parameters.tags) == null ? void 0 : _a.length) > 0 ? `**Tags**: ${event.parameters.tags.join(", ")}` : null,
|
|
14825
|
-
(() => {
|
|
14826
|
-
var _a2, _b2, _c2, _d2, _e2, _f2;
|
|
14827
|
-
const val = (_c2 = (_b2 = (_a2 = event.geocode) == null ? void 0 : _a2.office) == null ? void 0 : _b2.name) != null ? _c2 : `N/A`;
|
|
14828
|
-
const th = (_f2 = (_e2 = (_d2 = event.geocode) == null ? void 0 : _d2.office) == null ? void 0 : _e2.office) != null ? _f2 : null;
|
|
14829
|
-
return (val != null ? val : th) ? `**Sender**: ${val} ${th ? `(${th})` : ""}` : null;
|
|
14830
|
-
})(),
|
|
14831
|
-
((_b = event.metadata) == null ? void 0 : _b.tracking) ? `**Tracking**: ${event.metadata.tracking}` : null,
|
|
14832
|
-
((_c = event.metadata.history) == null ? void 0 : _c.length) > 0 ? `**Updates**: ${event.metadata.history.length}` : null,
|
|
14833
|
-
(() => {
|
|
14834
|
-
var _a2;
|
|
14835
|
-
if (event.status == `expires`) {
|
|
14836
|
-
return null;
|
|
14837
|
-
}
|
|
14838
|
-
const desc = ((_a2 = event.description) != null ? _a2 : "").split("\n").map((l) => l.trim()).filter(Boolean).join("\n");
|
|
14839
|
-
return desc ? "```\n" + desc + "\n```" : null;
|
|
14840
|
-
})()
|
|
14841
|
-
].filter(Boolean).join("\n");
|
|
14842
|
-
const isLimited = setTimeoutAction({ identifier: options.webhook.webhook, interval: options.webhook.rate, max: options.webhook.rate, addTime: true });
|
|
14843
|
-
if (isLimited.limited) {
|
|
14844
|
-
return;
|
|
14845
|
-
}
|
|
14846
|
-
if (body.length > 1900) {
|
|
14847
|
-
body = body.substring(0, 1900) + "\n\n[Message truncated due to length]";
|
|
14848
|
-
const blocks = ((_d = body.match(/```/g)) != null ? _d : []).length;
|
|
14849
|
-
if (blocks % 2 !== 0) body += "```";
|
|
14850
|
-
}
|
|
14851
|
-
const form = new import_form_data.default();
|
|
14852
|
-
const embed = {
|
|
14853
|
-
title: `${event.event} (${event.status})`,
|
|
14854
|
-
description: body,
|
|
14855
|
-
color: 16711680,
|
|
14856
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14857
|
-
footer: { text: settings.title }
|
|
14858
|
-
};
|
|
14859
|
-
form.append("payload_json", JSON.stringify({
|
|
14860
|
-
username: (_e = settings.title) != null ? _e : "AtmosphericX",
|
|
14861
|
-
content: (_f = settings.message) != null ? _f : "",
|
|
14862
|
-
embeds: [embed]
|
|
14863
|
-
}));
|
|
14864
|
-
if (settings.upload) {
|
|
14865
|
-
form.append("file", Buffer.from(JSON.stringify(getCleanedEvent(event), null, 2)), {
|
|
14866
|
-
filename: `${event.event}_${event.status}_${event.metadata.tracking}.json`,
|
|
14867
|
-
contentType: "application/json"
|
|
14868
|
-
});
|
|
14869
|
-
}
|
|
14870
|
-
yield createHttp({
|
|
14871
|
-
url: settings.webhook,
|
|
14872
|
-
timeout: 2e3,
|
|
14873
|
-
method: `POST`,
|
|
14874
|
-
headers: form.getHeaders(),
|
|
14875
|
-
body: form
|
|
14876
|
-
});
|
|
14877
|
-
});
|
|
14878
|
-
|
|
14879
|
-
// src/@manager/manager.updateWebhooks.ts
|
|
14880
|
-
var updateWebhooks = (event) => __async(null, null, function* () {
|
|
14881
|
-
const settings = bootstrap.settings;
|
|
14882
|
-
const webhooks = settings.WebhookSettings;
|
|
14883
|
-
const eventName = event.properties.event;
|
|
14884
|
-
for (const socket of webhooks) {
|
|
14885
|
-
const events = socket.events;
|
|
14886
|
-
if (!events || events.length === 0) {
|
|
14887
|
-
yield createWebhook({ webhook: socket, event });
|
|
14888
|
-
continue;
|
|
14889
|
-
}
|
|
14890
|
-
const matched = events.some((pattern) => {
|
|
14891
|
-
if (!pattern) return false;
|
|
14892
|
-
if (pattern === "*" || pattern === eventName) return true;
|
|
14893
|
-
if (pattern.includes("*")) {
|
|
14894
|
-
const regex = "^" + pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$";
|
|
14895
|
-
return new RegExp(regex).test(eventName);
|
|
14896
|
-
}
|
|
14897
|
-
return false;
|
|
14898
|
-
});
|
|
14899
|
-
if (matched) {
|
|
14900
|
-
yield createWebhook({ webhook: socket, event });
|
|
14901
|
-
}
|
|
14791
|
+
// src/@modules/@utilities/utilities.isImageReady.ts
|
|
14792
|
+
var isImageReady = (url) => __async(null, null, function* () {
|
|
14793
|
+
try {
|
|
14794
|
+
const res = yield fetch(url, { method: "HEAD" });
|
|
14795
|
+
return res.ok;
|
|
14796
|
+
} catch (e) {
|
|
14797
|
+
return false;
|
|
14902
14798
|
}
|
|
14903
14799
|
});
|
|
14904
14800
|
|
|
14905
|
-
// src/@modules/@
|
|
14906
|
-
var
|
|
14907
|
-
if (
|
|
14908
|
-
return
|
|
14801
|
+
// src/@modules/@eas/eas.getWavPCM16.ts
|
|
14802
|
+
var getWavPCM16 = (buffer) => {
|
|
14803
|
+
if (buffer.toString("ascii", 0, 4) !== "RIFF" || buffer.toString("ascii", 8, 12) !== "WAVE") {
|
|
14804
|
+
return null;
|
|
14909
14805
|
}
|
|
14910
|
-
|
|
14911
|
-
|
|
14912
|
-
|
|
14913
|
-
|
|
14914
|
-
|
|
14915
|
-
|
|
14916
|
-
|
|
14917
|
-
|
|
14918
|
-
|
|
14919
|
-
if (
|
|
14920
|
-
|
|
14921
|
-
}
|
|
14922
|
-
return [];
|
|
14923
|
-
};
|
|
14924
|
-
const polys = normalize(coordinates);
|
|
14925
|
-
if (polys.length === 0) return { proximity: false, point: [0, 0], distance: null };
|
|
14926
|
-
const lon = point[0];
|
|
14927
|
-
const lat = point[1];
|
|
14928
|
-
const pointInRing = (pt, ring) => {
|
|
14929
|
-
let x = pt[0], y = pt[1];
|
|
14930
|
-
let inside = false;
|
|
14931
|
-
for (let i = 0, j2 = ring.length - 1; i < ring.length; j2 = i++) {
|
|
14932
|
-
const xi = ring[i][0], yi = ring[i][1];
|
|
14933
|
-
const xj = ring[j2][0], yj = ring[j2][1];
|
|
14934
|
-
const intersect = yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi + 0) + xi;
|
|
14935
|
-
if (intersect) inside = !inside;
|
|
14936
|
-
}
|
|
14937
|
-
return inside;
|
|
14938
|
-
};
|
|
14939
|
-
const toRadians = (deg) => deg * Math.PI / 180;
|
|
14940
|
-
const haversineMiles = (a, b) => {
|
|
14941
|
-
const R = 3958.8;
|
|
14942
|
-
const dLat = toRadians(b[1] - a[1]);
|
|
14943
|
-
const dLon = toRadians(b[0] - a[0]);
|
|
14944
|
-
const lat1 = toRadians(a[1]);
|
|
14945
|
-
const lat2 = toRadians(b[1]);
|
|
14946
|
-
const sinDLat = Math.sin(dLat / 2);
|
|
14947
|
-
const sinDLon = Math.sin(dLon / 2);
|
|
14948
|
-
const c = 2 * Math.asin(Math.sqrt(sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon));
|
|
14949
|
-
return R * c;
|
|
14950
|
-
};
|
|
14951
|
-
let minDistance = Infinity;
|
|
14952
|
-
let closestPoint = null;
|
|
14953
|
-
for (const poly of polys) {
|
|
14954
|
-
const outer = poly[0];
|
|
14955
|
-
const holes = poly.slice(1);
|
|
14956
|
-
if (pointInRing(point, outer)) {
|
|
14957
|
-
let inHole = false;
|
|
14958
|
-
for (const hole of holes) {
|
|
14959
|
-
if (pointInRing(point, hole)) {
|
|
14960
|
-
inHole = true;
|
|
14961
|
-
break;
|
|
14962
|
-
}
|
|
14963
|
-
}
|
|
14964
|
-
if (!inHole) {
|
|
14965
|
-
return { proximity: true, point, distance: 0 };
|
|
14966
|
-
}
|
|
14967
|
-
}
|
|
14968
|
-
for (const ring of poly) {
|
|
14969
|
-
for (let i = 0; i < ring.length - 1; i++) {
|
|
14970
|
-
const start = [ring[i][0], ring[i][1]];
|
|
14971
|
-
const end = [ring[i + 1][0], ring[i + 1][1]];
|
|
14972
|
-
const A = lon - start[0];
|
|
14973
|
-
const B = lat - start[1];
|
|
14974
|
-
const C = end[0] - start[0];
|
|
14975
|
-
const D = end[1] - start[1];
|
|
14976
|
-
const lenSq = C * C + D * D;
|
|
14977
|
-
const t = lenSq === 0 ? 0 : Math.max(0, Math.min(1, (A * C + B * D) / lenSq));
|
|
14978
|
-
const candidate = [start[0] + t * C, start[1] + t * D];
|
|
14979
|
-
const dist = haversineMiles([lon, lat], candidate);
|
|
14980
|
-
if (!isNaN(dist) && dist < minDistance) {
|
|
14981
|
-
minDistance = Number(dist.toFixed(3));
|
|
14982
|
-
closestPoint = candidate;
|
|
14983
|
-
}
|
|
14984
|
-
}
|
|
14985
|
-
}
|
|
14806
|
+
let fmt = null;
|
|
14807
|
+
let data = null;
|
|
14808
|
+
let i = 12;
|
|
14809
|
+
while (i + 8 <= buffer.length) {
|
|
14810
|
+
const id2 = buffer.toString("ascii", i, i + 4);
|
|
14811
|
+
const size = buffer.readUInt32LE(i + 4);
|
|
14812
|
+
const start = i + 8;
|
|
14813
|
+
const end = start + size;
|
|
14814
|
+
if (id2 === "fmt ") fmt = buffer.slice(start, end);
|
|
14815
|
+
if (id2 === "data") data = buffer.slice(start, end);
|
|
14816
|
+
i = end + size % 2;
|
|
14986
14817
|
}
|
|
14987
|
-
if (!
|
|
14988
|
-
|
|
14818
|
+
if (!fmt || !data) return null;
|
|
14819
|
+
const audioFormat = fmt.readUInt16LE(0);
|
|
14820
|
+
const channels = fmt.readUInt16LE(2);
|
|
14821
|
+
const sampleRate = fmt.readUInt32LE(4);
|
|
14822
|
+
const bitsPerSample = fmt.readUInt16LE(14);
|
|
14823
|
+
if (audioFormat !== 1 || bitsPerSample !== 16 || channels !== 1) {
|
|
14824
|
+
return null;
|
|
14989
14825
|
}
|
|
14990
|
-
const
|
|
14991
|
-
|
|
14992
|
-
const distanceMeters = Math.round(distanceKm * 1e3);
|
|
14993
|
-
return { proximity: distanceMiles === 0, point: closestPoint, distance: distanceMiles, distanceKm, distanceMeters };
|
|
14826
|
+
const samples = new Int16Array(data.buffer, data.byteOffset, data.length / 2);
|
|
14827
|
+
return { samples: new Int16Array(samples), sampleRate, channels, bitsPerSample };
|
|
14994
14828
|
};
|
|
14995
14829
|
|
|
14996
|
-
// src/@
|
|
14997
|
-
var
|
|
14998
|
-
|
|
14999
|
-
const
|
|
15000
|
-
const
|
|
15001
|
-
|
|
15002
|
-
|
|
14830
|
+
// src/@modules/@eas/eas.getSampledPCM16.ts
|
|
14831
|
+
var getSampledPCM16 = (int16, originalRate, targetRate) => {
|
|
14832
|
+
if (originalRate === targetRate) return int16;
|
|
14833
|
+
const ratio = targetRate / originalRate;
|
|
14834
|
+
const outLen = Math.max(1, Math.round(int16.length * ratio));
|
|
14835
|
+
const out = new Int16Array(outLen);
|
|
14836
|
+
for (let i = 0; i < outLen; i++) {
|
|
14837
|
+
const pos = i / ratio;
|
|
14838
|
+
const i0 = Math.floor(pos);
|
|
14839
|
+
const i1 = Math.min(i0 + 1, int16.length - 1);
|
|
14840
|
+
const frac = pos - i0;
|
|
14841
|
+
const v = int16[i0] * (1 - frac) + int16[i1] * frac;
|
|
14842
|
+
out[i] = Math.round(v);
|
|
15003
14843
|
}
|
|
15004
|
-
|
|
15005
|
-
|
|
15006
|
-
|
|
15007
|
-
|
|
15008
|
-
|
|
15009
|
-
|
|
15010
|
-
|
|
15011
|
-
|
|
15012
|
-
|
|
15013
|
-
|
|
15014
|
-
|
|
15015
|
-
|
|
15016
|
-
|
|
15017
|
-
|
|
15018
|
-
|
|
15019
|
-
|
|
15020
|
-
metadata.proximity = true;
|
|
15021
|
-
info.proximity = true;
|
|
15022
|
-
}
|
|
14844
|
+
return out;
|
|
14845
|
+
};
|
|
14846
|
+
|
|
14847
|
+
// src/@modules/@eas/eas.getPCMToFloat.ts
|
|
14848
|
+
var getPCMToFloat = (int16) => {
|
|
14849
|
+
const out = new Float32Array(int16.length);
|
|
14850
|
+
for (let i = 0; i < int16.length; i++) out[i] = int16[i] / 32768;
|
|
14851
|
+
return out;
|
|
14852
|
+
};
|
|
14853
|
+
|
|
14854
|
+
// src/@modules/@eas/eas.getFloatPCM16.ts
|
|
14855
|
+
var getFloatPCM16 = (float32) => {
|
|
14856
|
+
const out = new Int16Array(float32.length);
|
|
14857
|
+
for (let i = 0; i < float32.length; i++) {
|
|
14858
|
+
let v = Math.max(-1, Math.min(1, float32[i]));
|
|
14859
|
+
out[i] = Math.round(v * 32767);
|
|
15023
14860
|
}
|
|
15024
|
-
return
|
|
15025
|
-
|
|
15026
|
-
filtered: metadata.proximity,
|
|
15027
|
-
updated: Date.now()
|
|
15028
|
-
};
|
|
15029
|
-
});
|
|
14861
|
+
return out;
|
|
14862
|
+
};
|
|
15030
14863
|
|
|
15031
|
-
// src/@
|
|
15032
|
-
var
|
|
15033
|
-
const
|
|
15034
|
-
const
|
|
15035
|
-
|
|
15036
|
-
|
|
15037
|
-
|
|
15038
|
-
|
|
15039
|
-
|
|
15040
|
-
|
|
15041
|
-
|
|
15042
|
-
|
|
15043
|
-
|
|
15044
|
-
|
|
15045
|
-
total++;
|
|
15046
|
-
}
|
|
15047
|
-
evt.properties.metadata.nodes = node.nodes;
|
|
15048
|
-
evt.properties.metadata.filtered_proximity = node.filtered;
|
|
15049
|
-
evt.properties.metadata.updated = node.updated;
|
|
15050
|
-
});
|
|
14864
|
+
// src/@modules/@eas/eas.setRadioEffect.ts
|
|
14865
|
+
var setRadioEffect = (int16, sampleRate) => {
|
|
14866
|
+
const hpCut = 3555;
|
|
14867
|
+
const lpCut = 1600;
|
|
14868
|
+
const x = getPCMToFloat(int16);
|
|
14869
|
+
const dt = 1 / sampleRate;
|
|
14870
|
+
const rcHP = 1 / (2 * Math.PI * hpCut);
|
|
14871
|
+
const aHP = rcHP / (rcHP + dt);
|
|
14872
|
+
let yHP = 0, xPrev = 0;
|
|
14873
|
+
for (let i = 0; i < x.length; i++) {
|
|
14874
|
+
const xi = x[i];
|
|
14875
|
+
yHP = aHP * (yHP + xi - xPrev);
|
|
14876
|
+
xPrev = xi;
|
|
14877
|
+
x[i] = yHP;
|
|
15051
14878
|
}
|
|
15052
|
-
|
|
15053
|
-
|
|
14879
|
+
const rcLP = 1 / (2 * Math.PI * lpCut);
|
|
14880
|
+
const aLP = dt / (rcLP + dt);
|
|
14881
|
+
let yLP = 0;
|
|
14882
|
+
for (let i = 0; i < x.length; i++) {
|
|
14883
|
+
yLP = yLP + aLP * (x[i] - yLP);
|
|
14884
|
+
x[i] = yLP;
|
|
14885
|
+
}
|
|
14886
|
+
const compGain = 2;
|
|
14887
|
+
const norm = Math.tanh(compGain);
|
|
14888
|
+
for (let i = 0; i < x.length; i++) x[i] = Math.tanh(x[i] * compGain) / norm;
|
|
14889
|
+
return getFloatPCM16(x);
|
|
14890
|
+
};
|
|
14891
|
+
|
|
14892
|
+
// src/@modules/@eas/eas.setAFSK.ts
|
|
14893
|
+
var setAFSK = (bits, sampleRate) => {
|
|
14894
|
+
const baud = 520.83;
|
|
14895
|
+
const markFreq = 2083.3;
|
|
14896
|
+
const spaceFreq = 1562.5;
|
|
14897
|
+
const amplitude = 0.6;
|
|
14898
|
+
const twoPi = Math.PI * 2;
|
|
14899
|
+
const result = [];
|
|
14900
|
+
let phase = 0;
|
|
14901
|
+
let frac = 0;
|
|
14902
|
+
for (let b = 0; b < bits.length; b++) {
|
|
14903
|
+
const bit = bits[b];
|
|
14904
|
+
const freq = bit ? markFreq : spaceFreq;
|
|
14905
|
+
const samplesPerBit = sampleRate / baud + frac;
|
|
14906
|
+
const n = Math.round(samplesPerBit);
|
|
14907
|
+
frac = samplesPerBit - n;
|
|
14908
|
+
const inc = twoPi * freq / sampleRate;
|
|
14909
|
+
for (let i = 0; i < n; i++) {
|
|
14910
|
+
result.push(Math.round(Math.sin(phase) * amplitude * 32767));
|
|
14911
|
+
phase += inc;
|
|
14912
|
+
if (phase > twoPi) phase -= twoPi;
|
|
14913
|
+
}
|
|
14914
|
+
}
|
|
14915
|
+
const fadeSamples = Math.floor(sampleRate * 2e-3);
|
|
14916
|
+
for (let i = 0; i < fadeSamples; i++) {
|
|
14917
|
+
const gain = i / fadeSamples;
|
|
14918
|
+
result[i] = Math.round(result[i] * gain);
|
|
14919
|
+
result[result.length - 1 - i] = Math.round(result[result.length - 1 - i] * gain);
|
|
14920
|
+
}
|
|
14921
|
+
return Int16Array.from(result);
|
|
14922
|
+
};
|
|
14923
|
+
|
|
14924
|
+
// src/@modules/@eas/eas.setAsciiToBits.ts
|
|
14925
|
+
var setAsciiToBits = (str) => {
|
|
14926
|
+
const bits = [];
|
|
14927
|
+
for (let i = 0; i < str.length; i++) {
|
|
14928
|
+
const c = str.charCodeAt(i) & 255;
|
|
14929
|
+
bits.push(0);
|
|
14930
|
+
for (let b = 0; b < 8; b++) bits.push(c >> b & 1);
|
|
14931
|
+
bits.push(1, 1);
|
|
14932
|
+
}
|
|
14933
|
+
return bits;
|
|
14934
|
+
};
|
|
14935
|
+
|
|
14936
|
+
// src/@modules/@eas/eas.getMergedPCM16.ts
|
|
14937
|
+
var getMergedPCM16 = (arrays) => {
|
|
14938
|
+
let total = 0;
|
|
14939
|
+
for (const a of arrays) total += a.length;
|
|
14940
|
+
const out = new Int16Array(total);
|
|
14941
|
+
let o = 0;
|
|
14942
|
+
for (const a of arrays) {
|
|
14943
|
+
out.set(a, o);
|
|
14944
|
+
o += a.length;
|
|
14945
|
+
}
|
|
14946
|
+
return out;
|
|
14947
|
+
};
|
|
14948
|
+
|
|
14949
|
+
// src/@modules/@eas/eas.setSameHeader.ts
|
|
14950
|
+
var setSameHeader = (vtec2, repeats, sampleRate = 8e3, options = {}) => {
|
|
14951
|
+
var _a, _b;
|
|
14952
|
+
const preMarkSec = (_a = options.preMarkSec) != null ? _a : 0.3;
|
|
14953
|
+
const gapSec = (_b = options.gapSec) != null ? _b : 0.1;
|
|
14954
|
+
const bursts = [];
|
|
14955
|
+
const gap = new Int16Array(Math.floor(gapSec * sampleRate));
|
|
14956
|
+
for (let i = 0; i < repeats; i++) {
|
|
14957
|
+
const bodyBits = setAsciiToBits(vtec2);
|
|
14958
|
+
const body = setAFSK(bodyBits, sampleRate);
|
|
14959
|
+
const extendedBodyDuration = Math.round(preMarkSec * sampleRate);
|
|
14960
|
+
const extendedBody = new Int16Array(extendedBodyDuration + gap.length);
|
|
14961
|
+
for (let j2 = 0; j2 < extendedBodyDuration; j2++) {
|
|
14962
|
+
extendedBody[j2] = Math.round(body[j2 % body.length] * 0.2);
|
|
14963
|
+
}
|
|
14964
|
+
extendedBody.set(gap, extendedBodyDuration);
|
|
14965
|
+
bursts.push(extendedBody);
|
|
14966
|
+
if (i !== repeats - 1) bursts.push(gap);
|
|
14967
|
+
}
|
|
14968
|
+
return getMergedPCM16(bursts);
|
|
14969
|
+
};
|
|
14970
|
+
|
|
14971
|
+
// src/@modules/@eas/eas.setAttentionTone.ts
|
|
14972
|
+
var setAttentionTone = (ms, sampleRate) => {
|
|
14973
|
+
const len = Math.floor(ms * sampleRate);
|
|
14974
|
+
const out = new Int16Array(len);
|
|
14975
|
+
const f1 = 853;
|
|
14976
|
+
const f2 = 960;
|
|
14977
|
+
const twoPi = Math.PI * 2;
|
|
14978
|
+
const amp = 0.1;
|
|
14979
|
+
const fadeLen = Math.floor(sampleRate * 0);
|
|
14980
|
+
for (let i = 0; i < len; i++) {
|
|
14981
|
+
const t = i / sampleRate;
|
|
14982
|
+
const s = Math.sin(twoPi * f1 * t) + Math.sin(twoPi * f2 * t);
|
|
14983
|
+
let gain = 1;
|
|
14984
|
+
if (i < fadeLen) gain = i / fadeLen;
|
|
14985
|
+
else if (i > len - fadeLen) gain = (len - i) / fadeLen;
|
|
14986
|
+
const v = Math.max(-1, Math.min(1, s / 2 * amp * gain));
|
|
14987
|
+
out[i] = Math.round(v * 32767);
|
|
14988
|
+
}
|
|
14989
|
+
return out;
|
|
14990
|
+
};
|
|
14991
|
+
|
|
14992
|
+
// src/@modules/@eas/eas.setNoise.ts
|
|
14993
|
+
var setNoise = (int16, noiseLevel = 0.02) => {
|
|
14994
|
+
const x = getPCMToFloat(int16);
|
|
14995
|
+
for (let i = 0; i < x.length; i++) x[i] += (Math.random() * 2 - 1) * noiseLevel;
|
|
14996
|
+
let peak = 0;
|
|
14997
|
+
for (let i = 0; i < x.length; i++) peak = Math.max(peak, Math.abs(x[i]));
|
|
14998
|
+
if (peak > 1) for (let i = 0; i < x.length; i++) x[i] *= 0.98 / peak;
|
|
14999
|
+
return getFloatPCM16(x);
|
|
15000
|
+
};
|
|
15001
|
+
|
|
15002
|
+
// src/@modules/@eas/eas.getPCM16.ts
|
|
15003
|
+
var getPCM16 = (samples, sampleRate) => {
|
|
15004
|
+
let o = 0;
|
|
15005
|
+
const bytesPerSample = 2;
|
|
15006
|
+
const blockAlign = 1 * bytesPerSample;
|
|
15007
|
+
const byteRate = sampleRate * blockAlign;
|
|
15008
|
+
const subchunk2Size = samples.length * bytesPerSample;
|
|
15009
|
+
const chunkSize = 36 + subchunk2Size;
|
|
15010
|
+
const buffer = Buffer.alloc(44 + subchunk2Size);
|
|
15011
|
+
buffer.write("RIFF", o);
|
|
15012
|
+
o += 4;
|
|
15013
|
+
buffer.writeUInt32LE(chunkSize, o);
|
|
15014
|
+
o += 4;
|
|
15015
|
+
buffer.write("WAVE", o);
|
|
15016
|
+
o += 4;
|
|
15017
|
+
buffer.write("fmt ", o);
|
|
15018
|
+
o += 4;
|
|
15019
|
+
buffer.writeUInt32LE(16, o);
|
|
15020
|
+
o += 4;
|
|
15021
|
+
buffer.writeUInt16LE(1, o);
|
|
15022
|
+
o += 2;
|
|
15023
|
+
buffer.writeUInt16LE(1, o);
|
|
15024
|
+
o += 2;
|
|
15025
|
+
buffer.writeUInt32LE(sampleRate, o);
|
|
15026
|
+
o += 4;
|
|
15027
|
+
buffer.writeUInt32LE(byteRate, o);
|
|
15028
|
+
o += 4;
|
|
15029
|
+
buffer.writeUInt16LE(blockAlign, o);
|
|
15030
|
+
o += 2;
|
|
15031
|
+
buffer.writeUInt16LE(16, o);
|
|
15032
|
+
o += 2;
|
|
15033
|
+
buffer.write("data", o);
|
|
15034
|
+
o += 4;
|
|
15035
|
+
buffer.writeUInt32LE(subchunk2Size, o);
|
|
15036
|
+
o += 4;
|
|
15037
|
+
for (let i = 0; i < samples.length; i++, o += 2) {
|
|
15038
|
+
buffer.writeInt16LE(samples[i].value, o);
|
|
15039
|
+
}
|
|
15040
|
+
return buffer;
|
|
15041
|
+
};
|
|
15042
|
+
|
|
15043
|
+
// src/@modules/@eas/eas.getTTS.ts
|
|
15044
|
+
import { platform } from "os";
|
|
15045
|
+
import { execSync } from "child_process";
|
|
15046
|
+
var getTTS = (text2, outputPath) => __async(null, null, function* () {
|
|
15047
|
+
const vPlatform = platform();
|
|
15048
|
+
switch (vPlatform) {
|
|
15049
|
+
case "win32": {
|
|
15050
|
+
const command = `Add-Type -AssemblyName System.Speech;$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;$speak.SetOutputToWaveFile('${outputPath}');$speak.Speak('${text2}');$speak.Dispose();`;
|
|
15051
|
+
execSync(`powershell -Command "${command}"`, { stdio: "ignore" });
|
|
15052
|
+
break;
|
|
15053
|
+
}
|
|
15054
|
+
case "linux":
|
|
15055
|
+
execSync(`espeak -w "${outputPath}" "${text2.replace(/"/g, '\\"')}"`);
|
|
15056
|
+
break;
|
|
15057
|
+
default:
|
|
15058
|
+
break;
|
|
15059
|
+
}
|
|
15060
|
+
});
|
|
15061
|
+
|
|
15062
|
+
// src/@modules/@eas/eas.getCleanDescription.ts
|
|
15063
|
+
var getCleanDescription = (message) => {
|
|
15064
|
+
const patches = [
|
|
15065
|
+
{ regex: /\.{3,}/g, replacement: ". " },
|
|
15066
|
+
{ regex: /\bUTC\b/g, replacement: "Coordinated Universal Time" },
|
|
15067
|
+
{ regex: /\bGMT\b/g, replacement: "Greenwich Mean Time" },
|
|
15068
|
+
{ regex: /\bEST\b(?!\w)/g, replacement: "Eastern Standard Time" },
|
|
15069
|
+
{ regex: /\bEDT\b(?!\w)/g, replacement: "Eastern Daylight Time" },
|
|
15070
|
+
{ regex: /\bCST\b(?!\w)/g, replacement: "Central Standard Time" },
|
|
15071
|
+
{ regex: /\bCDT\b(?!\w)/g, replacement: "Central Daylight Time" },
|
|
15072
|
+
{ regex: /\bMST\b(?!\w)/g, replacement: "Mountain Standard Time" },
|
|
15073
|
+
{ regex: /\bMDT\b(?!\w)/g, replacement: "Mountain Daylight Time" },
|
|
15074
|
+
{ regex: /\bPST\b(?!\w)/g, replacement: "Pacific Standard Time" },
|
|
15075
|
+
{ regex: /\bPDT\b(?!\w)/g, replacement: "Pacific Daylight Time" },
|
|
15076
|
+
{ regex: /\bAKST\b(?!\w)/g, replacement: "Alaska Standard Time" },
|
|
15077
|
+
{ regex: /\bAKDT\b(?!\w)/g, replacement: "Alaska Daylight Time" },
|
|
15078
|
+
{ regex: /\bHST\b(?!\w)/g, replacement: "Hawaii Standard Time" },
|
|
15079
|
+
{ regex: /\bHDT\b(?!\w)/g, replacement: "Hawaii Daylight Time" },
|
|
15080
|
+
{ regex: /\bmph\b(?!\w)/g, replacement: "miles per hour" },
|
|
15081
|
+
{ regex: /\bkm\/h\b(?!\w)/g, replacement: "kilometers per hour" },
|
|
15082
|
+
{ regex: /\bkmh\b(?!\w)/g, replacement: "kilometers per hour" },
|
|
15083
|
+
{ regex: /\bkt\b(?!\w)/g, replacement: "knots" },
|
|
15084
|
+
{ regex: /\bNE\b(?!\w)/g, replacement: "northeast" },
|
|
15085
|
+
{ regex: /\bNW\b(?!\w)/g, replacement: "northwest" },
|
|
15086
|
+
{ regex: /\bSE\b(?!\w)/g, replacement: "southeast" },
|
|
15087
|
+
{ regex: /\bSW\b(?!\w)/g, replacement: "southwest" },
|
|
15088
|
+
{ regex: /\bNM\b(?!\w)/g, replacement: "nautical miles" },
|
|
15089
|
+
{ regex: /\bdeg\b(?!\w)/g, replacement: "degrees" },
|
|
15090
|
+
{ regex: /\btstm\b(?!\w)/g, replacement: "thunderstorm" },
|
|
15091
|
+
{ regex: /\bmm\b(?!\w)/g, replacement: "millimeters" },
|
|
15092
|
+
{ regex: /\bcm\b(?!\w)/g, replacement: "centimeters" },
|
|
15093
|
+
{ regex: /\bin.\b(?!\w)/g, replacement: "inches" },
|
|
15094
|
+
{ regex: /\bft\b(?!\w)/g, replacement: "feet" },
|
|
15095
|
+
{ regex: /\bmi\b(?!\w)/g, replacement: "miles" },
|
|
15096
|
+
{ regex: /\bhr\b(?!\w)/g, replacement: "hour" },
|
|
15097
|
+
{ regex: /\bhourly\b(?!\w)/g, replacement: "per hour" },
|
|
15098
|
+
{ regex: /\bkg\b(?!\w)/g, replacement: "kilograms" },
|
|
15099
|
+
{ regex: /\bg\/kg\b(?!\w)/g, replacement: "grams per kilogram" },
|
|
15100
|
+
{ regex: /\bmb\b(?!\w)/g, replacement: "millibars" },
|
|
15101
|
+
{ regex: /\bhPa\b(?!\w)/g, replacement: "hectopascals" },
|
|
15102
|
+
{ regex: /\bPa\b(?!\w)/g, replacement: "pascals" },
|
|
15103
|
+
{ regex: /\bKPa\b(?!\w)/g, replacement: "kilopascals" },
|
|
15104
|
+
{ regex: /\bC\/hr\b(?!\w)/g, replacement: "degrees Celsius per hour" },
|
|
15105
|
+
{ regex: /\bF\/hr\b(?!\w)/g, replacement: "degrees Fahrenheit per hour" },
|
|
15106
|
+
{ regex: /\bC\/min\b(?!\w)/g, replacement: "degrees Celsius per minute" },
|
|
15107
|
+
{ regex: /\bF\/min\b(?!\w)/g, replacement: "degrees Fahrenheit per minute" },
|
|
15108
|
+
{ regex: /\bC\b(?!\w)/g, replacement: "degrees Celsius" },
|
|
15109
|
+
{ regex: /\bF\b(?!\w)/g, replacement: "degrees Fahrenheit" }
|
|
15110
|
+
];
|
|
15111
|
+
const hours = {
|
|
15112
|
+
0: "twelve",
|
|
15113
|
+
1: "one",
|
|
15114
|
+
2: "two",
|
|
15115
|
+
3: "three",
|
|
15116
|
+
4: "four",
|
|
15117
|
+
5: "five",
|
|
15118
|
+
6: "six",
|
|
15119
|
+
7: "seven",
|
|
15120
|
+
8: "eight",
|
|
15121
|
+
9: "nine",
|
|
15122
|
+
10: "ten",
|
|
15123
|
+
11: "eleven",
|
|
15124
|
+
12: "twelve"
|
|
15125
|
+
};
|
|
15126
|
+
const minWord = (m) => m === 0 ? "o'clock" : m < 10 ? `oh ${m}` : `${m}`;
|
|
15127
|
+
const fmt = (h, m, ap) => `${hours[h % 12]} ${minWord(m)} ${ap}`;
|
|
15128
|
+
for (const { regex, replacement } of patches) {
|
|
15129
|
+
message = message.replace(regex, replacement);
|
|
15130
|
+
}
|
|
15131
|
+
return message.replace(/\b(\d{1,2}):(\d{2})\s*(AM|PM)\b/gi, (_, h, m, ap) => fmt(+h, +m, ap.toUpperCase())).replace(/\b(\d{1,2})\s+(\d{2})\s+(AM|PM)\b/gi, (_, h, m, ap) => fmt(+h, +m, ap.toUpperCase())).replace(/\b(\d{2})(\d{2})\s+(AM|PM)\b/gi, (_, hh, mm, ap) => fmt(+hh, +mm, ap.toUpperCase())).replace(/\*+/g, " ").replace(/-/g, " ").replace(/\n/g, " ").trim();
|
|
15132
|
+
};
|
|
15133
|
+
|
|
15134
|
+
// src/@modules/@eas/eas.setEasTone.ts
|
|
15135
|
+
import { join } from "path";
|
|
15136
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
|
|
15137
|
+
import { execSync as execSync2 } from "child_process";
|
|
15138
|
+
import { platform as platform2 } from "os";
|
|
15139
|
+
var setEasTone = (options) => __async(null, null, function* () {
|
|
15140
|
+
const settings = bootstrap.settings;
|
|
15141
|
+
const directory = settings.GlobalSettings.EASSettings.ArchiveDirectory;
|
|
15142
|
+
const prefix = settings.GlobalSettings.EASSettings.IntroWavFile;
|
|
15143
|
+
let message = options.message;
|
|
15144
|
+
let header = options.header;
|
|
15145
|
+
if (!message || !header) {
|
|
15146
|
+
setWarning({
|
|
15147
|
+
title: `EAS`,
|
|
15148
|
+
message: `Message and header are required to generate an EAS tone.`
|
|
15149
|
+
});
|
|
15150
|
+
return null;
|
|
15151
|
+
}
|
|
15152
|
+
let buffTTS;
|
|
15153
|
+
let buffRadio;
|
|
15154
|
+
let buffFull = [];
|
|
15155
|
+
if (!existsSync(directory)) {
|
|
15156
|
+
mkdirSync(directory, { recursive: true });
|
|
15157
|
+
}
|
|
15158
|
+
if (!existsSync(join(directory, `/temp`))) {
|
|
15159
|
+
mkdirSync(join(directory, `/temp`), { recursive: true });
|
|
15160
|
+
}
|
|
15161
|
+
if (!existsSync(join(directory, `/output`))) {
|
|
15162
|
+
mkdirSync(join(directory, `/output`), { recursive: true });
|
|
15163
|
+
}
|
|
15164
|
+
const tmpTTS = join(directory, `/temp/${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, "")}.wav`);
|
|
15165
|
+
const outTTS = join(directory, `/output/${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, "")}.wav`);
|
|
15166
|
+
const vPlatform = platform2();
|
|
15167
|
+
if (vPlatform === "darwin") {
|
|
15168
|
+
setWarning({
|
|
15169
|
+
title: `EAS`,
|
|
15170
|
+
message: `EAS tone generation is not supported on macOS.`
|
|
15171
|
+
});
|
|
15172
|
+
return null;
|
|
15173
|
+
}
|
|
15174
|
+
yield new Promise((resolve6, reject) => {
|
|
15175
|
+
const tMsg = getCleanDescription(message);
|
|
15176
|
+
getTTS(tMsg, tmpTTS).then(() => {
|
|
15177
|
+
buffTTS = readFileSync(tmpTTS);
|
|
15178
|
+
resolve6();
|
|
15179
|
+
});
|
|
15180
|
+
});
|
|
15181
|
+
const vWav = getWavPCM16(buffTTS);
|
|
15182
|
+
const vSamples = getSampledPCM16(vWav.samples, vWav.sampleRate, 8e3);
|
|
15183
|
+
const vRadio = setRadioEffect(vSamples, 8e3);
|
|
15184
|
+
if (existsSync(prefix)) {
|
|
15185
|
+
let tBuffer = readFileSync(prefix);
|
|
15186
|
+
let tWav = getWavPCM16(tBuffer);
|
|
15187
|
+
if (tWav == null) {
|
|
15188
|
+
try {
|
|
15189
|
+
const converted = join(directory, `/temp/${Math.random().toString(36).substring(2, 15)}.converted.wav`);
|
|
15190
|
+
execSync2(`ffmpeg -y -i "${prefix}" -ar 8000 -ac 1 -sample_fmt s16 "${converted}"`, { stdio: "ignore" });
|
|
15191
|
+
if (existsSync(converted)) {
|
|
15192
|
+
tBuffer = readFileSync(converted);
|
|
15193
|
+
tWav = getWavPCM16(tBuffer);
|
|
15194
|
+
try {
|
|
15195
|
+
unlinkSync(converted);
|
|
15196
|
+
} catch (e) {
|
|
15197
|
+
}
|
|
15198
|
+
}
|
|
15199
|
+
} catch (e) {
|
|
15200
|
+
}
|
|
15201
|
+
}
|
|
15202
|
+
if (tWav == null) {
|
|
15203
|
+
setWarning({ title: `EAS`, message: `Intro tone isn't a valid .WAV file or isn't in PCM 16-bit format. Converted attempt failed; please convert it then try again.` });
|
|
15204
|
+
return null;
|
|
15205
|
+
}
|
|
15206
|
+
const tSamples = tWav.sampleRate != 8e3 ? getSampledPCM16(tWav.samples, tWav.sampleRate, 8e3) : tWav.samples;
|
|
15207
|
+
buffRadio = setRadioEffect(tSamples, 8e3);
|
|
15208
|
+
}
|
|
15209
|
+
buffFull = buffRadio != null ? [buffRadio, new Int16Array(Math.floor(0.5 * 8e3))] : [];
|
|
15210
|
+
buffFull.push(
|
|
15211
|
+
setSameHeader(header, 3, 8e3, {
|
|
15212
|
+
preMarkSec: 1.1,
|
|
15213
|
+
gapSec: 0.5
|
|
15214
|
+
}),
|
|
15215
|
+
new Int16Array(Math.floor(0.5 * 8e3)),
|
|
15216
|
+
setAttentionTone(8, 8e3),
|
|
15217
|
+
new Int16Array(Math.floor(0.5 * 8e3)),
|
|
15218
|
+
vRadio
|
|
15219
|
+
);
|
|
15220
|
+
for (let i = 0; i < 3; i++) {
|
|
15221
|
+
buffFull.push(setSameHeader(header, 1, 8e3, { preMarkSec: 0.5, gapSec: 0.1 }));
|
|
15222
|
+
buffFull.push(new Int16Array(Math.floor(0.5 * 8e3)));
|
|
15223
|
+
}
|
|
15224
|
+
const aSamples = getMergedPCM16(buffFull);
|
|
15225
|
+
const aFinal = setNoise(aSamples, 2e-3);
|
|
15226
|
+
const aBuffer = getPCM16(Array.from(aFinal).map((v) => ({ value: v })), 8e3);
|
|
15227
|
+
writeFileSync(outTTS, aBuffer);
|
|
15228
|
+
try {
|
|
15229
|
+
unlinkSync(tmpTTS);
|
|
15230
|
+
} catch (e) {
|
|
15231
|
+
}
|
|
15232
|
+
return outTTS;
|
|
15233
|
+
});
|
|
15234
|
+
|
|
15235
|
+
// src/@manager/manager.createWebhook.ts
|
|
15236
|
+
var import_form_data = __toESM(require_form_data());
|
|
15237
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
15238
|
+
var createWebhook = (options) => __async(null, null, function* () {
|
|
15239
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
15240
|
+
const event = options.event.properties;
|
|
15241
|
+
const settings = options.webhook;
|
|
15242
|
+
const line = (label, value, condition = true) => condition && value ? `${label} ${value}` : null;
|
|
15243
|
+
const isLimited = setTimeoutAction({ identifier: options.webhook.webhook, interval: options.webhook.rate, max: options.webhook.rate, addTime: true });
|
|
15244
|
+
if (!isLimited.limited) {
|
|
15245
|
+
const isStatement = event.status_metadata.is_statement;
|
|
15246
|
+
const isExpired = event.status_metadata.is_expired;
|
|
15247
|
+
let body = [
|
|
15248
|
+
line(`**Locations:**`, (_a = event == null ? void 0 : event.locations) == null ? void 0 : _a.slice(0, 100)),
|
|
15249
|
+
line(`**Issued:**`, `<t:${Math.floor(new Date(event.issued).getTime() / 1e3)}:R>`),
|
|
15250
|
+
line(`**Expires:**`, `<t:${Math.floor(new Date(event.expires).getTime() / 1e3)}:R>`, !isExpired && !isStatement),
|
|
15251
|
+
line(`**Damage Threat:**`, event.parameters.damage_threat, !isExpired),
|
|
15252
|
+
line(`**Flood Threat:**`, event.parameters.flood_threat, !isExpired),
|
|
15253
|
+
line(`**Tornado Threat:**`, event.parameters.tornado_threat, !isExpired),
|
|
15254
|
+
line(`**Estimated Wind Gusts:**`, `${event.parameters.estimated_wind_gusts} ${event.parameters.wind_threat ? ` (${event.parameters.wind_threat})` : ""}`, !isExpired && event.parameters.estimated_wind_gusts != null),
|
|
15255
|
+
line(`**Estimated Hail Size:**`, `${event.parameters.estimated_hail_size} ${event.parameters.hail_threat ? ` (${event.parameters.hail_threat})` : ""}`, !isExpired && event.parameters.estimated_hail_size != null),
|
|
15256
|
+
line(`**Discussion:**`, event.spc_parameters.spc_number, !isExpired),
|
|
15257
|
+
line(`**Concern:**`, event.spc_parameters.spc_concerning, !isExpired),
|
|
15258
|
+
line(`**SPC Max Tornado Threat:**`, event.spc_parameters.spc_max_tornado, !isExpired),
|
|
15259
|
+
line(`**SPC Max Hail Threat:**`, event.spc_parameters.spc_max_hail, !isExpired),
|
|
15260
|
+
line(`**SPC Max Wind Threat:**`, event.spc_parameters.spc_max_wind, !isExpired),
|
|
15261
|
+
line(`**SPC Watch Issuance Probability:**`, event.spc_parameters.spc_watch_issuance ? `${event.spc_parameters.spc_watch_issuance}%` : null, !isExpired),
|
|
15262
|
+
line(`**Watch Number:**`, event.watch_parameters.watch_number, !isExpired),
|
|
15263
|
+
line(`**Strong Tornadoes Probability:**`, event.watch_parameters.strong_tornadoes_probability ? `${event.watch_parameters.strong_tornadoes_probability}%` : null, !isExpired),
|
|
15264
|
+
line(`**Additional Tornadoes Probability:**`, event.watch_parameters.additional_tornadoes_probability ? `${event.watch_parameters.additional_tornadoes_probability}%` : null, !isExpired),
|
|
15265
|
+
line(`**Combined Hail/Wind Probability:**`, event.watch_parameters.combined_hail_wind_probability ? `${event.watch_parameters.combined_hail_wind_probability}%` : null, !isExpired),
|
|
15266
|
+
line(`**Severe Hail Probability:**`, event.watch_parameters.severe_hail_probability ? `${event.watch_parameters.severe_hail_probability}%` : null, !isExpired),
|
|
15267
|
+
line(`**Hail >2in Probability:**`, event.watch_parameters.hail_2in_probability ? `${event.watch_parameters.hail_2in_probability}%` : null, !isExpired),
|
|
15268
|
+
line(`**Max Hail Inches:**`, event.watch_parameters.max_hail_in, !isExpired),
|
|
15269
|
+
line(`**Severe Wind Probability:**`, event.watch_parameters.severe_wind_probability ? `${event.watch_parameters.severe_wind_probability}%` : null, !isExpired),
|
|
15270
|
+
line(`**Max Surface Wind:**`, event.watch_parameters.max_wind_surface, !isExpired),
|
|
15271
|
+
line(`**Max Tops (x100 feet):**`, event.watch_parameters.max_tops_x100feet, !isExpired),
|
|
15272
|
+
line(`**Tags:**`, ((_b = event.parameters.tags) == null ? void 0 : _b.length) > 0 ? event.parameters.tags.join(", ") : null, !isExpired),
|
|
15273
|
+
line(`**Sender:**`, ((_d = (_c = event.geocode) == null ? void 0 : _c.office) == null ? void 0 : _d.name) ? `${event.geocode.office.name} (${event.geocode.office.office})` : (_f = (_e = event.geocode) == null ? void 0 : _e.office) == null ? void 0 : _f.office),
|
|
15274
|
+
line(`**Tracking:**`, (_g = event.metadata) == null ? void 0 : _g.tracking),
|
|
15275
|
+
line(`**Logs:**`, ((_h = event.metadata.history) == null ? void 0 : _h.length) > 0 ? event.metadata.history.length : null),
|
|
15276
|
+
line(``, event.description ? "```\n" + event.description.split("\n").map((l) => l.trim()).filter(Boolean).join("\n") + "\n```" : null, !isExpired)
|
|
15277
|
+
].filter(Boolean).join("\n");
|
|
15278
|
+
if (body.length > 1900) {
|
|
15279
|
+
body = body.substring(0, 1900) + "\n\n[Message truncated due to length]";
|
|
15280
|
+
const blocks = ((_i = body.match(/```/g)) != null ? _i : []).length;
|
|
15281
|
+
if (blocks % 2 !== 0) body += "```";
|
|
15282
|
+
}
|
|
15283
|
+
if (event.description.length < 25) {
|
|
15284
|
+
return;
|
|
15285
|
+
}
|
|
15286
|
+
const form = new import_form_data.default();
|
|
15287
|
+
const img = (_j = event.metadata.attachments) == null ? void 0 : _j[0];
|
|
15288
|
+
const embed = {
|
|
15289
|
+
title: `${event.event} (${event.status})`,
|
|
15290
|
+
description: body,
|
|
15291
|
+
color: 16711680,
|
|
15292
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15293
|
+
image: {},
|
|
15294
|
+
footer: { text: settings.title }
|
|
15295
|
+
};
|
|
15296
|
+
if (img) {
|
|
15297
|
+
for (let i = 0; i < 5; i++) {
|
|
15298
|
+
const ok = yield isImageReady(img);
|
|
15299
|
+
if (ok) break;
|
|
15300
|
+
yield new Promise((r) => setTimeout(r, 5e3));
|
|
15301
|
+
}
|
|
15302
|
+
const finalCheck = yield isImageReady(img);
|
|
15303
|
+
if (finalCheck) {
|
|
15304
|
+
embed.image = { url: img };
|
|
15305
|
+
}
|
|
15306
|
+
}
|
|
15307
|
+
form.append("payload_json", JSON.stringify({
|
|
15308
|
+
username: (_k = settings.title) != null ? _k : "AtmosphericX",
|
|
15309
|
+
content: (_l = settings.message) != null ? _l : "",
|
|
15310
|
+
embeds: [embed]
|
|
15311
|
+
}));
|
|
15312
|
+
if (settings.upload) {
|
|
15313
|
+
form.append("fUpload", Buffer.from(`${event.metadata.raw}
|
|
15314
|
+
|
|
15315
|
+
${JSON.stringify(getCleanedEvent(event), null, 2)}`), { filename: `${event.event}_${event.status}_${event.metadata.tracking}.txt`, contentType: "application/text" });
|
|
15316
|
+
}
|
|
15317
|
+
if (settings.eas) {
|
|
15318
|
+
const audio = yield setEasTone({
|
|
15319
|
+
message: event.description,
|
|
15320
|
+
header: event.metadata.header
|
|
15321
|
+
});
|
|
15322
|
+
const file = readFileSync2(audio);
|
|
15323
|
+
if (audio) {
|
|
15324
|
+
form.append("fEas", Buffer.from(file), { filename: `${event.event}_${event.status}_${event.metadata.tracking}_eas.mp3`, contentType: "audio/mpeg" });
|
|
15325
|
+
}
|
|
15326
|
+
}
|
|
15327
|
+
yield createHttp({
|
|
15328
|
+
url: settings.webhook,
|
|
15329
|
+
timeout: 2e3,
|
|
15330
|
+
method: `POST`,
|
|
15331
|
+
headers: form.getHeaders(),
|
|
15332
|
+
body: form
|
|
15333
|
+
});
|
|
15334
|
+
}
|
|
15335
|
+
});
|
|
15336
|
+
|
|
15337
|
+
// src/@manager/manager.updateWebhooks.ts
|
|
15338
|
+
var updateWebhooks = (event) => __async(null, null, function* () {
|
|
15339
|
+
const settings = bootstrap.settings;
|
|
15340
|
+
const webhooks = settings.WebhookSettings;
|
|
15341
|
+
const eventName = event.properties.event;
|
|
15342
|
+
for (const socket of webhooks) {
|
|
15343
|
+
const events = socket.events;
|
|
15344
|
+
if (!events || events.length === 0) {
|
|
15345
|
+
yield createWebhook({ webhook: socket, event });
|
|
15346
|
+
continue;
|
|
15347
|
+
}
|
|
15348
|
+
const matched = events.some((pattern) => {
|
|
15349
|
+
if (!pattern) return false;
|
|
15350
|
+
if (pattern === "*" || pattern === eventName) return true;
|
|
15351
|
+
if (pattern.includes("*")) {
|
|
15352
|
+
const regex = "^" + pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$";
|
|
15353
|
+
return new RegExp(regex).test(eventName);
|
|
15354
|
+
}
|
|
15355
|
+
return false;
|
|
15356
|
+
});
|
|
15357
|
+
if (matched) {
|
|
15358
|
+
yield createWebhook({ webhook: socket, event });
|
|
15359
|
+
}
|
|
15360
|
+
}
|
|
15361
|
+
});
|
|
15362
|
+
|
|
15363
|
+
// src/@modules/@utilities/utilities.getShapeNearestPoint.ts
|
|
15364
|
+
var getShapeNearestPoint = (coordinates, point) => {
|
|
15365
|
+
if (!coordinates || !point) {
|
|
15366
|
+
return { proximity: false, point: [0, 0], distance: null };
|
|
15367
|
+
}
|
|
15368
|
+
const normalize = (coords) => {
|
|
15369
|
+
if (!Array.isArray(coords)) return [];
|
|
15370
|
+
if (typeof coords[0] === "number" && typeof coords[1] === "number") return [];
|
|
15371
|
+
if (Array.isArray(coords[0]) && typeof coords[0][0] === "number") {
|
|
15372
|
+
return [[coords]];
|
|
15373
|
+
}
|
|
15374
|
+
if (Array.isArray(coords[0]) && Array.isArray(coords[0][0]) && typeof coords[0][0][0] === "number") {
|
|
15375
|
+
return [coords];
|
|
15376
|
+
}
|
|
15377
|
+
if (Array.isArray(coords[0]) && Array.isArray(coords[0][0]) && Array.isArray(coords[0][0][0]) && typeof coords[0][0][0][0] === "number") {
|
|
15378
|
+
return coords;
|
|
15379
|
+
}
|
|
15380
|
+
return [];
|
|
15381
|
+
};
|
|
15382
|
+
const polys = normalize(coordinates);
|
|
15383
|
+
if (polys.length === 0) return { proximity: false, point: [0, 0], distance: null };
|
|
15384
|
+
const lon = point[0];
|
|
15385
|
+
const lat = point[1];
|
|
15386
|
+
const pointInRing = (pt, ring) => {
|
|
15387
|
+
let x = pt[0], y = pt[1];
|
|
15388
|
+
let inside = false;
|
|
15389
|
+
for (let i = 0, j2 = ring.length - 1; i < ring.length; j2 = i++) {
|
|
15390
|
+
const xi = ring[i][0], yi = ring[i][1];
|
|
15391
|
+
const xj = ring[j2][0], yj = ring[j2][1];
|
|
15392
|
+
const intersect = yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi + 0) + xi;
|
|
15393
|
+
if (intersect) inside = !inside;
|
|
15394
|
+
}
|
|
15395
|
+
return inside;
|
|
15396
|
+
};
|
|
15397
|
+
const toRadians = (deg) => deg * Math.PI / 180;
|
|
15398
|
+
const haversineMiles = (a, b) => {
|
|
15399
|
+
const R = 3958.8;
|
|
15400
|
+
const dLat = toRadians(b[1] - a[1]);
|
|
15401
|
+
const dLon = toRadians(b[0] - a[0]);
|
|
15402
|
+
const lat1 = toRadians(a[1]);
|
|
15403
|
+
const lat2 = toRadians(b[1]);
|
|
15404
|
+
const sinDLat = Math.sin(dLat / 2);
|
|
15405
|
+
const sinDLon = Math.sin(dLon / 2);
|
|
15406
|
+
const c = 2 * Math.asin(Math.sqrt(sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon));
|
|
15407
|
+
return R * c;
|
|
15408
|
+
};
|
|
15409
|
+
let minDistance = Infinity;
|
|
15410
|
+
let closestPoint = null;
|
|
15411
|
+
for (const poly of polys) {
|
|
15412
|
+
const outer = poly[0];
|
|
15413
|
+
const holes = poly.slice(1);
|
|
15414
|
+
if (pointInRing(point, outer)) {
|
|
15415
|
+
let inHole = false;
|
|
15416
|
+
for (const hole of holes) {
|
|
15417
|
+
if (pointInRing(point, hole)) {
|
|
15418
|
+
inHole = true;
|
|
15419
|
+
break;
|
|
15420
|
+
}
|
|
15421
|
+
}
|
|
15422
|
+
if (!inHole) {
|
|
15423
|
+
return { proximity: true, point, distance: 0 };
|
|
15424
|
+
}
|
|
15425
|
+
}
|
|
15426
|
+
for (const ring of poly) {
|
|
15427
|
+
for (let i = 0; i < ring.length - 1; i++) {
|
|
15428
|
+
const start = [ring[i][0], ring[i][1]];
|
|
15429
|
+
const end = [ring[i + 1][0], ring[i + 1][1]];
|
|
15430
|
+
const A = lon - start[0];
|
|
15431
|
+
const B = lat - start[1];
|
|
15432
|
+
const C = end[0] - start[0];
|
|
15433
|
+
const D = end[1] - start[1];
|
|
15434
|
+
const lenSq = C * C + D * D;
|
|
15435
|
+
const t = lenSq === 0 ? 0 : Math.max(0, Math.min(1, (A * C + B * D) / lenSq));
|
|
15436
|
+
const candidate = [start[0] + t * C, start[1] + t * D];
|
|
15437
|
+
const dist = haversineMiles([lon, lat], candidate);
|
|
15438
|
+
if (!isNaN(dist) && dist < minDistance) {
|
|
15439
|
+
minDistance = Number(dist.toFixed(3));
|
|
15440
|
+
closestPoint = candidate;
|
|
15441
|
+
}
|
|
15442
|
+
}
|
|
15443
|
+
}
|
|
15444
|
+
}
|
|
15445
|
+
if (!isFinite(minDistance) || closestPoint == null) {
|
|
15446
|
+
return { proximity: false, point: [0, 0], distance: null };
|
|
15447
|
+
}
|
|
15448
|
+
const distanceMiles = minDistance;
|
|
15449
|
+
const distanceKm = Number((distanceMiles * 1.609344).toFixed(3));
|
|
15450
|
+
const distanceMeters = Math.round(distanceKm * 1e3);
|
|
15451
|
+
return { proximity: distanceMiles === 0, point: closestPoint, distance: distanceMiles, distanceKm, distanceMeters };
|
|
15452
|
+
};
|
|
15453
|
+
|
|
15454
|
+
// src/@building/building.polygon.ts
|
|
15455
|
+
var getEventNodes = (event) => __async(null, null, function* () {
|
|
15456
|
+
var _a, _b;
|
|
15457
|
+
const metadata = { nodes: [], proximity: false, filtered: false };
|
|
15458
|
+
const geometry = yield getEventGeometry(event);
|
|
15459
|
+
if (!geometry || !geometry.coordinates) {
|
|
15460
|
+
return { nodes: [], filtered: false, updated: Date.now() };
|
|
15461
|
+
}
|
|
15462
|
+
const nodes = bootstrap.cache.nodes.features;
|
|
15463
|
+
for (const node of nodes) {
|
|
15464
|
+
const [longitude, latitude] = node.geometry.coordinates;
|
|
15465
|
+
const getPoint = getShapeNearestPoint(geometry.coordinates, [longitude, latitude]);
|
|
15466
|
+
const miles = (_a = getPoint.distance) != null ? _a : null;
|
|
15467
|
+
const kilometers = Number((miles * 1.609344).toFixed(3));
|
|
15468
|
+
const info = {
|
|
15469
|
+
id: (_b = node.properties) == null ? void 0 : _b.identifier,
|
|
15470
|
+
coordinates: [longitude, latitude],
|
|
15471
|
+
nearest: getPoint.point,
|
|
15472
|
+
miles,
|
|
15473
|
+
kilometers,
|
|
15474
|
+
proximity: getPoint.proximity
|
|
15475
|
+
};
|
|
15476
|
+
metadata.nodes.push(info);
|
|
15477
|
+
if (bootstrap.settings.GlobalSettings.EventFiltering.NodeLocationFiltering && miles < bootstrap.settings.GlobalSettings.NodeMinDistance) {
|
|
15478
|
+
metadata.proximity = true;
|
|
15479
|
+
info.proximity = true;
|
|
15480
|
+
}
|
|
15481
|
+
}
|
|
15482
|
+
return {
|
|
15483
|
+
nodes: metadata.nodes,
|
|
15484
|
+
filtered: metadata.proximity,
|
|
15485
|
+
updated: Date.now()
|
|
15486
|
+
};
|
|
15487
|
+
});
|
|
15488
|
+
|
|
15489
|
+
// src/@manager/manager.updateNodes.ts
|
|
15490
|
+
var updateNode = (selectedEvent) => __async(null, null, function* () {
|
|
15491
|
+
const events = bootstrap.cache.events.features;
|
|
15492
|
+
const ttl = bootstrap.settings.GlobalSettings.NodeTTL * 1e3;
|
|
15493
|
+
let total = 0;
|
|
15494
|
+
function update(evt) {
|
|
15495
|
+
return __async(this, null, function* () {
|
|
15496
|
+
var _a, _b, _c;
|
|
15497
|
+
const lastUpdate = (_c = (_b = (_a = evt == null ? void 0 : evt.properties) == null ? void 0 : _a.metadata) == null ? void 0 : _b.updated) != null ? _c : null;
|
|
15498
|
+
if (lastUpdate != null && Date.now() - lastUpdate < ttl) {
|
|
15499
|
+
return evt;
|
|
15500
|
+
}
|
|
15501
|
+
const node = yield getEventNodes(evt);
|
|
15502
|
+
if (node.nodes.length > 0) {
|
|
15503
|
+
total++;
|
|
15504
|
+
}
|
|
15505
|
+
evt.properties.metadata.nodes = node.nodes;
|
|
15506
|
+
evt.properties.metadata.filtered_proximity = node.filtered;
|
|
15507
|
+
evt.properties.metadata.updated = node.updated;
|
|
15508
|
+
});
|
|
15509
|
+
}
|
|
15510
|
+
if (!selectedEvent) {
|
|
15511
|
+
yield Promise.all(events.map((evt) => __async(null, null, function* () {
|
|
15054
15512
|
yield update(evt);
|
|
15055
15513
|
})));
|
|
15056
15514
|
}
|
|
@@ -15102,7 +15560,7 @@ var mkEvent = (event) => __async(null, null, function* () {
|
|
|
15102
15560
|
const iHistory = (_o = (_n = (_m = event.properties) == null ? void 0 : _m.metadata) == null ? void 0 : _n.history) != null ? _o : [];
|
|
15103
15561
|
const iLocations = (_r = (_q = (_p = event.properties) == null ? void 0 : _p.locations) == null ? void 0 : _q.split(";").map((l) => l.trim())) != null ? _r : [];
|
|
15104
15562
|
const iUgc = (_u = (_t = (_s = event.properties) == null ? void 0 : _s.geocode) == null ? void 0 : _t.ugc) != null ? _u : [];
|
|
15105
|
-
const mHistory = [...cHistory, ...iHistory].filter((v, i, a) => a.indexOf(v) === i);
|
|
15563
|
+
const mHistory = [...cHistory, ...iHistory].filter((v, i, a) => a.indexOf(v) === i).filter((v, i, a) => a.findIndex((h) => h.description === v.description && h.issued === v.issued) === i);
|
|
15106
15564
|
const mLocations = [...cLocations, ...iLocations].filter((v, i, a) => a.indexOf(v) === i).join("; ");
|
|
15107
15565
|
const mUgc = [...cUgc, ...iUgc].filter((v, i, a) => a.indexOf(v) === i);
|
|
15108
15566
|
bootstrap.cache.events.features[getIndex] = __spreadProps(__spreadValues({}, event), {
|
|
@@ -15155,6 +15613,37 @@ var rmEvent = (event) => {
|
|
|
15155
15613
|
});
|
|
15156
15614
|
};
|
|
15157
15615
|
|
|
15616
|
+
// src/@modules/@utilities/utilities.getLatestIssuance.ts
|
|
15617
|
+
var getLatestIssuance = () => {
|
|
15618
|
+
const now = /* @__PURE__ */ new Date();
|
|
15619
|
+
const current = now.getUTCHours() * 100 + now.getUTCMinutes();
|
|
15620
|
+
const issuances = [100, 600, 1300, 1630, 2e3];
|
|
15621
|
+
let latest = issuances[0];
|
|
15622
|
+
for (const issuance of issuances) {
|
|
15623
|
+
if (current >= issuance) {
|
|
15624
|
+
latest = issuance;
|
|
15625
|
+
}
|
|
15626
|
+
}
|
|
15627
|
+
return latest.toString().padStart(4, "0");
|
|
15628
|
+
};
|
|
15629
|
+
|
|
15630
|
+
// src/@building/building.outlooks.ts
|
|
15631
|
+
var getEventAttachments = (event) => {
|
|
15632
|
+
var _a, _b;
|
|
15633
|
+
const latestTime = getLatestIssuance();
|
|
15634
|
+
const validEvents = [
|
|
15635
|
+
{ target: "Day 1", attachment: `https://www.spc.noaa.gov/products/outlook/day1otlk_${latestTime}.png` },
|
|
15636
|
+
{ target: "Day 2", attachment: `https://www.spc.noaa.gov/products/outlook/day2otlk.png` },
|
|
15637
|
+
{ target: "Day 3", attachment: `https://www.spc.noaa.gov/products/outlook/day3otlk.png` },
|
|
15638
|
+
{ target: "Mesoscale Discussion", attachment: `https://www.spc.noaa.gov/products/md/mcd${(_b = (_a = event == null ? void 0 : event.properties) == null ? void 0 : _a.spc_parameters) == null ? void 0 : _b.spc_number}.png` }
|
|
15639
|
+
];
|
|
15640
|
+
const isValid = validEvents.find((outlook) => outlook.target == event.properties.event);
|
|
15641
|
+
if (isValid) {
|
|
15642
|
+
return (isValid == null ? void 0 : isValid.attachment) ? [isValid.attachment] : [];
|
|
15643
|
+
}
|
|
15644
|
+
return null;
|
|
15645
|
+
};
|
|
15646
|
+
|
|
15158
15647
|
// src/@building/building.validate.ts
|
|
15159
15648
|
var validateEvents = (events) => __async(null, null, function* () {
|
|
15160
15649
|
var _a;
|
|
@@ -15185,6 +15674,7 @@ var validateEvents = (events) => __async(null, null, function* () {
|
|
|
15185
15674
|
}
|
|
15186
15675
|
filteredProperties.metadata = (_a2 = filteredProperties.metadata) != null ? _a2 : {};
|
|
15187
15676
|
properties2.metadata.hash = createHash("sha256").update(JSON.stringify(filteredProperties)).digest("hex");
|
|
15677
|
+
properties2.metadata.attachments = getEventAttachments(event);
|
|
15188
15678
|
setEventEmit({ event: `onProductType${enhancedEventName.replace(/\s+/g, "")}`, metadata: define2 });
|
|
15189
15679
|
if (properties2.status_metadata.is_test) {
|
|
15190
15680
|
setEventEmit({ event: `onTestProduct`, metadata: define2 });
|
|
@@ -15309,6 +15799,7 @@ var text = (stanza) => __async(null, null, function* () {
|
|
|
15309
15799
|
header,
|
|
15310
15800
|
vtec: null,
|
|
15311
15801
|
hvtec: null,
|
|
15802
|
+
raw: message,
|
|
15312
15803
|
history: [
|
|
15313
15804
|
{
|
|
15314
15805
|
description: props.description,
|
|
@@ -15445,6 +15936,7 @@ var ugc = (stanza) => __async(null, null, function* () {
|
|
|
15445
15936
|
header,
|
|
15446
15937
|
vtec: null,
|
|
15447
15938
|
hvtec: null,
|
|
15939
|
+
raw: message,
|
|
15448
15940
|
history: [
|
|
15449
15941
|
{
|
|
15450
15942
|
description: props.description,
|
|
@@ -15677,6 +16169,7 @@ var vtec = (stanza) => __async(null, null, function* () {
|
|
|
15677
16169
|
header,
|
|
15678
16170
|
vtec: pv,
|
|
15679
16171
|
hvtec: hVtec,
|
|
16172
|
+
raw: message,
|
|
15680
16173
|
history: [
|
|
15681
16174
|
{
|
|
15682
16175
|
description: props.description,
|
|
@@ -15695,7 +16188,7 @@ var vtec = (stanza) => __async(null, null, function* () {
|
|
|
15695
16188
|
|
|
15696
16189
|
// src/@events/events.api.ts
|
|
15697
16190
|
var api = (stanza) => __async(null, null, function* () {
|
|
15698
|
-
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;
|
|
16191
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa, _ba, _ca, _da, _ea, _fa, _ga, _ha, _ia, _ja, _ka, _la, _ma, _na, _oa, _pa, _qa, _ra, _sa, _ta, _ua, _va, _wa, _xa, _ya, _za, _Aa, _Ba, _Ca, _Da, _Ea, _Fa, _Ga, _Ha, _Ia, _Ja, _Ka, _La, _Ma, _Na, _Oa, _Pa, _Qa, _Ra, _Sa, _Ta, _Ua, _Va, _Wa, _Xa, _Ya, _Za, __a, _$a, _ab, _bb, _cb, _db, _eb, _fb, _gb;
|
|
15699
16192
|
let processed = [];
|
|
15700
16193
|
const messages = Object.values(JSON.parse(stanza.message).features);
|
|
15701
16194
|
for (const feature of messages) {
|
|
@@ -15741,37 +16234,40 @@ var api = (stanza) => __async(null, null, function* () {
|
|
|
15741
16234
|
hail_threat: (_ma = (_la = (_ka = (_ja = feature == null ? void 0 : feature.properties) == null ? void 0 : _ja.parameters) == null ? void 0 : _ka.hailThreat) == null ? void 0 : _la[0]) != null ? _ma : null
|
|
15742
16235
|
},
|
|
15743
16236
|
spc_parameters: {
|
|
15744
|
-
|
|
15745
|
-
|
|
15746
|
-
|
|
15747
|
-
|
|
16237
|
+
spc_number: (_oa = getTextFromProduct({ message: (_na = feature == null ? void 0 : feature.properties) == null ? void 0 : _na.description, find: [`Mesoscale Discussion `], removal: [`Mesoscale Discussion`, `Number`, `...`] })) != null ? _oa : null,
|
|
16238
|
+
spc_concerning: (_qa = getTextFromProduct({ message: (_pa = feature == null ? void 0 : feature.properties) == null ? void 0 : _pa.description, find: [`Concerning...`] })) != null ? _qa : null,
|
|
16239
|
+
spc_max_tornado: (_sa = getTextFromProduct({ message: (_ra = feature == null ? void 0 : feature.properties) == null ? void 0 : _ra.description, find: [`MOST PROBABLE PEAK TORNADO INTENSITY...`] })) != null ? _sa : null,
|
|
16240
|
+
spc_max_hail: (_ua = getTextFromProduct({ message: (_ta = feature == null ? void 0 : feature.properties) == null ? void 0 : _ta.description, find: [`MOST PROBABLE PEAK HAIL SIZE...`] })) != null ? _ua : null,
|
|
16241
|
+
spc_max_wind: (_wa = getTextFromProduct({ message: (_va = feature == null ? void 0 : feature.properties) == null ? void 0 : _va.description, find: [`MOST PROBABLE PEAK WIND GUST...`] })) != null ? _wa : null,
|
|
16242
|
+
spc_watch_issuance: (_ya = getTextFromProduct({ message: (_xa = feature == null ? void 0 : feature.properties) == null ? void 0 : _xa.description, find: [`Probability of Watch Issuance...`], removal: [`percent`] })) != null ? _ya : null
|
|
15748
16243
|
},
|
|
15749
16244
|
watch_parameters: {
|
|
15750
|
-
watch_number: (
|
|
15751
|
-
watch_type: ((
|
|
15752
|
-
additional_tornadoes_probability: (
|
|
15753
|
-
strong_tornadoes_probability: (
|
|
15754
|
-
severe_wind_probability: (
|
|
15755
|
-
severe_hail_probability: (
|
|
15756
|
-
hail_2in_probability: (
|
|
15757
|
-
combined_hail_wind_probability: (
|
|
15758
|
-
max_hail_in: (
|
|
15759
|
-
max_wind_surface: (
|
|
15760
|
-
max_tops_x100feet: (
|
|
15761
|
-
pds_watch: getTextFromProduct({ message: (
|
|
16245
|
+
watch_number: (_Ca = (_Ba = (_Aa = getTextFromProduct({ message: (_za = feature == null ? void 0 : feature.properties) == null ? void 0 : _za.description, find: [`ITIES FOR`, `UPDATE FOR`, `Watch Number `], removal: [`%`, `<`, `:`] })) == null ? void 0 : _Aa.replace(/(WT|WS|)/g, "")) == null ? void 0 : _Ba.trim()) != null ? _Ca : null,
|
|
16246
|
+
watch_type: ((_Da = feature == null ? void 0 : feature.properties) == null ? void 0 : _Da.description.includes(`TORNADO WATCH`)) ? `Tornado` : ((_Ea = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ea.description.includes(`SEVERE`)) ? `Severe` : null,
|
|
16247
|
+
additional_tornadoes_probability: (_Ga = getTextFromProduct({ message: (_Fa = feature == null ? void 0 : feature.properties) == null ? void 0 : _Fa.description, find: [`PROB OF 2 OR MORE TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _Ga : null,
|
|
16248
|
+
strong_tornadoes_probability: (_Ia = getTextFromProduct({ message: (_Ha = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ha.description, find: [`PROB OF 1 OR MORE STRONG /EF2-EF5/ TORNADOES`], removal: [`%`, `<`, `:`] })) != null ? _Ia : null,
|
|
16249
|
+
severe_wind_probability: (_Ka = getTextFromProduct({ message: (_Ja = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ja.description, find: [`PROB OF 10 OR MORE SEVERE WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _Ka : null,
|
|
16250
|
+
severe_hail_probability: (_Ma = getTextFromProduct({ message: (_La = feature == null ? void 0 : feature.properties) == null ? void 0 : _La.description, find: [`PROB OF 10 OR MORE SEVERE HAIL EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _Ma : null,
|
|
16251
|
+
hail_2in_probability: (_Oa = getTextFromProduct({ message: (_Na = feature == null ? void 0 : feature.properties) == null ? void 0 : _Na.description, find: [`PROB OF 1 OR MORE HAIL EVENTS >= 2 INCHES`], removal: [`%`, `<`, `:`] })) != null ? _Oa : null,
|
|
16252
|
+
combined_hail_wind_probability: (_Qa = getTextFromProduct({ message: (_Pa = feature == null ? void 0 : feature.properties) == null ? void 0 : _Pa.description, find: [`PROB OF 6 OR MORE COMBINED SEVERE HAIL/WIND EVENTS`], removal: [`%`, `<`, `:`] })) != null ? _Qa : null,
|
|
16253
|
+
max_hail_in: (_Sa = getTextFromProduct({ message: (_Ra = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ra.description, find: [`MAX HAIL /INCHES/`], removal: [`%`, `<`, `:`] })) != null ? _Sa : null,
|
|
16254
|
+
max_wind_surface: (_Ua = getTextFromProduct({ message: (_Ta = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ta.description, find: [`MAX WIND GUSTS SURFACE /KNOTS/`], removal: [`%`, `<`, `:`] })) != null ? _Ua : null,
|
|
16255
|
+
max_tops_x100feet: (_Wa = getTextFromProduct({ message: (_Va = feature == null ? void 0 : feature.properties) == null ? void 0 : _Va.description, find: [`MAX TOPS /X 100 FEET/`], removal: [`%`, `<`, `:`] })) != null ? _Wa : null,
|
|
16256
|
+
pds_watch: getTextFromProduct({ message: (_Xa = feature == null ? void 0 : feature.properties) == null ? void 0 : _Xa.description, find: [`PARTICULARLY DANGEROUS SITUATION`], removal: [`%`, `<`, `:`] }) === `YES`
|
|
15762
16257
|
},
|
|
15763
16258
|
metadata: {
|
|
15764
16259
|
ms: performance.now() - tick,
|
|
15765
16260
|
source: `events.api`,
|
|
15766
|
-
tracking: getEventTracking({ type: `API`, organization: { wmoidentifier: (
|
|
15767
|
-
header: `ZCZC-ATMOSX-${(
|
|
16261
|
+
tracking: getEventTracking({ type: `API`, organization: { wmoidentifier: (__a = (_Za = (_Ya = feature == null ? void 0 : feature.properties) == null ? void 0 : _Ya.parameters) == null ? void 0 : _Za.WMOidentifier) == null ? void 0 : __a[0], featureId: feature == null ? void 0 : feature.id }, vtec: pVtec }),
|
|
16262
|
+
header: `ZCZC-ATMOSX-${(_ab = (_$a = feature == null ? void 0 : feature.properties) == null ? void 0 : _$a.parameters) == null ? void 0 : _ab.WMOidentifier}`,
|
|
15768
16263
|
vtec: pVtec,
|
|
15769
16264
|
hvtec: null,
|
|
16265
|
+
raw: (_bb = feature == null ? void 0 : feature.properties) == null ? void 0 : _bb.description,
|
|
15770
16266
|
history: [
|
|
15771
16267
|
{
|
|
15772
|
-
description: (
|
|
15773
|
-
issued: ((
|
|
15774
|
-
status: (
|
|
16268
|
+
description: (_cb = feature == null ? void 0 : feature.properties) == null ? void 0 : _cb.description,
|
|
16269
|
+
issued: ((_db = feature == null ? void 0 : feature.properties) == null ? void 0 : _db.sent) ? new Date((_eb = feature == null ? void 0 : feature.properties) == null ? void 0 : _eb.sent).toISOString() : null,
|
|
16270
|
+
status: (_gb = (_fb = feature == null ? void 0 : feature.properties) == null ? void 0 : _fb.messageType) != null ? _gb : null
|
|
15775
16271
|
}
|
|
15776
16272
|
]
|
|
15777
16273
|
}
|
|
@@ -15959,613 +16455,250 @@ var importShapefiles = () => __async(null, null, function* () {
|
|
|
15959
16455
|
if (properties2.FIPS) {
|
|
15960
16456
|
final2 = `${properties2.STATE}${shapefile.id}${properties2.FIPS.substring(2)}`;
|
|
15961
16457
|
location = `${properties2.COUNTYNAME}, ${properties2.STATE}`;
|
|
15962
|
-
} else if (properties2.FULLSTAID) {
|
|
15963
|
-
final2 = `${properties2.ST}${shapefile.id}${properties2.WFO}`;
|
|
15964
|
-
location = `${properties2.CITY}, ${properties2.STATE}`;
|
|
15965
|
-
} else if (properties2.STATE) {
|
|
15966
|
-
final2 = `${properties2.STATE}${shapefile.id}${(_a2 = properties2.ZONE) != null ? _a2 : properties2.SITE_ID}`;
|
|
15967
|
-
location = `${(_b2 = properties2.NAME) != null ? _b2 : `${properties2.RFC_NAME} ${properties2.RFC_CITY}`}, ${properties2.STATE}`;
|
|
15968
|
-
} else {
|
|
15969
|
-
final2 = (_c = properties2.ID) != null ? _c : properties2.WFO;
|
|
15970
|
-
location = properties2.NAME;
|
|
15971
|
-
}
|
|
15972
|
-
insert.run(final2, location, JSON.stringify(geometry));
|
|
15973
|
-
}
|
|
15974
|
-
});
|
|
15975
|
-
fs.unlinkSync(`${filepath}.shp`);
|
|
15976
|
-
fs.unlinkSync(`${filepath}.dbf`);
|
|
15977
|
-
setWarning({ message: `Cleaned up temporary files for ${shapefile.name}_${shapefile.id}` });
|
|
15978
|
-
transaction(features);
|
|
15979
|
-
}
|
|
15980
|
-
setWarning({ message: `Shapefiles have finished compiling, you can now continue and close this terminal` });
|
|
15981
|
-
fs.rm(resolve5(__dirname, "../../shapefiles"), { recursive: true, force: true }, () => {
|
|
15982
|
-
});
|
|
15983
|
-
}
|
|
15984
|
-
} catch (error) {
|
|
15985
|
-
setWarning({ message: `An error occurred while compiling shapefiles: ${error.message}` });
|
|
15986
|
-
}
|
|
15987
|
-
});
|
|
15988
|
-
|
|
15989
|
-
// src/@modules/@database/database.init.ts
|
|
15990
|
-
var initializeDatabase = () => __async(null, null, function* () {
|
|
15991
|
-
const settings = bootstrap.settings;
|
|
15992
|
-
try {
|
|
15993
|
-
if (!fs2.existsSync(settings.Database)) {
|
|
15994
|
-
fs2.writeFileSync(settings.Database, "");
|
|
15995
|
-
setWarning({ message: `Creating new database at ${settings.Database}` });
|
|
15996
|
-
}
|
|
15997
|
-
bootstrap.database = new sqlite3(settings.Database);
|
|
15998
|
-
bootstrap.database.prepare(`CREATE TABLE IF NOT EXISTS stanzas ( id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT, issued TEXT, stanza TEXT )`).run();
|
|
15999
|
-
bootstrap.database.prepare(`CREATE TABLE IF NOT EXISTS shapefiles (id TEXT PRIMARY KEY, location TEXT, geometry TEXT)`).run();
|
|
16000
|
-
yield importShapefiles();
|
|
16001
|
-
} catch (error) {
|
|
16002
|
-
setWarning({ message: `An error occurred while initializing the database: ${error.message}` });
|
|
16003
|
-
}
|
|
16004
|
-
});
|
|
16005
|
-
|
|
16006
|
-
// src/@modules/@database/database.cache.ts
|
|
16007
|
-
var getCachedEvents = () => __async(null, null, function* () {
|
|
16008
|
-
var _a;
|
|
16009
|
-
try {
|
|
16010
|
-
const settings = bootstrap.settings;
|
|
16011
|
-
const tick = performance.now();
|
|
16012
|
-
if (settings.NOAAWeatherWireServiceSettings.CacheSettings.Enabled) {
|
|
16013
|
-
const max = (_a = settings.NOAAWeatherWireServiceSettings.CacheSettings.MaxRetentionHistory) != null ? _a : 500;
|
|
16014
|
-
const get = yield bootstrap.database.prepare(`SELECT * FROM stanzas ORDER BY rowid DESC LIMIT ?`).all(max);
|
|
16015
|
-
setWarning({ message: `Fetched ${get.length} cached events from the database in ${Math.floor(performance.now() - tick)} ms` });
|
|
16016
|
-
let events = get.map((row) => JSON.parse(row.stanza)).filter((stanza) => {
|
|
16017
|
-
if (!stanza) {
|
|
16018
|
-
return;
|
|
16019
|
-
}
|
|
16020
|
-
const isSkippable = stanza.isIgnored || stanza.isCapEvent || stanza.isCapEvent && !stanza.isCapAreaDescription;
|
|
16021
|
-
return !isSkippable;
|
|
16022
|
-
});
|
|
16023
|
-
events = events.sort((a, b) => b.issued - a.issued);
|
|
16024
|
-
yield Promise.all(events.map((event) => createEvent(event)));
|
|
16025
|
-
setWarning({ message: `Processed ${events.length} cached events in ${Math.floor(performance.now() - tick)} ms` });
|
|
16026
|
-
}
|
|
16027
|
-
} catch (error) {
|
|
16028
|
-
setWarning({ message: `An error occurred while fetching cached events: ${error.message} -> ${error.stack}` });
|
|
16029
|
-
}
|
|
16030
|
-
});
|
|
16031
|
-
|
|
16032
|
-
// src/@modules/@xmpp/xmpp.xReconnect.ts
|
|
16033
|
-
var xReconnect = (interval) => __async(null, null, function* () {
|
|
16034
|
-
const settings = bootstrap.settings;
|
|
16035
|
-
const lastStanza = Date.now() - bootstrap.cache.lastStanza;
|
|
16036
|
-
if (interval < 15) {
|
|
16037
|
-
setWarning({ message: `Reconnection interval of ${interval} seconds is too low, setting to 15 seconds` });
|
|
16038
|
-
interval = 15;
|
|
16039
|
-
bootstrap.settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval = 15;
|
|
16040
|
-
}
|
|
16041
|
-
const reconnectThreshold = interval * 1e3;
|
|
16042
|
-
if (!bootstrap.cache.isConnected && !bootstrap.cache.sigHault || !bootstrap.session_xmpp) {
|
|
16043
|
-
return;
|
|
16044
|
-
}
|
|
16045
|
-
if (lastStanza > reconnectThreshold) {
|
|
16046
|
-
if (!bootstrap.cache.isReconnecting) {
|
|
16047
|
-
bootstrap.cache.isReconnecting = true;
|
|
16048
|
-
bootstrap.cache.isConnected = false;
|
|
16049
|
-
bootstrap.cache.tReconnects += 1;
|
|
16050
|
-
try {
|
|
16051
|
-
setEventEmit({
|
|
16052
|
-
event: `onServiceStatus`,
|
|
16053
|
-
metadata: {
|
|
16054
|
-
message: `Attempting to reconnect to XMPP Service (Reconnect Attempt ${bootstrap.cache.tReconnects})`,
|
|
16055
|
-
data: {
|
|
16056
|
-
last_stanza: lastStanza,
|
|
16057
|
-
nickname: settings.NOAAWeatherWireServiceSettings.CredentialSettings.Nickname
|
|
16058
|
-
},
|
|
16059
|
-
type: `reconnect`,
|
|
16060
|
-
error: true
|
|
16061
|
-
}
|
|
16062
|
-
});
|
|
16063
|
-
yield bootstrap.session_xmpp.stop().catch(() => {
|
|
16064
|
-
});
|
|
16065
|
-
yield bootstrap.session_xmpp.start().catch(() => {
|
|
16066
|
-
});
|
|
16067
|
-
} catch (error) {
|
|
16068
|
-
setWarning({ message: `XMPP Reconnect Failed - ${error.message}` });
|
|
16069
|
-
} finally {
|
|
16070
|
-
bootstrap.cache.isReconnecting = false;
|
|
16071
|
-
}
|
|
16072
|
-
}
|
|
16073
|
-
}
|
|
16074
|
-
});
|
|
16075
|
-
|
|
16076
|
-
// src/@modules/@utilities/utilities.setCronSchedule.ts
|
|
16077
|
-
var setCronSchedule = () => __async(null, null, function* () {
|
|
16078
|
-
const settings = bootstrap.settings;
|
|
16079
|
-
if (settings.EnableWireService) {
|
|
16080
|
-
if (settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.Enabled) {
|
|
16081
|
-
void xReconnect(settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval);
|
|
16082
|
-
}
|
|
16083
|
-
} else {
|
|
16084
|
-
const response2 = yield createHttp({
|
|
16085
|
-
url: settings.NationalWeatherServiceSettings.EventsEndpoint,
|
|
16086
|
-
headers: {
|
|
16087
|
-
"User-Agent": "@atmosx/event-product-parser"
|
|
16088
|
-
}
|
|
16089
|
-
});
|
|
16090
|
-
if (response2.error) {
|
|
16091
|
-
return setEventEmit({
|
|
16092
|
-
event: `onServiceStatus`,
|
|
16093
|
-
metadata: {
|
|
16094
|
-
type: "fetch-api",
|
|
16095
|
-
message: `Failed to fetch latest events from National Weather Service API - ${response2.message}`,
|
|
16096
|
-
data: {},
|
|
16097
|
-
error: true
|
|
16098
|
-
}
|
|
16099
|
-
});
|
|
16100
|
-
}
|
|
16101
|
-
setEventEmit({
|
|
16102
|
-
event: `onServiceStatus`,
|
|
16103
|
-
metadata: {
|
|
16104
|
-
message: `Fetched latest events from National Weather Service API`,
|
|
16105
|
-
data: {},
|
|
16106
|
-
type: "fetch-api",
|
|
16107
|
-
error: false
|
|
16108
|
-
}
|
|
16109
|
-
});
|
|
16110
|
-
createEvent({ message: response2.message, isNWWS: false });
|
|
16111
|
-
}
|
|
16112
|
-
});
|
|
16113
|
-
|
|
16114
|
-
// src/@manager/manager.updateEvents.ts
|
|
16115
|
-
var updateEvents = (selectedEvent) => __async(null, null, function* () {
|
|
16116
|
-
const events = bootstrap.cache.events.features;
|
|
16117
|
-
function update(evt) {
|
|
16118
|
-
return __async(this, null, function* () {
|
|
16119
|
-
if (new Date(evt.properties.expires) < /* @__PURE__ */ new Date()) {
|
|
16120
|
-
rmEvent(evt);
|
|
16121
|
-
}
|
|
16122
|
-
});
|
|
16123
|
-
}
|
|
16124
|
-
if (!selectedEvent) {
|
|
16125
|
-
yield Promise.all(events.map((evt) => __async(null, null, function* () {
|
|
16126
|
-
yield update(evt);
|
|
16127
|
-
})));
|
|
16128
|
-
}
|
|
16129
|
-
if (selectedEvent) {
|
|
16130
|
-
yield update(selectedEvent);
|
|
16131
|
-
}
|
|
16132
|
-
});
|
|
16133
|
-
|
|
16134
|
-
// src/@core/core.start.ts
|
|
16135
|
-
import { Cron } from "croner";
|
|
16136
|
-
var startService = (configurations) => __async(null, null, function* () {
|
|
16137
|
-
if (!bootstrap.isReady) {
|
|
16138
|
-
return setWarning({
|
|
16139
|
-
message: `You can not create another instance without shutting down the current one first, please make sure to call the stop() method first!`
|
|
16140
|
-
});
|
|
16141
|
-
}
|
|
16142
|
-
const settings = setSettings(configurations);
|
|
16143
|
-
bootstrap.isReady = true;
|
|
16144
|
-
yield initializeDatabase();
|
|
16145
|
-
if (settings.EnableWireService) {
|
|
16146
|
-
(() => __async(null, null, function* () {
|
|
16147
|
-
yield getCachedEvents();
|
|
16148
|
-
yield xDeploy();
|
|
16149
|
-
}))();
|
|
16150
|
-
}
|
|
16151
|
-
yield setCronSchedule();
|
|
16152
|
-
let scheduleInterval = !settings.EnableWireService ? settings.NationalWeatherServiceSettings.CallbackInterval : 1;
|
|
16153
|
-
if (!settings.EnableWireService && scheduleInterval < 15) {
|
|
16154
|
-
setWarning({ message: `Schedule interval of ${scheduleInterval} seconds is too low, setting to 15 seconds` });
|
|
16155
|
-
bootstrap.settings.NationalWeatherServiceSettings.CallbackInterval = 15;
|
|
16156
|
-
scheduleInterval = 15;
|
|
16157
|
-
}
|
|
16158
|
-
bootstrap.cron = new Cron(`*/${scheduleInterval} * * * * *`, () => __async(null, null, function* () {
|
|
16159
|
-
yield setCronSchedule();
|
|
16160
|
-
}));
|
|
16161
|
-
bootstrap.cron = new Cron(`* * * * * *`, () => __async(null, null, function* () {
|
|
16162
|
-
yield updateNode();
|
|
16163
|
-
yield updateEvents();
|
|
16164
|
-
}));
|
|
16165
|
-
});
|
|
16166
|
-
|
|
16167
|
-
// src/@core/core.stop.ts
|
|
16168
|
-
var stopService = () => __async(null, null, function* () {
|
|
16169
|
-
if (bootstrap.isReady) {
|
|
16170
|
-
bootstrap.isReady = false;
|
|
16171
|
-
if (bootstrap.session_xmpp) {
|
|
16172
|
-
try {
|
|
16173
|
-
yield bootstrap.session_xmpp.stop();
|
|
16174
|
-
} catch (e) {
|
|
16458
|
+
} else if (properties2.FULLSTAID) {
|
|
16459
|
+
final2 = `${properties2.ST}${shapefile.id}${properties2.WFO}`;
|
|
16460
|
+
location = `${properties2.CITY}, ${properties2.STATE}`;
|
|
16461
|
+
} else if (properties2.STATE) {
|
|
16462
|
+
final2 = `${properties2.STATE}${shapefile.id}${(_a2 = properties2.ZONE) != null ? _a2 : properties2.SITE_ID}`;
|
|
16463
|
+
location = `${(_b2 = properties2.NAME) != null ? _b2 : `${properties2.RFC_NAME} ${properties2.RFC_CITY}`}, ${properties2.STATE}`;
|
|
16464
|
+
} else {
|
|
16465
|
+
final2 = (_c = properties2.ID) != null ? _c : properties2.WFO;
|
|
16466
|
+
location = properties2.NAME;
|
|
16467
|
+
}
|
|
16468
|
+
insert.run(final2, location, JSON.stringify(geometry));
|
|
16469
|
+
}
|
|
16470
|
+
});
|
|
16471
|
+
fs.unlinkSync(`${filepath}.shp`);
|
|
16472
|
+
fs.unlinkSync(`${filepath}.dbf`);
|
|
16473
|
+
setWarning({ message: `Cleaned up temporary files for ${shapefile.name}_${shapefile.id}` });
|
|
16474
|
+
transaction(features);
|
|
16175
16475
|
}
|
|
16176
|
-
|
|
16177
|
-
|
|
16178
|
-
|
|
16476
|
+
setWarning({ message: `Shapefiles have finished compiling, you can now continue and close this terminal` });
|
|
16477
|
+
fs.rm(resolve5(__dirname, "../../shapefiles"), { recursive: true, force: true }, () => {
|
|
16478
|
+
});
|
|
16179
16479
|
}
|
|
16480
|
+
} catch (error) {
|
|
16481
|
+
setWarning({ message: `An error occurred while compiling shapefiles: ${error.message}` });
|
|
16180
16482
|
}
|
|
16181
16483
|
});
|
|
16182
16484
|
|
|
16183
|
-
// src/@
|
|
16184
|
-
var
|
|
16185
|
-
|
|
16186
|
-
|
|
16187
|
-
|
|
16188
|
-
|
|
16189
|
-
|
|
16190
|
-
|
|
16191
|
-
|
|
16192
|
-
|
|
16193
|
-
|
|
16194
|
-
|
|
16195
|
-
|
|
16196
|
-
|
|
16197
|
-
{ regex: /\bAKST\b(?!\w)/g, replacement: "Alaska Standard Time" },
|
|
16198
|
-
{ regex: /\bAKDT\b(?!\w)/g, replacement: "Alaska Daylight Time" },
|
|
16199
|
-
{ regex: /\bHST\b(?!\w)/g, replacement: "Hawaii Standard Time" },
|
|
16200
|
-
{ regex: /\bHDT\b(?!\w)/g, replacement: "Hawaii Daylight Time" },
|
|
16201
|
-
{ regex: /\bmph\b(?!\w)/g, replacement: "miles per hour" },
|
|
16202
|
-
{ regex: /\bkm\/h\b(?!\w)/g, replacement: "kilometers per hour" },
|
|
16203
|
-
{ regex: /\bkmh\b(?!\w)/g, replacement: "kilometers per hour" },
|
|
16204
|
-
{ regex: /\bkt\b(?!\w)/g, replacement: "knots" },
|
|
16205
|
-
{ regex: /\bNE\b(?!\w)/g, replacement: "northeast" },
|
|
16206
|
-
{ regex: /\bNW\b(?!\w)/g, replacement: "northwest" },
|
|
16207
|
-
{ regex: /\bSE\b(?!\w)/g, replacement: "southeast" },
|
|
16208
|
-
{ regex: /\bSW\b(?!\w)/g, replacement: "southwest" },
|
|
16209
|
-
{ regex: /\bNM\b(?!\w)/g, replacement: "nautical miles" },
|
|
16210
|
-
{ regex: /\bdeg\b(?!\w)/g, replacement: "degrees" },
|
|
16211
|
-
{ regex: /\btstm\b(?!\w)/g, replacement: "thunderstorm" },
|
|
16212
|
-
{ regex: /\bmm\b(?!\w)/g, replacement: "millimeters" },
|
|
16213
|
-
{ regex: /\bcm\b(?!\w)/g, replacement: "centimeters" },
|
|
16214
|
-
{ regex: /\bin.\b(?!\w)/g, replacement: "inches" },
|
|
16215
|
-
{ regex: /\bft\b(?!\w)/g, replacement: "feet" },
|
|
16216
|
-
{ regex: /\bmi\b(?!\w)/g, replacement: "miles" },
|
|
16217
|
-
{ regex: /\bhr\b(?!\w)/g, replacement: "hour" },
|
|
16218
|
-
{ regex: /\bhourly\b(?!\w)/g, replacement: "per hour" },
|
|
16219
|
-
{ regex: /\bkg\b(?!\w)/g, replacement: "kilograms" },
|
|
16220
|
-
{ regex: /\bg\/kg\b(?!\w)/g, replacement: "grams per kilogram" },
|
|
16221
|
-
{ regex: /\bmb\b(?!\w)/g, replacement: "millibars" },
|
|
16222
|
-
{ regex: /\bhPa\b(?!\w)/g, replacement: "hectopascals" },
|
|
16223
|
-
{ regex: /\bPa\b(?!\w)/g, replacement: "pascals" },
|
|
16224
|
-
{ regex: /\bKPa\b(?!\w)/g, replacement: "kilopascals" },
|
|
16225
|
-
{ regex: /\bC\/hr\b(?!\w)/g, replacement: "degrees Celsius per hour" },
|
|
16226
|
-
{ regex: /\bF\/hr\b(?!\w)/g, replacement: "degrees Fahrenheit per hour" },
|
|
16227
|
-
{ regex: /\bC\/min\b(?!\w)/g, replacement: "degrees Celsius per minute" },
|
|
16228
|
-
{ regex: /\bF\/min\b(?!\w)/g, replacement: "degrees Fahrenheit per minute" },
|
|
16229
|
-
{ regex: /\bC\b(?!\w)/g, replacement: "degrees Celsius" },
|
|
16230
|
-
{ regex: /\bF\b(?!\w)/g, replacement: "degrees Fahrenheit" }
|
|
16231
|
-
];
|
|
16232
|
-
|
|
16233
|
-
// src/@modules/@eas/eas.getWavPCM16.ts
|
|
16234
|
-
var getWavPCM16 = (buffer) => {
|
|
16235
|
-
if (buffer.toString("ascii", 0, 4) !== "RIFF" || buffer.toString("ascii", 8, 12) !== "WAVE") {
|
|
16236
|
-
return null;
|
|
16237
|
-
}
|
|
16238
|
-
let fmt = null;
|
|
16239
|
-
let data = null;
|
|
16240
|
-
let i = 12;
|
|
16241
|
-
while (i + 8 <= buffer.length) {
|
|
16242
|
-
const id2 = buffer.toString("ascii", i, i + 4);
|
|
16243
|
-
const size = buffer.readUInt32LE(i + 4);
|
|
16244
|
-
const start = i + 8;
|
|
16245
|
-
const end = start + size;
|
|
16246
|
-
if (id2 === "fmt ") fmt = buffer.slice(start, end);
|
|
16247
|
-
if (id2 === "data") data = buffer.slice(start, end);
|
|
16248
|
-
i = end + size % 2;
|
|
16249
|
-
}
|
|
16250
|
-
if (!fmt || !data) return null;
|
|
16251
|
-
const audioFormat = fmt.readUInt16LE(0);
|
|
16252
|
-
const channels = fmt.readUInt16LE(2);
|
|
16253
|
-
const sampleRate = fmt.readUInt32LE(4);
|
|
16254
|
-
const bitsPerSample = fmt.readUInt16LE(14);
|
|
16255
|
-
if (audioFormat !== 1 || bitsPerSample !== 16 || channels !== 1) {
|
|
16256
|
-
return null;
|
|
16257
|
-
}
|
|
16258
|
-
const samples = new Int16Array(data.buffer, data.byteOffset, data.length / 2);
|
|
16259
|
-
return { samples: new Int16Array(samples), sampleRate, channels, bitsPerSample };
|
|
16260
|
-
};
|
|
16261
|
-
|
|
16262
|
-
// src/@modules/@eas/eas.getSampledPCM16.ts
|
|
16263
|
-
var getSampledPCM16 = (int16, originalRate, targetRate) => {
|
|
16264
|
-
if (originalRate === targetRate) return int16;
|
|
16265
|
-
const ratio = targetRate / originalRate;
|
|
16266
|
-
const outLen = Math.max(1, Math.round(int16.length * ratio));
|
|
16267
|
-
const out = new Int16Array(outLen);
|
|
16268
|
-
for (let i = 0; i < outLen; i++) {
|
|
16269
|
-
const pos = i / ratio;
|
|
16270
|
-
const i0 = Math.floor(pos);
|
|
16271
|
-
const i1 = Math.min(i0 + 1, int16.length - 1);
|
|
16272
|
-
const frac = pos - i0;
|
|
16273
|
-
const v = int16[i0] * (1 - frac) + int16[i1] * frac;
|
|
16274
|
-
out[i] = Math.round(v);
|
|
16275
|
-
}
|
|
16276
|
-
return out;
|
|
16277
|
-
};
|
|
16278
|
-
|
|
16279
|
-
// src/@modules/@eas/eas.getPCMToFloat.ts
|
|
16280
|
-
var getPCMToFloat = (int16) => {
|
|
16281
|
-
const out = new Float32Array(int16.length);
|
|
16282
|
-
for (let i = 0; i < int16.length; i++) out[i] = int16[i] / 32768;
|
|
16283
|
-
return out;
|
|
16284
|
-
};
|
|
16285
|
-
|
|
16286
|
-
// src/@modules/@eas/eas.getFloatPCM16.ts
|
|
16287
|
-
var getFloatPCM16 = (float32) => {
|
|
16288
|
-
const out = new Int16Array(float32.length);
|
|
16289
|
-
for (let i = 0; i < float32.length; i++) {
|
|
16290
|
-
let v = Math.max(-1, Math.min(1, float32[i]));
|
|
16291
|
-
out[i] = Math.round(v * 32767);
|
|
16292
|
-
}
|
|
16293
|
-
return out;
|
|
16294
|
-
};
|
|
16295
|
-
|
|
16296
|
-
// src/@modules/@eas/eas.setRadioEffect.ts
|
|
16297
|
-
var setRadioEffect = (int16, sampleRate) => {
|
|
16298
|
-
const hpCut = 3555;
|
|
16299
|
-
const lpCut = 1600;
|
|
16300
|
-
const x = getPCMToFloat(int16);
|
|
16301
|
-
const dt = 1 / sampleRate;
|
|
16302
|
-
const rcHP = 1 / (2 * Math.PI * hpCut);
|
|
16303
|
-
const aHP = rcHP / (rcHP + dt);
|
|
16304
|
-
let yHP = 0, xPrev = 0;
|
|
16305
|
-
for (let i = 0; i < x.length; i++) {
|
|
16306
|
-
const xi = x[i];
|
|
16307
|
-
yHP = aHP * (yHP + xi - xPrev);
|
|
16308
|
-
xPrev = xi;
|
|
16309
|
-
x[i] = yHP;
|
|
16310
|
-
}
|
|
16311
|
-
const rcLP = 1 / (2 * Math.PI * lpCut);
|
|
16312
|
-
const aLP = dt / (rcLP + dt);
|
|
16313
|
-
let yLP = 0;
|
|
16314
|
-
for (let i = 0; i < x.length; i++) {
|
|
16315
|
-
yLP = yLP + aLP * (x[i] - yLP);
|
|
16316
|
-
x[i] = yLP;
|
|
16485
|
+
// src/@modules/@database/database.init.ts
|
|
16486
|
+
var initializeDatabase = () => __async(null, null, function* () {
|
|
16487
|
+
const settings = bootstrap.settings;
|
|
16488
|
+
try {
|
|
16489
|
+
if (!fs2.existsSync(settings.Database)) {
|
|
16490
|
+
fs2.writeFileSync(settings.Database, "");
|
|
16491
|
+
setWarning({ message: `Creating new database at ${settings.Database}` });
|
|
16492
|
+
}
|
|
16493
|
+
bootstrap.database = new sqlite3(settings.Database);
|
|
16494
|
+
bootstrap.database.prepare(`CREATE TABLE IF NOT EXISTS stanzas ( id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT, issued TEXT, stanza TEXT )`).run();
|
|
16495
|
+
bootstrap.database.prepare(`CREATE TABLE IF NOT EXISTS shapefiles (id TEXT PRIMARY KEY, location TEXT, geometry TEXT)`).run();
|
|
16496
|
+
yield importShapefiles();
|
|
16497
|
+
} catch (error) {
|
|
16498
|
+
setWarning({ message: `An error occurred while initializing the database: ${error.message}` });
|
|
16317
16499
|
}
|
|
16318
|
-
|
|
16319
|
-
const norm = Math.tanh(compGain);
|
|
16320
|
-
for (let i = 0; i < x.length; i++) x[i] = Math.tanh(x[i] * compGain) / norm;
|
|
16321
|
-
return getFloatPCM16(x);
|
|
16322
|
-
};
|
|
16500
|
+
});
|
|
16323
16501
|
|
|
16324
|
-
// src/@modules/@
|
|
16325
|
-
var
|
|
16326
|
-
|
|
16327
|
-
|
|
16328
|
-
|
|
16329
|
-
|
|
16330
|
-
|
|
16331
|
-
|
|
16332
|
-
|
|
16333
|
-
|
|
16334
|
-
|
|
16335
|
-
|
|
16336
|
-
|
|
16337
|
-
|
|
16338
|
-
|
|
16339
|
-
|
|
16340
|
-
|
|
16341
|
-
|
|
16342
|
-
|
|
16343
|
-
|
|
16344
|
-
if (phase > twoPi) phase -= twoPi;
|
|
16502
|
+
// src/@modules/@database/database.cache.ts
|
|
16503
|
+
var getCachedEvents = () => __async(null, null, function* () {
|
|
16504
|
+
var _a;
|
|
16505
|
+
try {
|
|
16506
|
+
const settings = bootstrap.settings;
|
|
16507
|
+
const tick = performance.now();
|
|
16508
|
+
if (settings.NOAAWeatherWireServiceSettings.CacheSettings.Enabled) {
|
|
16509
|
+
const max = (_a = settings.NOAAWeatherWireServiceSettings.CacheSettings.MaxRetentionHistory) != null ? _a : 500;
|
|
16510
|
+
const get = yield bootstrap.database.prepare(`SELECT * FROM stanzas ORDER BY rowid DESC LIMIT ?`).all(max);
|
|
16511
|
+
setWarning({ message: `Fetched ${get.length} cached events from the database in ${Math.floor(performance.now() - tick)} ms` });
|
|
16512
|
+
let events = get.map((row) => JSON.parse(row.stanza)).filter((stanza) => {
|
|
16513
|
+
if (!stanza) {
|
|
16514
|
+
return;
|
|
16515
|
+
}
|
|
16516
|
+
const isSkippable = stanza.isIgnored || stanza.isCapEvent || stanza.isCapEvent && !stanza.isCapAreaDescription;
|
|
16517
|
+
return !isSkippable;
|
|
16518
|
+
});
|
|
16519
|
+
events = events.sort((a, b) => b.issued - a.issued);
|
|
16520
|
+
yield Promise.all(events.map((event) => createEvent(event)));
|
|
16521
|
+
setWarning({ message: `Processed ${events.length} cached events in ${Math.floor(performance.now() - tick)} ms` });
|
|
16345
16522
|
}
|
|
16523
|
+
} catch (error) {
|
|
16524
|
+
setWarning({ message: `An error occurred while fetching cached events: ${error.message} -> ${error.stack}` });
|
|
16346
16525
|
}
|
|
16347
|
-
|
|
16348
|
-
for (let i = 0; i < fadeSamples; i++) {
|
|
16349
|
-
const gain = i / fadeSamples;
|
|
16350
|
-
result[i] = Math.round(result[i] * gain);
|
|
16351
|
-
result[result.length - 1 - i] = Math.round(result[result.length - 1 - i] * gain);
|
|
16352
|
-
}
|
|
16353
|
-
return Int16Array.from(result);
|
|
16354
|
-
};
|
|
16526
|
+
});
|
|
16355
16527
|
|
|
16356
|
-
// src/@modules/@
|
|
16357
|
-
var
|
|
16358
|
-
const
|
|
16359
|
-
|
|
16360
|
-
|
|
16361
|
-
|
|
16362
|
-
|
|
16363
|
-
|
|
16528
|
+
// src/@modules/@xmpp/xmpp.xReconnect.ts
|
|
16529
|
+
var xReconnect = (interval) => __async(null, null, function* () {
|
|
16530
|
+
const settings = bootstrap.settings;
|
|
16531
|
+
const lastStanza = Date.now() - bootstrap.cache.lastStanza;
|
|
16532
|
+
if (interval < 15) {
|
|
16533
|
+
setWarning({ message: `Reconnection interval of ${interval} seconds is too low, setting to 15 seconds` });
|
|
16534
|
+
interval = 15;
|
|
16535
|
+
bootstrap.settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval = 15;
|
|
16364
16536
|
}
|
|
16365
|
-
|
|
16366
|
-
|
|
16367
|
-
|
|
16368
|
-
// src/@modules/@eas/eas.getMergedPCM16.ts
|
|
16369
|
-
var getMergedPCM16 = (arrays) => {
|
|
16370
|
-
let total = 0;
|
|
16371
|
-
for (const a of arrays) total += a.length;
|
|
16372
|
-
const out = new Int16Array(total);
|
|
16373
|
-
let o = 0;
|
|
16374
|
-
for (const a of arrays) {
|
|
16375
|
-
out.set(a, o);
|
|
16376
|
-
o += a.length;
|
|
16537
|
+
const reconnectThreshold = interval * 1e3;
|
|
16538
|
+
if (!bootstrap.cache.isConnected && !bootstrap.cache.sigHault || !bootstrap.session_xmpp) {
|
|
16539
|
+
return;
|
|
16377
16540
|
}
|
|
16378
|
-
|
|
16379
|
-
|
|
16380
|
-
|
|
16381
|
-
|
|
16382
|
-
|
|
16383
|
-
|
|
16384
|
-
|
|
16385
|
-
|
|
16386
|
-
|
|
16387
|
-
|
|
16388
|
-
|
|
16389
|
-
|
|
16390
|
-
|
|
16391
|
-
|
|
16392
|
-
|
|
16393
|
-
|
|
16394
|
-
|
|
16541
|
+
if (lastStanza > reconnectThreshold) {
|
|
16542
|
+
if (!bootstrap.cache.isReconnecting) {
|
|
16543
|
+
bootstrap.cache.isReconnecting = true;
|
|
16544
|
+
bootstrap.cache.isConnected = false;
|
|
16545
|
+
bootstrap.cache.tReconnects += 1;
|
|
16546
|
+
try {
|
|
16547
|
+
setEventEmit({
|
|
16548
|
+
event: `onServiceStatus`,
|
|
16549
|
+
metadata: {
|
|
16550
|
+
message: `Attempting to reconnect to XMPP Service (Reconnect Attempt ${bootstrap.cache.tReconnects})`,
|
|
16551
|
+
data: {
|
|
16552
|
+
last_stanza: lastStanza,
|
|
16553
|
+
nickname: settings.NOAAWeatherWireServiceSettings.CredentialSettings.Nickname
|
|
16554
|
+
},
|
|
16555
|
+
type: `reconnect`,
|
|
16556
|
+
error: true
|
|
16557
|
+
}
|
|
16558
|
+
});
|
|
16559
|
+
yield bootstrap.session_xmpp.stop().catch(() => {
|
|
16560
|
+
});
|
|
16561
|
+
yield bootstrap.session_xmpp.start().catch(() => {
|
|
16562
|
+
});
|
|
16563
|
+
} catch (error) {
|
|
16564
|
+
setWarning({ message: `XMPP Reconnect Failed - ${error.message}` });
|
|
16565
|
+
} finally {
|
|
16566
|
+
bootstrap.cache.isReconnecting = false;
|
|
16567
|
+
}
|
|
16395
16568
|
}
|
|
16396
|
-
extendedBody.set(gap, extendedBodyDuration);
|
|
16397
|
-
bursts.push(extendedBody);
|
|
16398
|
-
if (i !== repeats - 1) bursts.push(gap);
|
|
16399
|
-
}
|
|
16400
|
-
return getMergedPCM16(bursts);
|
|
16401
|
-
};
|
|
16402
|
-
|
|
16403
|
-
// src/@modules/@eas/eas.setAttentionTone.ts
|
|
16404
|
-
var setAttentionTone = (ms, sampleRate) => {
|
|
16405
|
-
const len = Math.floor(ms * sampleRate);
|
|
16406
|
-
const out = new Int16Array(len);
|
|
16407
|
-
const f1 = 853;
|
|
16408
|
-
const f2 = 960;
|
|
16409
|
-
const twoPi = Math.PI * 2;
|
|
16410
|
-
const amp = 0.1;
|
|
16411
|
-
const fadeLen = Math.floor(sampleRate * 0);
|
|
16412
|
-
for (let i = 0; i < len; i++) {
|
|
16413
|
-
const t = i / sampleRate;
|
|
16414
|
-
const s = Math.sin(twoPi * f1 * t) + Math.sin(twoPi * f2 * t);
|
|
16415
|
-
let gain = 1;
|
|
16416
|
-
if (i < fadeLen) gain = i / fadeLen;
|
|
16417
|
-
else if (i > len - fadeLen) gain = (len - i) / fadeLen;
|
|
16418
|
-
const v = Math.max(-1, Math.min(1, s / 2 * amp * gain));
|
|
16419
|
-
out[i] = Math.round(v * 32767);
|
|
16420
|
-
}
|
|
16421
|
-
return out;
|
|
16422
|
-
};
|
|
16423
|
-
|
|
16424
|
-
// src/@modules/@eas/eas.setNoise.ts
|
|
16425
|
-
var setNoise = (int16, noiseLevel = 0.02) => {
|
|
16426
|
-
const x = getPCMToFloat(int16);
|
|
16427
|
-
for (let i = 0; i < x.length; i++) x[i] += (Math.random() * 2 - 1) * noiseLevel;
|
|
16428
|
-
let peak = 0;
|
|
16429
|
-
for (let i = 0; i < x.length; i++) peak = Math.max(peak, Math.abs(x[i]));
|
|
16430
|
-
if (peak > 1) for (let i = 0; i < x.length; i++) x[i] *= 0.98 / peak;
|
|
16431
|
-
return getFloatPCM16(x);
|
|
16432
|
-
};
|
|
16433
|
-
|
|
16434
|
-
// src/@modules/@eas/eas.getPCM16.ts
|
|
16435
|
-
var getPCM16 = (samples, sampleRate) => {
|
|
16436
|
-
let o = 0;
|
|
16437
|
-
const bytesPerSample = 2;
|
|
16438
|
-
const blockAlign = 1 * bytesPerSample;
|
|
16439
|
-
const byteRate = sampleRate * blockAlign;
|
|
16440
|
-
const subchunk2Size = samples.length * bytesPerSample;
|
|
16441
|
-
const chunkSize = 36 + subchunk2Size;
|
|
16442
|
-
const buffer = Buffer.alloc(44 + subchunk2Size);
|
|
16443
|
-
buffer.write("RIFF", o);
|
|
16444
|
-
o += 4;
|
|
16445
|
-
buffer.writeUInt32LE(chunkSize, o);
|
|
16446
|
-
o += 4;
|
|
16447
|
-
buffer.write("WAVE", o);
|
|
16448
|
-
o += 4;
|
|
16449
|
-
buffer.write("fmt ", o);
|
|
16450
|
-
o += 4;
|
|
16451
|
-
buffer.writeUInt32LE(16, o);
|
|
16452
|
-
o += 4;
|
|
16453
|
-
buffer.writeUInt16LE(1, o);
|
|
16454
|
-
o += 2;
|
|
16455
|
-
buffer.writeUInt16LE(1, o);
|
|
16456
|
-
o += 2;
|
|
16457
|
-
buffer.writeUInt32LE(sampleRate, o);
|
|
16458
|
-
o += 4;
|
|
16459
|
-
buffer.writeUInt32LE(byteRate, o);
|
|
16460
|
-
o += 4;
|
|
16461
|
-
buffer.writeUInt16LE(blockAlign, o);
|
|
16462
|
-
o += 2;
|
|
16463
|
-
buffer.writeUInt16LE(16, o);
|
|
16464
|
-
o += 2;
|
|
16465
|
-
buffer.write("data", o);
|
|
16466
|
-
o += 4;
|
|
16467
|
-
buffer.writeUInt32LE(subchunk2Size, o);
|
|
16468
|
-
o += 4;
|
|
16469
|
-
for (let i = 0; i < samples.length; i++, o += 2) {
|
|
16470
|
-
buffer.writeInt16LE(samples[i].value, o);
|
|
16471
16569
|
}
|
|
16472
|
-
|
|
16473
|
-
};
|
|
16570
|
+
});
|
|
16474
16571
|
|
|
16475
|
-
// src/@modules/@
|
|
16476
|
-
import {
|
|
16477
|
-
import {
|
|
16478
|
-
|
|
16479
|
-
import { platform } from "os";
|
|
16480
|
-
import say from "say";
|
|
16481
|
-
var setEasTone = (options) => __async(null, null, function* () {
|
|
16572
|
+
// src/@modules/@utilities/utilities.setCronSchedule.ts
|
|
16573
|
+
import { readdirSync, unlinkSync as unlinkSync2, statSync, existsSync as existsSync2 } from "fs";
|
|
16574
|
+
import { join as join2 } from "path";
|
|
16575
|
+
var setCronSchedule = () => __async(null, null, function* () {
|
|
16482
16576
|
const settings = bootstrap.settings;
|
|
16483
|
-
const
|
|
16484
|
-
const
|
|
16485
|
-
|
|
16486
|
-
|
|
16487
|
-
|
|
16488
|
-
|
|
16489
|
-
|
|
16490
|
-
|
|
16491
|
-
|
|
16492
|
-
|
|
16493
|
-
|
|
16494
|
-
|
|
16495
|
-
|
|
16577
|
+
const TTL = settings.GlobalSettings.EASSettings.ArchiveTTL;
|
|
16578
|
+
const TTLCUT = Date.now() - TTL * 1e3;
|
|
16579
|
+
const walk = (dir) => {
|
|
16580
|
+
if (existsSync2(dir)) {
|
|
16581
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
16582
|
+
for (const entry of entries) {
|
|
16583
|
+
const fullPath = join2(dir, entry.name);
|
|
16584
|
+
if (entry.isDirectory()) {
|
|
16585
|
+
walk(fullPath);
|
|
16586
|
+
continue;
|
|
16587
|
+
}
|
|
16588
|
+
const stats = statSync(fullPath);
|
|
16589
|
+
if (stats.mtime.getTime() < TTLCUT) {
|
|
16590
|
+
try {
|
|
16591
|
+
unlinkSync2(fullPath);
|
|
16592
|
+
} catch (err) {
|
|
16593
|
+
console.error(`Failed to delete ${fullPath}:`, err);
|
|
16594
|
+
}
|
|
16595
|
+
}
|
|
16596
|
+
}
|
|
16597
|
+
}
|
|
16598
|
+
};
|
|
16599
|
+
walk(settings.GlobalSettings.EASSettings.ArchiveDirectory);
|
|
16600
|
+
if (settings.EnableWireService) {
|
|
16601
|
+
if (settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.Enabled) {
|
|
16602
|
+
void xReconnect(settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval);
|
|
16603
|
+
}
|
|
16604
|
+
} else {
|
|
16605
|
+
const response2 = yield createHttp({
|
|
16606
|
+
url: settings.NationalWeatherServiceSettings.EventsEndpoint,
|
|
16607
|
+
headers: {
|
|
16608
|
+
"User-Agent": "@atmosx/event-product-parser"
|
|
16609
|
+
}
|
|
16610
|
+
});
|
|
16611
|
+
if (response2.error) {
|
|
16612
|
+
return setEventEmit({
|
|
16613
|
+
event: `onServiceStatus`,
|
|
16614
|
+
metadata: {
|
|
16615
|
+
type: "fetch-api",
|
|
16616
|
+
message: `Failed to fetch latest events from National Weather Service API - ${response2.message}`,
|
|
16617
|
+
data: {},
|
|
16618
|
+
error: true
|
|
16619
|
+
}
|
|
16620
|
+
});
|
|
16621
|
+
}
|
|
16622
|
+
setEventEmit({
|
|
16623
|
+
event: `onServiceStatus`,
|
|
16624
|
+
metadata: {
|
|
16625
|
+
message: `Fetched latest events from National Weather Service API`,
|
|
16626
|
+
data: {},
|
|
16627
|
+
type: "fetch-api",
|
|
16628
|
+
error: false
|
|
16629
|
+
}
|
|
16630
|
+
});
|
|
16631
|
+
createEvent({ message: response2.message, isNWWS: false });
|
|
16496
16632
|
}
|
|
16497
|
-
|
|
16498
|
-
|
|
16633
|
+
});
|
|
16634
|
+
|
|
16635
|
+
// src/@manager/manager.updateEvents.ts
|
|
16636
|
+
var updateEvents = (selectedEvent) => __async(null, null, function* () {
|
|
16637
|
+
const events = bootstrap.cache.events.features;
|
|
16638
|
+
function update(evt) {
|
|
16639
|
+
return __async(this, null, function* () {
|
|
16640
|
+
if (new Date(evt.properties.expires) < /* @__PURE__ */ new Date()) {
|
|
16641
|
+
rmEvent(evt);
|
|
16642
|
+
}
|
|
16643
|
+
});
|
|
16499
16644
|
}
|
|
16500
|
-
if (!
|
|
16501
|
-
|
|
16645
|
+
if (!selectedEvent) {
|
|
16646
|
+
yield Promise.all(events.map((evt) => __async(null, null, function* () {
|
|
16647
|
+
yield update(evt);
|
|
16648
|
+
})));
|
|
16502
16649
|
}
|
|
16503
|
-
|
|
16504
|
-
|
|
16650
|
+
if (selectedEvent) {
|
|
16651
|
+
yield update(selectedEvent);
|
|
16505
16652
|
}
|
|
16506
|
-
|
|
16507
|
-
|
|
16508
|
-
|
|
16509
|
-
|
|
16653
|
+
});
|
|
16654
|
+
|
|
16655
|
+
// src/@core/core.start.ts
|
|
16656
|
+
import { Cron } from "croner";
|
|
16657
|
+
var startService = (configurations) => __async(null, null, function* () {
|
|
16658
|
+
if (!bootstrap.isReady) {
|
|
16659
|
+
return setWarning({
|
|
16660
|
+
message: `You can not create another instance without shutting down the current one first, please make sure to call the stop() method first!`
|
|
16510
16661
|
});
|
|
16511
|
-
return null;
|
|
16512
16662
|
}
|
|
16513
|
-
|
|
16514
|
-
|
|
16515
|
-
|
|
16663
|
+
const settings = setSettings(configurations);
|
|
16664
|
+
bootstrap.isReady = true;
|
|
16665
|
+
yield initializeDatabase();
|
|
16666
|
+
if (settings.EnableWireService) {
|
|
16667
|
+
(() => __async(null, null, function* () {
|
|
16668
|
+
yield getCachedEvents();
|
|
16669
|
+
yield xDeploy();
|
|
16670
|
+
}))();
|
|
16516
16671
|
}
|
|
16517
|
-
|
|
16518
|
-
|
|
16519
|
-
|
|
16520
|
-
|
|
16521
|
-
|
|
16522
|
-
|
|
16523
|
-
|
|
16672
|
+
yield setCronSchedule();
|
|
16673
|
+
let scheduleInterval = !settings.EnableWireService ? settings.NationalWeatherServiceSettings.CallbackInterval : 1;
|
|
16674
|
+
if (!settings.EnableWireService && scheduleInterval < 15) {
|
|
16675
|
+
setWarning({ message: `Schedule interval of ${scheduleInterval} seconds is too low, setting to 15 seconds` });
|
|
16676
|
+
bootstrap.settings.NationalWeatherServiceSettings.CallbackInterval = 15;
|
|
16677
|
+
scheduleInterval = 15;
|
|
16678
|
+
}
|
|
16679
|
+
bootstrap.cron = new Cron(`*/${scheduleInterval} * * * * *`, () => __async(null, null, function* () {
|
|
16680
|
+
yield setCronSchedule();
|
|
16681
|
+
}));
|
|
16682
|
+
bootstrap.cron = new Cron(`* * * * * *`, () => __async(null, null, function* () {
|
|
16683
|
+
yield updateNode();
|
|
16684
|
+
yield updateEvents();
|
|
16685
|
+
}));
|
|
16686
|
+
});
|
|
16687
|
+
|
|
16688
|
+
// src/@core/core.stop.ts
|
|
16689
|
+
var stopService = () => __async(null, null, function* () {
|
|
16690
|
+
if (bootstrap.isReady) {
|
|
16691
|
+
bootstrap.isReady = false;
|
|
16692
|
+
if (bootstrap.session_xmpp) {
|
|
16524
16693
|
try {
|
|
16525
|
-
|
|
16526
|
-
execSync(`ffmpeg -y -i "${prefix}" -ar 8000 -ac 1 -sample_fmt s16 "${converted}"`, { stdio: "ignore" });
|
|
16527
|
-
if (existsSync(converted)) {
|
|
16528
|
-
tBuffer = readFileSync(converted);
|
|
16529
|
-
tWav = getWavPCM16(tBuffer);
|
|
16530
|
-
try {
|
|
16531
|
-
unlinkSync(converted);
|
|
16532
|
-
} catch (e) {
|
|
16533
|
-
}
|
|
16534
|
-
}
|
|
16694
|
+
yield bootstrap.session_xmpp.stop();
|
|
16535
16695
|
} catch (e) {
|
|
16536
16696
|
}
|
|
16697
|
+
bootstrap.cache.isConnected = false;
|
|
16698
|
+
bootstrap.cache.sigHault = true;
|
|
16699
|
+
bootstrap.session_xmpp = null;
|
|
16537
16700
|
}
|
|
16538
|
-
if (tWav == null) {
|
|
16539
|
-
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.` });
|
|
16540
|
-
return null;
|
|
16541
|
-
}
|
|
16542
|
-
const tSamples = tWav.sampleRate != 8e3 ? getSampledPCM16(tWav.samples, tWav.sampleRate, 8e3) : tWav.samples;
|
|
16543
|
-
buffRadio = setRadioEffect(tSamples, 8e3);
|
|
16544
|
-
}
|
|
16545
|
-
buffFull = buffRadio != null ? [buffRadio, new Int16Array(Math.floor(0.5 * 8e3))] : [];
|
|
16546
|
-
buffFull.push(
|
|
16547
|
-
setSameHeader(header, 3, 8e3, {
|
|
16548
|
-
preMarkSec: 1.1,
|
|
16549
|
-
gapSec: 0.5
|
|
16550
|
-
}),
|
|
16551
|
-
new Int16Array(Math.floor(0.5 * 8e3)),
|
|
16552
|
-
setAttentionTone(8, 8e3),
|
|
16553
|
-
new Int16Array(Math.floor(0.5 * 8e3)),
|
|
16554
|
-
vRadio
|
|
16555
|
-
);
|
|
16556
|
-
for (let i = 0; i < 3; i++) {
|
|
16557
|
-
buffFull.push(setSameHeader(header, 1, 8e3, { preMarkSec: 0.5, gapSec: 0.1 }));
|
|
16558
|
-
buffFull.push(new Int16Array(Math.floor(0.5 * 8e3)));
|
|
16559
|
-
}
|
|
16560
|
-
const aSamples = getMergedPCM16(buffFull);
|
|
16561
|
-
const aFinal = setNoise(aSamples, 2e-3);
|
|
16562
|
-
const aBuffer = getPCM16(Array.from(aFinal).map((v) => ({ value: v })), 8e3);
|
|
16563
|
-
writeFileSync(outTTS, aBuffer);
|
|
16564
|
-
try {
|
|
16565
|
-
unlinkSync(tmpTTS);
|
|
16566
|
-
} catch (e) {
|
|
16567
16701
|
}
|
|
16568
|
-
return outTTS;
|
|
16569
16702
|
});
|
|
16570
16703
|
|
|
16571
16704
|
// src/@core/core.setNode.ts
|
|
@@ -16636,6 +16769,16 @@ var getRandomEvent = () => {
|
|
|
16636
16769
|
return bootstrap.cache.events.features[Math.floor(Math.random() * bootstrap.cache.events.features.length)];
|
|
16637
16770
|
};
|
|
16638
16771
|
|
|
16772
|
+
// src/@core/core.query.ts
|
|
16773
|
+
var query = (options) => __async(null, null, function* () {
|
|
16774
|
+
var _a;
|
|
16775
|
+
const get = yield bootstrap.database.prepare(
|
|
16776
|
+
`SELECT * FROM stanzas WHERE stanza LIKE ? LIMIT ?`
|
|
16777
|
+
).all(`%${options.search}%`, (_a = options.max) != null ? _a : 100);
|
|
16778
|
+
const events = get.map((row) => JSON.parse(row.stanza));
|
|
16779
|
+
return events;
|
|
16780
|
+
});
|
|
16781
|
+
|
|
16639
16782
|
// src/@core/core.clearEvents.ts
|
|
16640
16783
|
var clearEvents = () => {
|
|
16641
16784
|
bootstrap.cache.events.features = [];
|
|
@@ -16686,6 +16829,7 @@ export {
|
|
|
16686
16829
|
getEvents,
|
|
16687
16830
|
getNodes,
|
|
16688
16831
|
getRandomEvent,
|
|
16832
|
+
query,
|
|
16689
16833
|
setEasTone,
|
|
16690
16834
|
setNode,
|
|
16691
16835
|
setSettings,
|