@atmosx/event-product-parser 3.0.62 → 3.0.75

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 (179) hide show
  1. package/.github/docs/docs-functions.md +1 -1
  2. package/.github/docs/docs-general-configurations.md +1 -11
  3. package/.github/docs/docs-integrations.md +3 -2
  4. package/README.md +10 -8
  5. package/dist/cjs/index.cjs +24482 -7207
  6. package/dist/esm/index.mjs +24275 -7003
  7. package/package.json +56 -47
  8. package/pnpm-workspace.yaml +4 -0
  9. package/src/bootstrap.ts +65 -48
  10. package/src/{@building → building}/CreateEvent.ts +22 -24
  11. package/src/{@building → building}/GetCleanedEvent.ts +2 -2
  12. package/src/{@building → building}/GetEventAttachments.ts +14 -12
  13. package/src/building/GetEventDirection.ts +28 -0
  14. package/src/{@building → building}/GetEventEnhancedName.ts +5 -8
  15. package/src/{@building → building}/GetEventGeometry.ts +19 -13
  16. package/src/{@building → building}/GetEventHeader.ts +13 -13
  17. package/src/{@building → building}/GetEventNodes.ts +22 -20
  18. package/src/{@building → building}/GetEventOffice.ts +13 -13
  19. package/src/building/GetEventPopulation.ts +58 -0
  20. package/src/building/GetEventProperties.ts +106 -0
  21. package/src/{@building → building}/GetEventSignature.ts +9 -9
  22. package/src/{@building → building}/GetEventTags.ts +3 -3
  23. package/src/building/GetEventTheme.ts +26 -0
  24. package/src/building/GetEventTracking.ts +64 -0
  25. package/src/components/audio/GenerateAudioMessage.ts +149 -0
  26. package/src/{@modules/@eas → components/audio/components}/GetCleanDescription.ts +2 -2
  27. package/src/{@modules/@eas → components/audio/components}/GetFloatPCM16.ts +2 -2
  28. package/src/{@modules/@eas → components/audio/components}/GetMergedPCM16.ts +2 -2
  29. package/src/{@modules/@eas → components/audio/components}/GetPCM16.ts +13 -8
  30. package/src/{@modules/@eas → components/audio/components}/GetPCMToFloat.ts +2 -2
  31. package/src/{@modules/@eas → components/audio/components}/GetSampledPCM16.ts +14 -8
  32. package/src/{@modules/@eas → components/audio/components}/GetTTS.ts +17 -10
  33. package/src/{@modules/@eas → components/audio/components}/GetWavPCM16.ts +7 -7
  34. package/src/{@modules/@eas → components/audio/components}/SetAFSK.ts +13 -8
  35. package/src/{@modules/@eas → components/audio/components}/SetAsciiToBits.ts +2 -2
  36. package/src/{@modules/@eas → components/audio/components}/SetAttentionTone.ts +11 -6
  37. package/src/{@modules/@eas → components/audio/components}/SetNoise.ts +12 -7
  38. package/src/{@modules/@eas → components/audio/components}/SetRadioEffect.ts +12 -7
  39. package/src/{@modules/@eas → components/audio/components}/SetSameHeader.ts +22 -14
  40. package/src/{@modules/@utilities/SetWarning.ts → components/database/CreateQuery.ts} +18 -13
  41. package/src/{@modules/@database → components/database}/GetCachedEvents.ts +18 -15
  42. package/src/components/database/ImportBoundaries.ts +168 -0
  43. package/src/{@modules/@database → components/database}/ImportBroadcastify.ts +14 -24
  44. package/src/components/database/ImportCities.ts +87 -0
  45. package/src/{@modules/@database → components/database}/ImportShapefiles.ts +23 -26
  46. package/src/{@modules/@database → components/database}/ImportStanza.ts +15 -19
  47. package/src/components/database/InitializeDatabase.ts +71 -0
  48. package/src/components/images/GenerateGraphic.ts +242 -0
  49. package/src/components/images/components/CreateRectangle.ts +22 -0
  50. package/src/components/images/components/CreateText.ts +22 -0
  51. package/src/components/images/modules/CreateSVG.ts +37 -0
  52. package/src/components/images/modules/GetGeographicalBoundaries.ts +72 -0
  53. package/src/components/images/modules/GetGeographicalCities.ts +58 -0
  54. package/src/components/images/modules/GetGeographicalEvents.ts +48 -0
  55. package/src/components/images/modules/GetGeometryBounds.ts +82 -0
  56. package/src/components/images/modules/GetParsedBoundary.ts +58 -0
  57. package/src/components/images/modules/GetSVGPath.ts +53 -0
  58. package/src/components/images/modules/NormalizePolygon.ts +57 -0
  59. package/src/{@modules/@stanza → components/stanza}/GetAwipsType.ts +16 -17
  60. package/src/{@modules/@stanza → components/stanza}/ValidateStanza.ts +27 -15
  61. package/src/{@modules/@utilities → components/utilities}/CreateHttp.ts +26 -26
  62. package/src/{@parsers/@text → components/utilities}/GetEmbededText.ts +8 -6
  63. package/src/{@modules/@utilities → components/utilities}/GetFormattedTime.ts +2 -2
  64. package/src/{@modules/@utilities → components/utilities}/GetLatestIssuance.ts +2 -2
  65. package/src/{@modules/@utilities → components/utilities}/GetMatched.ts +10 -5
  66. package/src/{@modules/@utilities → components/utilities}/GetShapeNearestPoint.ts +24 -19
  67. package/src/{@parsers/@text → components/utilities}/GetStringText.ts +9 -9
  68. package/src/components/utilities/GetUnionPolygon.ts +36 -0
  69. package/src/components/utilities/QueueManager.ts +70 -0
  70. package/src/components/utilities/SetCronSchedule.ts +106 -0
  71. package/src/{@modules/@utilities → components/utilities}/SetDebug.ts +12 -12
  72. package/src/components/utilities/SetEventEmit.ts +42 -0
  73. package/src/{@modules/@utilities → components/utilities}/SetSettings.ts +7 -7
  74. package/src/{@modules/@utilities → components/utilities}/SetSleep.ts +5 -5
  75. package/src/components/utilities/SetTimeoutAction.ts +64 -0
  76. package/src/components/utilities/SetWarning.ts +47 -0
  77. package/src/{@modules/@xmpp → components/xmpp}/DeployXMPP.ts +20 -20
  78. package/src/{@core/CreateListener.ts → components/xmpp/ErrorXMPP.ts} +8 -5
  79. package/src/{@modules/@xmpp → components/xmpp}/OfflineXMPP.ts +13 -13
  80. package/src/{@modules/@xmpp → components/xmpp}/OnlineXMPP.ts +18 -18
  81. package/src/components/xmpp/ReconnectXMPP.ts +64 -0
  82. package/src/{@modules/@xmpp → components/xmpp}/StanzaXMPP.ts +25 -25
  83. package/src/{@core → core}/ClearEvents.ts +9 -9
  84. package/src/{@core → core}/GetEvents.ts +4 -4
  85. package/src/{@core → core}/GetNodes.ts +4 -4
  86. package/src/{@core → core}/GetRandomEvent.ts +4 -4
  87. package/src/{@core → core}/GetVersion.ts +4 -4
  88. package/src/{@core → core}/ManualEvent.ts +23 -24
  89. package/src/{@core → core}/QueryStanza.ts +12 -11
  90. package/src/core/SetNode.ts +87 -0
  91. package/src/{@core → core}/StartService.ts +21 -20
  92. package/src/{@core → core}/StopService.ts +10 -10
  93. package/src/{@enums → enums}/AWIPS.ts +2 -2
  94. package/src/{@enums → enums}/Actions.ts +2 -2
  95. package/src/{@enums → enums}/Cancellation.ts +2 -2
  96. package/src/{@enums → enums}/Causes.ts +2 -2
  97. package/src/{@enums → enums}/Correlations.ts +2 -2
  98. package/src/{@enums → enums}/Enhanced.ts +4 -3
  99. package/src/{@enums → enums}/Events.ts +2 -2
  100. package/src/{@enums → enums}/Expressions.ts +3 -3
  101. package/src/{@enums → enums}/GlobalFilter.ts +2 -2
  102. package/src/{@enums → enums}/Hail.ts +2 -2
  103. package/src/{@enums → enums}/ICAO.ts +2 -2
  104. package/src/{@enums → enums}/Matches.ts +8 -3
  105. package/src/{@enums → enums}/Products.ts +2 -2
  106. package/src/{@enums → enums}/Records.ts +2 -2
  107. package/src/{@enums → enums}/Severity.ts +2 -2
  108. package/src/{@enums → enums}/Shapefiles.ts +2 -2
  109. package/src/{@enums → enums}/States.ts +68 -4
  110. package/src/{@enums → enums}/Status.ts +2 -2
  111. package/src/{@enums → enums}/Strings.ts +2 -2
  112. package/src/{@enums → enums}/Tags.ts +9 -4
  113. package/src/{@enums → enums}/Testing.ts +2 -2
  114. package/src/enums/Themes.ts +70 -0
  115. package/src/events/ParseAPI.ts +133 -0
  116. package/src/{@events → events}/ParseText.ts +24 -22
  117. package/src/{@events → events}/ParseUGC.ts +27 -26
  118. package/src/{@events → events}/ParseVTEC.ts +38 -37
  119. package/src/index.ts +57 -37
  120. package/src/{@manager → manager}/MakeEvents.ts +38 -47
  121. package/src/manager/RemoveEvent.ts +74 -0
  122. package/src/{@manager → manager}/SetHash.ts +18 -13
  123. package/src/{@manager → manager}/UpdateEvents.ts +12 -12
  124. package/src/{@manager → manager}/UpdateNode.ts +14 -14
  125. package/src/{@manager → manager}/ValidateEvents.ts +55 -45
  126. package/src/{@parsers/@hvtec → parsers/hvtec}/HVExtract.ts +11 -11
  127. package/src/{@parsers/@text → parsers/text}/GetDescriptionFromProduct.ts +20 -21
  128. package/src/parsers/text/GetPolygonFromProduct.ts +71 -0
  129. package/src/{@parsers/@text → parsers/text}/GetTextFromProduct.ts +12 -12
  130. package/src/parsers/ugc/GetCache.ts +24 -0
  131. package/src/{@parsers/@ugc → parsers/ugc}/GetExpiry.ts +2 -2
  132. package/src/{@parsers/@ugc/GetUGCHeader.ts → parsers/ugc/GetHeader.ts} +4 -4
  133. package/src/{@parsers/@ugc → parsers/ugc}/GetLocations.ts +10 -10
  134. package/src/parsers/ugc/GetZonePolygon.ts +73 -0
  135. package/src/{@parsers/@ugc → parsers/ugc}/GetZones.ts +3 -3
  136. package/src/{@parsers/@ugc → parsers/ugc}/SetCache.ts +13 -8
  137. package/src/{@parsers/@ugc → parsers/ugc}/UGCExtract.ts +14 -14
  138. package/src/{@parsers/@pvtec → parsers/vtec}/GetExpiry.ts +2 -2
  139. package/src/parsers/vtec/VTECExtract.ts +49 -0
  140. package/src/{@types → static}/Attributes.ts +2 -3
  141. package/src/{@types → static}/Event.ts +8 -7
  142. package/src/{@types → static}/Properties.ts +17 -3
  143. package/src/{@types → static}/Stanza.ts +2 -2
  144. package/src/tasks/CreateTasks.ts +116 -0
  145. package/src/tasks/TaskGenerateJSON.ts +34 -0
  146. package/src/tasks/TaskGenerateText.ts +34 -0
  147. package/src/tasks/TaskSendNTFY.ts +95 -0
  148. package/src/tasks/TaskSendWebhook.ts +107 -0
  149. package/src/{@types → types}/Actions.ts +3 -3
  150. package/src/{@types → types}/HVTEC.ts +6 -6
  151. package/src/{@types → types}/Hash.ts +5 -5
  152. package/src/types/Nodes.ts +29 -0
  153. package/src/{@types → types}/Settings.ts +17 -8
  154. package/src/{@types → types}/StanzaCompiled.ts +15 -15
  155. package/src/{@types → types}/UGC.ts +5 -5
  156. package/src/{@modules/@utilities/GetSettings.ts → types/VTEC.ts} +12 -7
  157. package/tools/build.js +47 -0
  158. package/tsconfig.json +28 -1
  159. package/src/@building/GetEventProperties.ts +0 -96
  160. package/src/@building/GetEventTracking.ts +0 -68
  161. package/src/@core/SetNode.ts +0 -81
  162. package/src/@events/ParseAPI.ts +0 -117
  163. package/src/@manager/RemoveEvent.ts +0 -70
  164. package/src/@manager/Tasks.ts +0 -246
  165. package/src/@modules/@database/InitializeDatabase.ts +0 -59
  166. package/src/@modules/@eas/GenerateEASMessage.ts +0 -144
  167. package/src/@modules/@utilities/SetCronSchedule.ts +0 -94
  168. package/src/@modules/@utilities/SetEventEmit.ts +0 -41
  169. package/src/@modules/@utilities/SetListener.ts +0 -30
  170. package/src/@modules/@utilities/SetTimeoutAction.ts +0 -64
  171. package/src/@modules/@xmpp/ErrorXMPP.ts +0 -27
  172. package/src/@modules/@xmpp/ReconnectXMPP.ts +0 -64
  173. package/src/@parsers/@pvtec/VTECExtract.ts +0 -49
  174. package/src/@parsers/@text/GetPolygonFromProduct.ts +0 -53
  175. package/src/@parsers/@text/GetXML.ts +0 -61
  176. package/src/@parsers/@ugc/GetCache.ts +0 -24
  177. package/src/@parsers/@ugc/GetZonePolygon.ts +0 -111
  178. package/src/@types/VTEC.ts +0 -30
  179. package/tsup.config.ts +0 -16
@@ -11,15 +11,15 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
17
17
 
18
18
  */
19
19
 
20
- import { TypeEvent } from "../../@types/Event"
20
+ import { TypeEvent } from "StaticTypes/Event"
21
21
 
22
- export const GetEmebedText = (event: TypeEvent): string => {
22
+ export const GetEmbededText = (event: TypeEvent): string => {
23
23
  const line = (label: string, value: unknown, condition = true) => condition && value ? `${label} ${value}` : null;
24
24
  const isStatement = event.properties.status_metadata.is_statement;
25
25
  const isExpired = event.properties.status_metadata.is_expired;
@@ -30,8 +30,9 @@ export const GetEmebedText = (event: TypeEvent): string => {
30
30
  line(`**Damage Threat:**`, event?.properties?.parameters?.damage_threat, !isExpired),
31
31
  line(`**Flood Threat:**`, event?.properties?.parameters?.flood_threat, !isExpired),
32
32
  line(`**Tornado Threat:**`, event?.properties?.parameters?.tornado_threat, !isExpired),
33
- line(`**Estimated Wind Gusts:**`, `${event?.properties?.parameters?.estimated_wind_gusts} ${event?.properties?.parameters?.wind_threat ? ` (${event?.properties?.parameters?.wind_threat})` : ''}`, !isExpired && event?.properties?.parameters?.estimated_wind_gusts != null),
34
- line(`**Estimated Hail Size:**`, `${event?.properties?.parameters?.estimated_hail_size} ${event?.properties?.parameters?.hail_threat ? ` (${event?.properties?.parameters?.hail_threat})` : ''}`, !isExpired && event?.properties?.parameters?.estimated_hail_size != null),
33
+ line(`**Wind Gusts:**`, `${event?.properties?.parameters?.estimated_wind_gusts} ${event?.properties?.parameters?.wind_threat ? ` (${event?.properties?.parameters?.wind_threat})` : ''}`, !isExpired && event?.properties?.parameters?.estimated_wind_gusts != null),
34
+ line(`**Hail Size:**`, `${event?.properties?.parameters?.estimated_hail_size} ${event?.properties?.parameters?.hail_threat ? ` (${event?.properties?.parameters?.hail_threat})` : ''}`, !isExpired && event?.properties?.parameters?.estimated_hail_size != null),
35
+ line(`**Direction:**`, event?.properties?.parameters?.direction, !isExpired && event?.properties?.parameters?.direction != null),
35
36
  line(`**Discussion:**`, event?.properties?.discussion_parameters?.discussion_number, !isExpired),
36
37
  line(`**Concern:**`, event?.properties?.discussion_parameters?.discussion_concerning, !isExpired),
37
38
  line(`**SPC Max Tornado Threat:**`, event?.properties?.discussion_parameters?.discussion_max_tornado, !isExpired),
@@ -50,6 +51,7 @@ export const GetEmebedText = (event: TypeEvent): string => {
50
51
  line(`**Max Tops (x100 feet):**`, event?.properties?.watch_parameters?.max_tops_x100feet, !isExpired),
51
52
  line(`**Tags:**`, event?.properties?.parameters?.tags?.length > 0 ? event?.properties?.parameters?.tags.join(', ') : null, !isExpired),
52
53
  line(`**Sender:**`, event?.properties?.geocode?.office?.name ? `${event?.properties?.geocode?.office?.name} (${event?.properties?.geocode?.office?.office})` : event?.properties?.geocode?.office?.office),
54
+ line(`**Population:**`, event?.properties?.geocode?.census?.population, !isExpired),
53
55
  line(`**Tracking:**`, event?.properties?.metadata?.tracking),
54
56
  line(`**Logs:**`, event?.properties?.metadata?.history?.length > 0 ? event?.properties?.metadata?.history.length : null),
55
57
  ].filter(Boolean).join('\n');
@@ -11,9 +11,9 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
17
17
 
18
18
 
19
19
  */
@@ -11,9 +11,9 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
17
17
 
18
18
 
19
19
  */
@@ -11,17 +11,22 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
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, ".*") + "$";
@@ -11,23 +11,28 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
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
  }
@@ -11,19 +11,17 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
17
17
 
18
18
  */
19
19
 
20
- import { TypeEvent } from "../../@types/Event"
21
- import { TypeSettings } from "../../@types/Settings";
22
- import { bootstrap } from "../../bootstrap";
20
+ import { TypeEvent } from "StaticTypes/Event"
21
+ import { Bootstrap } from "@Bootstrap"
23
22
 
24
23
  export const GetStringText = (event: TypeEvent): string => {
25
- const settings = bootstrap.settings as TypeSettings;
26
- const timezone = settings.NotifyServer.Timezone ?? `UTC`;
24
+ const timezone = Bootstrap.Settings.Timezone ?? `UTC`;
27
25
  const line = (label: string, value: unknown, condition = true) => condition && value ? `${label} ${value}` : null;
28
26
  const isStatement = event.properties.status_metadata.is_statement;
29
27
  const isExpired = event.properties.status_metadata.is_expired;
@@ -34,8 +32,9 @@ export const GetStringText = (event: TypeEvent): string => {
34
32
  line(`Damage Threat:`, event?.properties?.parameters?.damage_threat, !isExpired),
35
33
  line(`Flood Threat:`, event?.properties?.parameters?.flood_threat, !isExpired),
36
34
  line(`Tornado Threat:`, event?.properties?.parameters?.tornado_threat, !isExpired),
37
- line(`Estimated Wind Gusts:`, `${event?.properties?.parameters?.estimated_wind_gusts} ${event?.properties?.parameters?.wind_threat ? ` (${event?.properties?.parameters?.wind_threat})` : ''}`, !isExpired && event?.properties?.parameters?.estimated_wind_gusts != null),
38
- line(`Estimated Hail Size:`, `${event?.properties?.parameters?.estimated_hail_size} ${event?.properties?.parameters?.hail_threat ? ` (${event?.properties?.parameters?.hail_threat})` : ''}`, !isExpired && event?.properties?.parameters?.estimated_hail_size != null),
35
+ line(`Wind Gusts:`, `${event?.properties?.parameters?.estimated_wind_gusts} ${event?.properties?.parameters?.wind_threat ? ` (${event?.properties?.parameters?.wind_threat})` : ''}`, !isExpired && event?.properties?.parameters?.estimated_wind_gusts != null),
36
+ line(`Hail Size:`, `${event?.properties?.parameters?.estimated_hail_size} ${event?.properties?.parameters?.hail_threat ? ` (${event?.properties?.parameters?.hail_threat})` : ''}`, !isExpired && event?.properties?.parameters?.estimated_hail_size != null),
37
+ line(`Direction:`, event?.properties?.parameters?.direction, !isExpired && event?.properties?.parameters?.direction != null),
39
38
  line(`Discussion:`, event?.properties?.discussion_parameters?.discussion_number, !isExpired),
40
39
  line(`Concern:`, event?.properties?.discussion_parameters?.discussion_concerning, !isExpired),
41
40
  line(`SPC Max Tornado Threat:`, event?.properties?.discussion_parameters?.discussion_max_tornado, !isExpired),
@@ -53,6 +52,7 @@ export const GetStringText = (event: TypeEvent): string => {
53
52
  line(`Max Surface Wind:`, event?.properties?.watch_parameters?.max_wind_surface, !isExpired),
54
53
  line(`Max Tops (x100 feet):`, event?.properties?.watch_parameters?.max_tops_x100feet, !isExpired),
55
54
  line(`Sender:`, event?.properties?.geocode?.office?.name ? `${event?.properties?.geocode?.office?.name} (${event?.properties?.geocode?.office?.office})` : event?.properties?.geocode?.office?.office),
55
+ line(`Population:`, event?.properties?.geocode?.census?.population, !isExpired),
56
56
  line(`Tracking:`, event?.properties?.metadata?.tracking),
57
57
  ].filter(Boolean).join('\n');
58
58
  }
@@ -0,0 +1,36 @@
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: https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Independent Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { union } from "polygon-clipping";
21
+
22
+ interface GetUnionPolygonOptions {
23
+ Polygons: number[][][][] | null;
24
+ }
25
+
26
+ export const GetUnionPolygon = ({ Polygons }: GetUnionPolygonOptions): GeoJSON.MultiPolygon | null => {
27
+ if (!Polygons || Polygons.length === 0) {
28
+ return null;
29
+ }
30
+ const unionFn = union as unknown as (...polygons: number[][][][]) => number[][][][];
31
+ const unioned = unionFn(...Polygons)
32
+ return {
33
+ type: `MultiPolygon`,
34
+ coordinates: unioned
35
+ }
36
+ };
@@ -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: https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Independent 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
+ }
@@ -0,0 +1,106 @@
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: https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Independent Package: @atmosx/event-product-parser
17
+
18
+
19
+ */
20
+
21
+ import { TypeSettings } from "Types/Settings"
22
+ import { ReconnectXMPP } from "@XMPP/ReconnectXMPP"
23
+ import { Bootstrap } from "@Bootstrap"
24
+ import { CreateHttp } from "@Utilities/CreateHttp"
25
+ import { SetEventEmit } from "@Utilities/SetEventEmit"
26
+ import { CreateEvent } from "@Building/CreateEvent"
27
+ import { readdirSync, unlinkSync, statSync, rmdirSync, existsSync } from "fs"
28
+ import { join } from "path"
29
+
30
+ export const SetCronSchedule = async (): Promise<void> => {
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, deleteFolder = false): void => {
37
+ if (!existsSync(dir)) return;
38
+ const entries = readdirSync(dir, { withFileTypes: true });
39
+ for (const entry of entries) {
40
+ const fullPath = join(dir, entry.name);
41
+ if (entry.isDirectory()) {
42
+ walk(fullPath, deleteFolder);
43
+ continue;
44
+ }
45
+ const stats = statSync(fullPath);
46
+ if (stats.mtime.getTime() < TTLCUT) {
47
+ try {
48
+ unlinkSync(fullPath);
49
+ } catch (err) {
50
+ console.error(`Failed to delete ${fullPath}:`, err);
51
+ }
52
+ }
53
+ }
54
+ if (deleteFolder) {
55
+ try {
56
+ if (readdirSync(dir).length === 0 && statSync(dir).mtime.getTime() < TTLCUT) {
57
+ rmdirSync(dir);
58
+ }
59
+ } catch (err) {
60
+ console.error(`Failed to delete directory ${dir}:`, err);
61
+ }
62
+ }
63
+ };
64
+ walk(settings.GlobalSettings.ArchiveSettings.TextDirectory, true)
65
+ walk(settings.GlobalSettings.ArchiveSettings.AudioDirectory, true)
66
+ walk(settings.GlobalSettings.ArchiveSettings.JSONDirectory, true)
67
+ walk(settings.GlobalSettings.ArchiveSettings.ImageDirectory, true)
68
+
69
+
70
+
71
+ if (settings.EnableWireService) {
72
+ if (settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.Enabled) {
73
+ void ReconnectXMPP(settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval)
74
+ }
75
+ } else {
76
+ const response = await CreateHttp({
77
+ URL: settings.NationalWeatherServiceSettings.EventsEndpoint,
78
+ Headers: {
79
+ "User-Agent": "@atmosx/event-product-parser"
80
+ }
81
+ })
82
+ if (response.error) {
83
+ return SetEventEmit({
84
+ Event: `onServiceStatus`,
85
+ Metadata: {
86
+ type: "fetch-api",
87
+ message: `Failed to fetch latest events from National Weather Service API - ${response.message}`,
88
+ data: {},
89
+ error: true
90
+ },
91
+ })
92
+ }
93
+ SetEventEmit({
94
+ Event: `onServiceStatus`,
95
+ Metadata: {
96
+ Message: `Fetched latest events from National Weather Service API`,
97
+ Data: {},
98
+ Type: "fetch-api",
99
+ Error: false
100
+ },
101
+ })
102
+ await CreateEvent({ Message: response.message, NWWS: false })
103
+ }
104
+ }
105
+
106
+
@@ -11,27 +11,27 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
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
  interface SetDebugOptions {
24
- title?: string
25
- message: string
24
+ Title?: string
25
+ Message: string
26
26
  }
27
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`,
28
+ export const SetDebug = ({ Title, Message }: SetDebugOptions): void => {
29
+ const settings = Bootstrap.Settings as TypeSettings;
30
+ Bootstrap.Listener.emit(`debug`, {
31
+ message: Message,
32
+ function: Title ?? `debug`,
33
33
  })
34
34
  if (settings.EnableDebugging) {
35
- console.log(`[${bootstrap.ansi_colors.BLUE}${options.title ?? `debug`}${bootstrap.ansi_colors.RESET}] ${options.message}`)
35
+ console.log(`[${Bootstrap.Colors.Blue}${Title ?? `debug`}${Bootstrap.Colors.Reset}] ${Message}`)
36
36
  }
37
37
  }
@@ -0,0 +1,42 @@
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: https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Independent Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { Bootstrap } from "@Bootstrap"
21
+ import { SetTimeoutAction } from "@Utilities/SetTimeoutAction"
22
+ import { SetWarning } from "@Utilities/SetWarning"
23
+
24
+ interface SetEventEmitOptions {
25
+ Event: string
26
+ Metadata: any
27
+ Message?: string
28
+ Limited?: boolean
29
+ Tree?: string[]
30
+ }
31
+
32
+ export const SetEventEmit = ({ Event, Metadata, Message, Limited, Tree }: SetEventEmitOptions): void => {
33
+ if (Limited) {
34
+ const isTimeout = SetTimeoutAction({ Identifier: `event.${Event}`, AddTime: true, Max: 1, Interval: 1 })
35
+ if (isTimeout.Limited) return;
36
+ }
37
+ Bootstrap.Listener.emit(Event, Metadata)
38
+ if (Event != `log`) { Bootstrap.Listener.emit(`*`, {event: Event, data: Metadata}) }
39
+ if (Message) {
40
+ SetWarning({ Message: Message, Tree: Tree })
41
+ }
42
+ }
@@ -11,17 +11,17 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
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
- export const SetSettings = (newSettings: TypeSettings): TypeSettings => {
24
- const settings = bootstrap.settings as Record<string, unknown>;
23
+ export const SetSettings = (imported: TypeSettings): TypeSettings => {
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) {
27
27
  if (!Object.prototype.hasOwnProperty.call(source, key)) continue;
@@ -37,6 +37,6 @@ export const SetSettings = (newSettings: TypeSettings): TypeSettings => {
37
37
  }
38
38
  }
39
39
  };
40
- merge(settings, newSettings as Record<string, unknown>);
40
+ merge(settings, imported as Record<string, unknown>);
41
41
  return settings as TypeSettings;
42
42
  }
@@ -11,22 +11,22 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
17
17
 
18
18
 
19
19
  */
20
20
 
21
21
  interface SetSleepOptions {
22
- timeout: number
22
+ Timeout: number
23
23
  }
24
24
 
25
- export const SetSleep = async (options: SetSleepOptions): Promise<void> => {
25
+ export const SetSleep = async ({ Timeout }: SetSleepOptions): Promise<void> => {
26
26
  return new Promise((resolve) => {
27
27
  setTimeout(() => {
28
28
  resolve();
29
- }, options.timeout);
29
+ }, Timeout);
30
30
  });
31
31
  }
32
32
 
@@ -0,0 +1,64 @@
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: https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Independent Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { Bootstrap } from "@Bootstrap"
21
+
22
+ interface SetTimeoutActionOptions {
23
+ Identifier: string
24
+ AddTime?: boolean
25
+ Max?: number
26
+ Interval?: number
27
+ Expire?: boolean
28
+ }
29
+
30
+ type SetTimeoutActionResponse = {
31
+ Limited: boolean
32
+ Remaining?: number
33
+ Response?: string
34
+ }
35
+
36
+ export const SetTimeoutAction = ({ Identifier, AddTime, Max, Interval, Expire }: SetTimeoutActionOptions): SetTimeoutActionResponse => {
37
+ let target = Bootstrap?.Ratelimits?.[Identifier];
38
+ if (!target) {
39
+ Bootstrap.Ratelimits[Identifier] = [];
40
+ target = Bootstrap.Ratelimits[Identifier];
41
+ }
42
+ if (Expire) {
43
+ delete Bootstrap.Ratelimits[Identifier];
44
+ return { Limited: false };
45
+ }
46
+ if (target?.length > 0) {
47
+ Bootstrap.Ratelimits[Identifier] = target.filter((ts: number) => Date.now() - ts < Interval * 1000);
48
+ target = Bootstrap.Ratelimits[Identifier];
49
+ }
50
+
51
+ const oldestTimestamp = target?.[0];
52
+ const getWait = oldestTimestamp ? Math.ceil((Interval * 1000) - (Date.now() - oldestTimestamp)) : 0;
53
+ const max = Max ?? 1;
54
+
55
+ if (target?.length >= max && getWait > 0) {
56
+ return {
57
+ Limited: true,
58
+ Remaining: getWait,
59
+ Response: `You are being rate limited, please wait ${(getWait / 1e3).toFixed(1)} second(s) before performing this action again.`
60
+ }
61
+ }
62
+ Bootstrap.Ratelimits[Identifier].push(Date.now());
63
+ return { Limited: false };
64
+ }