@atmosx/event-product-parser 2.0.16 → 3.0.1

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 (136) hide show
  1. package/README.md +248 -187
  2. package/dist/cjs/index.cjs +12218 -3139
  3. package/dist/esm/index.mjs +12401 -3327
  4. package/dist/index.d.mts +235 -0
  5. package/dist/index.d.ts +235 -0
  6. package/package.json +6 -4
  7. package/src/@building/building.clean.ts +30 -0
  8. package/src/@building/building.create.ts +42 -0
  9. package/src/@building/building.enhance.ts +56 -0
  10. package/src/@building/building.geometry.ts +48 -0
  11. package/src/@building/building.headers.ts +37 -0
  12. package/src/@building/building.office.ts +43 -0
  13. package/src/@building/building.polygon.ts +71 -0
  14. package/src/@building/building.properties.ts +89 -0
  15. package/src/@building/building.signature.ts +61 -0
  16. package/src/@building/building.tags.ts +24 -0
  17. package/src/@building/building.tracking.ts +68 -0
  18. package/src/@building/building.validate.ts +147 -0
  19. package/src/@core/core.getEvents.ts +25 -0
  20. package/src/@core/core.getNodes.ts +25 -0
  21. package/src/@core/core.getRandomEvent.ts +25 -0
  22. package/src/@core/core.getVersion.ts +25 -0
  23. package/src/@core/core.listener.ts +24 -0
  24. package/src/@core/core.setNode.ts +81 -0
  25. package/src/@core/core.start.ts +59 -0
  26. package/src/@core/core.stop.ts +32 -0
  27. package/src/@dictionaries/dictionaries.betterEventNames.ts +89 -0
  28. package/src/@dictionaries/dictionaries.eventActions.ts +28 -0
  29. package/src/@dictionaries/{awips.ts → dictionaries.eventAwipAbreviations.ts} +13 -7
  30. package/src/@dictionaries/dictionaries.eventCancelMessages.ts +30 -0
  31. package/src/@dictionaries/dictionaries.eventCauses.ts +36 -0
  32. package/src/@dictionaries/dictionaries.eventProducts.ts +25 -0
  33. package/src/@dictionaries/dictionaries.eventRecords.ts +25 -0
  34. package/src/@dictionaries/dictionaries.eventSeverity.ts +27 -0
  35. package/src/@dictionaries/dictionaries.eventStatus.ts +31 -0
  36. package/src/@dictionaries/{signatures.ts → dictionaries.eventTags.ts} +13 -68
  37. package/src/@dictionaries/dictionaries.eventTypes.ts +82 -0
  38. package/src/@dictionaries/dictionaries.eventsOffshore.ts +31 -0
  39. package/src/@dictionaries/dictionaries.hailStrings.ts +33 -0
  40. package/src/@dictionaries/{icao.ts → dictionaries.officeICAOs.ts} +13 -6
  41. package/src/@dictionaries/dictionaries.regExp.ts +28 -0
  42. package/src/@dictionaries/dictionaries.shapefileLinks.ts +36 -0
  43. package/src/@dictionaries/dictionaries.statusCorrelationText.ts +40 -0
  44. package/src/@dictionaries/dictionaries.testSignatures.ts +24 -0
  45. package/src/@dictionaries/dictionaries.transcribedMessageReplacements.ts +68 -0
  46. package/src/@events/events.api.ts +113 -0
  47. package/src/@events/events.text.ts +79 -0
  48. package/src/@events/events.ugc.ts +83 -0
  49. package/src/@events/events.vtec.ts +87 -0
  50. package/src/@manager/manager.mkEvent.ts +95 -0
  51. package/src/@manager/manager.rmEvent.ts +46 -0
  52. package/src/@manager/manager.setHash.ts +37 -0
  53. package/src/@manager/manager.updateNodes.ts +55 -0
  54. package/src/@manager/manager.updateWebhooks.ts +50 -0
  55. package/src/@modules/@database/database.cache.ts +48 -0
  56. package/src/@modules/@database/database.init.ts +45 -0
  57. package/src/@modules/@database/database.shapefiles.ts +96 -0
  58. package/src/@modules/@database/database.stanza.ts +48 -0
  59. package/src/@modules/@eas/eas.getFloatPCM16.ts +29 -0
  60. package/src/@modules/@eas/eas.getMergedPCM16.ts +32 -0
  61. package/src/@modules/@eas/eas.getPCM16.ts +52 -0
  62. package/src/@modules/@eas/eas.getPCMToFloat.ts +26 -0
  63. package/src/@modules/@eas/eas.getSampledPCM16.ts +36 -0
  64. package/src/@modules/@eas/eas.getWavPCM16.ts +52 -0
  65. package/src/@modules/@eas/eas.setAFSK.ts +52 -0
  66. package/src/@modules/@eas/eas.setAsciiToBits.ts +32 -0
  67. package/src/@modules/@eas/eas.setAttentionTone.ts +40 -0
  68. package/src/@modules/@eas/eas.setEasTone.ts +137 -0
  69. package/src/@modules/@eas/eas.setNoise.ts +31 -0
  70. package/src/@modules/@eas/eas.setRadioEffect.ts +49 -0
  71. package/src/@modules/@eas/eas.setSameHeader.ts +45 -0
  72. package/src/@modules/@stanza/stanza.getAwipsType.ts +46 -0
  73. package/src/@modules/@stanza/stanza.validate.ts +50 -0
  74. package/src/@modules/@utilities/utilities.createHttp.ts +85 -0
  75. package/src/@modules/@utilities/utilities.createWebhook.ts +100 -0
  76. package/src/@modules/@utilities/utilities.getFormattedTime.ts +43 -0
  77. package/src/@modules/@utilities/utilities.getSettings.ts +25 -0
  78. package/src/@modules/@utilities/utilities.getShapeNearestPoint.ts +114 -0
  79. package/src/@modules/@utilities/utilities.setCronSchedule.ts +65 -0
  80. package/src/@modules/@utilities/utilities.setEventEmit.ts +41 -0
  81. package/src/@modules/@utilities/utilities.setListener.ts +30 -0
  82. package/src/@modules/@utilities/utilities.setSettings.ts +42 -0
  83. package/src/@modules/@utilities/utilities.setSleep.ts +33 -0
  84. package/src/@modules/@utilities/utilities.setTimeoutAction.ts +59 -0
  85. package/src/@modules/@utilities/utilities.setWarning.ts +34 -0
  86. package/src/@modules/@xmpp/xmpp.xDeploy.ts +58 -0
  87. package/src/@modules/@xmpp/xmpp.xError.ts +29 -0
  88. package/src/@modules/@xmpp/xmpp.xOffline.ts +38 -0
  89. package/src/@modules/@xmpp/xmpp.xOnline.ts +45 -0
  90. package/src/@modules/@xmpp/xmpp.xReconnect.ts +64 -0
  91. package/src/@modules/@xmpp/xmpp.xStanza.ts +63 -0
  92. package/src/@parsers/@hvtec/hvtec.extract.ts +40 -0
  93. package/src/@parsers/@pvtec/pvtec.expires.ts +26 -0
  94. package/src/@parsers/@pvtec/pvtec.extract.ts +49 -0
  95. package/src/@parsers/@text/text.getDescriptionFromProduct.ts +53 -0
  96. package/src/@parsers/@text/text.getPolygonFromProduct.ts +32 -0
  97. package/src/@parsers/@text/text.getTextFromProduct.ts +43 -0
  98. package/src/@parsers/@text/text.getXML.ts +61 -0
  99. package/src/@parsers/@ugc/ugc.coordinates.ts +110 -0
  100. package/src/@parsers/@ugc/ugc.expiry.ts +32 -0
  101. package/src/@parsers/@ugc/ugc.extract.ts +37 -0
  102. package/src/@parsers/@ugc/ugc.header.ts +30 -0
  103. package/src/@parsers/@ugc/ugc.locations.ts +29 -0
  104. package/src/@parsers/@ugc/ugc.zones.ts +52 -0
  105. package/src/@types/type.event.ts +67 -0
  106. package/src/@types/type.properties.ts +75 -0
  107. package/src/@types/types.attributes.ts +28 -0
  108. package/src/@types/types.compiled.ts +35 -0
  109. package/src/@types/types.hash.ts +24 -0
  110. package/src/@types/types.hvtec.ts +25 -0
  111. package/src/@types/types.pvtec.ts +30 -0
  112. package/src/@types/types.settings.ts +76 -0
  113. package/src/@types/types.stanza.ts +37 -0
  114. package/src/@types/types.ugc.ts +24 -0
  115. package/src/@types/types.webhook.ts +26 -0
  116. package/src/bootstrap.ts +85 -163
  117. package/src/index.ts +47 -216
  118. package/test.js +78 -51
  119. package/tsup.config.ts +1 -0
  120. package/src/@dictionaries/events.ts +0 -168
  121. package/src/@parsers/@events/api.ts +0 -146
  122. package/src/@parsers/@events/cap.ts +0 -123
  123. package/src/@parsers/@events/text.ts +0 -104
  124. package/src/@parsers/@events/ugc.ts +0 -107
  125. package/src/@parsers/@events/vtec.ts +0 -76
  126. package/src/@parsers/events.ts +0 -392
  127. package/src/@parsers/hvtec.ts +0 -46
  128. package/src/@parsers/pvtec.ts +0 -72
  129. package/src/@parsers/stanza.ts +0 -97
  130. package/src/@parsers/text.ts +0 -165
  131. package/src/@parsers/ugc.ts +0 -247
  132. package/src/@submodules/database.ts +0 -201
  133. package/src/@submodules/eas.ts +0 -490
  134. package/src/@submodules/utils.ts +0 -191
  135. package/src/@submodules/xmpp.ts +0 -142
  136. package/src/types.ts +0 -259
@@ -0,0 +1,37 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { TypePVTEC } from "../@types/types.pvtec";
21
+ import { TypeEventProperties } from "../@types/type.properties";
22
+
23
+ interface GetHeaderOptions {
24
+ properties: TypeEventProperties
25
+ vtec?: TypePVTEC
26
+ getType: {
27
+ type: string
28
+ prefix: string
29
+ }
30
+ }
31
+
32
+ export const getEventHeader = (options: GetHeaderOptions): string => {
33
+ const properties = options.properties
34
+ const vtec = options.vtec ?? null
35
+ const ugc = properties.geocode.ugc != null ? properties.geocode.ugc.join(`-`) : `0`;
36
+ return `ZCZC-ATMOSX-${options.getType.prefix}-${ugc}-${vtec?.status ?? `Issued`}-${new Date().toISOString().replace(/[-:]/g, '').split('.')[0]}-${properties.geocode.office.office ?? `KWNS`}`
37
+ }
@@ -0,0 +1,43 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { TypeAttributes } from "../@types/types.attributes";
21
+ import { TypePVTEC } from "../@types/types.pvtec";
22
+ import { officeICAOs } from "../@dictionaries/dictionaries.officeICAOs";
23
+
24
+ interface GetOfficeOptions {
25
+ attributes: TypeAttributes
26
+ organization: string
27
+ pVtec: TypePVTEC
28
+ }
29
+
30
+ interface GetOfficeResponse {
31
+ office: string | null
32
+ name: string | null
33
+ }
34
+
35
+ export const getEventOffice = (options: GetOfficeOptions): GetOfficeResponse => {
36
+ const office = options.pVtec != null
37
+ ? options.pVtec?.tracking?.split(`-`)[0] : (options.attributes?.cccc ||
38
+ (options.organization != null ?
39
+ (Array.isArray(options.organization) ? options.organization?.[0] : options.organization)
40
+ : null));
41
+ const name = officeICAOs?.[office] ?? null;
42
+ return { office, name };
43
+ }
@@ -0,0 +1,71 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+
21
+ import { TypeEvent } from "../@types/type.event"
22
+ import { getEventGeometry } from "./building.geometry"
23
+ import { bootstrap } from "../bootstrap"
24
+ import { getShapeNearestPoint } from "../@modules/@utilities/utilities.getShapeNearestPoint"
25
+
26
+ interface GetEventNodesResponse {
27
+ nodes: {
28
+ id?: string | number
29
+ coordinates: [number, number]
30
+ nearest: [number, number]
31
+ miles: number | null
32
+ kilometers: number | null
33
+ proximity: boolean
34
+ }[]
35
+ filtered: boolean
36
+ updated: number
37
+ }
38
+
39
+ export const getEventNodes = async (event: TypeEvent): Promise<GetEventNodesResponse> => {
40
+ const metadata = { nodes: [], proximity: false, filtered: false }
41
+ const geometry = await getEventGeometry(event);
42
+ if (!geometry || !geometry.coordinates) {
43
+ return { nodes: [], filtered: false, updated: Date.now() }
44
+ }
45
+ const nodes = bootstrap.cache.nodes.features;
46
+ for (const node of nodes) {
47
+ const [longitude, latitude] = node.geometry.coordinates;
48
+ const getPoint = getShapeNearestPoint(geometry.coordinates, [longitude, latitude])
49
+ const miles = getPoint.distance ?? null;
50
+ const kilometers = Number((miles * 1.609344).toFixed(3));
51
+
52
+ const info = {
53
+ id: node.properties?.identifier,
54
+ coordinates: [longitude, latitude],
55
+ nearest: getPoint.point,
56
+ miles,
57
+ kilometers,
58
+ proximity: getPoint.proximity
59
+ }
60
+ metadata.nodes.push(info)
61
+ if (bootstrap.settings.GlobalSettings.EventFiltering.NodeLocationFiltering && miles < bootstrap.settings.GlobalSettings.NodeMinDistance) {
62
+ metadata.proximity = true;
63
+ info.proximity = true;
64
+ }
65
+ }
66
+ return {
67
+ nodes: metadata.nodes,
68
+ filtered: metadata.proximity,
69
+ updated: Date.now()
70
+ }
71
+ }
@@ -0,0 +1,89 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { TypeEventProperties } from "../@types/type.properties";
21
+ import { TypeAttributes } from "../@types/types.attributes";
22
+ import { TypeUGC } from "../@types/types.ugc";
23
+ import { TypePVTEC } from "../@types/types.pvtec";
24
+ import { TypeHVTEC } from "../@types/types.hvtec";
25
+ import { regExp } from "../@dictionaries/dictionaries.regExp";
26
+ import { getDescriptionFromProduct } from "../@parsers/@text/text.getDescriptionFromProduct";
27
+ import { getPolygonFromProduct } from "../@parsers/@text/text.getPolygonFromProduct";
28
+ import { getTextFromProduct } from "../@parsers/@text/text.getTextFromProduct";
29
+ import { getEventOffice } from "./building.office";
30
+ import { getEventTags } from "./building.tags";
31
+
32
+ interface GetPropertiesOptions {
33
+ message: string
34
+ attributes: TypeAttributes
35
+ ugc?: TypeUGC
36
+ pVtec?: TypePVTEC
37
+ hVtec?: TypeHVTEC
38
+ }
39
+
40
+ export const properties = (options: GetPropertiesOptions): TypeEventProperties => {
41
+ const organization = options.message.match(regExp.wmo)?.[0] ?? null
42
+ const polygons = getPolygonFromProduct(options.message)
43
+ return {
44
+ locations: options?.ugc?.locations?.join(`; `) ?? null,
45
+ description: getDescriptionFromProduct({ message: options.message, handle: options?.pVtec?.vtec ?? null }),
46
+ attributes: options.attributes,
47
+ geocode: {
48
+ office: getEventOffice({ attributes: options.attributes, organization: organization, pVtec: options.pVtec }),
49
+ organization: organization,
50
+ ugc: options?.ugc?.zones ?? [],
51
+ polygon: polygons.length > 0 ? Buffer.from(JSON.stringify([polygons])).toString('base64') : null,
52
+ polygon_generated: polygons.length > 0 ? true : false
53
+ },
54
+ parameters: {
55
+ tags: getEventTags(options.message),
56
+ instructions: getTextFromProduct({ message: options.message, find: [`For your protection`, `do not`, `use extreme caution`], append: `...`, removal: [`.`]}) ?? null,
57
+ source: getTextFromProduct({ message: options.message, find: [`SOURCE...`], removal: [`.`]}) ?? null,
58
+ hazards: getTextFromProduct({ message: options.message, find: [`HAZARD...`], removal: [`.`]}) ?? null,
59
+ impacts: getTextFromProduct({ message: options.message, find: [`IMPACT...`], removal: [`.`]}) ?? null,
60
+ estimated_hail_size: getTextFromProduct({ message: options.message, find: [`MAX HAIL SIZE...`, `HAIL...`], removal: ['in']}) ?? null,
61
+ estimated_wind_gusts: getTextFromProduct({ message: options.message, find: [`MAX WIND GUST...`, `WIND...`]}) ?? null,
62
+ damage_threat: getTextFromProduct({ message: options.message, find: [`DAMAGE THREAT...`], removal: []}) ?? null,
63
+ tornado_threat: getTextFromProduct({ message: options.message, find: [`TORNADO...`, `WATERSPOUT...`] }) ?? null,
64
+ flood_threat: getTextFromProduct({ message: options.message, find: [`FLASH FLOOD...`]}) ?? null,
65
+ wind_threat: getTextFromProduct({ message: options.message, find: [`WIND THREAT...`]}) ?? null,
66
+ hail_threat: getTextFromProduct({ message: options.message, find: [`HAIL THREAT...`], removal: []}) ?? null,
67
+ },
68
+ spc_parameters: {
69
+ spc_max_tornado: getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK TORNADO INTENSITY...`] }) ?? null,
70
+ spc_max_hail: getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK HAIL SIZE...`] }) ?? null,
71
+ spc_max_wind: getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK WIND GUST...`] }) ?? null,
72
+ spc_watch_issuance: getTextFromProduct({ message: options.message, find: [`Probability of Watch Issuance...`], removal: [`percent`]}) ?? null,
73
+ },
74
+ watch_parameters: {
75
+ watch_number: getTextFromProduct({ message: options.message, find: [`ITIES FOR`, `UPDATE FOR`, `Watch Number `], removal: [`%`, `<`, `:`] })?.replace(/(WT|WS|)/g, '')?.trim() ?? null,
76
+ watch_type: options.message.includes(`TORNADO WATCH`) ? `Tornado` : options?.message.includes(`SEVERE`) ? `Severe` : null,
77
+ additional_tornadoes_probability: getTextFromProduct({ message: options.message, find: [`PROB OF 2 OR MORE TORNADOES`], removal: [`%`, `<`, `:`] }) ?? null,
78
+ strong_tornadoes_probability: getTextFromProduct({ message: options.message, find: [`PROB OF 1 OR MORE STRONG /EF2-EF5/ TORNADOES`], removal: [`%`, `<`, `:`] }) ?? null,
79
+ severe_wind_probability: getTextFromProduct({ message: options.message, find: [`PROB OF 10 OR MORE SEVERE WIND EVENTS`], removal: [`%`, `<`, `:`] }) ?? null,
80
+ severe_hail_probability: getTextFromProduct({ message: options.message, find: [`PROB OF 10 OR MORE SEVERE HAIL EVENTS`], removal: [`%`, `<`, `:`] }) ?? null,
81
+ hail_2in_probability: getTextFromProduct({ message: options.message, find: [`PROB OF 1 OR MORE HAIL EVENTS >= 2 INCHES`], removal: [`%`, `<`, `:`] }) ?? null,
82
+ combined_hail_wind_probability: getTextFromProduct({ message: options.message, find: [`PROB OF 6 OR MORE COMBINED SEVERE HAIL/WIND EVENTS`], removal: [`%`, `<`, `:`] }) ?? null,
83
+ max_hail_in: getTextFromProduct({ message: options.message, find: [`MAX HAIL /INCHES/`], removal: [`%`, `<`, `:`] }) ?? null,
84
+ max_wind_surface: getTextFromProduct({ message: options.message, find: [`MAX WIND GUSTS SURFACE /KNOTS/`], removal: [`%`, `<`, `:`] }) ?? null,
85
+ max_tops_x100feet: getTextFromProduct({ message: options.message, find: [`MAX TOPS /X 100 FEET/`], removal: [`%`, `<`, `:`] }) ?? null,
86
+ pds_watch: (getTextFromProduct({ message: options.message, find: [`PARTICULARLY DANGEROUS SITUATION`], removal: [`%`, `<`, `:`] }) === `YES`)
87
+ }
88
+ }
89
+ }
@@ -0,0 +1,61 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { TypeEvent } from "../@types/type.event";
21
+ import { statusCorrelationText } from "../@dictionaries/dictionaries.statusCorrelationText";
22
+ import { eventCancelMessages } from "../@dictionaries/dictionaries.eventCancelMessages";
23
+ import { testSignatures} from "../@dictionaries/dictionaries.testSignatures"
24
+ import { eventProducts } from "../@dictionaries/dictionaries.eventProducts";
25
+ import { hailStrings } from "../@dictionaries/dictionaries.hailStrings"
26
+
27
+
28
+ export const getEventSignature = (event: TypeEvent): TypeEvent => {
29
+ const properties = event?.properties;
30
+ const vtec = event?.properties?.metadata?.vtec
31
+ const status = statusCorrelationText
32
+ .find((c: { type: string }) => c.type === properties?.status);
33
+ const csig = eventCancelMessages.find(sig => properties.description.toLowerCase().includes(sig.toLowerCase()));
34
+ properties.status_metadata = { ...properties.status_metadata, is_issued: true, is_test: false};
35
+
36
+ if (properties.parameters.estimated_hail_size) {
37
+ properties.parameters.estimated_hail_size += ` (${hailStrings[properties.parameters.estimated_hail_size] ?? '--'})`
38
+ }
39
+
40
+ if (status) {
41
+ properties.status = status.name ?? properties.status;
42
+ properties.status_metadata = { ...properties.status_metadata, is_updated: !!status.isUpdate, is_issued: !!status.isIssued, is_expired: !!status.isCancel };
43
+ }
44
+ if (csig) {
45
+ properties.status_metadata = { ...properties.status_metadata, is_expired: true };
46
+ }
47
+ const getProduct = vtec?.vtec?.split(`.`)[0]?.replace(`/`, ``)
48
+ const isTestProduct = eventProducts[getProduct] == `Test Product`
49
+ if (isTestProduct || testSignatures.some(sig => properties.description?.toLowerCase().includes(sig.toLowerCase()) || properties?.parameters?.instructions?.toLowerCase().includes(sig.toLowerCase()))) {
50
+ properties.status_metadata = { ...properties.status_metadata, is_test: true }
51
+ }
52
+
53
+ if (new Date(properties.expires).getTime() < Date.now()) {
54
+ properties.status_metadata = { ...properties.status_metadata, is_expired: true };
55
+ }
56
+ properties.status_metadata = {
57
+ ...properties.status_metadata,
58
+ }
59
+
60
+ return event
61
+ }
@@ -0,0 +1,24 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { eventTags } from "../@dictionaries/dictionaries.eventTags";
21
+
22
+ export const getEventTags = (message: string): string[] => {
23
+ return Object.entries(eventTags).filter(([key]) => message?.toLowerCase().includes(key.toLowerCase())).map(([, value]) => value)
24
+ }
@@ -0,0 +1,68 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { TypeAttributes } from "../@types/types.attributes";
21
+ import { TypeEventProperties } from "../@types/type.properties";
22
+ import { TypeStanzaCompiled } from "../@types/types.compiled";
23
+ import { TypePVTEC } from "../@types/types.pvtec";
24
+
25
+ interface GetTrackingOptions {
26
+ type: `RAW` | `VTEC` | `API`
27
+ stanza?: TypeStanzaCompiled
28
+ attributes?: TypeAttributes
29
+ properties?: TypeEventProperties
30
+ organization?: {
31
+ wmoidentifier: string
32
+ featureId: string
33
+ }
34
+ vtec?: TypePVTEC
35
+ }
36
+
37
+ export const getEventTracking = (options: GetTrackingOptions): string => {
38
+ const proprties = options.properties
39
+ const attributes = options.attributes
40
+ const stanza = options.stanza
41
+ const vtec = options.vtec
42
+ if (options.type === `RAW`) {
43
+ const getWatchNumber = proprties.watch_parameters.watch_number ?? null
44
+ if (getWatchNumber) {
45
+ return `${proprties.geocode.office.office}-${stanza.getType.prefix}-A-${getWatchNumber}`
46
+ }
47
+ return `${proprties.geocode.office.office}-${attributes.ttaaii}-${attributes.id.slice(-4).replace(`.`, ``) ?? '0'}`
48
+ }
49
+ if (options.type === `VTEC`) {
50
+ return vtec.tracking;
51
+ }
52
+ if (options.type === `API`) {
53
+ if (options.vtec) {
54
+ const vtecValue = Array.isArray(options.vtec)
55
+ ? options.vtec[0] : options.vtec;
56
+ const splitPVTEC = vtecValue.split('.');
57
+ return `${splitPVTEC[2]}-${splitPVTEC[3]}-${splitPVTEC[4]}-${splitPVTEC[5]}`;
58
+ }
59
+ const wmoMatch = options.organization?.wmoidentifier?.match(/([A-Z]{4}\d{2})\s+([A-Z]{4})/);
60
+ const station = wmoMatch?.[2] ?? 'N/A';
61
+ if (options.organization.featureId) {
62
+ const idMatch = options.organization.featureId.match(/([a-f0-9]+)\.(\d+)\.(\d+)$/);
63
+ return `${station}-${idMatch?.[1] ?? 'N/A'}`;
64
+ }
65
+ const id = wmoMatch?.[1] ?? 'N/A';
66
+ return `${station}-${id}`;
67
+ }
68
+ }
@@ -0,0 +1,147 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { createHash } from "crypto"
21
+ import { TypeEvent } from "../@types/type.event";
22
+ import { TypeSettings } from "../@types/types.settings";
23
+ import { bootstrap } from "../bootstrap"
24
+ import { getEventEnhancedName } from "./building.enhance";
25
+ import { getEventSignature } from "./building.signature"
26
+ import { mkEvent } from "../@manager/manager.mkEvent";
27
+ import { rmEvent } from "../@manager/manager.rmEvent";
28
+ import { getEventGeometry } from "./building.geometry";
29
+ import { updateNode } from "../@manager/manager.updateNodes";
30
+ import { setEventEmit } from "../@modules/@utilities/utilities.setEventEmit";
31
+
32
+ export const validateEvents = async (events: TypeEvent[]): Promise<void> => {
33
+ if (events.length === 0) return;
34
+ const configurations = bootstrap.settings as TypeSettings
35
+ const sets = {} as Record<string, Set<string>>;
36
+ const bools = {} as Record<string, boolean>;
37
+ const megered = {...configurations.GlobalSettings, ...configurations.GlobalSettings.EventFiltering}
38
+ for (const key in megered) {
39
+ const setting = megered[key];
40
+ if (Array.isArray(setting)) { sets[key] = new Set(setting.map(item => item.toLowerCase())); }
41
+ if (typeof setting === 'boolean') { bools[key] = setting; }
42
+ }
43
+ const filterd = events.filter((event: TypeEvent) => {
44
+ const define = getEventSignature(event) as TypeEvent;
45
+ const properties = define.properties;
46
+ const zones = properties.geocode.ugc;
47
+ const icao = properties.geocode.office.office
48
+ const enhancedEventName = properties.event = getEventEnhancedName(event)
49
+ const filteredProperties = JSON.parse(JSON.stringify(properties)) as typeof properties;
50
+ if (filteredProperties?.metadata && 'ms' in filteredProperties.metadata) {
51
+ delete filteredProperties.metadata.ms;
52
+ }
53
+ filteredProperties.metadata = filteredProperties.metadata ?? {} as any;
54
+ filteredProperties.metadata.hash = createHash("sha256").update(JSON.stringify(filteredProperties)).digest("hex")
55
+
56
+ setEventEmit({ event: `onProductType${enhancedEventName.replace(/\s+/g, '')}`, metadata: define });
57
+
58
+ if (properties.status_metadata.is_test) {
59
+ setEventEmit({ event: `onTestProduct`, metadata: define })
60
+ if (bools?.IgnoreTestProducts) return false;
61
+ }
62
+
63
+ if (properties.status_metadata.is_expired) {
64
+ setEventEmit({ event: `onExpiredProduct`, metadata: define })
65
+ rmEvent(define)
66
+ return false;
67
+ }
68
+
69
+ if (properties.metadata?.vtec?.is_watch) {
70
+ const isSPC = properties.metadata?.vtec?.prediction_center;
71
+ setEventEmit({ event: isSPC ? `onStormPredictionWatch` : `onNonStormPredictionWatch`, metadata: define })
72
+ if (bools?.SPCWatchesOnly && !isSPC) {
73
+ return false;
74
+ }
75
+ if ((!bools?.SPCWatchesOnly) && isSPC) {
76
+ return false
77
+ }
78
+ }
79
+
80
+
81
+ for (const key in sets) {
82
+ const setting = sets[key]
83
+ if (key === 'ListeningEvents' && setting.size > 0 && !setting.has(define.properties.event.toLowerCase())) {
84
+ setEventEmit({
85
+ event: `onFilteredEvent`,
86
+ metadata: define
87
+ });
88
+ return false
89
+ }
90
+ if (key === 'IgnoredEvents' && setting.size > 0 && setting.has(define.properties.event.toLowerCase())) {
91
+ setEventEmit({
92
+ event: `onIgnoredEvent`,
93
+ metadata: define
94
+ });
95
+ return false
96
+ }
97
+ if (key === 'ListeningICAO' && setting.size > 0 && icao != null && !setting.has(icao.toLowerCase())) {
98
+ setEventEmit({
99
+ event: `onFilteredICAO`,
100
+ metadata: define
101
+ });
102
+ return false
103
+ }
104
+ if (key === 'IgnoredICAO' && setting.size > 0 && icao != null && setting.has(icao.toLowerCase())) {
105
+ setEventEmit({
106
+ event: `onIgnoredICAO`,
107
+ metadata: define
108
+ });
109
+ return false
110
+ }
111
+ if (key === 'ListeningUGC' && setting.size > 0 && zones.length > 0 && !zones.some((ugc: string) => setting.has(ugc.toLowerCase()))) {
112
+ setEventEmit({
113
+ event: `onFilteredUGC`,
114
+ metadata: define
115
+ });
116
+ return false
117
+ }
118
+ if (key === 'ListeningStates' && setting.size > 0 && zones.length > 0 && !zones.some((ugc: string) => setting.has(ugc.substring(0, 2).toLowerCase()))) {
119
+ setEventEmit({
120
+ event: `onFilteredState`,
121
+ metadata: define
122
+ });
123
+ return false
124
+ }
125
+ }
126
+ return true;
127
+ })
128
+
129
+
130
+ if (!configurations?.GlobalSettings?.DisableGeometryParsing) {
131
+ for (const event of filterd) {
132
+ event.geometry = await getEventGeometry(event)
133
+ }
134
+ }
135
+
136
+ if (filterd.length > 0) {
137
+ for (const event of filterd) {
138
+ await mkEvent(event)
139
+ }
140
+ }
141
+ await updateNode()
142
+ setEventEmit({
143
+ event: `onEventCache`,
144
+ metadata: bootstrap.cache.events,
145
+ limited: true
146
+ })
147
+ }
@@ -0,0 +1,25 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { bootstrap } from "../bootstrap";
21
+
22
+
23
+ export const getEvents = (): any => {
24
+ return bootstrap.cache.events
25
+ }
@@ -0,0 +1,25 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { bootstrap } from "../bootstrap";
21
+
22
+
23
+ export const getNodes = (): any => {
24
+ return bootstrap.cache.nodes
25
+ }
@@ -0,0 +1,25 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { bootstrap } from "../bootstrap";
21
+
22
+
23
+ export const getRandomEvent = (): any => {
24
+ return bootstrap.cache.events.features[Math.floor(Math.random() * bootstrap.cache.events.features.length)]
25
+ }
@@ -0,0 +1,25 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { bootstrap } from "../bootstrap";
21
+
22
+
23
+ export const getVersion = (): any => {
24
+ return bootstrap.version
25
+ }