@atmosx/event-product-parser 3.0.622 → 3.1.0

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 (199) hide show
  1. package/.github/CHANGELOGS.md +52 -0
  2. package/.github/CODE_OF_CONDUCT.md +24 -1
  3. package/.github/CONTRIBUTING.md +22 -3
  4. package/.github/FUNDING.yaml +3 -0
  5. package/.github/LICENSE +24 -1
  6. package/.github/SECURITY.md +25 -6
  7. package/.github/docs/chapters/general-configurations.md +109 -0
  8. package/.github/docs/chapters/sources-and-attributes.md +219 -0
  9. package/README.md +56 -148
  10. package/dist/{cjs/index.cjs → index.cjs} +4486 -1471
  11. package/package.json +13 -8
  12. package/pnpm-workspace.yaml +1 -0
  13. package/src/bootstrap.ts +66 -51
  14. package/src/components/audio/GenerateAudioMessage.ts +149 -0
  15. package/src/{@modules/@eas → components/audio/components}/GetCleanDescription.ts +2 -2
  16. package/src/{@modules/@eas → components/audio/components}/GetFloatPCM16.ts +2 -2
  17. package/src/{@modules/@eas → components/audio/components}/GetMergedPCM16.ts +2 -2
  18. package/src/{@modules/@eas → components/audio/components}/GetPCM16.ts +13 -8
  19. package/src/{@modules/@eas → components/audio/components}/GetPCMToFloat.ts +2 -2
  20. package/src/{@modules/@eas → components/audio/components}/GetSampledPCM16.ts +14 -8
  21. package/src/{@modules/@eas → components/audio/components}/GetTTS.ts +15 -8
  22. package/src/{@modules/@eas → components/audio/components}/GetWavPCM16.ts +7 -7
  23. package/src/{@modules/@eas → components/audio/components}/SetAFSK.ts +13 -8
  24. package/src/{@modules/@eas → components/audio/components}/SetAsciiToBits.ts +2 -2
  25. package/src/{@modules/@eas → components/audio/components}/SetAttentionTone.ts +11 -6
  26. package/src/{@modules/@eas → components/audio/components}/SetNoise.ts +12 -7
  27. package/src/{@modules/@eas → components/audio/components}/SetRadioEffect.ts +12 -7
  28. package/src/{@modules/@eas → components/audio/components}/SetSameHeader.ts +22 -14
  29. package/src/components/database/CreateQuery.ts +39 -0
  30. package/src/components/database/InitializeDatabase.ts +71 -0
  31. package/src/components/database/imports/Boundaires.ts +168 -0
  32. package/src/{@modules/@database/ImportBroadcastify.ts → components/database/imports/Broadcastify.ts} +15 -25
  33. package/src/components/database/imports/Census.ts +87 -0
  34. package/src/{@modules/@database/ImportShapefiles.ts → components/database/imports/Shapefiles.ts} +18 -21
  35. package/src/{@modules/@database/ImportStanza.ts → components/database/imports/Stanza.ts} +15 -19
  36. package/src/components/events/CreateEvents.ts +88 -0
  37. package/src/components/events/FilterEvents.ts +149 -0
  38. package/src/{@building/CreateEvent.ts → components/events/ProcessStanza.ts} +22 -22
  39. package/src/components/events/RemoveEvents.ts +74 -0
  40. package/src/{@building → components/events/components}/GetCleanedEvent.ts +2 -2
  41. package/src/{@building → components/events/components}/GetEventAttachments.ts +14 -12
  42. package/src/components/events/components/GetEventDirection.ts +28 -0
  43. package/src/{@building → components/events/components}/GetEventEnhancedName.ts +5 -6
  44. package/src/{@building → components/events/components}/GetEventGeometry.ts +19 -13
  45. package/src/{@building → components/events/components}/GetEventHeader.ts +13 -13
  46. package/src/components/events/components/GetEventMerged.ts +51 -0
  47. package/src/{@building → components/events/components}/GetEventNodes.ts +20 -18
  48. package/src/{@building → components/events/components}/GetEventOffice.ts +13 -13
  49. package/src/components/events/components/GetEventPopulation.ts +58 -0
  50. package/src/components/events/components/GetEventProperties.ts +106 -0
  51. package/src/{@building → components/events/components}/GetEventSignature.ts +9 -9
  52. package/src/{@building → components/events/components}/GetEventTags.ts +3 -3
  53. package/src/{@core/CreateListener.ts → components/events/components/GetEventTheme.ts} +8 -6
  54. package/src/components/events/components/GetEventTracking.ts +64 -0
  55. package/src/{@modules/@database → components/events/utilities}/GetCachedEvents.ts +18 -14
  56. package/src/{@manager → components/events/utilities}/SetHash.ts +18 -13
  57. package/src/{@manager → components/events/utilities}/UpdateEvents.ts +12 -12
  58. package/src/{@manager → components/events/utilities}/UpdateNode.ts +14 -14
  59. package/src/{@parsers/@text → components/formatting}/GetEmbededText.ts +12 -6
  60. package/src/{@parsers/@text → components/formatting}/GetStringText.ts +13 -9
  61. package/src/{@modules/@utilities → components/geometry}/GetShapeNearestPoint.ts +24 -19
  62. package/src/components/geometry/GetUnionPolygon.ts +36 -0
  63. package/src/components/images/GenerateGraphic.ts +242 -0
  64. package/src/components/images/components/CreateRectangle.ts +22 -0
  65. package/src/components/images/components/CreateText.ts +22 -0
  66. package/src/components/images/modules/CreateSVG.ts +37 -0
  67. package/src/components/images/modules/GetGeographicalBoundaries.ts +72 -0
  68. package/src/components/images/modules/GetGeographicalCities.ts +58 -0
  69. package/src/components/images/modules/GetGeographicalEvents.ts +48 -0
  70. package/src/components/images/modules/GetGeometryBounds.ts +82 -0
  71. package/src/components/images/modules/GetParsedBoundary.ts +58 -0
  72. package/src/components/images/modules/GetSVGPath.ts +53 -0
  73. package/src/components/images/modules/NormalizePolygon.ts +57 -0
  74. package/src/{@modules/@stanza → components/stanza}/GetAwipsType.ts +16 -17
  75. package/src/{@modules/@stanza → components/stanza}/ValidateStanza.ts +27 -15
  76. package/src/{@modules/@utilities → components/utilities}/CreateHttp.ts +26 -26
  77. package/src/components/utilities/EmitThread.ts +97 -0
  78. package/src/{@modules/@utilities → components/utilities}/GetLatestIssuance.ts +2 -2
  79. package/src/{@modules/@utilities → components/utilities}/GetMatched.ts +10 -5
  80. package/src/{@modules/@utilities → components/utilities}/QueueManager.ts +7 -8
  81. package/src/{@modules/@utilities → components/utilities}/SetDebug.ts +13 -13
  82. package/src/components/utilities/SetEventEmit.ts +42 -0
  83. package/src/{@modules/@utilities → components/utilities}/SetSettings.ts +7 -7
  84. package/src/{@modules/@utilities → components/utilities}/SetSleep.ts +5 -5
  85. package/src/components/utilities/SetTimeoutAction.ts +64 -0
  86. package/src/components/utilities/SetWarning.ts +47 -0
  87. package/src/{@modules/@xmpp → components/xmpp}/DeployXMPP.ts +20 -20
  88. package/src/{@modules/@xmpp → components/xmpp}/ErrorXMPP.ts +6 -6
  89. package/src/{@modules/@xmpp → components/xmpp}/OfflineXMPP.ts +13 -13
  90. package/src/{@modules/@xmpp → components/xmpp}/OnlineXMPP.ts +18 -18
  91. package/src/components/xmpp/ReconnectXMPP.ts +64 -0
  92. package/src/{@modules/@xmpp → components/xmpp}/StanzaXMPP.ts +26 -26
  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 +8 -3
  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 +37 -36
  119. package/src/{@core → exports}/ClearEvents.ts +9 -9
  120. package/src/{@core → exports}/GetEvents.ts +4 -4
  121. package/src/exports/GetNearestCity.ts +45 -0
  122. package/src/{@core → exports}/GetNodes.ts +4 -4
  123. package/src/{@core → exports}/GetRandomEvent.ts +4 -4
  124. package/src/{@core → exports}/GetVersion.ts +4 -4
  125. package/src/{@core → exports}/ManualEvent.ts +24 -24
  126. package/src/{@core → exports}/QueryStanza.ts +12 -11
  127. package/src/exports/SetNode.ts +100 -0
  128. package/src/{@core → exports}/StartService.ts +22 -21
  129. package/src/{@core → exports}/StopService.ts +10 -10
  130. package/src/index.ts +55 -37
  131. package/src/{@parsers/@hvtec → parsers/hvtec}/HVExtract.ts +7 -7
  132. package/src/{@parsers/@text → parsers/text}/GetDescriptionFromProduct.ts +20 -21
  133. package/src/parsers/text/GetPolygonFromProduct.ts +71 -0
  134. package/src/{@parsers/@text → parsers/text}/GetTextFromProduct.ts +12 -12
  135. package/src/parsers/ugc/GetCache.ts +24 -0
  136. package/src/{@parsers/@ugc → parsers/ugc}/GetExpiry.ts +2 -2
  137. package/src/{@parsers/@ugc/GetUGCHeader.ts → parsers/ugc/GetHeader.ts} +4 -4
  138. package/src/{@parsers/@ugc → parsers/ugc}/GetLocations.ts +10 -10
  139. package/src/parsers/ugc/GetZonePolygon.ts +73 -0
  140. package/src/{@parsers/@ugc → parsers/ugc}/GetZones.ts +3 -3
  141. package/src/{@parsers/@ugc → parsers/ugc}/SetCache.ts +13 -8
  142. package/src/{@parsers/@ugc → parsers/ugc}/UGCExtract.ts +14 -14
  143. package/src/{@parsers/@pvtec → parsers/vtec}/GetExpiry.ts +2 -2
  144. package/src/{@parsers/@pvtec → parsers/vtec}/VTECExtract.ts +17 -17
  145. package/src/tasks/CreateTasks.ts +116 -0
  146. package/src/{@tasks → tasks}/TaskGenerateJSON.ts +10 -11
  147. package/src/{@tasks → tasks}/TaskGenerateText.ts +11 -12
  148. package/src/tasks/TaskSendNTFY.ts +96 -0
  149. package/src/tasks/TaskSendWebhook.ts +107 -0
  150. package/src/{@types → types/event}/Attributes.ts +2 -3
  151. package/src/{@types → types/event}/Event.ts +8 -7
  152. package/src/{@types → types/event}/HVTEC.ts +2 -2
  153. package/src/{@types → types/event}/Properties.ts +17 -4
  154. package/src/{@types → types/event}/Stanza.ts +2 -2
  155. package/src/{@types → types/event}/VTEC.ts +8 -8
  156. package/src/{@types → types/standard}/Actions.ts +3 -3
  157. package/src/{@types → types/standard}/Hash.ts +5 -5
  158. package/src/{@modules/@utilities/GetSettings.ts → types/standard/Nodes.ts} +15 -7
  159. package/src/{@types → types/standard}/Settings.ts +19 -12
  160. package/src/{@types → types/standard}/StanzaCompiled.ts +15 -15
  161. package/src/{@types → types/standard}/UGC.ts +5 -5
  162. package/tools/build.js +2 -15
  163. package/tsconfig.json +29 -17
  164. package/.github/SUPPORTED_EVENTS.md +0 -370
  165. package/.github/docs/docs-functions.md +0 -30
  166. package/.github/docs/docs-general-configurations.md +0 -209
  167. package/.github/docs/docs-integrations.md +0 -37
  168. package/.github/docs/docs-listeners.md +0 -28
  169. package/.github/docs/docs-source-configuration.md +0 -218
  170. package/.github/docs/docs-technical.md +0 -50
  171. package/.github/logo.png +0 -0
  172. package/.github/samples/SAMPLE_EAS_GENERATION.wav +0 -0
  173. package/.github/samples/SAMPLE_GEOJSON.json +0 -204
  174. package/.github/samples/SAMPLE_TEXT_PRODUCT.txt +0 -119
  175. package/dist/esm/index.mjs +0 -22298
  176. package/src/@building/GetEventProperties.ts +0 -101
  177. package/src/@building/GetEventTracking.ts +0 -68
  178. package/src/@core/SetNode.ts +0 -87
  179. package/src/@events/ParseAPI.ts +0 -122
  180. package/src/@manager/MakeEvents.ts +0 -109
  181. package/src/@manager/RemoveEvent.ts +0 -70
  182. package/src/@manager/ValidateEvents.ts +0 -141
  183. package/src/@modules/@database/InitializeDatabase.ts +0 -59
  184. package/src/@modules/@eas/GenerateEASMessage.ts +0 -152
  185. package/src/@modules/@utilities/GetFormattedTime.ts +0 -43
  186. package/src/@modules/@utilities/SetCronSchedule.ts +0 -94
  187. package/src/@modules/@utilities/SetEventEmit.ts +0 -41
  188. package/src/@modules/@utilities/SetListener.ts +0 -30
  189. package/src/@modules/@utilities/SetTimeoutAction.ts +0 -64
  190. package/src/@modules/@utilities/SetWarning.ts +0 -34
  191. package/src/@modules/@xmpp/ReconnectXMPP.ts +0 -64
  192. package/src/@parsers/@text/GetPolygonFromProduct.ts +0 -53
  193. package/src/@parsers/@text/GetXML.ts +0 -61
  194. package/src/@parsers/@ugc/GetCache.ts +0 -24
  195. package/src/@parsers/@ugc/GetZonePolygon.ts +0 -111
  196. package/src/@tasks/CreateTasks.ts +0 -110
  197. package/src/@tasks/TaskGenerateAudio.ts +0 -35
  198. package/src/@tasks/TaskSendNTFY.ts +0 -93
  199. package/src/@tasks/TaskSendWebhook.ts +0 -101
@@ -11,30 +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 { EnumShapefiles } from "@enums/Shapefiles"
22
- import { bootstrap } from "@bootstrap"
23
- import { SetSleep } from "@utilities/SetSleep"
24
- import { SetWarning } from "@utilities/SetWarning"
20
+ import { EnumShapefiles } from "@Enums/Shapefiles"
21
+ import { Bootstrap } from "@Bootstrap"
22
+ import { SetSleep } from "@Utilities/SetSleep"
23
+ import { SetWarning } from "@Utilities/SetWarning"
24
+ import { CreateQuery } from "@Database/CreateQuery"
25
25
  import { existsSync, mkdirSync, writeFileSync, unlinkSync, rm } from "fs"
26
26
  import { resolve, extname} from "path"
27
27
  import { loadAsync } from "jszip"
28
28
  import { read } from "shapefile"
29
29
 
30
- export const ImportShapefiles = async (): Promise<void> => {
31
- const settings = bootstrap.settings as TypeSettings;
30
+ export const Shapefiles = async (): Promise<void> => {
32
31
  try {
33
- const tShapefiles = bootstrap.database
34
- .prepare(`SELECT COUNT(*) AS count FROM shapefiles`)
35
- .get().count;
36
- if (tShapefiles === 0) {
37
- await SetSleep({timeout: 1e3});
32
+ const tShapefiles = CreateQuery({ Query: `SELECT COUNT(*) AS count FROM shapefiles` })[0] as { count: number };
33
+ if (tShapefiles.count === 0) {
34
+ await SetSleep({Timeout: 1e3});
38
35
  for (const shapefile of EnumShapefiles) {
39
36
  const response = await fetch(shapefile.link);
40
37
  const arrayBuff = await response.arrayBuffer();
@@ -55,10 +52,9 @@ export const ImportShapefiles = async (): Promise<void> => {
55
52
  filepath,
56
53
  filepath,
57
54
  );
58
- SetWarning({ message: `Importing ${features.length} features from ${shapefile.name}_${shapefile.id} for Shapefiles` })
59
- const insert = bootstrap.database
60
- .prepare(`INSERT OR REPLACE INTO shapefiles (id, location, geometry) VALUES (?, ?, ?)`)
61
- const transaction = bootstrap.database.transaction((entries: any[]) => {
55
+ SetWarning({ Message: `Importing ${features.length} features from ${shapefile.name}_${shapefile.id} for Shapefiles` })
56
+ const insert = `INSERT INTO shapefiles (id, location, source, geometry) VALUES (?, ?, ?, ?)`;
57
+ const transaction = Bootstrap.Database.transaction((entries: any[]) => {
62
58
  for (const entry of entries) {
63
59
  const { properties, geometry } = entry;
64
60
  let final: string, location: string;
@@ -78,7 +74,7 @@ export const ImportShapefiles = async (): Promise<void> => {
78
74
  final = properties.ID ?? properties.WFO
79
75
  location = properties.NAME;
80
76
  }
81
- insert.run(final, location, JSON.stringify(geometry));
77
+ CreateQuery({ Query: insert, Parameters: [final, location, `${shapefile.name}_${shapefile.id}`, JSON.stringify(geometry)] })
82
78
  }
83
79
  })
84
80
  unlinkSync(`${filepath}.shp`)
@@ -87,7 +83,8 @@ export const ImportShapefiles = async (): Promise<void> => {
87
83
  }
88
84
  rm(resolve(__dirname, 'shapefiles'), { recursive: true, force: true }, () => {});
89
85
  }
90
- } catch (error) {
91
- SetWarning( {message: `An error occurred while compiling shapefiles: ${error.message}` })
86
+ } catch (error: unknown) {
87
+ const message = error instanceof Error ? error.message : String(error);
88
+ SetWarning( {Message: `An error occurred while compiling shapefiles: ${message}` })
92
89
  }
93
90
  }
@@ -11,37 +11,33 @@
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 { TypeStanzaCompiled } from "types/StanzaCompiled"
22
- import { bootstrap } from "@bootstrap"
23
- import { SetWarning } from "@utilities/SetWarning"
20
+ import { TypeSettings } from "TypesStandard/Settings"
21
+ import { TypeStanzaCompiled } from "TypesStandard/StanzaCompiled"
22
+ import { Bootstrap } from "@Bootstrap"
23
+ import { SetWarning } from "@Utilities/SetWarning"
24
+ import { CreateQuery } from "@Database/CreateQuery"
24
25
 
25
- export const ImportStanza = async (stanza: TypeStanzaCompiled): Promise<void> => {
26
- const settings = bootstrap.settings as TypeSettings;
26
+ export const ImportStanza = async (Stanza: TypeStanzaCompiled): Promise<void> => {
27
+ const settings = Bootstrap.Settings as TypeSettings;
27
28
  try {
28
29
  if (!settings.NOAAWeatherWireServiceSettings.CacheSettings.Enabled) { return }
29
- bootstrap.database
30
- .prepare(`INSERT OR IGNORE INTO stanzas (type, stanza, issued) VALUES (?, ?, ?)`)
31
- .run(stanza.getType.type, JSON.stringify(stanza), stanza.attributes.issue)
32
- const count = bootstrap.database
33
- .prepare(`SELECT COUNT(*) as total FROM stanzas`)
34
- .get() as { total: number }
30
+ CreateQuery({ Query: `INSERT OR IGNORE INTO stanzas (type, stanza, issued) VALUES (?, ?, ?)`, Parameters: [Stanza.Type.Type, JSON.stringify(Stanza), Stanza.Attributes.issue] })
31
+ const count = CreateQuery({ Query: `SELECT COUNT(*) as total FROM stanzas` }) as { total: number };
35
32
  const max = settings.NOAAWeatherWireServiceSettings.CacheSettings.MaxDatabaseHistory;
36
33
  if (count.total > max) {
37
34
  const toDelete = count.total - max;
38
35
  if (toDelete > 0) {
39
- bootstrap.database
40
- .prepare(`DELETE FROM stanzas WHERE id IN (SELECT id FROM stanzas ORDER BY issued ASC LIMIT ?)`)
41
- .run(toDelete);
36
+ CreateQuery({ Query: `DELETE FROM stanzas WHERE id IN (SELECT id FROM stanzas ORDER BY issued ASC LIMIT ?)`, Parameters: [toDelete] })
42
37
  }
43
38
  }
44
- } catch (error) {
45
- SetWarning({ message: `An error occurred while importing stanza: ${error.message}` })
39
+ } catch (error: unknown) {
40
+ const message = error instanceof Error ? error.message : String(error);
41
+ SetWarning({ Message: `An error occurred while importing stanza: ${message}` })
46
42
  }
47
43
  }
@@ -0,0 +1,88 @@
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 { TypeEvent } from "TypesEvent/Event"
21
+ import { TypeSettings } from "TypesStandard/Settings"
22
+ import { EnumGlobalFilter } from "@Enums/GlobalFilter"
23
+ import { Bootstrap } from "@Bootstrap"
24
+ import { CreateTasks } from "@Tasks/CreateTasks"
25
+ import { SetHash } from "@BuilderUtilities/SetHash"
26
+ import { UpdateNode } from "@BuilderUtilities/UpdateNode"
27
+ import { SetEventEmit } from "@Utilities/SetEventEmit"
28
+ import { SetTimeoutAction } from "@Utilities/SetTimeoutAction"
29
+ import { GetStringText } from "@Formatting/GetStringText"
30
+ import { GetEventMerged } from "@BuilderComponents/GetEventMerged"
31
+
32
+ export const CreateEvents = async (events: TypeEvent[]): Promise<void> => {
33
+ let tasked = [] as TypeEvent[];
34
+ const settings = Bootstrap.Settings as TypeSettings;
35
+ if (events.length === 0) return
36
+ await Promise.all(events.map(async event => {
37
+ const features = Bootstrap.Cache.Events.features;
38
+ const getHash = event.properties.metadata.hash;
39
+ const getTracking = event.properties.metadata.tracking;
40
+ const isEntry = Bootstrap.Cache.Hashes?.find(hash => hash.Tracking === getTracking)
41
+ const isHashed = isEntry?.Hashes?.includes(getHash) ?? false;
42
+ const isNodeFiltering = settings.GlobalSettings.EventFiltering.NodeLocationFiltering
43
+ const getNodes = Bootstrap.Cache.Nodes.features;
44
+
45
+
46
+ if (isHashed || event.properties.status_metadata.is_expired) return
47
+ SetHash({ Event: event, Entry: isEntry })
48
+ await UpdateNode(event);
49
+ if (isNodeFiltering && getNodes.length > 0) {
50
+ if (!event.properties.metadata.filtered_proximity && !EnumGlobalFilter.includes(event.properties.event.toLowerCase())) {
51
+ return
52
+ }
53
+ }
54
+
55
+ const isRatelimited = SetTimeoutAction({ Identifier: getTracking, Interval: 1, Max: 1, AddTime: true })
56
+ const isLocal = event?.properties?.metadata?.filtered_proximity ? `[LOCAL] ` : ``;
57
+ const getFeature = features.find(feature => feature.properties.metadata.tracking === getTracking);
58
+ const isWatch = event?.properties?.metadata?.vtec?.watch
59
+ const isWOU = event?.properties?.metadata?.vtec?.wou
60
+
61
+ if (!isRatelimited.Limited) {
62
+ SetEventEmit({
63
+ Event: `onEventStatus`,
64
+ Metadata: {
65
+ Type: getFeature ? `Updated` : `New`,
66
+ Event: event
67
+ },
68
+ Tree: Bootstrap.Settings.DeveloperEventLogging ? GetStringText(event).split('\n').filter(line => line.trim() !== '') : [],
69
+ Message: `${isLocal}[${getFeature ? 'Updated' : 'New'}] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
70
+ })
71
+ }
72
+ if (event.properties.status_metadata.is_issued || event.properties.status_metadata.is_updated) {
73
+ if (getFeature) {
74
+ const getIndex = features.indexOf(getFeature);
75
+ if (isWatch && isWOU) { return }
76
+ Bootstrap.Cache.Events.features[getIndex] = GetEventMerged({ Event1: getFeature, Event2: event })
77
+ tasked.push(Bootstrap.Cache.Events.features[getIndex])
78
+ } else {
79
+ features.push(event);
80
+ tasked.push(event)
81
+ }
82
+ }
83
+ }))
84
+
85
+ tasked = tasked.filter((v, i, a) => a.reduce((last, t, index) => t.properties.metadata.tracking === v.properties.metadata.tracking ? index : last, -1) === i)
86
+ SetEventEmit({ Event: `onEventCache`, Metadata: Bootstrap.Cache.Events, Limited: true })
87
+ return await CreateTasks(tasked)
88
+ }
@@ -0,0 +1,149 @@
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 { TypeEvent } from "TypesEvent/Event"
21
+ import { TypeSettings } from "TypesStandard/Settings"
22
+ import { Bootstrap } from "@Bootstrap"
23
+ import { GetEventEnhancedName } from "@BuilderComponents/GetEventEnhancedName"
24
+ import { GetEventSignature } from "@BuilderComponents/GetEventSignature"
25
+ import { CreateEvents } from "@Builder/CreateEvents"
26
+ import { RemoveEvents } from "@Builder/RemoveEvents"
27
+ import { GetEventAttachments } from "@BuilderComponents/GetEventAttachments"
28
+ import { SetEventEmit } from "@Utilities/SetEventEmit"
29
+ import { SetDebug } from "@Utilities/SetDebug"
30
+ import { GetMatched } from "@Utilities/GetMatched"
31
+ import { GetEventPopulation } from "@BuilderComponents/GetEventPopulation"
32
+ import { GetEventGeometry } from "@BuilderComponents/GetEventGeometry"
33
+ import { createHash } from "crypto"
34
+
35
+ export const FilterEvents = async (events: TypeEvent[]): Promise<void> => {
36
+ const tick = performance.now();
37
+ if (events.length === 0) return
38
+ const configurations = Bootstrap.Settings as TypeSettings
39
+ const sets = {} as Record<string, Set<string>>;
40
+ const bools = {} as Record<string, boolean>;
41
+ const megered = {...configurations.GlobalSettings, ...configurations.GlobalSettings.EventFiltering}
42
+ for (const key in megered) {
43
+ const setting = megered[key as keyof typeof megered]
44
+ if (Array.isArray(setting)) {
45
+ (sets as Record<string, any>)[key] = new Set(setting.map(item => String(item).toLowerCase()));
46
+ }
47
+ if (typeof setting === 'boolean') {
48
+ (bools as Record<string, any>)[key] = setting;
49
+ }
50
+ }
51
+ const isFiltered = (define: TypeEvent): boolean => {
52
+ const properties = define.properties;
53
+ const zones = properties.geocode.ugc;
54
+ const icao = properties.geocode.office.office
55
+
56
+ if (properties.status_metadata.is_test) {
57
+ SetEventEmit({ Event: `onTestProduct`, Metadata: define })
58
+ if (bools?.IgnoreTestProducts) return true;
59
+ }
60
+
61
+ if (properties.status_metadata.is_expired) {
62
+ SetEventEmit({ Event: `onExpiredProduct`, Metadata: define })
63
+ RemoveEvents({ Event: define, IsTimeBasedExpiration: false })
64
+ return true;
65
+ }
66
+
67
+ if (properties.metadata?.vtec?.watch && properties.metadata.source != `events.api`) {
68
+ const isWOU = properties.metadata?.vtec?.wou;
69
+ if (!isWOU) {
70
+ properties.metadata.tracking = properties.metadata.tracking.replace(properties.metadata.tracking.split(`.`)[0], `KWNS`)
71
+ }
72
+ SetEventEmit({ Event: isWOU ? `onWatchOutlineUpdate` : `onWatchCountyNotification`, Metadata: define })
73
+ }
74
+
75
+ for (const key in sets) {
76
+ const setting = sets[key]
77
+ const values = [...setting];
78
+ if (key === 'ListeningEvents' && setting.size > 0 && !GetMatched({ Strings: values, String: define.properties.event })) {
79
+ SetEventEmit({
80
+ Event: `onFilteredEvent`,
81
+ Metadata: define
82
+ });
83
+ return true
84
+ }
85
+ if (key === 'IgnoredEvents' && setting.size > 0 && GetMatched({ Strings: values, String: define.properties.event })) {
86
+ SetEventEmit({
87
+ Event: `onIgnoredEvent`,
88
+ Metadata: define
89
+ });
90
+ return true
91
+ }
92
+ if (key === 'ListeningICAO' && setting.size > 0 && icao != null && !setting.has(icao.toLowerCase())) {
93
+ SetEventEmit({
94
+ Event: `onFilteredICAO`,
95
+ Metadata: define
96
+ });
97
+ return true
98
+ }
99
+ if (key === 'IgnoredICAO' && setting.size > 0 && icao != null && setting.has(icao.toLowerCase())) {
100
+ SetEventEmit({
101
+ Event: `onIgnoredICAO`,
102
+ Metadata: define
103
+ });
104
+ return true
105
+ }
106
+ if (key === 'ListeningUGC' && setting.size > 0 && zones.length > 0 && !zones.some((ugc: string) => setting.has(ugc.toLowerCase()))) {
107
+ SetEventEmit({
108
+ Event: `onFilteredUGC`,
109
+ Metadata: define
110
+ });
111
+ return true
112
+ }
113
+ if (key === 'ListeningStates' && setting.size > 0 && zones.length > 0 && !zones.some((ugc: string) => setting.has(ugc.substring(0, 2).toLowerCase()))) {
114
+ SetEventEmit({
115
+ Event: `onFilteredState`,
116
+ Metadata: define
117
+ });
118
+ return true
119
+ }
120
+ }
121
+ return false
122
+ }
123
+
124
+ const filtering = events.filter((event: TypeEvent) => {
125
+ Bootstrap.Cache.Parsed = Bootstrap.Cache.Parsed.filter((e) => e !== event);
126
+ const define = GetEventSignature(event) as TypeEvent;
127
+ const pre = {...define,properties: {...define.properties, metadata: {...define.properties.metadata }}};
128
+ const properties = define.properties; delete pre.properties.metadata.ms; delete pre.properties.metadata.header;
129
+ const enhanced = properties.event = GetEventEnhancedName(event)
130
+ const filtered = isFiltered(define)
131
+ if (!filtered) {
132
+ const tick2 = performance.now();
133
+ const geometry = !bools?.DisableGeometryParsing ? GetEventGeometry({ Event: event }) : null;
134
+ const population = GetEventPopulation(geometry)
135
+ const attachments = GetEventAttachments(event)
136
+ event.geometry = geometry;
137
+ event.properties.geocode.census.population = population.population;
138
+ event.properties.geocode.census.cities = population.cities;
139
+ properties.metadata.attachments = attachments;
140
+ SetDebug({ Title: `Filtered`, Message: `${Math.round(performance.now() - tick2)}ms` })
141
+ }
142
+ properties.metadata.hash = createHash("sha256").update(JSON.stringify(pre)).digest("hex")
143
+ SetEventEmit({ Event: `onProductType${enhanced.replace(/\s+/g, '')}`, Metadata: define });
144
+ return !filtered
145
+ })
146
+
147
+ SetDebug({ Title: `FilterEvents (${filtering.length}/${events.length})`, Message: `${Math.round(performance.now() - tick)}ms` })
148
+ await CreateEvents(filtering)
149
+ }
@@ -11,44 +11,44 @@
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 { TypeStanzaCompiled } from "types/StanzaCompiled"
21
- import { TypeSettings } from "types/Settings"
22
- import { bootstrap } from "@bootstrap"
23
- import { ParseText } from "@events/ParseText"
24
- import { ParseUGC } from "@events/ParseUGC"
25
- import { ParseVTEC } from "@events/ParseVTEC"
26
- import { ParseAPI } from "@events/ParseAPI"
27
- import { ValidateEvents } from "@manager/ValidateEvents"
20
+ import { TypeStanzaCompiled } from "TypesStandard/StanzaCompiled"
21
+ import { TypeSettings } from "TypesStandard/Settings"
22
+ import { Bootstrap } from "@Bootstrap"
23
+ import { ParseText } from "@Events/ParseText"
24
+ import { ParseUGC } from "@Events/ParseUGC"
25
+ import { ParseVTEC } from "@Events/ParseVTEC"
26
+ import { ParseAPI } from "@Events/ParseAPI"
27
+ import { FilterEvents } from "@Builder/FilterEvents"
28
28
 
29
- export const CreateEvent = async (stanza: TypeStanzaCompiled): Promise<void | string> => {
30
- const settings = bootstrap.settings as TypeSettings
29
+ export const ProcessStanza = async (Stanza: TypeStanzaCompiled): Promise<void | string> => {
30
+ const settings = Bootstrap.Settings as TypeSettings
31
31
  const StanzaSettings = settings.NOAAWeatherWireServiceSettings.StanzaSettings;
32
32
 
33
- const isVtecEvent = (stanza.isVTEC && stanza.isUGC)
34
- const isUgcEvent = (!stanza.isVTEC && stanza.isUGC)
35
- const isTextEvent = (!stanza.isVTEC && !stanza.isUGC)
36
- const isNWWS = (stanza.isNWWS)
37
-
33
+ const isVtecEvent = (Stanza.VTEC && Stanza.UGC)
34
+ const isUgcEvent = (!Stanza.VTEC && Stanza.UGC)
35
+ const isTextEvent = (!Stanza.VTEC && !Stanza.UGC)
36
+
37
+ const isNWWS = (Stanza.NWWS)
38
38
  switch (true) {
39
39
  case (!isNWWS):
40
- await ParseAPI(stanza)
40
+ await ParseAPI(Stanza)
41
41
  break;
42
42
  case (isNWWS && !StanzaSettings.DisableVTEC && isVtecEvent):
43
- await ParseVTEC(stanza)
43
+ await ParseVTEC(Stanza)
44
44
  break;
45
45
  case (isNWWS && !StanzaSettings.DisableUGC && isUgcEvent):
46
- await ParseUGC(stanza)
46
+ await ParseUGC(Stanza)
47
47
  break;
48
48
  case (isNWWS && !StanzaSettings.DisableText && isTextEvent):
49
- await ParseText(stanza)
49
+ await ParseText(Stanza)
50
50
  break;
51
51
  }
52
- await ValidateEvents(bootstrap.cache.processed)
52
+ await FilterEvents(Bootstrap.Cache.Parsed)
53
53
  return 'nothing picked';
54
54
  }
@@ -0,0 +1,74 @@
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 { TypeEvent } from "TypesEvent/Event"
21
+ import { EnumStrings } from "@Enums/Strings"
22
+ import { Bootstrap } from "@Bootstrap"
23
+ import { SetEventEmit } from "@Utilities/SetEventEmit"
24
+ import { SetTimeoutAction } from "@Utilities/SetTimeoutAction"
25
+ import { CreateTasks } from "@Tasks/CreateTasks"
26
+
27
+ interface RemoveEventOptions {
28
+ Event: TypeEvent
29
+ IsTimeBasedExpiration: boolean
30
+ }
31
+
32
+ export const RemoveEvents = async ({ Event, IsTimeBasedExpiration }: RemoveEventOptions):Promise<void> => {
33
+ const gTracking = Event.properties.metadata.tracking;
34
+ const isTrackingEventLogged = Bootstrap.Cache.Events.features
35
+ .find(f => f?.properties?.metadata?.tracking === gTracking);
36
+ const isStatement = Event.properties.status_metadata.is_statement;
37
+
38
+ if (isTrackingEventLogged) {
39
+ Event.properties.expires = new Date().toISOString();
40
+ Event.properties.status = `Expired`;
41
+ Event.properties.status_metadata.is_expired = true;
42
+
43
+ const description = IsTimeBasedExpiration ? EnumStrings.cancellation
44
+ .replace(`{SENDER}`, Event.properties.geocode.office.name)
45
+ .replace(`{EVENT}`, Event.properties.event) : Event.properties.description
46
+ Event.properties.description = description;
47
+ Event.properties.metadata.raw = IsTimeBasedExpiration ? description : Event.properties.metadata.raw;
48
+ Event.properties.metadata.history.push({
49
+ description: IsTimeBasedExpiration ? description : Event.properties.description,
50
+ issued: Event.properties.expires,
51
+ status: Event.properties.status
52
+ })
53
+
54
+ Bootstrap.Cache.Events.features
55
+ .splice(Bootstrap.Cache.Events.features.indexOf(isTrackingEventLogged), 1);
56
+ Bootstrap.Cache.Hashes = Bootstrap.Cache.Hashes
57
+ .filter(hash => hash.Tracking !== gTracking);
58
+
59
+ if (!isStatement) {
60
+ SetEventEmit({
61
+ Event: `onEventStatus`,
62
+ Metadata: { type: `Removed`, event: Event },
63
+ Message: `[Removed] ${Event.properties.event} (${Event.properties.status}) (${gTracking})`
64
+ })
65
+ CreateTasks([Event])
66
+ }
67
+ SetTimeoutAction({ Identifier: gTracking, Expire: true })
68
+ }
69
+ SetEventEmit({
70
+ Event: `onEventCache`,
71
+ Metadata: Bootstrap.Cache.Events,
72
+ Limited: true
73
+ })
74
+ }
@@ -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,18 @@
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 { bootstrap } from "@bootstrap"
22
- import { EnumStates } from "@enums/States"
23
- import { EnumExpressions } from "@enums/Expressions"
24
- import { GetLatestIssuance } from "@utilities/GetLatestIssuance"
20
+ import { TypeEvent } from "TypesEvent/Event"
21
+ import { EnumStates } from "@Enums/States"
22
+ import { Bootstrap } from "@Bootstrap"
23
+ import { EnumExpressions } from "@Enums/Expressions"
24
+ import { GetLatestIssuance } from "@Utilities/GetLatestIssuance"
25
+ import { CreateQuery } from "@Database/CreateQuery"
25
26
 
26
27
  interface GetEventAttachmentsResponse {
27
28
  name: string
@@ -38,7 +39,7 @@ type BroadcastifyResponse = {
38
39
 
39
40
  export const GetEventAttachments = (event: TypeEvent): GetEventAttachmentsResponse[] | null => {
40
41
  let attachments = [];
41
- const settings = bootstrap.settings;
42
+ const settings = Bootstrap.Settings;
42
43
  const issuanceTime = GetLatestIssuance();
43
44
  const spcNumber = event?.properties?.discussion_parameters?.discussion_number;
44
45
  const watchNumber = event?.properties?.watch_parameters?.watch_number;
@@ -64,14 +65,15 @@ export const GetEventAttachments = (event: TypeEvent): GetEventAttachmentsRespon
64
65
  const lines = [`Northern`, `Southern`, `Eastern`, `Western`, `Inland`, `Costal`, `County`]
65
66
  const county = location?.split(',')[0]?.trim().replace(new RegExp(`^(${lines.join('|')}) `), '')
66
67
  const state = EnumStates[location?.split(',')[1]?.trim()]
67
- const feeds = bootstrap.database.prepare(`SELECT * FROM broadcastify WHERE state = ? AND county = ?`).all(state, county).sort((a, b) => {
68
+ const feeds = CreateQuery({ Query: `SELECT * FROM broadcastify WHERE state = ? AND county = ?`, Parameters: [state, county] }) as BroadcastifyResponse[];
69
+ const so = feeds.sort((a: BroadcastifyResponse, b: BroadcastifyResponse) => {
68
70
  const typeOrder = ['Other', 'Public Safety'];
69
71
  const indexA = typeOrder.indexOf(a.type);
70
72
  const indexB = typeOrder.indexOf(b.type);
71
73
  return indexA - indexB;
72
- })
73
- const tags = bootstrap.settings.BroadcastifySettings.BroadcastifyTags;
74
- const filtered = feeds.filter((feed: BroadcastifyResponse) => tags.includes(feed.type));
74
+ });
75
+ const tags = Bootstrap.Settings.BroadcastifySettings.BroadcastifyTags;
76
+ const filtered = so.filter((feed: BroadcastifyResponse) => tags.includes(feed.type));
75
77
  if (filtered.length > 0) {
76
78
  filtered.map((filtered: BroadcastifyResponse) => {
77
79
  if (!attachments.some((a) => a.link === filtered.link)) {
@@ -0,0 +1,28 @@
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
+ export const GetEventDirection = (message: string): string | null => {
21
+ const direction = message
22
+ .replace(/\s+/g, ' ')
23
+ .match(/moving\s+(north|south|east|west|northeast|northwest|southeast|southwest)\s+at\s+(\d+)\s+mph/i);
24
+ if (direction) {
25
+ return direction[1].charAt(0).toUpperCase() + direction[1].slice(1).toLowerCase() + ` @ ${direction[2]} MPH`;
26
+ }
27
+ return null;
28
+ };
@@ -11,19 +11,18 @@
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 { EnumEnhanced } from "@enums/Enhanced"
20
+ import { TypeEvent } from "TypesEvent/Event"
21
+ import { EnumEnhanced } from "@Enums/Enhanced"
22
22
 
23
23
  export const GetEventEnhancedName = (event: TypeEvent): string => {
24
24
  let name = event?.properties?.event;
25
-
26
- const damage = event?.properties?.parameters?.damage_threat
25
+ const damage = event?.properties?.parameters?.damage_threat ?? event?.properties?.parameters?.flood_threat
27
26
  const tornado = event?.properties?.parameters?.tornado_threat;
28
27
  const pdswatch = event?.properties?.watch_parameters?.pds_watch;
29
28
  const description = event?.properties?.description?.toLowerCase()