@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.
- package/README.md +299 -5
- package/dist/cjs/index.cjs +10188 -237
- package/dist/esm/index.mjs +10186 -237
- package/dist/index.d.mts +235 -0
- package/dist/index.d.ts +235 -0
- package/package.json +4 -3
- package/src/@building/building.clean.ts +1 -1
- package/src/@building/building.create.ts +1 -1
- package/src/@building/building.enhance.ts +1 -1
- package/src/@building/building.geometry.ts +7 -1
- package/src/@building/building.headers.ts +1 -1
- package/src/@building/building.office.ts +1 -1
- package/src/@building/building.polygon.ts +1 -1
- package/src/@building/building.properties.ts +1 -1
- package/src/@building/building.signature.ts +9 -26
- package/src/@building/building.tags.ts +1 -1
- package/src/@building/building.tracking.ts +1 -1
- package/src/@building/building.validate.ts +19 -4
- package/src/@core/core.getEvents.ts +1 -1
- package/src/@core/core.getNodes.ts +1 -1
- package/src/@core/{core.callback.ts → core.getRandomEvent.ts} +3 -17
- package/src/@core/core.getVersion.ts +25 -0
- package/src/@core/core.listener.ts +1 -1
- package/src/@core/core.setNode.ts +2 -2
- package/src/@core/core.start.ts +9 -4
- package/src/@core/core.stop.ts +1 -1
- package/src/@dictionaries/dictionaries.betterEventNames.ts +5 -1
- package/src/@dictionaries/dictionaries.eventActions.ts +1 -1
- package/src/@dictionaries/dictionaries.eventAwipAbreviations.ts +2 -2
- package/src/@dictionaries/dictionaries.eventCancelMessages.ts +2 -1
- package/src/@dictionaries/dictionaries.eventCauses.ts +1 -1
- package/src/@dictionaries/dictionaries.eventProducts.ts +1 -1
- package/src/@dictionaries/dictionaries.eventRecords.ts +1 -1
- package/src/@dictionaries/dictionaries.eventSeverity.ts +1 -1
- package/src/@dictionaries/dictionaries.eventStatus.ts +1 -1
- package/src/@dictionaries/dictionaries.eventTags.ts +1 -1
- package/src/@dictionaries/dictionaries.eventTypes.ts +1 -1
- package/src/@dictionaries/dictionaries.eventsOffshore.ts +1 -1
- package/src/@dictionaries/dictionaries.hailStrings.ts +3 -1
- package/src/@dictionaries/dictionaries.officeICAOs.ts +1 -1
- package/src/@dictionaries/dictionaries.regExp.ts +1 -1
- package/src/@dictionaries/dictionaries.shapefileLinks.ts +1 -1
- package/src/@dictionaries/dictionaries.statusCorrelationText.ts +1 -1
- package/src/@dictionaries/{dictionaries.test_signatures.ts → dictionaries.testSignatures.ts} +3 -2
- package/src/@dictionaries/dictionaries.transcribedMessageReplacements.ts +1 -1
- package/src/@events/events.api.ts +1 -1
- package/src/@events/events.text.ts +1 -1
- package/src/@events/events.ugc.ts +1 -1
- package/src/@events/events.vtec.ts +5 -5
- package/src/@manager/manager.mkEvent.ts +54 -38
- package/src/@manager/manager.rmEvent.ts +3 -1
- package/src/@manager/manager.setHash.ts +2 -2
- package/src/@manager/manager.updateNodes.ts +10 -6
- package/src/@manager/manager.updateWebhooks.ts +50 -0
- 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 +2 -3
- package/src/@modules/@database/database.stanza.ts +2 -1
- package/src/@modules/@eas/eas.getFloatPCM16.ts +29 -0
- package/src/@modules/@eas/eas.getMergedPCM16.ts +32 -0
- package/src/@modules/@eas/eas.getPCM16.ts +52 -0
- package/src/@modules/@eas/eas.getPCMToFloat.ts +26 -0
- package/src/@modules/@eas/eas.getSampledPCM16.ts +36 -0
- package/src/@modules/@eas/eas.getWavPCM16.ts +52 -0
- package/src/@modules/@eas/eas.setAFSK.ts +52 -0
- package/src/@modules/@eas/eas.setAsciiToBits.ts +32 -0
- package/src/@modules/@eas/eas.setAttentionTone.ts +40 -0
- package/src/@modules/@eas/eas.setEasTone.ts +137 -0
- package/src/@modules/@eas/eas.setNoise.ts +31 -0
- package/src/@modules/@eas/eas.setRadioEffect.ts +49 -0
- package/src/@modules/@eas/eas.setSameHeader.ts +45 -0
- package/src/@modules/@stanza/stanza.getAwipsType.ts +1 -1
- package/src/@modules/@stanza/stanza.validate.ts +1 -1
- package/src/@modules/@utilities/utilities.createHttp.ts +17 -7
- package/src/@modules/@utilities/utilities.createWebhook.ts +100 -0
- package/src/@modules/@utilities/utilities.getFormattedTime.ts +1 -1
- package/src/@modules/@utilities/utilities.getSettings.ts +1 -1
- package/src/@modules/@utilities/utilities.getShapeNearestPoint.ts +1 -1
- package/src/@modules/@utilities/utilities.setCronSchedule.ts +31 -4
- package/src/@modules/@utilities/utilities.setEventEmit.ts +1 -1
- package/src/@modules/@utilities/utilities.setListener.ts +3 -3
- package/src/@modules/@utilities/utilities.setSettings.ts +1 -1
- package/src/@modules/@utilities/utilities.setSleep.ts +3 -3
- package/src/@modules/@utilities/utilities.setTimeoutAction.ts +4 -4
- package/src/@modules/@utilities/utilities.setWarning.ts +3 -3
- package/src/@modules/@xmpp/xmpp.xDeploy.ts +2 -2
- package/src/@modules/@xmpp/xmpp.xError.ts +1 -10
- package/src/@modules/@xmpp/xmpp.xOffline.ts +2 -2
- package/src/@modules/@xmpp/xmpp.xOnline.ts +3 -19
- package/src/@modules/@xmpp/xmpp.xReconnect.ts +7 -2
- package/src/@modules/@xmpp/xmpp.xStanza.ts +3 -3
- package/src/@parsers/@hvtec/hvtec.extract.ts +1 -1
- package/src/@parsers/@pvtec/pvtec.expires.ts +1 -1
- package/src/@parsers/@pvtec/pvtec.extract.ts +3 -4
- package/src/@parsers/@text/text.getDescriptionFromProduct.ts +1 -1
- package/src/@parsers/@text/text.getPolygonFromProduct.ts +1 -1
- package/src/@parsers/@text/text.getTextFromProduct.ts +1 -1
- package/src/@parsers/@text/text.getXML.ts +1 -1
- package/src/@parsers/@ugc/ugc.coordinates.ts +1 -1
- package/src/@parsers/@ugc/ugc.expiry.ts +1 -1
- package/src/@parsers/@ugc/ugc.extract.ts +1 -1
- package/src/@parsers/@ugc/ugc.header.ts +1 -1
- package/src/@parsers/@ugc/ugc.locations.ts +1 -1
- package/src/@parsers/@ugc/ugc.zones.ts +1 -1
- package/src/@types/type.event.ts +12 -12
- package/src/@types/type.properties.ts +1 -1
- package/src/@types/types.attributes.ts +1 -1
- package/src/@types/types.compiled.ts +1 -1
- package/src/@types/types.hash.ts +1 -1
- package/src/@types/types.hvtec.ts +1 -1
- package/src/@types/types.pvtec.ts +2 -1
- package/src/@types/types.settings.ts +10 -5
- package/src/@types/types.stanza.ts +1 -1
- package/src/@types/types.ugc.ts +1 -1
- package/src/@types/types.webhook.ts +26 -0
- package/src/bootstrap.ts +7 -4
- package/src/index.ts +11 -12
- package/test.js +29 -18
- 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,
|
|
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,
|
|
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,
|
|
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
|
|
22
|
+
interface CreateHttpOptions {
|
|
23
23
|
proxy?: string
|
|
24
|
-
url
|
|
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:
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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 {
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
22
|
+
interface SetListenerOptions {
|
|
23
23
|
event: string,
|
|
24
24
|
callback: () => void
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export const setListener = (options:
|
|
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,
|
|
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,
|
|
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
|
|
21
|
+
interface SetSleepOptions {
|
|
22
22
|
timeout: number
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export const setSleep = async (options:
|
|
25
|
+
export const setSleep = async (options: SetSleepOptions): Promise<void> => {
|
|
26
26
|
return new Promise((resolve) => {
|
|
27
27
|
setTimeout(() => {
|
|
28
28
|
resolve();
|