@atmosx/event-product-parser 3.0.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/README.md +299 -5
  2. package/dist/cjs/index.cjs +10188 -237
  3. package/dist/esm/index.mjs +10186 -237
  4. package/dist/index.d.mts +235 -0
  5. package/dist/index.d.ts +235 -0
  6. package/package.json +4 -3
  7. package/src/@building/building.clean.ts +1 -1
  8. package/src/@building/building.create.ts +1 -1
  9. package/src/@building/building.enhance.ts +1 -1
  10. package/src/@building/building.geometry.ts +7 -1
  11. package/src/@building/building.headers.ts +1 -1
  12. package/src/@building/building.office.ts +1 -1
  13. package/src/@building/building.polygon.ts +1 -1
  14. package/src/@building/building.properties.ts +1 -1
  15. package/src/@building/building.signature.ts +9 -26
  16. package/src/@building/building.tags.ts +1 -1
  17. package/src/@building/building.tracking.ts +1 -1
  18. package/src/@building/building.validate.ts +19 -4
  19. package/src/@core/core.getEvents.ts +1 -1
  20. package/src/@core/core.getNodes.ts +1 -1
  21. package/src/@core/{core.callback.ts → core.getRandomEvent.ts} +3 -17
  22. package/src/@core/core.getVersion.ts +25 -0
  23. package/src/@core/core.listener.ts +1 -1
  24. package/src/@core/core.setNode.ts +2 -2
  25. package/src/@core/core.start.ts +9 -4
  26. package/src/@core/core.stop.ts +1 -1
  27. package/src/@dictionaries/dictionaries.betterEventNames.ts +5 -1
  28. package/src/@dictionaries/dictionaries.eventActions.ts +1 -1
  29. package/src/@dictionaries/dictionaries.eventAwipAbreviations.ts +2 -2
  30. package/src/@dictionaries/dictionaries.eventCancelMessages.ts +2 -1
  31. package/src/@dictionaries/dictionaries.eventCauses.ts +1 -1
  32. package/src/@dictionaries/dictionaries.eventProducts.ts +1 -1
  33. package/src/@dictionaries/dictionaries.eventRecords.ts +1 -1
  34. package/src/@dictionaries/dictionaries.eventSeverity.ts +1 -1
  35. package/src/@dictionaries/dictionaries.eventStatus.ts +1 -1
  36. package/src/@dictionaries/dictionaries.eventTags.ts +1 -1
  37. package/src/@dictionaries/dictionaries.eventTypes.ts +1 -1
  38. package/src/@dictionaries/dictionaries.eventsOffshore.ts +1 -1
  39. package/src/@dictionaries/dictionaries.hailStrings.ts +3 -1
  40. package/src/@dictionaries/dictionaries.officeICAOs.ts +1 -1
  41. package/src/@dictionaries/dictionaries.regExp.ts +1 -1
  42. package/src/@dictionaries/dictionaries.shapefileLinks.ts +1 -1
  43. package/src/@dictionaries/dictionaries.statusCorrelationText.ts +1 -1
  44. package/src/@dictionaries/{dictionaries.test_signatures.ts → dictionaries.testSignatures.ts} +3 -2
  45. package/src/@dictionaries/dictionaries.transcribedMessageReplacements.ts +1 -1
  46. package/src/@events/events.api.ts +1 -1
  47. package/src/@events/events.text.ts +1 -1
  48. package/src/@events/events.ugc.ts +1 -1
  49. package/src/@events/events.vtec.ts +5 -5
  50. package/src/@manager/manager.mkEvent.ts +54 -38
  51. package/src/@manager/manager.rmEvent.ts +3 -1
  52. package/src/@manager/manager.setHash.ts +2 -2
  53. package/src/@manager/manager.updateNodes.ts +10 -6
  54. package/src/@manager/manager.updateWebhooks.ts +50 -0
  55. package/src/@modules/@database/database.cache.ts +1 -1
  56. package/src/@modules/@database/database.init.ts +1 -1
  57. package/src/@modules/@database/database.shapefiles.ts +2 -3
  58. package/src/@modules/@database/database.stanza.ts +2 -1
  59. package/src/@modules/@eas/eas.getFloatPCM16.ts +29 -0
  60. package/src/@modules/@eas/eas.getMergedPCM16.ts +32 -0
  61. package/src/@modules/@eas/eas.getPCM16.ts +52 -0
  62. package/src/@modules/@eas/eas.getPCMToFloat.ts +26 -0
  63. package/src/@modules/@eas/eas.getSampledPCM16.ts +36 -0
  64. package/src/@modules/@eas/eas.getWavPCM16.ts +52 -0
  65. package/src/@modules/@eas/eas.setAFSK.ts +52 -0
  66. package/src/@modules/@eas/eas.setAsciiToBits.ts +32 -0
  67. package/src/@modules/@eas/eas.setAttentionTone.ts +40 -0
  68. package/src/@modules/@eas/eas.setEasTone.ts +137 -0
  69. package/src/@modules/@eas/eas.setNoise.ts +31 -0
  70. package/src/@modules/@eas/eas.setRadioEffect.ts +49 -0
  71. package/src/@modules/@eas/eas.setSameHeader.ts +45 -0
  72. package/src/@modules/@stanza/stanza.getAwipsType.ts +1 -1
  73. package/src/@modules/@stanza/stanza.validate.ts +1 -1
  74. package/src/@modules/@utilities/utilities.createHttp.ts +17 -7
  75. package/src/@modules/@utilities/utilities.createWebhook.ts +100 -0
  76. package/src/@modules/@utilities/utilities.getFormattedTime.ts +1 -1
  77. package/src/@modules/@utilities/utilities.getSettings.ts +1 -1
  78. package/src/@modules/@utilities/utilities.getShapeNearestPoint.ts +1 -1
  79. package/src/@modules/@utilities/utilities.setCronSchedule.ts +31 -4
  80. package/src/@modules/@utilities/utilities.setEventEmit.ts +1 -1
  81. package/src/@modules/@utilities/utilities.setListener.ts +3 -3
  82. package/src/@modules/@utilities/utilities.setSettings.ts +1 -1
  83. package/src/@modules/@utilities/utilities.setSleep.ts +3 -3
  84. package/src/@modules/@utilities/utilities.setTimeoutAction.ts +4 -4
  85. package/src/@modules/@utilities/utilities.setWarning.ts +3 -3
  86. package/src/@modules/@xmpp/xmpp.xDeploy.ts +2 -2
  87. package/src/@modules/@xmpp/xmpp.xError.ts +1 -10
  88. package/src/@modules/@xmpp/xmpp.xOffline.ts +2 -2
  89. package/src/@modules/@xmpp/xmpp.xOnline.ts +3 -19
  90. package/src/@modules/@xmpp/xmpp.xReconnect.ts +7 -2
  91. package/src/@modules/@xmpp/xmpp.xStanza.ts +3 -3
  92. package/src/@parsers/@hvtec/hvtec.extract.ts +1 -1
  93. package/src/@parsers/@pvtec/pvtec.expires.ts +1 -1
  94. package/src/@parsers/@pvtec/pvtec.extract.ts +3 -4
  95. package/src/@parsers/@text/text.getDescriptionFromProduct.ts +1 -1
  96. package/src/@parsers/@text/text.getPolygonFromProduct.ts +1 -1
  97. package/src/@parsers/@text/text.getTextFromProduct.ts +1 -1
  98. package/src/@parsers/@text/text.getXML.ts +1 -1
  99. package/src/@parsers/@ugc/ugc.coordinates.ts +1 -1
  100. package/src/@parsers/@ugc/ugc.expiry.ts +1 -1
  101. package/src/@parsers/@ugc/ugc.extract.ts +1 -1
  102. package/src/@parsers/@ugc/ugc.header.ts +1 -1
  103. package/src/@parsers/@ugc/ugc.locations.ts +1 -1
  104. package/src/@parsers/@ugc/ugc.zones.ts +1 -1
  105. package/src/@types/type.event.ts +12 -12
  106. package/src/@types/type.properties.ts +1 -1
  107. package/src/@types/types.attributes.ts +1 -1
  108. package/src/@types/types.compiled.ts +1 -1
  109. package/src/@types/types.hash.ts +1 -1
  110. package/src/@types/types.hvtec.ts +1 -1
  111. package/src/@types/types.pvtec.ts +2 -1
  112. package/src/@types/types.settings.ts +10 -5
  113. package/src/@types/types.stanza.ts +1 -1
  114. package/src/@types/types.ugc.ts +1 -1
  115. package/src/@types/types.webhook.ts +26 -0
  116. package/src/bootstrap.ts +7 -4
  117. package/src/index.ts +11 -12
  118. package/test.js +29 -18
  119. package/tsup.config.ts +1 -0
@@ -0,0 +1,40 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+
19
+ */
20
+
21
+ export const setAttentionTone = (ms: number, sampleRate: number): Int16Array => {
22
+ const len = Math.floor(ms * sampleRate);
23
+ const out = new Int16Array(len);
24
+ const f1 = 853;
25
+ const f2 = 960;
26
+ const twoPi = Math.PI * 2;
27
+ const amp = 0.1;
28
+ const fadeLen = Math.floor(sampleRate * 0.00);
29
+ for (let i = 0; i < len; i++) {
30
+ const t = i / sampleRate;
31
+ const s = Math.sin(twoPi * f1 * t) + Math.sin(twoPi * f2 * t);
32
+ let gain = 1;
33
+ if (i < fadeLen) gain = i / fadeLen;
34
+ else if (i > len - fadeLen) gain = (len - i) / fadeLen;
35
+ const v = Math.max(-1, Math.min(1, (s / 2) * amp * gain));
36
+ out[i] = Math.round(v * 32767);
37
+ }
38
+ return out;
39
+ }
40
+
@@ -0,0 +1,137 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { TypeSettings } from "../../@types/types.settings";
21
+ import { transcribedMessageReplacements } from "../../@dictionaries/dictionaries.transcribedMessageReplacements";
22
+ import { bootstrap } from "../../bootstrap";
23
+ import { setSleep } from "../@utilities/utilities.setSleep"
24
+ import { getWavPCM16 } from "./eas.getWavPCM16";
25
+ import { getSampledPCM16 } from "./eas.getSampledPCM16";
26
+ import { setRadioEffect } from "./eas.setRadioEffect";
27
+ import { setSameHeader } from "./eas.setSameHeader";
28
+ import { setAttentionTone } from "./eas.setAttentionTone";
29
+ import { getMergedPCM16 } from "./eas.getMergedPCM16";
30
+ import { setNoise } from "./eas.setNoise";
31
+ import { getPCM16 } from "./eas.getPCM16";
32
+ import { join } from 'path'
33
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'fs'
34
+ import { execSync } from 'child_process'
35
+ import { platform } from 'os'
36
+ import { setWarning } from "../@utilities/utilities.setWarning";
37
+ import say from 'say'
38
+
39
+ interface GenerateEASOptions {
40
+ message: string
41
+ header: string
42
+ }
43
+
44
+ export const setEasTone = async (options: GenerateEASOptions): Promise<string> => {
45
+ const settings = bootstrap.settings as TypeSettings;
46
+ const directory = settings.GlobalSettings.EASSettings.ArchiveDirectory;
47
+ const prefix = settings.GlobalSettings.EASSettings.IntroWavFile;
48
+ let message = options.message;
49
+ let header = options.header;
50
+ let buffTTS: Buffer;
51
+ let buffRadio: any;
52
+ let buffFull: any[] = [];
53
+
54
+
55
+ const tmpTTS = join(directory, `/temp/${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, '')}.wav`)
56
+ const outTTS = join(directory, `/output/${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, '')}.wav`)
57
+ const vTTS = process.platform === `win32` ? `Microsoft David Desktop` : `en-US-GuyNerual`;
58
+ const vPlatform = platform();
59
+
60
+ if (!existsSync(directory)) {
61
+ mkdirSync(directory, { recursive: true });
62
+ }
63
+ if (!existsSync(join(directory, `/temp`))) {
64
+ mkdirSync(join(directory, `/temp`), { recursive: true });
65
+ }
66
+ if (!existsSync(join(directory, `/output`))) {
67
+ mkdirSync(join(directory, `/output`), { recursive: true });
68
+ }
69
+ for (const {regex, replacement} of transcribedMessageReplacements) {
70
+ message = message.replace(regex, replacement)
71
+ }
72
+
73
+ if (vPlatform != `win32`) {
74
+ setWarning({
75
+ title: `EAS`,
76
+ message: `Generation isn't supported with this OS. Please wait for further updates before trying again`
77
+ })
78
+ return null;
79
+ }
80
+
81
+ say.export(message, vTTS, 1.0, tmpTTS)
82
+ while (!existsSync(tmpTTS) || (buffTTS = readFileSync(tmpTTS)).length == 0) {
83
+ await setSleep({timeout: 25});
84
+ }
85
+ const vWav = getWavPCM16(buffTTS);
86
+ const vSamples = getSampledPCM16(vWav.samples, vWav.sampleRate, 8000)
87
+ const vRadio = setRadioEffect(vSamples, 8000)
88
+
89
+ if (existsSync(prefix)) {
90
+ let tBuffer = readFileSync(prefix);
91
+ let tWav = getWavPCM16(tBuffer);
92
+
93
+ if (tWav == null) {
94
+ try {
95
+ const converted = join(directory, `/temp/${Math.random().toString(36).substring(2, 15)}.converted.wav`)
96
+ execSync(`ffmpeg -y -i "${prefix}" -ar 8000 -ac 1 -sample_fmt s16 "${converted}"`, { stdio: 'ignore' })
97
+ if (existsSync(converted)) {
98
+ tBuffer = readFileSync(converted)
99
+ tWav = getWavPCM16(tBuffer)
100
+ try { unlinkSync(converted) } catch {}
101
+ }
102
+ } catch (e) {}
103
+ }
104
+
105
+ if (tWav == null) {
106
+ 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.` })
107
+ return null;
108
+ }
109
+
110
+ const tSamples = (tWav.sampleRate != 8000 ? getSampledPCM16(tWav.samples, tWav.sampleRate, 8000) : tWav.samples)
111
+ buffRadio = setRadioEffect(tSamples, 8000)
112
+ }
113
+
114
+ buffFull = buffRadio != null ? [buffRadio, new Int16Array(Math.floor(0.5 * 8000))] : [];
115
+ buffFull.push(
116
+ setSameHeader(header, 3, 8000, {
117
+ preMarkSec: 1.1,
118
+ gapSec: 0.5,
119
+ }),
120
+ new Int16Array(Math.floor(0.5 * 8000)),
121
+ setAttentionTone(8, 8000),
122
+ new Int16Array(Math.floor(0.5 * 8000)),
123
+ vRadio
124
+ )
125
+ for (let i = 0; i < 3; i++) {
126
+ buffFull.push(setSameHeader(header, 1, 8000, { preMarkSec: 0.5, gapSec: 0.1 }))
127
+ buffFull.push(new Int16Array(Math.floor(0.5 * 8000)));
128
+ }
129
+ const aSamples = getMergedPCM16(buffFull);
130
+ const aFinal = setNoise(aSamples, 0.002);
131
+ const aBuffer = getPCM16(Array.from(aFinal).map(v => ({ value: v })), 8000);
132
+ writeFileSync(outTTS, aBuffer)
133
+ try{unlinkSync(tmpTTS)} catch {}
134
+ return outTTS;
135
+ }
136
+
137
+
@@ -0,0 +1,31 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+
19
+ */
20
+ import { getPCMToFloat } from "./eas.getPCMToFloat";
21
+ import { getFloatPCM16 } from "./eas.getFloatPCM16";
22
+
23
+ export const setNoise = (int16: Int16Array, noiseLevel: number = 0.02): Int16Array => {
24
+ const x = getPCMToFloat(int16);
25
+ for (let i = 0; i < x.length; i++) x[i] += (Math.random() * 2 - 1) * noiseLevel;
26
+ let peak = 0;
27
+ for (let i = 0; i < x.length; i++) peak = Math.max(peak, Math.abs(x[i]));
28
+ if (peak > 1) for (let i = 0; i < x.length; i++) x[i] *= 0.98 / peak;
29
+ return getFloatPCM16(x);
30
+ }
31
+
@@ -0,0 +1,49 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+
19
+ */
20
+ import { getPCMToFloat } from "./eas.getPCMToFloat";
21
+ import { getFloatPCM16 } from "./eas.getFloatPCM16";
22
+
23
+ export const setRadioEffect = (int16: Int16Array, sampleRate: number): Int16Array => {
24
+ const hpCut = 3555;
25
+ const lpCut = 1600;
26
+ const x = getPCMToFloat(int16);
27
+ const dt = 1 / sampleRate;
28
+ const rcHP = 1 / (2 * Math.PI * hpCut);
29
+ const aHP = rcHP / (rcHP + dt);
30
+ let yHP = 0, xPrev = 0;
31
+ for (let i = 0; i < x.length; i++) {
32
+ const xi = x[i];
33
+ yHP = aHP * (yHP + xi - xPrev);
34
+ xPrev = xi;
35
+ x[i] = yHP;
36
+ }
37
+ const rcLP = 1 / (2 * Math.PI * lpCut);
38
+ const aLP = dt / (rcLP + dt);
39
+ let yLP = 0;
40
+ for (let i = 0; i < x.length; i++) {
41
+ yLP = yLP + aLP * (x[i] - yLP);
42
+ x[i] = yLP;
43
+ }
44
+ const compGain = 2.0;
45
+ const norm = Math.tanh(compGain);
46
+ for (let i = 0; i < x.length; i++) x[i] = Math.tanh(x[i] * compGain) / norm;
47
+ return getFloatPCM16(x);
48
+ }
49
+
@@ -0,0 +1,45 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+
19
+ */
20
+
21
+
22
+ import { setAFSK } from "./eas.setAFSK";
23
+ import { setAsciiToBits } from "./eas.setAsciiToBits";
24
+ import { getMergedPCM16 } from "./eas.getMergedPCM16";
25
+
26
+ export const setSameHeader = (vtec: string, repeats: number, sampleRate: number = 8000, options: {preMarkSec?: number, gapSec?: number} = {}): Int16Array => {
27
+ const preMarkSec = options.preMarkSec ?? 0.3;
28
+ const gapSec = options.gapSec ?? 0.1;
29
+ const bursts = [];
30
+ const gap = new Int16Array(Math.floor(gapSec * sampleRate));
31
+ for (let i = 0; i < repeats; i++) {
32
+ const bodyBits = setAsciiToBits(vtec);
33
+ const body = setAFSK(bodyBits, sampleRate);
34
+ const extendedBodyDuration = Math.round(preMarkSec * sampleRate);
35
+ const extendedBody = new Int16Array(extendedBodyDuration + gap.length);
36
+ for (let j = 0; j < extendedBodyDuration; j++) {
37
+ extendedBody[j] = Math.round(body[j % body.length] * 0.2);
38
+ }
39
+ extendedBody.set(gap, extendedBodyDuration);
40
+ bursts.push(extendedBody);
41
+ if (i !== repeats - 1) bursts.push(gap);
42
+ }
43
+ return getMergedPCM16(bursts);
44
+ }
45
+
@@ -8,7 +8,7 @@
8
8
  | |
9
9
  |_|
10
10
 
11
- Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, Everwatch1, & CJ Ziegler)
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
14
  Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
@@ -8,7 +8,7 @@
8
8
  | |
9
9
  |_|
10
10
 
11
- Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, Everwatch1, & CJ Ziegler)
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
14
  Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
@@ -8,7 +8,7 @@
8
8
  | |
9
9
  |_|
10
10
 
11
- Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, Everwatch1, & CJ Ziegler)
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
14
  Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
@@ -19,14 +19,17 @@
19
19
 
20
20
  import request from 'request'
21
21
 
22
- interface ImportOptions {
22
+ interface CreateHttpOptions {
23
23
  proxy?: string
24
- url?: string
24
+ url: string
25
25
  headers?: any
26
- timeout?: number
26
+ timeout?: number
27
+ method?: `GET` | `POST` | `PUT` | `DELETE`
28
+ body?: any;
29
+ formData?: any;
27
30
  }
28
31
 
29
- export const createHttp = async (options: ImportOptions): Promise<any> => {
32
+ export const createHttp = async (options: CreateHttpOptions): Promise<any> => {
30
33
  return new Promise((resolve, reject) => {
31
34
  const requestOptions = {
32
35
  url: options.url ?? `https://api.weather.gov/alerts/active`,
@@ -35,10 +38,17 @@ export const createHttp = async (options: ImportOptions): Promise<any> => {
35
38
  "Accept": "application/geo+json, text/plain, */*; q=0.9",
36
39
  "Accept-Language": "en-US,en;q=0.9"
37
40
  },
41
+ method: options.method ?? `GET`,
38
42
  timeout: options.timeout ?? 10e3,
39
43
  proxy: options.proxy ?? null,
40
44
  maxRedirects: 1,
41
45
  };
46
+ if (options.formData) {
47
+ requestOptions['formData'] = options.formData;
48
+ } else if (options.body) {
49
+ requestOptions['body'] = options.body;
50
+ }
51
+
42
52
  request(requestOptions, (error, response, body) => {
43
53
  if (error) {
44
54
  return resolve({
@@ -48,12 +58,12 @@ export const createHttp = async (options: ImportOptions): Promise<any> => {
48
58
  message: error.message ?? `Unknown Error`
49
59
  })
50
60
  }
51
- if (response.statusCode !== 200) {
61
+ if (response.statusCode < 200 || response.statusCode >= 300) {
52
62
  return resolve({
53
63
  error: true,
54
64
  options: requestOptions,
55
65
  status: response.statusCode ?? -1,
56
- message: `HTTP Status Code ${response.statusCode ?? `Unknown Status Code`}`
66
+ message: `HTTP Status Code ${response.statusCode ?? `Unknown Status Code`} (${body})`
57
67
  })
58
68
  }
59
69
  if (body == undefined || body == null) {
@@ -0,0 +1,100 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { TypeEvent } from "../../@types/type.event";
21
+ import { setTimeoutAction } from "./utilities.setTimeoutAction"
22
+ import { createHttp } from "./utilities.createHttp"
23
+ import { TypeWebhook } from "../../@types/types.webhook";
24
+ import { getCleanedEvent } from "../../@building/building.clean";
25
+ import FormData from "form-data";
26
+
27
+ interface CreateWebhookOptions {
28
+ webhook: TypeWebhook
29
+ event: TypeEvent
30
+ }
31
+
32
+ export const createWebhook = async (options: CreateWebhookOptions): Promise<void> => {
33
+ const event = options.event.properties;
34
+ const settings = options.webhook;
35
+ let body = [
36
+ event.locations ? `**Locations**: ${event.locations.slice(0,100)}` : null,
37
+ event.issued ? `**Issued**: <t:${Math.floor(new Date(event.issued).getTime()/1000)}:R>` : null,
38
+ event.expires ? `**Expires**: <t:${Math.floor(new Date(event.expires).getTime()/1000)}:R>` : null,
39
+ (() => {
40
+ const val = event.parameters.estimated_wind_gusts ?? null
41
+ const th = event.parameters.wind_threat ?? null
42
+ const combined = [val, th].filter(Boolean).join(' ');
43
+ return combined ? `**Wind Gusts**: ${val} ${th ? `(${th})` : ''}` : null;
44
+ })(),
45
+ (() => {
46
+ const val = event.parameters.estimated_hail_size ?? null
47
+ const th = event.parameters.hail_threat ?? null
48
+ return (val || th) ? `**Hail Threat**: ${val} ${th ? `(${th})` : ''}` : null;
49
+ })(),
50
+ event.parameters.damage_threat ? `**Damage Threat**: ${event.parameters.damage_threat}` : null,
51
+ event.parameters.flood_threat ? `**Flood Threat**: ${event.parameters.flood_threat}` : null,
52
+ event.parameters.tornado_threat ? `**Tornado Threat**: ${event.parameters.tornado_threat}` : null,
53
+ (event.parameters.tags?.length > 0) ? `**Tags**: ${event.parameters.tags.join(', ')}` : null,
54
+ (() => {
55
+ const val = event.geocode?.office?.name ?? `N/A`
56
+ const th = event.geocode?.office?.office ?? null
57
+ return (val || th) ? `**Sender**: ${val} ${th ? `(${th})` : ''}` : null;
58
+ })(),
59
+ event.metadata?.tracking ? `**Tracking**: ${event.metadata.tracking}` : null,
60
+ event.metadata?.vtec?.vtec ? `**VTEC**: ${event.metadata.vtec?.vtec}` : null,
61
+ event.metadata?.filtered_proximity != null ? `**Currently in polygon (Node)**: ${event.metadata.filtered_proximity ? 'Yes' : 'No'}` : null,
62
+ (() => {
63
+ const desc = (event.description || '').split('\n').map(l => l.trim()).filter(Boolean).join('\n');
64
+ return desc ? '```' + '\n' + desc + '\n' + '```' : null;
65
+ })(),
66
+ ].filter(Boolean).join('\n');
67
+
68
+ const isLimited = setTimeoutAction({ identifier: options.webhook.webhook, interval: options.webhook.rate, max: options.webhook.rate, addTime: true })
69
+ if (isLimited.limited) { return }
70
+
71
+ if (body.length > 1900) {
72
+ body = body.substring(0, 1900) + "\n\n[Message truncated due to length]";
73
+ const blocks = (body.match(/```/g) || []).length;
74
+ if (blocks % 2 !== 0) body += "```";
75
+ }
76
+ const form = new FormData();
77
+ const embed = {
78
+ title: `${event.event} (${event.status})`,
79
+ description: body,
80
+ color: 16711680,
81
+ timestamp: new Date().toISOString(),
82
+ footer: { text: settings.title }
83
+ };
84
+ form.append("payload_json", JSON.stringify({
85
+ username: settings.title ?? "AtmosphericX",
86
+ content: settings.message ?? "",
87
+ embeds: [embed]
88
+ }));
89
+ form.append("file", Buffer.from(JSON.stringify({ type: "FeatureCollection", features: [(getCleanedEvent(options.event))] }, null, 2)), {
90
+ filename: `${event.event}_${event.status}_${event.metadata.tracking}.json`,
91
+ contentType: "application/json"
92
+ });
93
+ await createHttp({
94
+ url: settings.webhook,
95
+ timeout: 2000,
96
+ method: `POST`,
97
+ headers: form.getHeaders(),
98
+ body: form
99
+ })
100
+ }
@@ -8,7 +8,7 @@
8
8
  | |
9
9
  |_|
10
10
 
11
- Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, Everwatch1, & CJ Ziegler)
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
14
  Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
@@ -8,7 +8,7 @@
8
8
  | |
9
9
  |_|
10
10
 
11
- Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, Everwatch1, & CJ Ziegler)
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
14
  Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
@@ -8,7 +8,7 @@
8
8
  | |
9
9
  |_|
10
10
 
11
- Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, Everwatch1, & CJ Ziegler)
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
14
  Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
@@ -8,7 +8,7 @@
8
8
  | |
9
9
  |_|
10
10
 
11
- Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, Everwatch1, & CJ Ziegler)
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
14
  Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
@@ -20,9 +20,10 @@
20
20
 
21
21
  import { TypeSettings } from "../../@types/types.settings";
22
22
  import { xReconnect } from "../@xmpp/xmpp.xReconnect"
23
- import { callback } from "../../@core/core.callback"
24
23
  import { bootstrap } from "../../bootstrap";
25
- import { updateNodes } from "../../@manager/manager.updateNodes";
24
+ import { createHttp } from "./utilities.createHttp";
25
+ import { createEvent } from "../../@building/building.create";
26
+ import { setEventEmit } from "./utilities.setEventEmit";
26
27
 
27
28
  export const setCronSchedule = async (): Promise<void> => {
28
29
  const settings = bootstrap.settings as TypeSettings;
@@ -31,7 +32,33 @@ export const setCronSchedule = async (): Promise<void> => {
31
32
  void xReconnect(settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval)
32
33
  }
33
34
  } else {
34
- await callback();
35
+ const response = await createHttp({
36
+ url: settings.NationalWeatherServiceSettings.EventsEndpoint,
37
+ headers: {
38
+ "User-Agent": "@atmosx/event-product-parser"
39
+ }
40
+ })
41
+ if (response.error) {
42
+ return setEventEmit({
43
+ event: `onServiceStatus`,
44
+ metadata: {
45
+ type: "fetch-api",
46
+ message: `Failed to fetch latest events from National Weather Service API - ${response.message}`,
47
+ data: {},
48
+ error: true
49
+ },
50
+ })
51
+ }
52
+ setEventEmit({
53
+ event: `onServiceStatus`,
54
+ metadata: {
55
+ message: `Fetched latest events from National Weather Service API`,
56
+ data: {},
57
+ type: "fetch-api",
58
+ error: false
59
+ },
60
+ })
61
+ createEvent({ message: response.message, isNWWS: false })
35
62
  }
36
63
  }
37
64
 
@@ -8,7 +8,7 @@
8
8
  | |
9
9
  |_|
10
10
 
11
- Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, Everwatch1, & CJ Ziegler)
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
14
  Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
@@ -8,7 +8,7 @@
8
8
  | |
9
9
  |_|
10
10
 
11
- Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, Everwatch1, & CJ Ziegler)
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
14
  Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
@@ -19,12 +19,12 @@
19
19
 
20
20
  import { bootstrap } from "../../bootstrap"
21
21
 
22
- interface ImportOptions {
22
+ interface SetListenerOptions {
23
23
  event: string,
24
24
  callback: () => void
25
25
  }
26
26
 
27
- export const setListener = (options: ImportOptions): (() => void) => {
27
+ export const setListener = (options: SetListenerOptions): (() => void) => {
28
28
  bootstrap.listener.on(options.event, options.callback)
29
29
  return () => { void bootstrap.listener.off(options.event, options.callback) };
30
30
  }
@@ -8,7 +8,7 @@
8
8
  | |
9
9
  |_|
10
10
 
11
- Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, Everwatch1, & CJ Ziegler)
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
14
  Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
@@ -8,7 +8,7 @@
8
8
  | |
9
9
  |_|
10
10
 
11
- Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, Everwatch1, & CJ Ziegler)
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
14
  Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
@@ -18,11 +18,11 @@
18
18
 
19
19
  */
20
20
 
21
- interface ImportOptions {
21
+ interface SetSleepOptions {
22
22
  timeout: number
23
23
  }
24
24
 
25
- export const setSleep = async (options: ImportOptions): Promise<void> => {
25
+ export const setSleep = async (options: SetSleepOptions): Promise<void> => {
26
26
  return new Promise((resolve) => {
27
27
  setTimeout(() => {
28
28
  resolve();