@atmosx/event-product-parser 3.0.3 → 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.
Files changed (162) hide show
  1. package/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +1 -1
  2. package/.github/README.md +163 -0
  3. package/.github/SUPPORTED_EVENTS.md +370 -0
  4. package/.github/docs/docs-functions.md +30 -0
  5. package/.github/docs/docs-general-configurations.md +209 -0
  6. package/.github/docs/docs-integrations.md +37 -0
  7. package/.github/docs/docs-listeners.md +28 -0
  8. package/.github/docs/docs-source-configuration.md +218 -0
  9. package/.github/docs/docs-technical.md +50 -0
  10. package/.github/logo.png +0 -0
  11. package/.github/samples/SAMPLE_EAS_GENERATION.wav +0 -0
  12. package/.github/samples/SAMPLE_GEOJSON.json +204 -0
  13. package/.github/samples/SAMPLE_TEXT_PRODUCT.txt +119 -0
  14. package/dist/cjs/index.cjs +4681 -13425
  15. package/dist/esm/index.mjs +3163 -11909
  16. package/package.json +4 -8
  17. package/src/@building/{building.create.ts → CreateEvent.ts} +25 -11
  18. package/src/@building/{building.clean.ts → GetCleanedEvent.ts} +2 -2
  19. package/src/@building/GetEventAttachments.ts +86 -0
  20. package/src/@building/{building.enhance.ts → GetEventEnhancedName.ts} +11 -12
  21. package/src/@building/{building.geometry.ts → GetEventGeometry.ts} +7 -7
  22. package/src/@building/{building.headers.ts → GetEventHeader.ts} +3 -3
  23. package/src/@building/{building.polygon.ts → GetEventNodes.ts} +13 -11
  24. package/src/@building/{building.office.ts → GetEventOffice.ts} +6 -6
  25. package/src/@building/GetEventProperties.ts +96 -0
  26. package/src/@building/{building.signature.ts → GetEventSignature.ts} +14 -15
  27. package/src/@building/{building.tags.ts → GetEventTags.ts} +9 -4
  28. package/src/@building/{building.tracking.ts → GetEventTracking.ts} +15 -15
  29. package/src/@building/{building.validate.ts → ValidateEvents.ts} +67 -60
  30. package/src/@core/{core.clearEvents.ts → ClearEvents.ts} +3 -4
  31. package/src/@core/{core.createListener.ts → CreateListener.ts} +3 -3
  32. package/src/@core/{core.getEvents.ts → GetEvents.ts} +1 -2
  33. package/src/@core/{core.getNodes.ts → GetNodes.ts} +1 -2
  34. package/src/@core/{core.getRandomEvent.ts → GetRandomEvent.ts} +1 -2
  35. package/src/@core/{core.getVersion.ts → GetVersion.ts} +1 -2
  36. package/src/@core/ManualEvent.ts +56 -0
  37. package/src/@core/QueryStanza.ts +39 -0
  38. package/src/@core/{core.setNode.ts → SetNode.ts} +8 -8
  39. package/src/@core/{core.start.ts → StartService.ts} +21 -21
  40. package/src/@core/{core.stop.ts → StopService.ts} +1 -1
  41. package/src/@enums/AWIPS.ts +366 -0
  42. package/src/{@dictionaries/dictionaries.eventActions.ts → @enums/Actions.ts} +1 -1
  43. package/src/{@dictionaries/dictionaries.eventCancelMessages.ts → @enums/Cancellation.ts} +2 -1
  44. package/src/{@dictionaries/dictionaries.eventCauses.ts → @enums/Causes.ts} +1 -1
  45. package/src/{@dictionaries/dictionaries.statusCorrelationText.ts → @enums/Correlations.ts} +1 -1
  46. package/src/@enums/Enhanced.ts +70 -0
  47. package/src/{@dictionaries/dictionaries.eventTypes.ts → @enums/Events.ts} +1 -1
  48. package/src/{@dictionaries/dictionaries.regExp.ts → @enums/Expressions.ts} +2 -1
  49. package/src/@enums/GlobalFilter.ts +24 -0
  50. package/src/{@dictionaries/dictionaries.hailStrings.ts → @enums/Hail.ts} +7 -2
  51. package/src/{@dictionaries/dictionaries.officeICAOs.ts → @enums/ICAO.ts} +3 -1
  52. package/src/@enums/Matches.ts +55 -0
  53. package/src/{@dictionaries/dictionaries.eventProducts.ts → @enums/Products.ts} +1 -1
  54. package/src/{@dictionaries/dictionaries.eventRecords.ts → @enums/Records.ts} +1 -1
  55. package/src/{@dictionaries/dictionaries.eventSeverity.ts → @enums/Severity.ts} +1 -1
  56. package/src/{@dictionaries/dictionaries.shapefileLinks.ts → @enums/Shapefiles.ts} +1 -1
  57. package/src/@enums/States.ts +72 -0
  58. package/src/{@dictionaries/dictionaries.eventStatus.ts → @enums/Status.ts} +1 -1
  59. package/src/@enums/Strings.ts +22 -0
  60. package/src/@enums/Tags.ts +167 -0
  61. package/src/{@dictionaries/dictionaries.testSignatures.ts → @enums/Testing.ts} +3 -2
  62. package/src/@events/{events.api.ts → ParseAPI.ts} +42 -38
  63. package/src/@events/{events.text.ts → ParseText.ts} +25 -18
  64. package/src/@events/{events.ugc.ts → ParseUGC.ts} +28 -19
  65. package/src/@events/{events.vtec.ts → ParseVTEC.ts} +21 -21
  66. package/src/@manager/CreateActions.ts +213 -0
  67. package/src/@manager/{manager.mkEvent.ts → MakeEvent.ts} +34 -30
  68. package/src/@manager/RemoveEvent.ts +70 -0
  69. package/src/@manager/{manager.setHash.ts → SetHash.ts} +8 -9
  70. package/src/@manager/{manager.updateEvents.ts → UpdateEvents.ts} +9 -9
  71. package/src/@manager/{manager.updateNodes.ts → UpdateNode.ts} +24 -17
  72. package/src/@modules/@database/{database.cache.ts → GetCachedEvents.ts} +10 -8
  73. package/src/@modules/@database/ImportBroadcastify.ts +70 -0
  74. package/src/@modules/@database/{database.shapefiles.ts → ImportShapefiles.ts} +17 -20
  75. package/src/@modules/@database/{database.stanza.ts → ImportStanza.ts} +5 -6
  76. package/src/@modules/@database/{database.init.ts → InitializeDatabase.ts} +25 -11
  77. package/src/@modules/@eas/GenerateEASMessage.ts +144 -0
  78. package/src/@modules/@eas/GetCleanDescription.ts +91 -0
  79. package/src/@modules/@eas/{eas.getFloatPCM16.ts → GetFloatPCM16.ts} +1 -1
  80. package/src/@modules/@eas/{eas.getMergedPCM16.ts → GetMergedPCM16.ts} +1 -1
  81. package/src/@modules/@eas/{eas.getPCM16.ts → GetPCM16.ts} +1 -1
  82. package/src/@modules/@eas/{eas.getPCMToFloat.ts → GetPCMToFloat.ts} +1 -1
  83. package/src/@modules/@eas/{eas.getSampledPCM16.ts → GetSampledPCM16.ts} +1 -1
  84. package/src/@modules/@eas/GetTTS.ts +54 -0
  85. package/src/@modules/@eas/{eas.getWavPCM16.ts → GetWavPCM16.ts} +1 -1
  86. package/src/@modules/@eas/{eas.setAFSK.ts → SetAFSK.ts} +1 -2
  87. package/src/@modules/@eas/{eas.setAsciiToBits.ts → SetAsciiToBits.ts} +1 -2
  88. package/src/@modules/@eas/{eas.setAttentionTone.ts → SetAttentionTone.ts} +1 -1
  89. package/src/@modules/@eas/{eas.setNoise.ts → SetNoise.ts} +6 -5
  90. package/src/@modules/@eas/{eas.setRadioEffect.ts → SetRadioEffect.ts} +6 -5
  91. package/src/@modules/@eas/{eas.setSameHeader.ts → SetSameHeader.ts} +7 -8
  92. package/src/@modules/@stanza/{stanza.getAwipsType.ts → GetAwipsType.ts} +11 -9
  93. package/src/@modules/@stanza/{stanza.validate.ts → ValidateStanza.ts} +9 -9
  94. package/src/@modules/@utilities/CreateHttp.ts +83 -0
  95. package/src/@modules/@utilities/{utilities.getFormattedTime.ts → GetFormattedTime.ts} +1 -1
  96. package/src/@modules/@utilities/GetLatestIssuance.ts +32 -0
  97. package/src/@modules/@utilities/GetMatched.ts +33 -0
  98. package/src/@modules/@utilities/{utilities.getSettings.ts → GetSettings.ts} +2 -2
  99. package/src/@modules/@utilities/{utilities.getShapeNearestPoint.ts → GetShapeNearestPoint.ts} +1 -1
  100. package/src/@modules/@utilities/{utilities.setCronSchedule.ts → SetCronSchedule.ts} +41 -12
  101. package/src/{@types/types.webhook.ts → @modules/@utilities/SetDebug.ts} +16 -6
  102. package/src/@modules/@utilities/{utilities.setEventEmit.ts → SetEventEmit.ts} +5 -5
  103. package/src/@modules/@utilities/{utilities.setListener.ts → SetListener.ts} +1 -1
  104. package/src/@modules/@utilities/{utilities.setSettings.ts → SetSettings.ts} +2 -2
  105. package/src/@modules/@utilities/{utilities.setSleep.ts → SetSleep.ts} +1 -1
  106. package/src/@modules/@utilities/{utilities.setTimeoutAction.ts → SetTimeoutAction.ts} +8 -3
  107. package/src/@modules/@utilities/{utilities.setWarning.ts → SetWarning.ts} +4 -4
  108. package/src/@modules/@xmpp/{xmpp.xDeploy.ts → DeployXMPP.ts} +13 -14
  109. package/src/@modules/@xmpp/{xmpp.xError.ts → ErrorXMPP.ts} +1 -3
  110. package/src/@modules/@xmpp/{xmpp.xOffline.ts → OfflineXMPP.ts} +3 -4
  111. package/src/@modules/@xmpp/{xmpp.xOnline.ts → OnlineXMPP.ts} +6 -5
  112. package/src/@modules/@xmpp/{xmpp.xReconnect.ts → ReconnectXMPP.ts} +8 -8
  113. package/src/@modules/@xmpp/{xmpp.xStanza.ts → StanzaXMPP.ts} +11 -11
  114. package/src/@parsers/@hvtec/{hvtec.extract.ts → HVExtract.ts} +10 -10
  115. package/src/@parsers/@pvtec/{pvtec.expires.ts → GetExpiry.ts} +1 -1
  116. package/src/@parsers/@pvtec/{pvtec.extract.ts → VTECExtract.ts} +17 -17
  117. package/src/@parsers/@text/{text.getDescriptionFromProduct.ts → GetDescriptionFromProduct.ts} +12 -5
  118. package/src/@parsers/@text/GetEmbededText.ts +56 -0
  119. package/src/@parsers/@text/{text.getPolygonFromProduct.ts → GetPolygonFromProduct.ts} +31 -10
  120. package/src/@parsers/@text/GetStringText.ts +58 -0
  121. package/src/@parsers/@text/{text.getTextFromProduct.ts → GetTextFromProduct.ts} +1 -1
  122. package/src/@parsers/@text/{text.getXML.ts → GetXML.ts} +1 -1
  123. package/src/@parsers/@ugc/GetCache.ts +24 -0
  124. package/src/@parsers/@ugc/{ugc.expiry.ts → GetExpiry.ts} +1 -1
  125. package/src/@parsers/@ugc/{ugc.locations.ts → GetLocations.ts} +35 -7
  126. package/src/@parsers/@ugc/{ugc.header.ts → GetUGCHeader.ts} +3 -3
  127. package/src/@parsers/@ugc/{ugc.coordinates.ts → GetZonePolygon.ts} +4 -3
  128. package/src/@parsers/@ugc/SetCache.ts +28 -0
  129. package/src/@parsers/@ugc/{ugc.extract.ts → UGCExtract.ts} +6 -6
  130. package/src/@types/Actions.ts +37 -0
  131. package/src/@types/{type.event.ts → Event.ts} +7 -5
  132. package/src/@types/{type.properties.ts → Properties.ts} +11 -8
  133. package/src/@types/{types.settings.ts → Settings.ts} +31 -7
  134. package/src/@types/{types.compiled.ts → StanzaCompiled.ts} +2 -1
  135. package/src/bootstrap.ts +33 -9
  136. package/src/index.ts +28 -26
  137. package/tsup.config.ts +1 -1
  138. package/README.md +0 -339
  139. package/dist/index.d.mts +0 -239
  140. package/dist/index.d.ts +0 -239
  141. package/src/@building/building.properties.ts +0 -89
  142. package/src/@dictionaries/dictionaries.betterEventNames.ts +0 -99
  143. package/src/@dictionaries/dictionaries.eventAwipAbreviations.ts +0 -364
  144. package/src/@dictionaries/dictionaries.eventTags.ts +0 -93
  145. package/src/@dictionaries/dictionaries.eventsMatchText.ts +0 -36
  146. package/src/@dictionaries/dictionaries.transcribedMessageReplacements.ts +0 -68
  147. package/src/@manager/manager.rmEvent.ts +0 -49
  148. package/src/@manager/manager.updateWebhooks.ts +0 -50
  149. package/src/@modules/@eas/eas.setEasTone.ts +0 -137
  150. package/src/@modules/@utilities/utilities.createHttp.ts +0 -85
  151. package/src/@modules/@utilities/utilities.createWebhook.ts +0 -115
  152. package/test.js +0 -91
  153. /package/{CODE_OF_CONDUCT.md → .github/CODE_OF_CONDUCT.md} +0 -0
  154. /package/{LICENSE → .github/LICENSE} +0 -0
  155. /package/{SECURITY.md → .github/SECURITY.md} +0 -0
  156. /package/src/@parsers/@ugc/{ugc.zones.ts → GetZones.ts} +0 -0
  157. /package/src/@types/{types.attributes.ts → Attributes.ts} +0 -0
  158. /package/src/@types/{types.hvtec.ts → HVTEC.ts} +0 -0
  159. /package/src/@types/{types.hash.ts → Hash.ts} +0 -0
  160. /package/src/@types/{types.stanza.ts → Stanza.ts} +0 -0
  161. /package/src/@types/{types.ugc.ts → UGC.ts} +0 -0
  162. /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
- export const setRadioEffect = (int16: Int16Array, sampleRate: number): Int16Array => {
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 = getPCMToFloat(int16);
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 getFloatPCM16(x);
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
- 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 => {
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 = setAsciiToBits(vtec);
33
- const body = setAFSK(bodyBits, sampleRate);
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 getMergedPCM16(bursts);
42
+ return GetMergedPCM16(bursts);
44
43
  }
45
44
 
@@ -17,30 +17,32 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeAttributes } from "../../@types/types.attributes"
21
- import { eventAwipAbreviations } from "../../@dictionaries/dictionaries.eventAwipAbreviations"
20
+ import { TypeAttributes } from "../../@types/Attributes"
21
+ import { EnumAWIPS } from "../../@enums/AWIPS"
22
22
 
23
- interface ValidateOptions {
23
+ interface GetAwipsTypeOptions {
24
24
  attributes: TypeAttributes
25
25
  }
26
26
 
27
- interface ValidiateResponse {
27
+ interface GetAwipsTypeResponse {
28
28
  type: string
29
29
  prefix: string
30
+ discovered: boolean
30
31
  }
31
32
 
32
- export const getAwipsType = (options: ValidateOptions): ValidiateResponse => {
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(eventAwipAbreviations)) {
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: null, prefix: null }
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/types.stanza"
21
- import { TypeStanzaCompiled } from "../../@types/types.compiled"
22
- import { regExp } from "../../@dictionaries/dictionaries.regExp"
23
- import { getAwipsType } from "./stanza.getAwipsType"
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 ValidateOptions {
25
+ interface ValidateStanzaOptions {
26
26
  stanza: TypeStanza
27
27
  }
28
28
 
29
- export const validate = (options: ValidateOptions): TypeStanzaCompiled => {
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(regExp.pvtec) != null;
39
- const isUGC = message.match(regExp.ugc1) != null;
40
- const getType = getAwipsType({ attributes: attributes})
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 getFormattedTime = (date: string): string => {
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/types.settings'
20
+ import { TypeSettings } from '../../@types/Settings'
21
21
  import { bootstrap } from "../../bootstrap"
22
22
 
23
- export const getSettings = (): TypeSettings => {
23
+ export const GetSettings = (): TypeSettings => {
24
24
  return bootstrap.settings;
25
25
  }
@@ -25,7 +25,7 @@ interface GetShapeNearestPointResponse {
25
25
  distanceMeters?: number | null
26
26
  }
27
27
 
28
- export const getShapeNearestPoint = (coordinates: number[][], point: [number, number]): GetShapeNearestPointResponse => {
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/types.settings";
22
- import { xReconnect } from "../@xmpp/xmpp.xReconnect"
21
+ import { TypeSettings } from "../../@types/Settings";
22
+ import { ReconnectXMPP } from "../@xmpp/ReconnectXMPP"
23
23
  import { bootstrap } from "../../bootstrap";
24
- import { createHttp } from "./utilities.createHttp";
25
- import { createEvent } from "../../@building/building.create";
26
- import { setEventEmit } from "./utilities.setEventEmit";
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 setCronSchedule = async (): Promise<void> => {
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 xReconnect(settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval)
61
+ void ReconnectXMPP(settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval)
33
62
  }
34
63
  } else {
35
- const response = await createHttp({
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 setEventEmit({
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
- setEventEmit({
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
- createEvent({ message: response.message, isNWWS: false })
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
- export type TypeWebhook = {
21
- webhook: string
22
- title: string
20
+ import { TypeSettings } from "../../@types/Settings";
21
+ import { bootstrap } from "../../bootstrap"
22
+
23
+ interface SetDebugOptions {
24
+ title?: string
23
25
  message: string
24
- upload: boolean
25
- rate: number
26
- events: string[]
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 { setTimeoutAction } from "./utilities.setTimeoutAction";
22
- import { setWarning } from "./utilities.setWarning";
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 setEventEmit = (options: SetEventEmitOptions): void => {
31
+ export const SetEventEmit = (options: SetEventEmitOptions): void => {
32
32
  if (options.limited) {
33
- const isTimeout = setTimeoutAction({ identifier: `event.${options.event}`, addTime: true, max: 1, interval: 1 })
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
- setWarning({ message: options.message })
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 setListener = (options: SetListenerOptions): (() => 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
  }
@@ -17,10 +17,10 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeSettings } from '../../@types/types.settings'
20
+ import { TypeSettings } from '../../@types/Settings'
21
21
  import { bootstrap } from "../../bootstrap"
22
22
 
23
- export const setSettings = (newSettings: TypeSettings): TypeSettings => {
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 setSleep = async (options: SetSleepOptions): Promise<void> => {
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: number
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 setTimeoutAction = (options: SetTimeoutActionOptions): SetTimeoutActionResponse => {
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 || 1;
53
+ const max = options?.max ?? 1;
49
54
 
50
55
  if (target?.length >= max && getWait > 0) {
51
56
  return {
@@ -18,17 +18,17 @@
18
18
  */
19
19
 
20
20
  import { bootstrap } from "../../bootstrap"
21
- import { TypeSettings } from "../../@types/types.settings";
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 setWarning = (options: SetWarningOptions): void => {
28
+ export const SetWarning = (options: SetWarningOptions): void => {
29
29
  const settings = bootstrap.settings as TypeSettings;
30
- bootstrap.listener.emit(`log`, `${options.title ?? `[${bootstrap.ansi_colors.YELLOW}ATMOSX-PARSER${bootstrap.ansi_colors.RESET}]`} ${options.message}`)
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) {
32
- console.log(`${options.title ?? `[${bootstrap.ansi_colors.YELLOW}ATMOSX-PARSER${bootstrap.ansi_colors.RESET}]`} ${options.message}`)
32
+ console.log(`${options.title ?? `[${bootstrap.ansi_colors.YELLOW}@atmosx/product-parser${bootstrap.ansi_colors.RESET}]`} ${options.message}`)
33
33
  }
34
34
  }
@@ -17,17 +17,16 @@
17
17
 
18
18
  */
19
19
 
20
- import { client } from '@xmpp/client';
21
- import { TypeSettings } from "../../@types/types.settings";
20
+ import { TypeSettings } from "../../@types/Settings";
22
21
  import { bootstrap } from "../../bootstrap"
23
- import { setWarning } from "../@utilities/utilities.setWarning";
24
- import { xOnline } from "./xmpp.xOnline";
25
- import { xOffline } from "./xmpp.xOffline";
26
- import { xError } from "./xmpp.xError";
27
- import { xStanza } from "./xmpp.xStanza";
28
- import { setEventEmit } from '../@utilities/utilities.setEventEmit';
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 xDeploy = async (): Promise<void> => {
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 xOffline();
43
- await xError();
44
- await xStanza();
45
- await xOnline();
41
+ await OfflineXMPP();
42
+ await ErrorXMPP();
43
+ await StanzaXMPP();
44
+ await OnlineXMPP();
46
45
  await session.start()
47
46
  } catch (error) {
48
- setEventEmit({
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 xError = () => {
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 { setEventEmit } from "../@utilities/utilities.setEventEmit";
22
- import { setWarning } from "../@utilities/utilities.setWarning";
21
+ import { SetEventEmit } from "../@utilities/SetEventEmit";
23
22
 
24
- export const xOffline = () => {
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
- setEventEmit({
27
+ SetEventEmit({
29
28
  event: `onServiceStatus`,
30
29
  metadata: {
31
30
  message: `Client has gone offline`,