@atmosx/event-product-parser 3.0.62 → 3.0.63

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 (112) hide show
  1. package/README.md +6 -4
  2. package/dist/cjs/index.cjs +21216 -6908
  3. package/dist/esm/index.mjs +21207 -6900
  4. package/package.json +49 -47
  5. package/pnpm-workspace.yaml +4 -0
  6. package/src/@building/CreateEvent.ts +20 -22
  7. package/src/@building/GetEventAttachments.ts +8 -8
  8. package/src/@building/GetEventEnhancedName.ts +2 -4
  9. package/src/@building/GetEventGeometry.ts +5 -5
  10. package/src/@building/GetEventHeader.ts +11 -11
  11. package/src/@building/GetEventNodes.ts +12 -12
  12. package/src/@building/GetEventOffice.ts +11 -11
  13. package/src/@building/GetEventProperties.ts +60 -55
  14. package/src/@building/GetEventSignature.ts +7 -7
  15. package/src/@building/GetEventTags.ts +1 -1
  16. package/src/@building/GetEventTracking.ts +28 -32
  17. package/src/@core/ClearEvents.ts +7 -7
  18. package/src/@core/CreateListener.ts +2 -2
  19. package/src/@core/GetEvents.ts +2 -2
  20. package/src/@core/GetNodes.ts +2 -2
  21. package/src/@core/GetRandomEvent.ts +2 -2
  22. package/src/@core/GetVersion.ts +2 -2
  23. package/src/@core/ManualEvent.ts +20 -21
  24. package/src/@core/QueryStanza.ts +7 -7
  25. package/src/@core/SetNode.ts +32 -26
  26. package/src/@core/StartService.ts +18 -18
  27. package/src/@core/StopService.ts +8 -8
  28. package/src/@enums/Expressions.ts +1 -1
  29. package/src/@enums/Tags.ts +1 -1
  30. package/src/@events/ParseAPI.ts +44 -39
  31. package/src/@events/ParseText.ts +19 -19
  32. package/src/@events/ParseUGC.ts +21 -21
  33. package/src/@events/ParseVTEC.ts +32 -33
  34. package/src/@manager/MakeEvents.ts +33 -30
  35. package/src/@manager/RemoveEvent.ts +38 -34
  36. package/src/@manager/SetHash.ts +16 -11
  37. package/src/@manager/UpdateEvents.ts +10 -10
  38. package/src/@manager/UpdateNode.ts +13 -13
  39. package/src/@manager/ValidateEvents.ts +36 -37
  40. package/src/@modules/@database/GetCachedEvents.ts +10 -12
  41. package/src/@modules/@database/ImportBroadcastify.ts +12 -13
  42. package/src/@modules/@database/ImportShapefiles.ts +17 -18
  43. package/src/@modules/@database/ImportStanza.ts +11 -11
  44. package/src/@modules/@database/InitializeDatabase.ts +16 -16
  45. package/src/@modules/@eas/GenerateEASMessage.ts +53 -47
  46. package/src/@modules/@eas/GetPCM16.ts +11 -6
  47. package/src/@modules/@eas/GetSampledPCM16.ts +12 -6
  48. package/src/@modules/@eas/GetTTS.ts +12 -7
  49. package/src/@modules/@eas/GetWavPCM16.ts +5 -5
  50. package/src/@modules/@eas/SetAFSK.ts +11 -6
  51. package/src/@modules/@eas/SetAttentionTone.ts +9 -4
  52. package/src/@modules/@eas/SetNoise.ts +10 -5
  53. package/src/@modules/@eas/SetRadioEffect.ts +10 -5
  54. package/src/@modules/@eas/SetSameHeader.ts +20 -12
  55. package/src/@modules/@stanza/GetAwipsType.ts +14 -15
  56. package/src/@modules/@stanza/ValidateStanza.ts +25 -13
  57. package/src/@modules/@utilities/CreateHttp.ts +24 -24
  58. package/src/@modules/@utilities/GetMatched.ts +8 -3
  59. package/src/@modules/@utilities/GetSettings.ts +3 -3
  60. package/src/@modules/@utilities/GetShapeNearestPoint.ts +22 -17
  61. package/src/@modules/@utilities/QueueManager.ts +70 -0
  62. package/src/@modules/@utilities/SetCronSchedule.ts +20 -20
  63. package/src/@modules/@utilities/SetDebug.ts +10 -10
  64. package/src/@modules/@utilities/SetEventEmit.ts +15 -15
  65. package/src/@modules/@utilities/SetListener.ts +6 -6
  66. package/src/@modules/@utilities/SetSettings.ts +5 -5
  67. package/src/@modules/@utilities/SetSleep.ts +3 -3
  68. package/src/@modules/@utilities/SetTimeoutAction.ts +25 -25
  69. package/src/@modules/@utilities/SetWarning.ts +8 -8
  70. package/src/@modules/@xmpp/DeployXMPP.ts +16 -16
  71. package/src/@modules/@xmpp/ErrorXMPP.ts +4 -4
  72. package/src/@modules/@xmpp/OfflineXMPP.ts +11 -11
  73. package/src/@modules/@xmpp/OnlineXMPP.ts +16 -16
  74. package/src/@modules/@xmpp/ReconnectXMPP.ts +27 -27
  75. package/src/@modules/@xmpp/StanzaXMPP.ts +23 -23
  76. package/src/@parsers/@hvtec/HVExtract.ts +9 -9
  77. package/src/@parsers/@text/GetDescriptionFromProduct.ts +18 -19
  78. package/src/@parsers/@text/GetEmbededText.ts +3 -3
  79. package/src/@parsers/@text/GetStringText.ts +6 -6
  80. package/src/@parsers/@text/GetTextFromProduct.ts +10 -10
  81. package/src/@parsers/@text/GetXML.ts +5 -5
  82. package/src/@parsers/@ugc/GetCache.ts +2 -2
  83. package/src/@parsers/@ugc/{GetUGCHeader.ts → GetHeader.ts} +2 -2
  84. package/src/@parsers/@ugc/GetLocations.ts +5 -5
  85. package/src/@parsers/@ugc/GetZonePolygon.ts +10 -10
  86. package/src/@parsers/@ugc/GetZones.ts +1 -1
  87. package/src/@parsers/@ugc/SetCache.ts +11 -6
  88. package/src/@parsers/@ugc/UGCExtract.ts +10 -10
  89. package/src/@parsers/{@pvtec → @vtec}/VTECExtract.ts +19 -19
  90. package/src/@tasks/CreateTasks.ts +110 -0
  91. package/src/@tasks/TaskGenerateAudio.ts +34 -0
  92. package/src/@tasks/TaskGenerateJSON.ts +34 -0
  93. package/src/@tasks/TaskGenerateText.ts +34 -0
  94. package/src/@tasks/TaskSendNTFY.ts +91 -0
  95. package/src/@tasks/TaskSendWebhook.ts +100 -0
  96. package/src/@types/HVTEC.ts +4 -4
  97. package/src/@types/Hash.ts +3 -3
  98. package/src/@types/Settings.ts +1 -1
  99. package/src/@types/StanzaCompiled.ts +13 -13
  100. package/src/@types/UGC.ts +3 -3
  101. package/src/@types/VTEC.ts +10 -10
  102. package/src/{@types → @types-lower}/Event.ts +4 -4
  103. package/src/{@types → @types-lower}/Properties.ts +2 -1
  104. package/src/{@types → @types-lower}/Stanza.ts +1 -1
  105. package/src/bootstrap.ts +26 -26
  106. package/src/index.ts +30 -27
  107. package/tools/build.js +45 -0
  108. package/tsconfig.json +21 -1
  109. package/src/@manager/Tasks.ts +0 -246
  110. package/tsup.config.ts +0 -16
  111. /package/src/@parsers/{@pvtec → @vtec}/GetExpiry.ts +0 -0
  112. /package/src/{@types → @types-lower}/Attributes.ts +0 -0
@@ -18,17 +18,23 @@
18
18
 
19
19
  */
20
20
 
21
- export const GetSampledPCM16 = (int16: Int16Array, originalRate: number, targetRate: number): Int16Array => {
22
- if (originalRate === targetRate) return int16;
23
- const ratio = targetRate / originalRate;
24
- const outLen = Math.max(1, Math.round(int16.length * ratio));
21
+ interface GetSampledPCM16Options {
22
+ Int16: Int16Array
23
+ OriginalRate: number
24
+ TargetRate: number
25
+ }
26
+
27
+ export const GetSampledPCM16 = ({ Int16, OriginalRate, TargetRate }: GetSampledPCM16Options): Int16Array => {
28
+ if (OriginalRate === TargetRate) return Int16;
29
+ const ratio = TargetRate / OriginalRate;
30
+ const outLen = Math.max(1, Math.round(Int16.length * ratio));
25
31
  const out = new Int16Array(outLen);
26
32
  for (let i = 0; i < outLen; i++) {
27
33
  const pos = i / ratio;
28
34
  const i0 = Math.floor(pos);
29
- const i1 = Math.min(i0 + 1, int16.length - 1);
35
+ const i1 = Math.min(i0 + 1, Int16.length - 1);
30
36
  const frac = pos - i0;
31
- const v = int16[i0] * (1 - frac) + int16[i1] * frac;
37
+ const v = Int16[i0] * (1 - frac) + Int16[i1] * frac;
32
38
  out[i] = Math.round(v);
33
39
  }
34
40
  return out;
@@ -18,22 +18,27 @@
18
18
 
19
19
  */
20
20
 
21
- import { platform } from 'os'
21
+ import { platform } from "os"
22
22
  import { writeFileSync } from "fs"
23
- import { execSync } from 'child_process'
23
+ import { execSync } from "child_process"
24
24
 
25
- export const GetTTS = async (text: string, outputPath: string): Promise<void> => {
25
+ interface GetTTSOptions {
26
+ Text: string
27
+ OutputPath: string
28
+ }
29
+
30
+ export const GetTTS = async ({ Text, OutputPath }: GetTTSOptions): Promise<void> => {
26
31
  const vPlatform = platform();
27
32
  switch (vPlatform) {
28
33
  case 'win32': {
29
34
  try {
30
- const txtPath = outputPath + ".txt";
31
- writeFileSync(txtPath, text, "utf8");
35
+ const txtPath = OutputPath + ".txt";
36
+ writeFileSync(txtPath, Text, "utf8");
32
37
  const command = [
33
38
  "Add-Type -AssemblyName System.Speech;",
34
39
  `$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;`,
35
40
  `$text = Get-Content -Raw -LiteralPath '${txtPath}';`,
36
- `$speak.SetOutputToWaveFile('${outputPath}');`,
41
+ `$speak.SetOutputToWaveFile('${OutputPath}');`,
37
42
  `$speak.Speak($text);`,
38
43
  `$speak.Dispose();`
39
44
  ].join(" ");
@@ -45,7 +50,7 @@ export const GetTTS = async (text: string, outputPath: string): Promise<void> =>
45
50
  }
46
51
  case 'linux':
47
52
  try {
48
- execSync(`espeak -w "${outputPath}" "${text.replace(/"/g, '\\"')}"`);
53
+ execSync(`espeak -w "${OutputPath}" "${Text.replace(/"/g, '\\"')}"`);
49
54
  } catch {}
50
55
  break;
51
56
  default: break;
@@ -19,10 +19,10 @@
19
19
  */
20
20
 
21
21
  interface getWavPCM16Response {
22
- samples: Int16Array
23
- sampleRate: number
24
- channels: number
25
- bitsPerSample: number
22
+ Samples: Int16Array
23
+ SampleRate: number
24
+ Channels: number
25
+ BitsPerSample: number
26
26
  }
27
27
 
28
28
  export const GetWavPCM16 = (buffer: Buffer): getWavPCM16Response => {
@@ -46,7 +46,7 @@ export const GetWavPCM16 = (buffer: Buffer): getWavPCM16Response => {
46
46
  const bitsPerSample = fmt.readUInt16LE(14);
47
47
  if (audioFormat !== 1 || bitsPerSample !== 16 || channels !== 1) { return null; }
48
48
  const samples = new Int16Array(data.buffer, data.byteOffset, data.length / 2);
49
- return { samples: new Int16Array(samples), sampleRate, channels, bitsPerSample };
49
+ return { Samples: new Int16Array(samples), SampleRate: sampleRate, Channels: channels, BitsPerSample: bitsPerSample };
50
50
  }
51
51
 
52
52
 
@@ -18,7 +18,12 @@
18
18
 
19
19
  */
20
20
 
21
- export const SetAFSK = (bits: number[], sampleRate: number): Int16Array => {
21
+ interface SetAFSKOptions {
22
+ Bits: number[]
23
+ SampleRate: number
24
+ }
25
+
26
+ export const SetAFSK = ({ Bits, SampleRate }: SetAFSKOptions): Int16Array => {
22
27
  const baud = 520.83;
23
28
  const markFreq = 2083.3;
24
29
  const spaceFreq = 1562.5;
@@ -27,20 +32,20 @@ export const SetAFSK = (bits: number[], sampleRate: number): Int16Array => {
27
32
  const result = [];
28
33
  let phase = 0;
29
34
  let frac = 0;
30
- for (let b = 0; b < bits.length; b++) {
31
- const bit = bits[b];
35
+ for (let b = 0; b < Bits.length; b++) {
36
+ const bit = Bits[b];
32
37
  const freq = bit ? markFreq : spaceFreq;
33
- const samplesPerBit = sampleRate / baud + frac;
38
+ const samplesPerBit = SampleRate / baud + frac;
34
39
  const n = Math.round(samplesPerBit);
35
40
  frac = samplesPerBit - n;
36
- const inc = twoPi * freq / sampleRate;
41
+ const inc = twoPi * freq / SampleRate;
37
42
  for (let i = 0; i < n; i++) {
38
43
  result.push(Math.round(Math.sin(phase) * amplitude * 32767));
39
44
  phase += inc;
40
45
  if (phase > twoPi) phase -= twoPi;
41
46
  }
42
47
  }
43
- const fadeSamples = Math.floor(sampleRate * 0.002);
48
+ const fadeSamples = Math.floor(SampleRate * 0.002);
44
49
  for (let i = 0; i < fadeSamples; i++) {
45
50
  const gain = i / fadeSamples;
46
51
  result[i] = Math.round(result[i] * gain);
@@ -18,16 +18,21 @@
18
18
 
19
19
  */
20
20
 
21
- export const SetAttentionTone = (ms: number, sampleRate: number): Int16Array => {
22
- const len = Math.floor(ms * sampleRate);
21
+ interface SetAttentionToneOptions {
22
+ MS: number
23
+ SampleRate: number
24
+ }
25
+
26
+ export const SetAttentionTone = ({ MS, SampleRate }: SetAttentionToneOptions): Int16Array => {
27
+ const len = Math.floor(MS * SampleRate);
23
28
  const out = new Int16Array(len);
24
29
  const f1 = 853;
25
30
  const f2 = 960;
26
31
  const twoPi = Math.PI * 2;
27
32
  const amp = 0.1;
28
- const fadeLen = Math.floor(sampleRate * 0.00);
33
+ const fadeLen = Math.floor(SampleRate * 0.00);
29
34
  for (let i = 0; i < len; i++) {
30
- const t = i / sampleRate;
35
+ const t = i / SampleRate;
31
36
  const s = Math.sin(twoPi * f1 * t) + Math.sin(twoPi * f2 * t);
32
37
  let gain = 1;
33
38
  if (i < fadeLen) gain = i / fadeLen;
@@ -18,12 +18,17 @@
18
18
 
19
19
  */
20
20
 
21
- import { GetPCMToFloat } from "./GetPCMToFloat";
22
- import { GetFloatPCM16 } from "./GetFloatPCM16";
21
+ import { GetPCMToFloat } from "@eas/GetPCMToFloat"
22
+ import { GetFloatPCM16 } from "@eas/GetFloatPCM16"
23
23
 
24
- export const SetNoise = (int16: Int16Array, noiseLevel: number = 0.02): Int16Array => {
25
- const x = GetPCMToFloat(int16);
26
- for (let i = 0; i < x.length; i++) x[i] += (Math.random() * 2 - 1) * noiseLevel;
24
+ interface SetNoiseOptions {
25
+ Int16: Int16Array
26
+ NoiseLevel?: number
27
+ }
28
+
29
+ export const SetNoise = ({ Int16, NoiseLevel }: SetNoiseOptions): Int16Array => {
30
+ const x = GetPCMToFloat(Int16);
31
+ for (let i = 0; i < x.length; i++) x[i] += (Math.random() * 2 - 1) * (NoiseLevel ?? 0.02);
27
32
  let peak = 0;
28
33
  for (let i = 0; i < x.length; i++) peak = Math.max(peak, Math.abs(x[i]));
29
34
  if (peak > 1) for (let i = 0; i < x.length; i++) x[i] *= 0.98 / peak;
@@ -18,14 +18,19 @@
18
18
 
19
19
  */
20
20
 
21
- import { GetPCMToFloat } from "./GetPCMToFloat";
22
- import { GetFloatPCM16 } from "./GetFloatPCM16";
21
+ import { GetPCMToFloat } from "@eas/GetPCMToFloat"
22
+ import { GetFloatPCM16 } from "@eas/GetFloatPCM16"
23
23
 
24
- export const SetRadioEffect = (int16: Int16Array, sampleRate: number): Int16Array => {
24
+ interface SetRadioEffectOptions {
25
+ Int16: Int16Array
26
+ SampleRate: number
27
+ }
28
+
29
+ export const SetRadioEffect = ({ Int16, SampleRate }: SetRadioEffectOptions): Int16Array => {
25
30
  const hpCut = 3555;
26
31
  const lpCut = 1600;
27
- const x = GetPCMToFloat(int16);
28
- const dt = 1 / sampleRate;
32
+ const x = GetPCMToFloat(Int16);
33
+ const dt = 1 / SampleRate;
29
34
  const rcHP = 1 / (2 * Math.PI * hpCut);
30
35
  const aHP = rcHP / (rcHP + dt);
31
36
  let yHP = 0, xPrev = 0;
@@ -18,26 +18,34 @@
18
18
 
19
19
  */
20
20
 
21
- import { SetAFSK } from "./SetAFSK";
22
- import { SetAsciiToBits } from "./SetAsciiToBits";
23
- import { GetMergedPCM16 } from "./GetMergedPCM16";
21
+ import { SetAFSK } from "@eas/SetAFSK"
22
+ import { SetAsciiToBits } from "@eas/SetAsciiToBits"
23
+ import { GetMergedPCM16 } from "@eas/GetMergedPCM16"
24
24
 
25
- export const SetSameHeader = (vtec: string, repeats: number, sampleRate: number = 8000, options: {preMarkSec?: number, gapSec?: number} = {}): Int16Array => {
26
- const preMarkSec = options.preMarkSec ?? 0.3;
27
- const gapSec = options.gapSec ?? 0.1;
25
+ interface SetSameHeaderOptions {
26
+ VTEC: string
27
+ Repeats: number
28
+ SampleRate?: number
29
+ PreMarkSec?: number
30
+ GapSec?: number
31
+ }
32
+
33
+ export const SetSameHeader = ({ VTEC, Repeats, SampleRate, PreMarkSec, GapSec }: SetSameHeaderOptions): Int16Array => {
34
+ const preMarkSec = PreMarkSec ?? 0.3;
35
+ const gapSec = GapSec ?? 0.1;
28
36
  const bursts = [];
29
- const gap = new Int16Array(Math.floor(gapSec * sampleRate));
30
- for (let i = 0; i < repeats; i++) {
31
- const bodyBits = SetAsciiToBits(vtec);
32
- const body = SetAFSK(bodyBits, sampleRate);
33
- const extendedBodyDuration = Math.round(preMarkSec * sampleRate);
37
+ const gap = new Int16Array(Math.floor(gapSec * SampleRate));
38
+ for (let i = 0; i < Repeats; i++) {
39
+ const bodyBits = SetAsciiToBits(VTEC);
40
+ const body = SetAFSK({ Bits: bodyBits, SampleRate: SampleRate});
41
+ const extendedBodyDuration = Math.round(preMarkSec * SampleRate);
34
42
  const extendedBody = new Int16Array(extendedBodyDuration + gap.length);
35
43
  for (let j = 0; j < extendedBodyDuration; j++) {
36
44
  extendedBody[j] = Math.round(body[j % body.length] * 0.2);
37
45
  }
38
46
  extendedBody.set(gap, extendedBodyDuration);
39
47
  bursts.push(extendedBody);
40
- if (i !== repeats - 1) bursts.push(gap);
48
+ if (i !== Repeats - 1) bursts.push(gap);
41
49
  }
42
50
  return GetMergedPCM16(bursts);
43
51
  }
@@ -17,32 +17,31 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeAttributes } from "../../@types/Attributes"
21
- import { EnumAWIPS } from "../../@enums/AWIPS"
20
+ import { TypeAttributes } from "types-lower/Attributes"
21
+ import { EnumAWIPS } from "@enums/AWIPS"
22
22
 
23
23
  interface GetAwipsTypeOptions {
24
- attributes: TypeAttributes
24
+ Attributes: TypeAttributes
25
25
  }
26
26
 
27
27
  interface GetAwipsTypeResponse {
28
- type: string
29
- prefix: string
30
- discovered: boolean
28
+ Type: string
29
+ Prefix: string
30
+ Discovered: boolean
31
31
  }
32
32
 
33
- export const GetAwipsType = (options: GetAwipsTypeOptions): GetAwipsTypeResponse => {
34
- const attributes = options.attributes;
35
- if (!attributes.awipsid) {
33
+ export const GetAwipsType = ({ Attributes }: GetAwipsTypeOptions): GetAwipsTypeResponse => {
34
+ if (!Attributes.awipsid) {
36
35
  return {
37
- type: null,
38
- prefix: null,
39
- discovered: false
36
+ Type: null,
37
+ Prefix: null,
38
+ Discovered: false
40
39
  }
41
40
  }
42
41
  for (const [prefix, type] of Object.entries(EnumAWIPS)) {
43
- if (attributes.awipsid.startsWith(prefix)) {
44
- return { type, prefix, discovered: true }
42
+ if (Attributes.awipsid.startsWith(prefix)) {
43
+ return { Type: type, Prefix: prefix, Discovered: true }
45
44
  }
46
45
  }
47
- return { type: options.attributes.awipsid, prefix: options.attributes.awipsid, discovered: false }
46
+ return { Type: Attributes.awipsid, Prefix: Attributes.awipsid, Discovered: false }
48
47
  }
@@ -17,34 +17,46 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeStanza } from "../../@types/Stanza"
21
- import { TypeStanzaCompiled } from "../../@types/StanzaCompiled"
22
- import { EnumExpressions } from "../../@enums/Expressions"
23
- import { GetAwipsType } from "./GetAwipsType"
20
+ import { TypeStanza } from "types-lower/Stanza"
21
+ import { TypeStanzaCompiled } from "types/StanzaCompiled"
22
+ import { EnumExpressions } from "@enums/Expressions"
23
+ import { GetAwipsType } from "@stanza/GetAwipsType"
24
24
 
25
25
  interface ValidateStanzaOptions {
26
- stanza: TypeStanza
26
+ Stanza: TypeStanza
27
27
  }
28
28
 
29
- export const ValidateStanza = (options: ValidateStanzaOptions): TypeStanzaCompiled => {
30
- if (options.stanza.is(`message`)) {
31
- const cb = options.stanza.getChild(`x`) as TypeStanza;
29
+ export const ValidateStanza = ({ Stanza }: ValidateStanzaOptions): TypeStanzaCompiled => {
30
+ if (Stanza.is(`message`)) {
31
+ const cb = Stanza.getChild(`x`) as TypeStanza;
32
32
  if (cb && cb.children) {
33
33
  const message = unescape(cb.children[0]);
34
34
  const attributes = cb.attrs;
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(EnumExpressions.pvtec) != null;
38
+ const isVTEC = message.match(EnumExpressions.vtec) != null;
39
39
  const isUGC = message.match(EnumExpressions.ugc1) != null;
40
- const getType = GetAwipsType({ attributes: attributes})
41
- if (getType.type != null) {
40
+ const getType = GetAwipsType({ Attributes: attributes})
41
+ if (getType.Type != null) {
42
42
  return {
43
- message, attributes, isCapEvent, isVTEC, isUGC, isCapAreaDescription, isIgnored: false, isNWWS: true, getType
43
+ Message: message,
44
+ Attributes: attributes,
45
+ CapEvent: isCapEvent,
46
+ VTEC: isVTEC,
47
+ UGC: isUGC,
48
+ CapAreaDescription: isCapAreaDescription,
49
+ Ignored: false,
50
+ NWWS: true,
51
+ Type: {
52
+ Type: getType.Type,
53
+ Prefix: getType.Prefix,
54
+ Discovered: getType.Discovered
55
+ }
44
56
  }
45
57
  }
46
58
  }
47
59
  }
48
60
  }
49
- return { isIgnored: true}
61
+ return { Ignored: true}
50
62
  }
@@ -18,27 +18,27 @@
18
18
  */
19
19
 
20
20
  interface CreateHttpOptions {
21
- url: string
22
- headers?: any
23
- timeout?: number
24
- auth?: {
25
- username: string
26
- password: string
21
+ URL: string
22
+ Headers?: any
23
+ Timeout?: number
24
+ Auth?: {
25
+ Username: string
26
+ Password: string
27
27
  }
28
- method?: `GET` | `POST` | `PUT` | `DELETE`
29
- body?: any;
30
- formData?: any;
28
+ Method?: `GET` | `POST` | `PUT` | `DELETE`
29
+ Body?: any;
30
+ Form?: any;
31
31
  }
32
32
 
33
- export const CreateHttp = async (options: CreateHttpOptions): Promise<any> => {
33
+ export const CreateHttp = async ({ URL, Headers, Timeout, Auth, Method, Body, Form }: CreateHttpOptions): Promise<any> => {
34
34
  const requestOptions: RequestInit = {
35
- method: options.method ?? "GET",
36
- headers: options.headers ?? {
35
+ method: Method ?? "GET",
36
+ headers: Headers ?? {
37
37
  "User-Agent": "AtmosphericX",
38
38
  "Accept": "application/geo+json, text/plain, */*; q=0.9",
39
39
  "Accept-Language": "en-US,en;q=0.9",
40
40
  },
41
- signal: AbortSignal.timeout(options.timeout ?? 10_000),
41
+ signal: AbortSignal.timeout(Timeout ?? 10_000),
42
42
  redirect: "follow"
43
43
  };
44
44
 
@@ -47,8 +47,8 @@ export const CreateHttp = async (options: CreateHttpOptions): Promise<any> => {
47
47
  return { error: error, options: requestOptions, status, message };
48
48
  }
49
49
 
50
- if (options?.auth) {
51
- const authString = `${options.auth.username}:${options.auth.password}`;
50
+ if (Auth) {
51
+ const authString = `${Auth.Username}:${Auth.Password}`;
52
52
  const encodedAuth = Buffer.from(authString).toString("base64");
53
53
  requestOptions.headers = {
54
54
  ...requestOptions.headers,
@@ -56,20 +56,20 @@ export const CreateHttp = async (options: CreateHttpOptions): Promise<any> => {
56
56
  };
57
57
  }
58
58
 
59
- if (options?.formData) {
60
- requestOptions.body = options.formData;
61
- } else if (options?.body != undefined) {
59
+ if (Form) {
60
+ requestOptions.body = Form;
61
+ } else if (Body != undefined) {
62
62
  requestOptions.body =
63
- options.body instanceof FormData
64
- ? options.body
65
- : typeof options.body === "string"
66
- ? options.body
67
- : JSON.stringify(options.body);
63
+ Body instanceof FormData
64
+ ? Body
65
+ : typeof Body === "string"
66
+ ? Body
67
+ : JSON.stringify(Body);
68
68
  }
69
69
 
70
70
  try {
71
71
  const response = await fetch(
72
- options?.url ?? `https://api.weather.gov/alerts/active`,
72
+ URL ?? `https://api.weather.gov/alerts/active`,
73
73
  requestOptions
74
74
  )
75
75
  const body = await response.text();
@@ -17,11 +17,16 @@
17
17
 
18
18
  */
19
19
 
20
- export const GetMatched = (strings: string[], string: string): boolean => {
21
- const isMatched = strings.some(pattern => {
20
+ interface GetMatchedOptions {
21
+ Strings: string[]
22
+ String: string
23
+ }
24
+
25
+ export const GetMatched = ({ Strings, String }: GetMatchedOptions): boolean => {
26
+ const isMatched = Strings.some(pattern => {
22
27
  if (!pattern) return false;
23
28
  const lowerP = pattern.toLowerCase();
24
- const lowerS = string.toLowerCase()
29
+ const lowerS = String.toLowerCase()
25
30
  if (lowerP === "*" || lowerP === lowerS) return true;
26
31
  if (lowerP.includes("*")) {
27
32
  const regex = "^" + lowerP.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$";
@@ -17,9 +17,9 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeSettings } from '../../@types/Settings'
21
- import { bootstrap } from "../../bootstrap"
20
+ import { TypeSettings } from "types/Settings"
21
+ import { Bootstrap } from "@bootstrap"
22
22
 
23
23
  export const GetSettings = (): TypeSettings => {
24
- return bootstrap.settings;
24
+ return Bootstrap.Settings;
25
25
  }
@@ -17,17 +17,22 @@
17
17
 
18
18
  */
19
19
 
20
+ interface GetShapeNearestPointOptions {
21
+ Coordinates: number[][]
22
+ Point: [number, number]
23
+ }
24
+
20
25
  interface GetShapeNearestPointResponse {
21
- proximity: boolean
22
- point: [number, number]
23
- distance: number | null
24
- distanceKm?: number | null
25
- distanceMeters?: number | null
26
+ Proximity: boolean
27
+ Point: [number, number]
28
+ Distance: number | null
29
+ DistanceKm?: number | null
30
+ DistanceMeters?: number | null
26
31
  }
27
32
 
28
- export const GetShapeNearestPoint = (coordinates: number[][], point: [number, number]): GetShapeNearestPointResponse => {
29
- if (!coordinates || !point) {
30
- return { proximity: false, point: [0, 0], distance: null }
33
+ export const GetShapeNearestPoint = ({ Coordinates, Point }: GetShapeNearestPointOptions): GetShapeNearestPointResponse => {
34
+ if (!Coordinates || !Point) {
35
+ return { Proximity: false, Point: [0, 0], Distance: null }
31
36
  }
32
37
  const normalize = (coords: any): any[] => {
33
38
  if (!Array.isArray(coords)) return [];
@@ -43,10 +48,10 @@ export const GetShapeNearestPoint = (coordinates: number[][], point: [number, nu
43
48
  }
44
49
  return [];
45
50
  }
46
- const polys = normalize(coordinates);
47
- if (polys.length === 0) return { proximity: false, point: [0, 0], distance: null };
48
- const lon = point[0];
49
- const lat = point[1];
51
+ const polys = normalize(Coordinates);
52
+ if (polys.length === 0) return { Proximity: false, Point: [0, 0], Distance: null };
53
+ const lon = Point[0];
54
+ const lat = Point[1];
50
55
  const pointInRing = (pt: [number, number], ring: number[][]): boolean => {
51
56
  let x = pt[0], y = pt[1];
52
57
  let inside = false;
@@ -76,13 +81,13 @@ export const GetShapeNearestPoint = (coordinates: number[][], point: [number, nu
76
81
  for (const poly of polys) {
77
82
  const outer = poly[0];
78
83
  const holes = poly.slice(1);
79
- if (pointInRing(point, outer)) {
84
+ if (pointInRing(Point, outer)) {
80
85
  let inHole = false;
81
86
  for (const hole of holes) {
82
- if (pointInRing(point, hole)) { inHole = true; break; }
87
+ if (pointInRing(Point, hole)) { inHole = true; break; }
83
88
  }
84
89
  if (!inHole) {
85
- return { proximity: true, point, distance: 0 };
90
+ return { Proximity: true, Point, Distance: 0 };
86
91
  }
87
92
  }
88
93
  for (const ring of poly) {
@@ -105,10 +110,10 @@ export const GetShapeNearestPoint = (coordinates: number[][], point: [number, nu
105
110
  }
106
111
  }
107
112
  if (!isFinite(minDistance) || closestPoint == null) {
108
- return { proximity: false, point: [0,0], distance: null };
113
+ return { Proximity: false, Point: [0,0], Distance: null };
109
114
  }
110
115
  const distanceMiles = minDistance;
111
116
  const distanceKm = Number((distanceMiles * 1.609344).toFixed(3));
112
117
  const distanceMeters = Math.round(distanceKm * 1000);
113
- return { proximity: distanceMiles === 0, point: closestPoint, distance: distanceMiles, distanceKm, distanceMeters };
118
+ return { Proximity: distanceMiles === 0, Point: closestPoint, Distance: distanceMiles, DistanceKm: distanceKm, DistanceMeters: distanceMeters };
114
119
  }
@@ -0,0 +1,70 @@
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
+ export type QueueTask = () => Promise<void>;
20
+
21
+ export interface QueueManagerOptions {
22
+ Concurrency?: number;
23
+ Error?: (error: unknown) => void;
24
+ }
25
+
26
+ export class QueueManager {
27
+ private readonly queue: QueueTask[] = [];
28
+ private readonly concurrency: number;
29
+ private readonly onError: (error: unknown) => void;
30
+
31
+ private running = 0;
32
+ private draining = false;
33
+
34
+ public constructor({ Concurrency, Error }: QueueManagerOptions = {}) {
35
+ this.concurrency = Concurrency ?? 1;
36
+ this.onError = Error ?? ((error) => {
37
+ console.error("[QueueManager] Task failed:", error);
38
+ });
39
+ }
40
+
41
+ public enqueue(task: QueueTask): void {
42
+ this.queue.push(task);
43
+ this.drain();
44
+ }
45
+
46
+ private drain(): void {
47
+ if (this.draining) { return; }
48
+ this.draining = true;
49
+ while (this.running < this.concurrency && this.queue.length > 0) {
50
+ const task = this.queue.shift();
51
+ if (!task) { continue; }
52
+ this.running++;
53
+ void this.execute(task);
54
+ }
55
+ this.draining = false;
56
+ }
57
+
58
+ private async execute(task: QueueTask): Promise<void> {
59
+ try {
60
+ await task();
61
+ } catch (error) {
62
+ try {
63
+ this.onError(error);
64
+ } catch (handlerError) {}
65
+ } finally {
66
+ this.running--;
67
+ this.drain();
68
+ }
69
+ }
70
+ }