@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,32 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ export const getPolygonFromProduct = (message: string): number[][] => {
21
+ const coordinates: [number, number][] = [];
22
+ const match = message.match(/LAT\.{3}LON\s+([\d\s]+)/i);
23
+ if (!match || !match[1]) return coordinates;
24
+ const coordStrings = match[1].replace(/\n/g, ' ').trim().split(/\s+/);
25
+ for (let i = 0; i < coordStrings.length - 1; i += 2) {
26
+ const lat = parseFloat(coordStrings[i]) / 100;
27
+ const lon = -parseFloat(coordStrings[i + 1]) / 100;
28
+ if (!isNaN(lat) && !isNaN(lon)) { coordinates.push([lon, lat]); }
29
+ }
30
+ if (coordinates.length > 2) { coordinates.push(coordinates[0]); }
31
+ return coordinates;
32
+ }
@@ -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
+ interface GetTextFromProductOptions {
21
+ message: string
22
+ find: string[]
23
+ append?: string
24
+ removal?: string[]
25
+ }
26
+
27
+ export const getTextFromProduct = (options: GetTextFromProductOptions): string => {
28
+ const lines = options.message.split(`\n`);
29
+ for (const line of lines) {
30
+ const matchedFind = options.find.find((find) => line.includes(find));
31
+ if (matchedFind) {
32
+ let result = line.slice(line.indexOf(matchedFind) + matchedFind.length).trim();
33
+ if (options.removal) {
34
+ for (const str of options.removal) {
35
+ result = result.toLowerCase().split(str.toLowerCase()).join('');
36
+ }
37
+ result = result.replace(matchedFind, '').replace('<', '').trim();
38
+ }
39
+ return result.toUpperCase() + (options?.append ?? ``);
40
+ }
41
+ }
42
+ return null;
43
+ }
@@ -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
+ interface GetXMLOptions {
21
+ message: string
22
+ targets: string[]
23
+ }
24
+
25
+ export const getXML = (options: GetXMLOptions): Record<string, string> => {
26
+ const extracted: Record<string, any> = {};
27
+ const findValueByKey = (obj: any, searchKey: string) => {
28
+ const results = [];
29
+ if (obj === null || typeof obj !== 'object') {
30
+ return results;
31
+ }
32
+ const searchKeyLower = searchKey.toLowerCase();
33
+ for (const key in obj) {
34
+ if (obj.hasOwnProperty(key) && key.toLowerCase() === searchKeyLower) {
35
+ results.push(obj[key]);
36
+ }
37
+ }
38
+ if (Array.isArray(obj)) {
39
+ for (const item of obj) {
40
+ if (item.valueName && item.valueName.toLowerCase() === searchKeyLower && item.value !== undefined) {
41
+ results.push(item.value);
42
+ }
43
+ const nestedResults = findValueByKey(item, searchKey);
44
+ results.push(...nestedResults);
45
+ }
46
+ }
47
+ for (const key in obj) {
48
+ if (obj.hasOwnProperty(key)) {
49
+ const nestedResults = findValueByKey(obj[key], searchKey);
50
+ results.push(...nestedResults);
51
+ }
52
+ }
53
+ return results;
54
+ };
55
+ for (const key of options.targets) {
56
+ const values = findValueByKey(options.message, key);
57
+ const uniqueValues = [...new Set(values)];
58
+ extracted[key] = uniqueValues.length === 0 ? null : (uniqueValues.length === 1 ? uniqueValues[0] : uniqueValues);
59
+ }
60
+ return extracted;
61
+ }
@@ -0,0 +1,110 @@
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
+ import { union } from "polygon-clipping";
20
+ import { bootstrap } from "../../bootstrap";
21
+
22
+ interface CoordinatesOptions {
23
+ zones: string[]
24
+ isUnion: boolean
25
+ }
26
+
27
+ interface CoordinatesResponse {
28
+ type: `Polygon` | `MultiPolygon`
29
+ coordinates: any[]
30
+ }
31
+
32
+ export const getZonePolygon = (options: CoordinatesOptions): CoordinatesResponse | null => {
33
+ const list = [...new Set(options.zones.map(z => z.trim()))].filter(z => z === 'XX000' ? false : true);
34
+ if (list.length === 0) return null;
35
+
36
+ const placeholders = list.map(() => "?").join(",");
37
+ const rows = bootstrap.database
38
+ .prepare(`SELECT geometry FROM shapefiles WHERE id IN (${placeholders})`)
39
+ .all(...list);
40
+ const polygons: any[] = [];
41
+ for (const row of rows) {
42
+ if (!row?.geometry) continue;
43
+ const geom = JSON.parse(row.geometry);
44
+ if (geom?.type === "Polygon") {
45
+ polygons.push(geom.coordinates);
46
+ }
47
+ }
48
+
49
+ if (polygons.length === 0) return null;
50
+
51
+ if (options.isUnion) {
52
+ const unionFn = union as (...polys: any[]) => any;
53
+ const mergedCoords = unionFn(...polygons);
54
+ if (!mergedCoords || mergedCoords.length === 0) return null;
55
+ let maxArea = -1;
56
+ let bestPoly: any[] = [];
57
+ for (const poly of mergedCoords) {
58
+ const outerRing = poly[0];
59
+ let area = 0;
60
+ for (let i = 0; i < outerRing.length - 1; i++) {
61
+ const [x1, y1] = outerRing[i];
62
+ const [x2, y2] = outerRing[i + 1];
63
+ area += x1 * y2 - x2 * y1;
64
+ }
65
+ area = Math.abs(area / 2);
66
+ if (area > maxArea) {
67
+ maxArea = area;
68
+ bestPoly = poly;
69
+ }
70
+ }
71
+ if (!bestPoly || bestPoly.length === 0) return null;
72
+ const outerRing = bestPoly[0];
73
+ const skip = Math.max(1, parseInt(String(bootstrap.settings.GlobalSettings.ShapefileSkipPoints), 10) || 1);
74
+ let skipped = outerRing.filter((_: any, idx: number) => idx % skip === 0);
75
+ if (skipped.length < 4) {
76
+ skipped = outerRing.slice();
77
+ }
78
+ const first = skipped[0];
79
+ const last = skipped[skipped.length - 1];
80
+ if (!first || !last || first[0] !== last[0] || first[1] !== last[1]) {
81
+ skipped.push([first[0], first[1]]);
82
+ }
83
+ return {type: "Polygon", coordinates: [skipped]};
84
+ } else {
85
+ const multi: any[] = [];
86
+ for (const polyCoords of polygons) {
87
+ if (Array.isArray(polyCoords) && Array.isArray(polyCoords[0])) {
88
+ multi.push(polyCoords);
89
+ }
90
+ }
91
+ if (multi.length === 0) return null;
92
+ const skip = Math.max(1, parseInt(String(bootstrap.settings.GlobalSettings.ShapefileSkipPoints), 10) || 1);
93
+ if (skip > 1) {
94
+ for (let p = 0; p < multi.length; p++) {
95
+ for (let r = 0; r < multi[p].length; r++) {
96
+ const ring = multi[p][r];
97
+ let reduced = ring.filter((_: any, i: number) => i % skip === 0);
98
+ if (reduced.length < 4) reduced = ring.slice();
99
+ const first = reduced[0];
100
+ const last = reduced[reduced.length - 1];
101
+ if ( first && last && (first[0] !== last[0] || first[1] !== last[1])) {
102
+ reduced.push([first[0], first[1]]);
103
+ }
104
+ multi[p][r] = reduced;
105
+ }
106
+ }
107
+ }
108
+ return {type: "MultiPolygon", coordinates: multi};
109
+ }
110
+ }
@@ -0,0 +1,32 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ export const getExpiry = (message: string): string | null => {
21
+ const match = message.match(/\b(\d{6})-/);
22
+ if (!match) {
23
+ return null;
24
+ }
25
+ const date = match?.[1];
26
+ const day = parseInt(date?.slice(0, 2), 10);
27
+ const hour = parseInt(date?.slice(2, 4), 10);
28
+ const minute = parseInt(date?.slice(4, 6), 10);
29
+ const now = new Date();
30
+ const expires = new Date(Date.UTC(now.getUTCFullYear(),now.getUTCMonth(),day,hour,minute));
31
+ return expires.toISOString();
32
+ }
@@ -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 { TypeUGC } from "../../@types/types.ugc";
21
+ import { getUGCHeader } from "./ugc.header"
22
+ import { getZones } from "./ugc.zones";
23
+ import { getExpiry } from './ugc.expiry';
24
+ import { getLocations } from "./ugc.locations";
25
+
26
+ export const ugcExtract = async (message: string): Promise<TypeUGC> => {
27
+ const head = getUGCHeader(message);
28
+ const ugcs = getZones(head)
29
+ const expires = getExpiry(message)
30
+ const areas = await getLocations(ugcs)
31
+ if (!head || ugcs?.length == 0) return;
32
+ return {
33
+ zones: ugcs,
34
+ locations: areas,
35
+ expires: expires
36
+ }
37
+ }
@@ -0,0 +1,30 @@
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 { regExp } from "../../@dictionaries/dictionaries.regExp"
21
+
22
+ export const getUGCHeader = (message: string): string | null => {
23
+ const start = message.search(regExp.ugc1)
24
+ const sub = message.substring(start)
25
+ const end = sub.search(regExp.ugc2)
26
+ const fin = sub.substring(0, end)
27
+ .replace(/\s+/g, '')
28
+ .slice(0, -1);
29
+ return fin ?? null
30
+ }
@@ -0,0 +1,29 @@
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
+ export const getLocations = async (zones: string[]): Promise<string[]> => {
23
+ const sites = Array.from(new Set(zones));
24
+ const placeholders = sites.map(() => '?').join(',');
25
+ const rows = await bootstrap.database
26
+ .prepare(`SELECT id, location FROM shapefiles WHERE id IN (${placeholders})`)
27
+ .all(...sites)
28
+ return rows.map((row: any) => row.location).sort();
29
+ }
@@ -0,0 +1,52 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ export const getZones = (header: string): string[] => {
21
+ const splits = header.split('-');
22
+ const zones: string[] = [];
23
+ let state = splits[0].substring(0, 2);
24
+ const format = splits[0].substring(2, 3);
25
+ for (const part of splits) {
26
+ if (/^[A-Z]/.test(part)) {
27
+ state = part.substring(0, 2);
28
+ if (part.includes('>')) {
29
+ const [start, end] = part.split('>');
30
+ const startNum = parseInt(start.substring(3), 10);
31
+ const endNum = parseInt(end, 10);
32
+ for (let j = startNum; j <= endNum; j++) {
33
+ zones.push(`${state}${format}${j.toString().padStart(3, '0')}`);
34
+ }
35
+ } else {
36
+ zones.push(part);
37
+ }
38
+ continue;
39
+ }
40
+ if (part.includes('>')) {
41
+ const [start, end] = part.split('>');
42
+ const startNum = parseInt(start, 10);
43
+ const endNum = parseInt(end, 10);
44
+ for (let j = startNum; j <= endNum; j++) {
45
+ zones.push(`${state}${format}${j.toString().padStart(3, '0')}`);
46
+ }
47
+ } else {
48
+ zones.push(`${state}${format}${part}`);
49
+ }
50
+ }
51
+ return zones.filter(item => item !== '');
52
+ }
@@ -0,0 +1,67 @@
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 as BaseTypeEventProperties } from "./type.properties";
21
+ import { TypeHVTEC } from "../@types/types.hvtec";
22
+ import { TypePVTEC } from "./types.pvtec";
23
+
24
+ export type TypeEvent = {
25
+ type: string
26
+ geometry: {
27
+ type: string
28
+ coordinates: number[][]
29
+ }
30
+ properties: {
31
+ event: string
32
+ parent: string
33
+ status: string
34
+ issued: string
35
+ expires: string
36
+ status_metadata?: {
37
+ is_issued?: boolean
38
+ is_updated?: boolean
39
+ is_expired?: boolean
40
+ is_test?: boolean
41
+ }
42
+ metadata: {
43
+ ms: number
44
+ source: string
45
+ tracking: string
46
+ hash?: string
47
+ header: string
48
+ vtec: TypePVTEC | null
49
+ hvtec: TypeHVTEC[]
50
+ nodes?: {
51
+ id?: string | number
52
+ coordinates: [number, number]
53
+ nearest: [number, number]
54
+ miles: number | null
55
+ kilometers: number | null
56
+ proximity: boolean
57
+ }[],
58
+ filtered_proximity?: boolean
59
+ updated?: number
60
+ history: {
61
+ description: string
62
+ issued: string
63
+ status: string
64
+ }[]
65
+ }
66
+ } & BaseTypeEventProperties
67
+ }
@@ -0,0 +1,75 @@
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.attributes";
21
+
22
+ export type TypeEventProperties = {
23
+ locations: string
24
+ description: string
25
+ attributes: TypeAttributes
26
+ geocode: {
27
+ office: {
28
+ name: string
29
+ office: string
30
+ }
31
+ organization: string
32
+ ugc: string[]
33
+ polygon: string
34
+ polygon_generated: boolean
35
+ }
36
+ parameters: {
37
+ tags: string[]
38
+ instructions: string
39
+ source: string
40
+ hazards: string
41
+ impacts: string
42
+ estimated_hail_size: string
43
+ estimated_wind_gusts: string
44
+ damage_threat: string
45
+ tornado_threat: string
46
+ flood_threat: string
47
+ wind_threat: string
48
+ hail_threat: string
49
+ max_hail_inches?: string
50
+ max_wind_gusts_surface_knots?: string
51
+ max_tops_x100feet?: string
52
+ mean_storm_motion_vector?: string
53
+ particularly_dangerous_situation?: string
54
+ }
55
+ watch_parameters?: {
56
+ watch_number: string
57
+ watch_type: string
58
+ additional_tornadoes_probability: string
59
+ strong_tornadoes_probability: string
60
+ severe_wind_probability: string
61
+ severe_hail_probability: string
62
+ hail_2in_probability: string
63
+ combined_hail_wind_probability: string
64
+ max_hail_in: string
65
+ max_wind_surface: string
66
+ max_tops_x100feet: string
67
+ pds_watch: boolean
68
+ }
69
+ spc_parameters: {
70
+ spc_max_tornado: string
71
+ spc_max_hail: string
72
+ spc_max_wind: string
73
+ spc_watch_issuance: string
74
+ }
75
+ }
@@ -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: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Internal Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+
21
+ export type TypeAttributes = {
22
+ xmlns: string
23
+ id: string
24
+ issue: string
25
+ ttaaii: string
26
+ cccc: string
27
+ awipsid: string
28
+ }
@@ -0,0 +1,35 @@
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.attributes"
21
+
22
+ export type TypeStanzaCompiled = {
23
+ message?: string
24
+ attributes?: TypeAttributes
25
+ isCapEvent?: boolean
26
+ isVTEC?: boolean
27
+ isUGC?: boolean
28
+ isCapAreaDescription?: boolean
29
+ isIgnored?: boolean
30
+ isNWWS?: boolean
31
+ getType?: {
32
+ type: string
33
+ prefix: string
34
+ }
35
+ }
@@ -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
+ export type TypeHash = {
21
+ tracking: string
22
+ hashes: string[]
23
+ expires: string
24
+ }