@atmosx/event-product-parser 3.0.4 → 3.0.6
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/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +1 -1
- package/.github/README.md +163 -0
- package/.github/SUPPORTED_EVENTS.md +370 -0
- package/.github/docs/docs-functions.md +30 -0
- package/.github/docs/docs-general-configurations.md +209 -0
- package/.github/docs/docs-integrations.md +37 -0
- package/.github/docs/docs-listeners.md +28 -0
- package/.github/docs/docs-source-configuration.md +218 -0
- package/.github/docs/docs-technical.md +50 -0
- package/.github/logo.png +0 -0
- package/.github/samples/SAMPLE_EAS_GENERATION.wav +0 -0
- package/.github/samples/SAMPLE_GEOJSON.json +204 -0
- package/.github/samples/SAMPLE_TEXT_PRODUCT.txt +119 -0
- package/dist/cjs/index.cjs +4677 -13422
- package/dist/esm/index.mjs +3159 -11906
- package/package.json +3 -9
- package/src/@building/{building.create.ts → CreateEvent.ts} +25 -11
- package/src/@building/{building.clean.ts → GetCleanedEvent.ts} +2 -2
- package/src/@building/GetEventAttachments.ts +86 -0
- package/src/@building/{building.enhance.ts → GetEventEnhancedName.ts} +11 -12
- package/src/@building/{building.geometry.ts → GetEventGeometry.ts} +7 -7
- package/src/@building/{building.headers.ts → GetEventHeader.ts} +3 -3
- package/src/@building/{building.polygon.ts → GetEventNodes.ts} +13 -11
- package/src/@building/{building.office.ts → GetEventOffice.ts} +6 -6
- package/src/@building/GetEventProperties.ts +96 -0
- package/src/@building/{building.signature.ts → GetEventSignature.ts} +14 -15
- package/src/@building/{building.tags.ts → GetEventTags.ts} +9 -4
- package/src/@building/{building.tracking.ts → GetEventTracking.ts} +15 -15
- package/src/@building/{building.validate.ts → ValidateEvents.ts} +67 -60
- package/src/@core/{core.clearEvents.ts → ClearEvents.ts} +3 -4
- package/src/@core/{core.createListener.ts → CreateListener.ts} +3 -3
- package/src/@core/{core.getEvents.ts → GetEvents.ts} +1 -2
- package/src/@core/{core.getNodes.ts → GetNodes.ts} +1 -2
- package/src/@core/{core.getRandomEvent.ts → GetRandomEvent.ts} +1 -2
- package/src/@core/{core.getVersion.ts → GetVersion.ts} +1 -2
- package/src/@core/ManualEvent.ts +56 -0
- package/src/@core/QueryStanza.ts +39 -0
- package/src/@core/{core.setNode.ts → SetNode.ts} +8 -8
- package/src/@core/{core.start.ts → StartService.ts} +21 -21
- package/src/@core/{core.stop.ts → StopService.ts} +1 -1
- package/src/@enums/AWIPS.ts +366 -0
- package/src/{@dictionaries/dictionaries.eventActions.ts → @enums/Actions.ts} +1 -1
- package/src/{@dictionaries/dictionaries.eventCancelMessages.ts → @enums/Cancellation.ts} +2 -1
- package/src/{@dictionaries/dictionaries.eventCauses.ts → @enums/Causes.ts} +1 -1
- package/src/{@dictionaries/dictionaries.statusCorrelationText.ts → @enums/Correlations.ts} +1 -1
- package/src/@enums/Enhanced.ts +70 -0
- package/src/{@dictionaries/dictionaries.eventTypes.ts → @enums/Events.ts} +1 -1
- package/src/{@dictionaries/dictionaries.regExp.ts → @enums/Expressions.ts} +2 -1
- package/src/@enums/GlobalFilter.ts +24 -0
- package/src/{@dictionaries/dictionaries.hailStrings.ts → @enums/Hail.ts} +7 -2
- package/src/{@dictionaries/dictionaries.officeICAOs.ts → @enums/ICAO.ts} +3 -1
- package/src/@enums/Matches.ts +55 -0
- package/src/{@dictionaries/dictionaries.eventProducts.ts → @enums/Products.ts} +1 -1
- package/src/{@dictionaries/dictionaries.eventRecords.ts → @enums/Records.ts} +1 -1
- package/src/{@dictionaries/dictionaries.eventSeverity.ts → @enums/Severity.ts} +1 -1
- package/src/{@dictionaries/dictionaries.shapefileLinks.ts → @enums/Shapefiles.ts} +1 -1
- package/src/@enums/States.ts +72 -0
- package/src/{@dictionaries/dictionaries.eventStatus.ts → @enums/Status.ts} +1 -1
- package/src/@enums/Strings.ts +22 -0
- package/src/@enums/Tags.ts +167 -0
- package/src/{@dictionaries/dictionaries.testSignatures.ts → @enums/Testing.ts} +3 -2
- package/src/@events/{events.api.ts → ParseAPI.ts} +42 -38
- package/src/@events/{events.text.ts → ParseText.ts} +25 -18
- package/src/@events/{events.ugc.ts → ParseUGC.ts} +28 -19
- package/src/@events/{events.vtec.ts → ParseVTEC.ts} +21 -21
- package/src/@manager/CreateActions.ts +213 -0
- package/src/@manager/{manager.mkEvent.ts → MakeEvent.ts} +34 -31
- package/src/@manager/RemoveEvent.ts +70 -0
- package/src/@manager/{manager.setHash.ts → SetHash.ts} +8 -9
- package/src/@manager/{manager.updateEvents.ts → UpdateEvents.ts} +9 -9
- package/src/@manager/{manager.updateNodes.ts → UpdateNode.ts} +24 -17
- package/src/@modules/@database/{database.cache.ts → GetCachedEvents.ts} +10 -8
- package/src/@modules/@database/ImportBroadcastify.ts +70 -0
- package/src/@modules/@database/{database.shapefiles.ts → ImportShapefiles.ts} +17 -20
- package/src/@modules/@database/{database.stanza.ts → ImportStanza.ts} +5 -6
- package/src/@modules/@database/{database.init.ts → InitializeDatabase.ts} +25 -11
- package/src/@modules/@eas/GenerateEASMessage.ts +144 -0
- package/src/@modules/@eas/GetCleanDescription.ts +91 -0
- package/src/@modules/@eas/{eas.getFloatPCM16.ts → GetFloatPCM16.ts} +1 -1
- package/src/@modules/@eas/{eas.getMergedPCM16.ts → GetMergedPCM16.ts} +1 -1
- package/src/@modules/@eas/{eas.getPCM16.ts → GetPCM16.ts} +1 -1
- package/src/@modules/@eas/{eas.getPCMToFloat.ts → GetPCMToFloat.ts} +1 -1
- package/src/@modules/@eas/{eas.getSampledPCM16.ts → GetSampledPCM16.ts} +1 -1
- package/src/@modules/@eas/GetTTS.ts +54 -0
- package/src/@modules/@eas/{eas.getWavPCM16.ts → GetWavPCM16.ts} +1 -1
- package/src/@modules/@eas/{eas.setAFSK.ts → SetAFSK.ts} +1 -2
- package/src/@modules/@eas/{eas.setAsciiToBits.ts → SetAsciiToBits.ts} +1 -2
- package/src/@modules/@eas/{eas.setAttentionTone.ts → SetAttentionTone.ts} +1 -1
- package/src/@modules/@eas/{eas.setNoise.ts → SetNoise.ts} +6 -5
- package/src/@modules/@eas/{eas.setRadioEffect.ts → SetRadioEffect.ts} +6 -5
- package/src/@modules/@eas/{eas.setSameHeader.ts → SetSameHeader.ts} +7 -8
- package/src/@modules/@stanza/{stanza.getAwipsType.ts → GetAwipsType.ts} +11 -9
- package/src/@modules/@stanza/{stanza.validate.ts → ValidateStanza.ts} +9 -9
- package/src/@modules/@utilities/CreateHttp.ts +83 -0
- package/src/@modules/@utilities/{utilities.getFormattedTime.ts → GetFormattedTime.ts} +1 -1
- package/src/@modules/@utilities/GetLatestIssuance.ts +32 -0
- package/src/@modules/@utilities/GetMatched.ts +33 -0
- package/src/@modules/@utilities/{utilities.getSettings.ts → GetSettings.ts} +2 -2
- package/src/@modules/@utilities/{utilities.getShapeNearestPoint.ts → GetShapeNearestPoint.ts} +1 -1
- package/src/@modules/@utilities/{utilities.setCronSchedule.ts → SetCronSchedule.ts} +41 -12
- package/src/{@types/types.webhook.ts → @modules/@utilities/SetDebug.ts} +16 -6
- package/src/@modules/@utilities/{utilities.setEventEmit.ts → SetEventEmit.ts} +5 -5
- package/src/@modules/@utilities/{utilities.setListener.ts → SetListener.ts} +1 -1
- package/src/@modules/@utilities/{utilities.setSettings.ts → SetSettings.ts} +2 -2
- package/src/@modules/@utilities/{utilities.setSleep.ts → SetSleep.ts} +1 -1
- package/src/@modules/@utilities/{utilities.setTimeoutAction.ts → SetTimeoutAction.ts} +8 -3
- package/src/@modules/@utilities/{utilities.setWarning.ts → SetWarning.ts} +2 -2
- package/src/@modules/@xmpp/{xmpp.xDeploy.ts → DeployXMPP.ts} +13 -14
- package/src/@modules/@xmpp/{xmpp.xError.ts → ErrorXMPP.ts} +1 -3
- package/src/@modules/@xmpp/{xmpp.xOffline.ts → OfflineXMPP.ts} +3 -4
- package/src/@modules/@xmpp/{xmpp.xOnline.ts → OnlineXMPP.ts} +6 -5
- package/src/@modules/@xmpp/{xmpp.xReconnect.ts → ReconnectXMPP.ts} +8 -8
- package/src/@modules/@xmpp/{xmpp.xStanza.ts → StanzaXMPP.ts} +11 -11
- package/src/@parsers/@hvtec/{hvtec.extract.ts → HVExtract.ts} +10 -10
- package/src/@parsers/@pvtec/{pvtec.expires.ts → GetExpiry.ts} +1 -1
- package/src/@parsers/@pvtec/{pvtec.extract.ts → VTECExtract.ts} +17 -17
- package/src/@parsers/@text/{text.getDescriptionFromProduct.ts → GetDescriptionFromProduct.ts} +12 -5
- package/src/@parsers/@text/GetEmbededText.ts +56 -0
- package/src/@parsers/@text/{text.getPolygonFromProduct.ts → GetPolygonFromProduct.ts} +31 -10
- package/src/@parsers/@text/GetStringText.ts +58 -0
- package/src/@parsers/@text/{text.getTextFromProduct.ts → GetTextFromProduct.ts} +1 -1
- package/src/@parsers/@text/{text.getXML.ts → GetXML.ts} +1 -1
- package/src/@parsers/@ugc/GetCache.ts +24 -0
- package/src/@parsers/@ugc/{ugc.expiry.ts → GetExpiry.ts} +1 -1
- package/src/@parsers/@ugc/{ugc.locations.ts → GetLocations.ts} +35 -7
- package/src/@parsers/@ugc/{ugc.header.ts → GetUGCHeader.ts} +3 -3
- package/src/@parsers/@ugc/{ugc.coordinates.ts → GetZonePolygon.ts} +4 -3
- package/src/@parsers/@ugc/SetCache.ts +28 -0
- package/src/@parsers/@ugc/{ugc.extract.ts → UGCExtract.ts} +6 -6
- package/src/@types/Actions.ts +37 -0
- package/src/@types/{type.event.ts → Event.ts} +7 -5
- package/src/@types/{type.properties.ts → Properties.ts} +11 -8
- package/src/@types/{types.settings.ts → Settings.ts} +31 -7
- package/src/@types/{types.compiled.ts → StanzaCompiled.ts} +2 -1
- package/src/bootstrap.ts +33 -9
- package/src/index.ts +26 -24
- package/tsup.config.ts +1 -1
- package/README.md +0 -349
- package/dist/index.d.mts +0 -239
- package/dist/index.d.ts +0 -239
- package/src/@building/building.properties.ts +0 -89
- package/src/@dictionaries/dictionaries.betterEventNames.ts +0 -99
- package/src/@dictionaries/dictionaries.eventAwipAbreviations.ts +0 -364
- package/src/@dictionaries/dictionaries.eventTags.ts +0 -93
- package/src/@dictionaries/dictionaries.eventsMatchText.ts +0 -36
- package/src/@dictionaries/dictionaries.transcribedMessageReplacements.ts +0 -68
- package/src/@manager/manager.rmEvent.ts +0 -49
- package/src/@manager/manager.updateWebhooks.ts +0 -50
- package/src/@modules/@eas/eas.setEasTone.ts +0 -137
- package/src/@modules/@utilities/utilities.createHttp.ts +0 -85
- package/src/@modules/@utilities/utilities.createWebhook.ts +0 -115
- package/test.js +0 -91
- /package/{CODE_OF_CONDUCT.md → .github/CODE_OF_CONDUCT.md} +0 -0
- /package/{LICENSE → .github/LICENSE} +0 -0
- /package/{SECURITY.md → .github/SECURITY.md} +0 -0
- /package/src/@parsers/@ugc/{ugc.zones.ts → GetZones.ts} +0 -0
- /package/src/@types/{types.attributes.ts → Attributes.ts} +0 -0
- /package/src/@types/{types.hvtec.ts → HVTEC.ts} +0 -0
- /package/src/@types/{types.hash.ts → Hash.ts} +0 -0
- /package/src/@types/{types.stanza.ts → Stanza.ts} +0 -0
- /package/src/@types/{types.ugc.ts → UGC.ts} +0 -0
- /package/src/@types/{types.pvtec.ts → VTEC.ts} +0 -0
|
@@ -17,13 +17,14 @@
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
*/
|
|
20
|
-
import { getPCMToFloat } from "./eas.getPCMToFloat";
|
|
21
|
-
import { getFloatPCM16 } from "./eas.getFloatPCM16";
|
|
22
20
|
|
|
23
|
-
|
|
21
|
+
import { GetPCMToFloat } from "./GetPCMToFloat";
|
|
22
|
+
import { GetFloatPCM16 } from "./GetFloatPCM16";
|
|
23
|
+
|
|
24
|
+
export const SetRadioEffect = (int16: Int16Array, sampleRate: number): Int16Array => {
|
|
24
25
|
const hpCut = 3555;
|
|
25
26
|
const lpCut = 1600;
|
|
26
|
-
const x =
|
|
27
|
+
const x = GetPCMToFloat(int16);
|
|
27
28
|
const dt = 1 / sampleRate;
|
|
28
29
|
const rcHP = 1 / (2 * Math.PI * hpCut);
|
|
29
30
|
const aHP = rcHP / (rcHP + dt);
|
|
@@ -44,6 +45,6 @@ export const setRadioEffect = (int16: Int16Array, sampleRate: number): Int16Arra
|
|
|
44
45
|
const compGain = 2.0;
|
|
45
46
|
const norm = Math.tanh(compGain);
|
|
46
47
|
for (let i = 0; i < x.length; i++) x[i] = Math.tanh(x[i] * compGain) / norm;
|
|
47
|
-
return
|
|
48
|
+
return GetFloatPCM16(x);
|
|
48
49
|
}
|
|
49
50
|
|
|
@@ -18,19 +18,18 @@
|
|
|
18
18
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
import { SetAFSK } from "./SetAFSK";
|
|
22
|
+
import { SetAsciiToBits } from "./SetAsciiToBits";
|
|
23
|
+
import { GetMergedPCM16 } from "./GetMergedPCM16";
|
|
21
24
|
|
|
22
|
-
|
|
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 => {
|
|
25
|
+
export const SetSameHeader = (vtec: string, repeats: number, sampleRate: number = 8000, options: {preMarkSec?: number, gapSec?: number} = {}): Int16Array => {
|
|
27
26
|
const preMarkSec = options.preMarkSec ?? 0.3;
|
|
28
27
|
const gapSec = options.gapSec ?? 0.1;
|
|
29
28
|
const bursts = [];
|
|
30
29
|
const gap = new Int16Array(Math.floor(gapSec * sampleRate));
|
|
31
30
|
for (let i = 0; i < repeats; i++) {
|
|
32
|
-
const bodyBits =
|
|
33
|
-
const body =
|
|
31
|
+
const bodyBits = SetAsciiToBits(vtec);
|
|
32
|
+
const body = SetAFSK(bodyBits, sampleRate);
|
|
34
33
|
const extendedBodyDuration = Math.round(preMarkSec * sampleRate);
|
|
35
34
|
const extendedBody = new Int16Array(extendedBodyDuration + gap.length);
|
|
36
35
|
for (let j = 0; j < extendedBodyDuration; j++) {
|
|
@@ -40,6 +39,6 @@ export const setSameHeader = (vtec: string, repeats: number, sampleRate: number
|
|
|
40
39
|
bursts.push(extendedBody);
|
|
41
40
|
if (i !== repeats - 1) bursts.push(gap);
|
|
42
41
|
}
|
|
43
|
-
return
|
|
42
|
+
return GetMergedPCM16(bursts);
|
|
44
43
|
}
|
|
45
44
|
|
|
@@ -17,30 +17,32 @@
|
|
|
17
17
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { TypeAttributes } from "../../@types/
|
|
21
|
-
import {
|
|
20
|
+
import { TypeAttributes } from "../../@types/Attributes"
|
|
21
|
+
import { EnumAWIPS } from "../../@enums/AWIPS"
|
|
22
22
|
|
|
23
|
-
interface
|
|
23
|
+
interface GetAwipsTypeOptions {
|
|
24
24
|
attributes: TypeAttributes
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
interface
|
|
27
|
+
interface GetAwipsTypeResponse {
|
|
28
28
|
type: string
|
|
29
29
|
prefix: string
|
|
30
|
+
discovered: boolean
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
export const
|
|
33
|
+
export const GetAwipsType = (options: GetAwipsTypeOptions): GetAwipsTypeResponse => {
|
|
33
34
|
const attributes = options.attributes;
|
|
34
35
|
if (!attributes.awipsid) {
|
|
35
36
|
return {
|
|
36
37
|
type: null,
|
|
37
|
-
prefix: null
|
|
38
|
+
prefix: null,
|
|
39
|
+
discovered: false
|
|
38
40
|
}
|
|
39
41
|
}
|
|
40
|
-
for (const [prefix, type] of Object.entries(
|
|
42
|
+
for (const [prefix, type] of Object.entries(EnumAWIPS)) {
|
|
41
43
|
if (attributes.awipsid.startsWith(prefix)) {
|
|
42
|
-
return { type, prefix }
|
|
44
|
+
return { type, prefix, discovered: true }
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
|
-
return { type:
|
|
47
|
+
return { type: options.attributes.awipsid, prefix: options.attributes.awipsid, discovered: false }
|
|
46
48
|
}
|
|
@@ -17,16 +17,16 @@
|
|
|
17
17
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { TypeStanza } from "../../@types/
|
|
21
|
-
import { TypeStanzaCompiled } from "../../@types/
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
20
|
+
import { TypeStanza } from "../../@types/Stanza"
|
|
21
|
+
import { TypeStanzaCompiled } from "../../@types/StanzaCompiled"
|
|
22
|
+
import { EnumExpressions } from "../../@enums/Expressions"
|
|
23
|
+
import { GetAwipsType } from "./GetAwipsType"
|
|
24
24
|
|
|
25
|
-
interface
|
|
25
|
+
interface ValidateStanzaOptions {
|
|
26
26
|
stanza: TypeStanza
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export const
|
|
29
|
+
export const ValidateStanza = (options: ValidateStanzaOptions): TypeStanzaCompiled => {
|
|
30
30
|
if (options.stanza.is(`message`)) {
|
|
31
31
|
const cb = options.stanza.getChild(`x`) as TypeStanza;
|
|
32
32
|
if (cb && cb.children) {
|
|
@@ -35,9 +35,9 @@ export const validate = (options: ValidateOptions): TypeStanzaCompiled => {
|
|
|
35
35
|
if (attributes.awipsid && attributes.awipsid.length > 1) {
|
|
36
36
|
const isCapEvent = message.includes(`<?xml`);
|
|
37
37
|
const isCapAreaDescription = message.includes(`<areaDesc>`)
|
|
38
|
-
const isVTEC = message.match(
|
|
39
|
-
const isUGC = message.match(
|
|
40
|
-
const getType =
|
|
38
|
+
const isVTEC = message.match(EnumExpressions.pvtec) != null;
|
|
39
|
+
const isUGC = message.match(EnumExpressions.ugc1) != null;
|
|
40
|
+
const getType = GetAwipsType({ attributes: attributes})
|
|
41
41
|
if (getType.type != null) {
|
|
42
42
|
return {
|
|
43
43
|
message, attributes, isCapEvent, isVTEC, isUGC, isCapAreaDescription, isIgnored: false, isNWWS: true, getType
|
|
@@ -0,0 +1,83 @@
|
|
|
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
|
+
interface CreateHttpOptions {
|
|
21
|
+
url: string
|
|
22
|
+
headers?: any
|
|
23
|
+
timeout?: number
|
|
24
|
+
auth?: {
|
|
25
|
+
username: string
|
|
26
|
+
password: string
|
|
27
|
+
}
|
|
28
|
+
method?: `GET` | `POST` | `PUT` | `DELETE`
|
|
29
|
+
body?: any;
|
|
30
|
+
formData?: any;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const CreateHttp = async (options: CreateHttpOptions): Promise<any> => {
|
|
34
|
+
const requestOptions: RequestInit = {
|
|
35
|
+
method: options.method ?? "GET",
|
|
36
|
+
headers: options.headers ?? {
|
|
37
|
+
"User-Agent": "AtmosphericX",
|
|
38
|
+
"Accept": "application/geo+json, text/plain, */*; q=0.9",
|
|
39
|
+
"Accept-Language": "en-US,en;q=0.9",
|
|
40
|
+
},
|
|
41
|
+
signal: AbortSignal.timeout(options.timeout ?? 10_000),
|
|
42
|
+
redirect: "follow"
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
const returnHttp = function(error: boolean,status: number, message: string) {
|
|
47
|
+
return { error: error, options: requestOptions, status, message };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (options?.auth) {
|
|
51
|
+
const authString = `${options.auth.username}:${options.auth.password}`;
|
|
52
|
+
const encodedAuth = Buffer.from(authString).toString("base64");
|
|
53
|
+
requestOptions.headers = {
|
|
54
|
+
...requestOptions.headers,
|
|
55
|
+
"Authorization": `Basic ${encodedAuth}`
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (options?.formData) {
|
|
60
|
+
requestOptions.body = options.formData;
|
|
61
|
+
} else if (options?.body != undefined) {
|
|
62
|
+
requestOptions.body =
|
|
63
|
+
options.body instanceof FormData
|
|
64
|
+
? options.body
|
|
65
|
+
: typeof options.body === "string"
|
|
66
|
+
? options.body
|
|
67
|
+
: JSON.stringify(options.body);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const response = await fetch(
|
|
72
|
+
options?.url ?? `https://api.weather.gov/alerts/active`,
|
|
73
|
+
requestOptions
|
|
74
|
+
)
|
|
75
|
+
const body = await response.text();
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
return returnHttp(true, response.status, `HTTP Status Code ${response.status} (${response.statusText})`)
|
|
78
|
+
}
|
|
79
|
+
return returnHttp(false, response.status, body)
|
|
80
|
+
} catch (error) {
|
|
81
|
+
return returnHttp(true, 500, `Internal Server Error: ${error}`)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
export const
|
|
21
|
+
export const GetFormattedTime = (date: string): string => {
|
|
22
22
|
const now = Date.now();
|
|
23
23
|
const then = typeof date === "number" ? date : new Date(date).getTime()
|
|
24
24
|
const seconds = Math.floor((now - then) / 1000);
|
|
@@ -0,0 +1,32 @@
|
|
|
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 GetLatestIssuance = (): string => {
|
|
22
|
+
const now = new Date();
|
|
23
|
+
const current = now.getUTCHours() * 100 + now.getUTCMinutes();
|
|
24
|
+
const issuances = [100, 600, 1300, 1630, 2000];
|
|
25
|
+
let latest = issuances[0];
|
|
26
|
+
for (const issuance of issuances) {
|
|
27
|
+
if (current >= issuance) {
|
|
28
|
+
latest = issuance;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return latest.toString().padStart(4, "0");
|
|
32
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
export const GetMatched = (strings: string[], string: string): boolean => {
|
|
21
|
+
const isMatched = strings.some(pattern => {
|
|
22
|
+
if (!pattern) return false;
|
|
23
|
+
const lowerP = pattern.toLowerCase();
|
|
24
|
+
const lowerS = string.toLowerCase()
|
|
25
|
+
if (lowerP === "*" || lowerP === lowerS) return true;
|
|
26
|
+
if (lowerP.includes("*")) {
|
|
27
|
+
const regex = "^" + lowerP.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$";
|
|
28
|
+
return new RegExp(regex).test(lowerS);
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
});
|
|
32
|
+
return isMatched;
|
|
33
|
+
}
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { TypeSettings } from '../../@types/
|
|
20
|
+
import { TypeSettings } from '../../@types/Settings'
|
|
21
21
|
import { bootstrap } from "../../bootstrap"
|
|
22
22
|
|
|
23
|
-
export const
|
|
23
|
+
export const GetSettings = (): TypeSettings => {
|
|
24
24
|
return bootstrap.settings;
|
|
25
25
|
}
|
package/src/@modules/@utilities/{utilities.getShapeNearestPoint.ts → GetShapeNearestPoint.ts}
RENAMED
|
@@ -25,7 +25,7 @@ interface GetShapeNearestPointResponse {
|
|
|
25
25
|
distanceMeters?: number | null
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export const
|
|
28
|
+
export const GetShapeNearestPoint = (coordinates: number[][], point: [number, number]): GetShapeNearestPointResponse => {
|
|
29
29
|
if (!coordinates || !point) {
|
|
30
30
|
return { proximity: false, point: [0, 0], distance: null }
|
|
31
31
|
}
|
|
@@ -14,32 +14,61 @@
|
|
|
14
14
|
Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
15
|
|
|
16
16
|
Internal Package: @atmosx/event-product-parser
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import { TypeSettings } from "../../@types/
|
|
22
|
-
import {
|
|
21
|
+
import { TypeSettings } from "../../@types/Settings";
|
|
22
|
+
import { ReconnectXMPP } from "../@xmpp/ReconnectXMPP"
|
|
23
23
|
import { bootstrap } from "../../bootstrap";
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
24
|
+
import { CreateHttp } from "./CreateHttp";
|
|
25
|
+
import { CreateEvent } from "../../@building/CreateEvent";
|
|
26
|
+
import { SetEventEmit } from "./SetEventEmit";
|
|
27
|
+
import { readdirSync, unlinkSync, statSync, existsSync } from "fs";
|
|
28
|
+
import { join } from "path";
|
|
27
29
|
|
|
28
|
-
export const
|
|
30
|
+
export const SetCronSchedule = async (): Promise<void> => {
|
|
29
31
|
const settings = bootstrap.settings as TypeSettings;
|
|
32
|
+
|
|
33
|
+
const TTL = settings.GlobalSettings.ArchiveSettings.TTL
|
|
34
|
+
const TTLCUT = Date.now() - TTL * 1000;
|
|
35
|
+
|
|
36
|
+
const walk = (dir: string): void => {
|
|
37
|
+
if (existsSync(dir)) {
|
|
38
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
39
|
+
for (const entry of entries) {
|
|
40
|
+
const fullPath = join(dir, entry.name);
|
|
41
|
+
if (entry.isDirectory()) { walk(fullPath); continue; }
|
|
42
|
+
const stats = statSync(fullPath);
|
|
43
|
+
if (stats.mtime.getTime() < TTLCUT) {
|
|
44
|
+
try {
|
|
45
|
+
unlinkSync(fullPath);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
console.error(`Failed to delete ${fullPath}:`, err);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
walk(settings.GlobalSettings.ArchiveSettings.TextDirectory)
|
|
54
|
+
walk(settings.GlobalSettings.ArchiveSettings.EasDirectory)
|
|
55
|
+
walk(settings.GlobalSettings.ArchiveSettings.JSONDirectory)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
30
59
|
if (settings.EnableWireService) {
|
|
31
60
|
if (settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.Enabled) {
|
|
32
|
-
void
|
|
61
|
+
void ReconnectXMPP(settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval)
|
|
33
62
|
}
|
|
34
63
|
} else {
|
|
35
|
-
const response = await
|
|
64
|
+
const response = await CreateHttp({
|
|
36
65
|
url: settings.NationalWeatherServiceSettings.EventsEndpoint,
|
|
37
66
|
headers: {
|
|
38
67
|
"User-Agent": "@atmosx/event-product-parser"
|
|
39
68
|
}
|
|
40
69
|
})
|
|
41
70
|
if (response.error) {
|
|
42
|
-
return
|
|
71
|
+
return SetEventEmit({
|
|
43
72
|
event: `onServiceStatus`,
|
|
44
73
|
metadata: {
|
|
45
74
|
type: "fetch-api",
|
|
@@ -49,7 +78,7 @@ export const setCronSchedule = async (): Promise<void> => {
|
|
|
49
78
|
},
|
|
50
79
|
})
|
|
51
80
|
}
|
|
52
|
-
|
|
81
|
+
SetEventEmit({
|
|
53
82
|
event: `onServiceStatus`,
|
|
54
83
|
metadata: {
|
|
55
84
|
message: `Fetched latest events from National Weather Service API`,
|
|
@@ -58,7 +87,7 @@ export const setCronSchedule = async (): Promise<void> => {
|
|
|
58
87
|
error: false
|
|
59
88
|
},
|
|
60
89
|
})
|
|
61
|
-
|
|
90
|
+
await CreateEvent({ message: response.message, isNWWS: false })
|
|
62
91
|
}
|
|
63
92
|
}
|
|
64
93
|
|
|
@@ -17,11 +17,21 @@
|
|
|
17
17
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
import { TypeSettings } from "../../@types/Settings";
|
|
21
|
+
import { bootstrap } from "../../bootstrap"
|
|
22
|
+
|
|
23
|
+
interface SetDebugOptions {
|
|
24
|
+
title?: string
|
|
23
25
|
message: string
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const SetDebug = (options: SetDebugOptions): void => {
|
|
29
|
+
const settings = bootstrap.settings as TypeSettings;
|
|
30
|
+
bootstrap.listener.emit(`debug`, {
|
|
31
|
+
message: options.message,
|
|
32
|
+
function: options.title ?? `debug`,
|
|
33
|
+
})
|
|
34
|
+
if (settings.EnableDebugging) {
|
|
35
|
+
console.log(`[${bootstrap.ansi_colors.BLUE}${options.title ?? `debug`}${bootstrap.ansi_colors.RESET}] ${options.message}`)
|
|
36
|
+
}
|
|
27
37
|
}
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import { bootstrap } from "../../bootstrap"
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
21
|
+
import { SetTimeoutAction } from "./SetTimeoutAction";
|
|
22
|
+
import { SetWarning } from "./SetWarning";
|
|
23
23
|
|
|
24
24
|
interface SetEventEmitOptions {
|
|
25
25
|
event: string
|
|
@@ -28,14 +28,14 @@ interface SetEventEmitOptions {
|
|
|
28
28
|
limited?: boolean
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
export const
|
|
31
|
+
export const SetEventEmit = (options: SetEventEmitOptions): void => {
|
|
32
32
|
if (options.limited) {
|
|
33
|
-
const isTimeout =
|
|
33
|
+
const isTimeout = SetTimeoutAction({ identifier: `event.${options.event}`, addTime: true, max: 1, interval: 1 })
|
|
34
34
|
if (isTimeout.limited) return;
|
|
35
35
|
}
|
|
36
36
|
bootstrap.listener.emit(options.event, options.metadata)
|
|
37
37
|
if (options.event != `log`) { bootstrap.listener.emit(`*`, {event: options.event, data: options.metadata}) }
|
|
38
38
|
if (options.message) {
|
|
39
|
-
|
|
39
|
+
SetWarning({ message: options.message })
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -24,7 +24,7 @@ interface SetListenerOptions {
|
|
|
24
24
|
callback: () => void
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export const
|
|
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
|
}
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { TypeSettings } from '../../@types/
|
|
20
|
+
import { TypeSettings } from '../../@types/Settings'
|
|
21
21
|
import { bootstrap } from "../../bootstrap"
|
|
22
22
|
|
|
23
|
-
export const
|
|
23
|
+
export const SetSettings = (newSettings: TypeSettings): TypeSettings => {
|
|
24
24
|
const settings = bootstrap.settings as Record<string, unknown>;
|
|
25
25
|
const merge = (target: Record<string, unknown>, source: Record<string, unknown>) => {
|
|
26
26
|
for (const key in source) {
|
|
@@ -22,7 +22,7 @@ interface SetSleepOptions {
|
|
|
22
22
|
timeout: number
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export const
|
|
25
|
+
export const SetSleep = async (options: SetSleepOptions): Promise<void> => {
|
|
26
26
|
return new Promise((resolve) => {
|
|
27
27
|
setTimeout(() => {
|
|
28
28
|
resolve();
|
|
@@ -23,7 +23,8 @@ interface SetTimeoutActionOptions {
|
|
|
23
23
|
identifier: string
|
|
24
24
|
addTime?: boolean
|
|
25
25
|
max?: number
|
|
26
|
-
interval
|
|
26
|
+
interval?: number
|
|
27
|
+
expire?: boolean
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
type SetTimeoutActionResponse = {
|
|
@@ -32,12 +33,16 @@ type SetTimeoutActionResponse = {
|
|
|
32
33
|
response?: string
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
export const
|
|
36
|
+
export const SetTimeoutAction = (options: SetTimeoutActionOptions): SetTimeoutActionResponse => {
|
|
36
37
|
let target = bootstrap?.ratelimits?.[options?.identifier];
|
|
37
38
|
if (!target) {
|
|
38
39
|
bootstrap.ratelimits[options?.identifier] = [];
|
|
39
40
|
target = bootstrap.ratelimits[options?.identifier];
|
|
40
41
|
}
|
|
42
|
+
if (options?.expire) {
|
|
43
|
+
delete bootstrap.ratelimits[options?.identifier];
|
|
44
|
+
return { limited: false };
|
|
45
|
+
}
|
|
41
46
|
if (target?.length > 0) {
|
|
42
47
|
bootstrap.ratelimits[options?.identifier] = target.filter((ts: number) => Date.now() - ts < options?.interval * 1000);
|
|
43
48
|
target = bootstrap.ratelimits[options?.identifier];
|
|
@@ -45,7 +50,7 @@ export const setTimeoutAction = (options: SetTimeoutActionOptions): SetTimeoutAc
|
|
|
45
50
|
|
|
46
51
|
const oldestTimestamp = target?.[0];
|
|
47
52
|
const getWait = oldestTimestamp ? Math.ceil((options?.interval * 1000) - (Date.now() - oldestTimestamp)) : 0;
|
|
48
|
-
const max = options?.max
|
|
53
|
+
const max = options?.max ?? 1;
|
|
49
54
|
|
|
50
55
|
if (target?.length >= max && getWait > 0) {
|
|
51
56
|
return {
|
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import { bootstrap } from "../../bootstrap"
|
|
21
|
-
import { TypeSettings } from "../../@types/
|
|
21
|
+
import { TypeSettings } from "../../@types/Settings";
|
|
22
22
|
|
|
23
23
|
interface SetWarningOptions {
|
|
24
24
|
title?: string
|
|
25
25
|
message: string
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export const
|
|
28
|
+
export const SetWarning = (options: SetWarningOptions): void => {
|
|
29
29
|
const settings = bootstrap.settings as TypeSettings;
|
|
30
30
|
bootstrap.listener.emit(`log`, `${options.title ?? `[${bootstrap.ansi_colors.YELLOW}@atmosx/product-parser${bootstrap.ansi_colors.RESET}]`} ${options.message}`)
|
|
31
31
|
if (settings.EnableJournal) {
|
|
@@ -17,17 +17,16 @@
|
|
|
17
17
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import {
|
|
21
|
-
import { TypeSettings } from "../../@types/types.settings";
|
|
20
|
+
import { TypeSettings } from "../../@types/Settings";
|
|
22
21
|
import { bootstrap } from "../../bootstrap"
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
22
|
+
import { OnlineXMPP } from "./OnlineXMPP";
|
|
23
|
+
import { OfflineXMPP } from "./OfflineXMPP";
|
|
24
|
+
import { ErrorXMPP } from "./ErrorXMPP";
|
|
25
|
+
import { StanzaXMPP } from "./StanzaXMPP";
|
|
26
|
+
import { SetEventEmit } from '../@utilities/SetEventEmit';
|
|
27
|
+
import { client } from '@xmpp/client';
|
|
29
28
|
|
|
30
|
-
export const
|
|
29
|
+
export const DeployXMPP = async (): Promise<void> => {
|
|
31
30
|
let session;
|
|
32
31
|
const settings = bootstrap.settings as TypeSettings
|
|
33
32
|
settings.NOAAWeatherWireServiceSettings.CredentialSettings.Nickname
|
|
@@ -39,13 +38,13 @@ export const xDeploy = async (): Promise<void> => {
|
|
|
39
38
|
password: settings.NOAAWeatherWireServiceSettings.CredentialSettings.Password
|
|
40
39
|
})
|
|
41
40
|
try {
|
|
42
|
-
await
|
|
43
|
-
await
|
|
44
|
-
await
|
|
45
|
-
await
|
|
41
|
+
await OfflineXMPP();
|
|
42
|
+
await ErrorXMPP();
|
|
43
|
+
await StanzaXMPP();
|
|
44
|
+
await OnlineXMPP();
|
|
46
45
|
await session.start()
|
|
47
46
|
} catch (error) {
|
|
48
|
-
|
|
47
|
+
SetEventEmit({
|
|
49
48
|
event: `onServiceStatus`,
|
|
50
49
|
metadata: {
|
|
51
50
|
message: `Error occured while starting XMPP Session: ${error}`,
|
|
@@ -18,10 +18,8 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import { bootstrap } from "../../bootstrap";
|
|
21
|
-
import { setEventEmit } from "../@utilities/utilities.setEventEmit";
|
|
22
|
-
import { setWarning } from "../@utilities/utilities.setWarning";
|
|
23
21
|
|
|
24
|
-
export const
|
|
22
|
+
export const ErrorXMPP = () => {
|
|
25
23
|
bootstrap.session_xmpp.on(`error`, async (error: Error) => {
|
|
26
24
|
bootstrap.cache.isConnected = false;
|
|
27
25
|
bootstrap.cache.sigHault = true;
|
|
@@ -18,14 +18,13 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import { bootstrap } from "../../bootstrap";
|
|
21
|
-
import {
|
|
22
|
-
import { setWarning } from "../@utilities/utilities.setWarning";
|
|
21
|
+
import { SetEventEmit } from "../@utilities/SetEventEmit";
|
|
23
22
|
|
|
24
|
-
export const
|
|
23
|
+
export const OfflineXMPP = () => {
|
|
25
24
|
bootstrap.session_xmpp.on(`offline`, async () => {
|
|
26
25
|
bootstrap.cache.isConnected = false;
|
|
27
26
|
bootstrap.cache.sigHault = true;
|
|
28
|
-
|
|
27
|
+
SetEventEmit({
|
|
29
28
|
event: `onServiceStatus`,
|
|
30
29
|
metadata: {
|
|
31
30
|
message: `Client has gone offline`,
|