@atmosx/event-product-parser 3.0.4 → 3.0.7

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 (212) hide show
  1. package/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +1 -1
  2. package/.github/SUPPORTED_EVENTS.md +370 -0
  3. package/.github/docs/docs-functions.md +30 -0
  4. package/.github/docs/docs-general-configurations.md +199 -0
  5. package/.github/docs/docs-integrations.md +38 -0
  6. package/.github/docs/docs-listeners.md +28 -0
  7. package/.github/docs/docs-source-configuration.md +218 -0
  8. package/.github/docs/docs-technical.md +50 -0
  9. package/.github/logo.png +0 -0
  10. package/.github/samples/SAMPLE_EAS_GENERATION.wav +0 -0
  11. package/.github/samples/SAMPLE_GEOJSON.json +204 -0
  12. package/.github/samples/SAMPLE_TEXT_PRODUCT.txt +119 -0
  13. package/README.md +157 -337
  14. package/dist/cjs/index.cjs +24125 -15815
  15. package/dist/esm/index.mjs +24144 -15839
  16. package/package.json +56 -53
  17. package/pnpm-workspace.yaml +4 -0
  18. package/src/bootstrap.ts +83 -43
  19. package/src/building/CreateEvent.ts +54 -0
  20. package/src/{@building/building.clean.ts → building/GetCleanedEvent.ts} +4 -4
  21. package/src/building/GetEventAttachments.ts +88 -0
  22. package/src/building/GetEventDirection.ts +28 -0
  23. package/src/{@building/building.enhance.ts → building/GetEventEnhancedName.ts} +13 -17
  24. package/src/{@building/building.geometry.ts → building/GetEventGeometry.ts} +19 -13
  25. package/src/{@building/building.headers.ts → building/GetEventHeader.ts} +13 -13
  26. package/src/{@building/building.polygon.ts → building/GetEventNodes.ts} +26 -22
  27. package/src/{@building/building.office.ts → building/GetEventOffice.ts} +14 -14
  28. package/src/building/GetEventProperties.ts +105 -0
  29. package/src/{@building/building.signature.ts → building/GetEventSignature.ts} +16 -17
  30. package/src/{@core/core.createListener.ts → building/GetEventTags.ts} +11 -6
  31. package/src/building/GetEventTheme.ts +26 -0
  32. package/src/building/GetEventTracking.ts +64 -0
  33. package/src/components/audio/GenerateAudioMessage.ts +149 -0
  34. package/src/components/audio/components/GetCleanDescription.ts +91 -0
  35. package/src/{@modules/@eas/eas.getFloatPCM16.ts → components/audio/components/GetFloatPCM16.ts} +3 -3
  36. package/src/{@modules/@eas/eas.getMergedPCM16.ts → components/audio/components/GetMergedPCM16.ts} +3 -3
  37. package/src/{@modules/@eas/eas.getPCM16.ts → components/audio/components/GetPCM16.ts} +13 -8
  38. package/src/{@modules/@eas/eas.getPCMToFloat.ts → components/audio/components/GetPCMToFloat.ts} +3 -3
  39. package/src/{@modules/@eas/eas.getSampledPCM16.ts → components/audio/components/GetSampledPCM16.ts} +14 -8
  40. package/src/components/audio/components/GetTTS.ts +61 -0
  41. package/src/{@modules/@eas/eas.getWavPCM16.ts → components/audio/components/GetWavPCM16.ts} +8 -8
  42. package/src/{@modules/@eas/eas.setAFSK.ts → components/audio/components/SetAFSK.ts} +12 -8
  43. package/src/{@modules/@eas/eas.setAsciiToBits.ts → components/audio/components/SetAsciiToBits.ts} +3 -4
  44. package/src/{@modules/@eas/eas.setAttentionTone.ts → components/audio/components/SetAttentionTone.ts} +11 -6
  45. package/src/{@modules/@eas/eas.setNoise.ts → components/audio/components/SetNoise.ts} +14 -8
  46. package/src/{@modules/@eas/eas.setRadioEffect.ts → components/audio/components/SetRadioEffect.ts} +14 -8
  47. package/src/{@modules/@eas/eas.setSameHeader.ts → components/audio/components/SetSameHeader.ts} +22 -15
  48. package/src/{@modules/@utilities/utilities.setWarning.ts → components/database/CreateQuery.ts} +18 -13
  49. package/src/{@modules/@database/database.cache.ts → components/database/GetCachedEvents.ts} +19 -14
  50. package/src/components/database/ImportBoundaries.ts +168 -0
  51. package/src/components/database/ImportBroadcastify.ts +60 -0
  52. package/src/components/database/ImportCities.ts +87 -0
  53. package/src/{@modules/@database/database.shapefiles.ts → components/database/ImportShapefiles.ts} +31 -37
  54. package/src/components/database/ImportStanza.ts +43 -0
  55. package/src/components/database/InitializeDatabase.ts +71 -0
  56. package/src/components/images/GenerateGraphic.ts +234 -0
  57. package/src/components/images/components/CreateRectangle.ts +22 -0
  58. package/src/components/images/components/CreateText.ts +22 -0
  59. package/src/components/images/modules/CreateSVG.ts +37 -0
  60. package/src/components/images/modules/GetGeographicalBoundaries.ts +72 -0
  61. package/src/components/images/modules/GetGeographicalCities.ts +58 -0
  62. package/src/components/images/modules/GetGeographicalEvents.ts +48 -0
  63. package/src/components/images/modules/GetGeometryBounds.ts +82 -0
  64. package/src/components/images/modules/GetParsedBoundary.ts +58 -0
  65. package/src/components/images/modules/GetSVGPath.ts +53 -0
  66. package/src/components/images/modules/NormalizePolygon.ts +57 -0
  67. package/src/{@modules/@stanza/stanza.getAwipsType.ts → components/stanza/GetAwipsType.ts} +19 -18
  68. package/src/components/stanza/ValidateStanza.ts +62 -0
  69. package/src/components/utilities/CreateHttp.ts +83 -0
  70. package/src/{@modules/@utilities/utilities.getFormattedTime.ts → components/utilities/GetFormattedTime.ts} +3 -3
  71. package/src/components/utilities/GetLatestIssuance.ts +32 -0
  72. package/src/components/utilities/GetMatched.ts +38 -0
  73. package/src/{@modules/@utilities/utilities.getShapeNearestPoint.ts → components/utilities/GetShapeNearestPoint.ts} +24 -19
  74. package/src/components/utilities/GetUnionPolygon.ts +36 -0
  75. package/src/components/utilities/QueueManager.ts +70 -0
  76. package/src/components/utilities/SetCronSchedule.ts +98 -0
  77. package/src/{@core/core.clearEvents.ts → components/utilities/SetDebug.ts} +17 -12
  78. package/src/components/utilities/SetEventEmit.ts +42 -0
  79. package/src/{@modules/@utilities/utilities.setSettings.ts → components/utilities/SetSettings.ts} +7 -7
  80. package/src/{@modules/@utilities/utilities.setSleep.ts → components/utilities/SetSleep.ts} +5 -5
  81. package/src/components/utilities/SetTimeoutAction.ts +64 -0
  82. package/src/components/utilities/SetWarning.ts +47 -0
  83. package/src/{@modules/@xmpp/xmpp.xDeploy.ts → components/xmpp/DeployXMPP.ts} +26 -27
  84. package/src/components/xmpp/ErrorXMPP.ts +27 -0
  85. package/src/{@modules/@xmpp/xmpp.xError.ts → components/xmpp/OfflineXMPP.ts} +17 -9
  86. package/src/{@modules/@xmpp/xmpp.xOnline.ts → components/xmpp/OnlineXMPP.ts} +21 -20
  87. package/src/components/xmpp/ReconnectXMPP.ts +64 -0
  88. package/src/components/xmpp/StanzaXMPP.ts +63 -0
  89. package/src/{@building/building.tags.ts → core/ClearEvents.ts} +12 -5
  90. package/src/{@core/core.getVersion.ts → core/GetEvents.ts} +5 -6
  91. package/src/core/GetNodes.ts +24 -0
  92. package/src/{@core/core.getNodes.ts → core/GetRandomEvent.ts} +5 -6
  93. package/src/core/GetVersion.ts +24 -0
  94. package/src/core/ManualEvent.ts +55 -0
  95. package/src/core/QueryStanza.ts +40 -0
  96. package/src/core/SetNode.ts +87 -0
  97. package/src/core/StartService.ts +62 -0
  98. package/src/core/StopService.ts +32 -0
  99. package/src/enums/AWIPS.ts +366 -0
  100. package/src/{@dictionaries/dictionaries.eventActions.ts → enums/Actions.ts} +3 -3
  101. package/src/{@dictionaries/dictionaries.eventCancelMessages.ts → enums/Cancellation.ts} +4 -3
  102. package/src/{@dictionaries/dictionaries.eventCauses.ts → enums/Causes.ts} +3 -3
  103. package/src/{@dictionaries/dictionaries.statusCorrelationText.ts → enums/Correlations.ts} +3 -3
  104. package/src/enums/Enhanced.ts +70 -0
  105. package/src/{@dictionaries/dictionaries.eventTypes.ts → enums/Events.ts} +3 -3
  106. package/src/{@dictionaries/dictionaries.regExp.ts → enums/Expressions.ts} +5 -4
  107. package/src/{@core/core.getEvents.ts → enums/GlobalFilter.ts} +7 -8
  108. package/src/{@dictionaries/dictionaries.hailStrings.ts → enums/Hail.ts} +9 -4
  109. package/src/{@dictionaries/dictionaries.officeICAOs.ts → enums/ICAO.ts} +5 -3
  110. package/src/enums/Matches.ts +60 -0
  111. package/src/{@dictionaries/dictionaries.eventProducts.ts → enums/Products.ts} +3 -3
  112. package/src/{@dictionaries/dictionaries.eventRecords.ts → enums/Records.ts} +3 -3
  113. package/src/{@dictionaries/dictionaries.eventSeverity.ts → enums/Severity.ts} +3 -3
  114. package/src/{@dictionaries/dictionaries.shapefileLinks.ts → enums/Shapefiles.ts} +3 -3
  115. package/src/enums/States.ts +136 -0
  116. package/src/{@dictionaries/dictionaries.eventStatus.ts → enums/Status.ts} +3 -3
  117. package/src/enums/Strings.ts +22 -0
  118. package/src/enums/Tags.ts +172 -0
  119. package/src/{@dictionaries/dictionaries.testSignatures.ts → enums/Testing.ts} +5 -4
  120. package/src/enums/Themes.ts +70 -0
  121. package/src/events/ParseAPI.ts +129 -0
  122. package/src/{@events/events.text.ts → events/ParseText.ts} +32 -23
  123. package/src/{@events/events.ugc.ts → events/ParseUGC.ts} +36 -26
  124. package/src/events/ParseVTEC.ts +88 -0
  125. package/src/index.ts +60 -38
  126. package/src/manager/MakeEvents.ts +110 -0
  127. package/src/manager/RemoveEvent.ts +74 -0
  128. package/src/{@manager/manager.setHash.ts → manager/SetHash.ts} +19 -15
  129. package/src/manager/UpdateEvents.ts +35 -0
  130. package/src/manager/UpdateNode.ts +62 -0
  131. package/src/manager/ValidateEvents.ts +144 -0
  132. package/src/{@parsers/@hvtec/hvtec.extract.ts → parsers/hvtec/HVExtract.ts} +13 -13
  133. package/src/parsers/text/GetDescriptionFromProduct.ts +59 -0
  134. package/src/parsers/text/GetEmbededText.ts +57 -0
  135. package/src/parsers/text/GetPolygonFromProduct.ts +71 -0
  136. package/src/parsers/text/GetStringText.ts +58 -0
  137. package/src/{@parsers/@text/text.getTextFromProduct.ts → parsers/text/GetTextFromProduct.ts} +12 -12
  138. package/src/parsers/ugc/GetCache.ts +24 -0
  139. package/src/{@parsers/@ugc/ugc.expiry.ts → parsers/ugc/GetExpiry.ts} +3 -3
  140. package/src/{@parsers/@ugc/ugc.header.ts → parsers/ugc/GetHeader.ts} +6 -6
  141. package/src/parsers/ugc/GetLocations.ts +57 -0
  142. package/src/parsers/ugc/GetZonePolygon.ts +73 -0
  143. package/src/{@parsers/@ugc/ugc.zones.ts → parsers/ugc/GetZones.ts} +3 -3
  144. package/src/{@modules/@utilities/utilities.setListener.ts → parsers/ugc/SetCache.ts} +13 -10
  145. package/src/{@parsers/@ugc/ugc.extract.ts → parsers/ugc/UGCExtract.ts} +15 -15
  146. package/src/{@parsers/@pvtec/pvtec.expires.ts → parsers/vtec/GetExpiry.ts} +3 -3
  147. package/src/parsers/vtec/VTECExtract.ts +49 -0
  148. package/src/{@types/types.attributes.ts → static/Attributes.ts} +2 -3
  149. package/src/{@types/type.event.ts → static/Event.ts} +11 -8
  150. package/src/{@types/type.properties.ts → static/Properties.ts} +17 -10
  151. package/src/{@types/types.stanza.ts → static/Stanza.ts} +2 -2
  152. package/src/tasks/CreateTasks.ts +123 -0
  153. package/src/{@core/core.stop.ts → tasks/TaskGenerateJSON.ts} +14 -12
  154. package/src/tasks/TaskGenerateText.ts +34 -0
  155. package/src/tasks/TaskSendNTFY.ts +97 -0
  156. package/src/tasks/TaskSendWebhook.ts +107 -0
  157. package/src/types/Actions.ts +37 -0
  158. package/src/{@types/types.hvtec.ts → types/HVTEC.ts} +6 -6
  159. package/src/{@types/types.hash.ts → types/Hash.ts} +5 -5
  160. package/src/types/Nodes.ts +29 -0
  161. package/src/{@types/types.settings.ts → types/Settings.ts} +42 -10
  162. package/src/{@types/types.compiled.ts → types/StanzaCompiled.ts} +15 -14
  163. package/src/{@types/types.ugc.ts → types/UGC.ts} +5 -5
  164. package/src/{@modules/@utilities/utilities.getSettings.ts → types/VTEC.ts} +12 -7
  165. package/tools/build.js +47 -0
  166. package/tsconfig.json +28 -1
  167. package/dist/index.d.mts +0 -239
  168. package/dist/index.d.ts +0 -239
  169. package/src/@building/building.create.ts +0 -42
  170. package/src/@building/building.properties.ts +0 -89
  171. package/src/@building/building.tracking.ts +0 -68
  172. package/src/@building/building.validate.ts +0 -147
  173. package/src/@core/core.getRandomEvent.ts +0 -25
  174. package/src/@core/core.setNode.ts +0 -81
  175. package/src/@core/core.start.ts +0 -61
  176. package/src/@dictionaries/dictionaries.betterEventNames.ts +0 -99
  177. package/src/@dictionaries/dictionaries.eventAwipAbreviations.ts +0 -364
  178. package/src/@dictionaries/dictionaries.eventTags.ts +0 -93
  179. package/src/@dictionaries/dictionaries.eventsMatchText.ts +0 -36
  180. package/src/@dictionaries/dictionaries.transcribedMessageReplacements.ts +0 -68
  181. package/src/@events/events.api.ts +0 -113
  182. package/src/@events/events.vtec.ts +0 -87
  183. package/src/@manager/manager.mkEvent.ts +0 -96
  184. package/src/@manager/manager.rmEvent.ts +0 -49
  185. package/src/@manager/manager.updateEvents.ts +0 -35
  186. package/src/@manager/manager.updateNodes.ts +0 -55
  187. package/src/@manager/manager.updateWebhooks.ts +0 -50
  188. package/src/@modules/@database/database.init.ts +0 -45
  189. package/src/@modules/@database/database.stanza.ts +0 -48
  190. package/src/@modules/@eas/eas.setEasTone.ts +0 -137
  191. package/src/@modules/@stanza/stanza.validate.ts +0 -50
  192. package/src/@modules/@utilities/utilities.createHttp.ts +0 -85
  193. package/src/@modules/@utilities/utilities.createWebhook.ts +0 -115
  194. package/src/@modules/@utilities/utilities.setCronSchedule.ts +0 -65
  195. package/src/@modules/@utilities/utilities.setEventEmit.ts +0 -41
  196. package/src/@modules/@utilities/utilities.setTimeoutAction.ts +0 -59
  197. package/src/@modules/@xmpp/xmpp.xOffline.ts +0 -38
  198. package/src/@modules/@xmpp/xmpp.xReconnect.ts +0 -64
  199. package/src/@modules/@xmpp/xmpp.xStanza.ts +0 -63
  200. package/src/@parsers/@pvtec/pvtec.extract.ts +0 -49
  201. package/src/@parsers/@text/text.getDescriptionFromProduct.ts +0 -53
  202. package/src/@parsers/@text/text.getPolygonFromProduct.ts +0 -32
  203. package/src/@parsers/@text/text.getXML.ts +0 -61
  204. package/src/@parsers/@ugc/ugc.coordinates.ts +0 -110
  205. package/src/@parsers/@ugc/ugc.locations.ts +0 -29
  206. package/src/@types/types.pvtec.ts +0 -30
  207. package/src/@types/types.webhook.ts +0 -27
  208. package/test.js +0 -91
  209. package/tsup.config.ts +0 -16
  210. /package/{CODE_OF_CONDUCT.md → .github/CODE_OF_CONDUCT.md} +0 -0
  211. /package/{LICENSE → .github/LICENSE} +0 -0
  212. /package/{SECURITY.md → .github/SECURITY.md} +0 -0
@@ -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: https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Independent Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ export const GetPolygonFromProduct = (message: string): number[][] => {
21
+ const coordinates: number[][] = [];
22
+ const match = message.match(
23
+ /LAT\.\.\.LON\s+([\s\S]*?)(?=\n\s*(?:TIME\.\.\.MOT\.\.\.LOC|\$\$|[A-Za-z]|$))/i
24
+ );
25
+ if (!match) return coordinates;
26
+ const text = match[1]
27
+ .split(/\r?\n/).map(l => l.trim())
28
+ .filter(l => l && !/[A-Za-z]/.test(l))
29
+ .join(' ').trim();
30
+ if (!text) return coordinates;
31
+ const values = text.match(/\d{4,8}/g);
32
+ if (!values || values.length === 0) return coordinates;
33
+ const points: { lat: number; lon: number }[] = [];
34
+ if (values.every(v => v.length === 8)) {
35
+ for (const value of values) {
36
+ const lat = parseInt(value.slice(0, 4), 10) / 100;
37
+ let lon = parseInt(value.slice(4, 8), 10) / 100;
38
+ if (lon < 20) lon += 100;
39
+ points.push({ lat, lon });
40
+ }
41
+ } else if (values.every(v => v.length === 4)) {
42
+ for (let i = 0; i + 1 < values.length; i += 2) {
43
+ const lat = parseInt(values[i], 10) / 100;
44
+ const lon = parseInt(values[i + 1], 10) / 100;
45
+ points.push({ lat, lon });
46
+ }
47
+ } else {
48
+ for (let i = 0; i + 1 < values.length; i += 2) {
49
+ const latStr = values[i];
50
+ const lonStr = values[i + 1];
51
+ if (latStr.length !== 4) continue;
52
+ if (lonStr.length < 4 || lonStr.length > 5) continue;
53
+ const lat = parseInt(latStr, 10) / 100;
54
+ let lon = parseInt(lonStr, 10) / 100;
55
+ points.push({ lat, lon });
56
+ }
57
+ }
58
+ if (points.length === 0) return coordinates;
59
+ const isEast = points.some(p => p.lon > 130 && p.lon < 180);
60
+ for (const p of points) {
61
+ const lon = isEast ? p.lon : -p.lon;
62
+ if (Number.isFinite(p.lat) && Number.isFinite(lon) && p.lat >= -90 && p.lat <= 90 && lon >= -180 && lon <= 180) {
63
+ coordinates.push([lon, p.lat]);
64
+ }
65
+ }
66
+ if (coordinates.length > 2 && (coordinates[0][0] !== coordinates[coordinates.length - 1][0] || coordinates[0][1] !== coordinates[coordinates.length - 1][1])) {
67
+ coordinates.push([...coordinates[0]]);
68
+ }
69
+
70
+ return coordinates;
71
+ };
@@ -0,0 +1,58 @@
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 "StaticTypes/Event"
21
+ import { TypeSettings } from "Types/Settings"
22
+ import { Bootstrap } from "@Bootstrap"
23
+
24
+ export const GetStringText = (event: TypeEvent): string => {
25
+ const timezone = Bootstrap.Settings.Timezone ?? `UTC`;
26
+ const line = (label: string, value: unknown, condition = true) => condition && value ? `${label} ${value}` : null;
27
+ const isStatement = event.properties.status_metadata.is_statement;
28
+ const isExpired = event.properties.status_metadata.is_expired;
29
+ return [
30
+ line(`Locations:`, event?.properties?.locations?.slice(0, 100)),
31
+ line(`Issued:`, `${new Date(event.properties.issued).toLocaleString([], { timeZone: timezone })} (${(timezone.replace(`America/`, ``))})`, !isExpired),
32
+ line(`Expires:`, `${new Date(event.properties.expires).toLocaleString([], { timeZone: timezone })} (${(timezone.replace(`America/`, ``))})`, !isStatement),
33
+ line(`Damage Threat:`, event?.properties?.parameters?.damage_threat, !isExpired),
34
+ line(`Flood Threat:`, event?.properties?.parameters?.flood_threat, !isExpired),
35
+ line(`Tornado Threat:`, event?.properties?.parameters?.tornado_threat, !isExpired),
36
+ line(`Wind Gusts:`, `${event?.properties?.parameters?.estimated_wind_gusts} ${event?.properties?.parameters?.wind_threat ? ` (${event?.properties?.parameters?.wind_threat})` : ''}`, !isExpired && event?.properties?.parameters?.estimated_wind_gusts != null),
37
+ line(`Hail Size:`, `${event?.properties?.parameters?.estimated_hail_size} ${event?.properties?.parameters?.hail_threat ? ` (${event?.properties?.parameters?.hail_threat})` : ''}`, !isExpired && event?.properties?.parameters?.estimated_hail_size != null),
38
+ line(`Direction:`, event?.properties?.parameters?.direction, !isExpired && event?.properties?.parameters?.direction != null),
39
+ line(`Discussion:`, event?.properties?.discussion_parameters?.discussion_number, !isExpired),
40
+ line(`Concern:`, event?.properties?.discussion_parameters?.discussion_concerning, !isExpired),
41
+ line(`SPC Max Tornado Threat:`, event?.properties?.discussion_parameters?.discussion_max_tornado, !isExpired),
42
+ line(`SPC Max Hail Threat:`, event?.properties?.discussion_parameters?.discussion_max_hail, !isExpired),
43
+ line(`SPC Max Wind Threat:`, event?.properties?.discussion_parameters?.discussion_max_wind, !isExpired),
44
+ line(`SPC Watch Issuance Probability:`, event?.properties?.discussion_parameters?.discussion_watch_issuance ? `${event?.properties?.discussion_parameters?.discussion_watch_issuance}%` : null, !isExpired),
45
+ line(`Watch Number:`, event?.properties?.watch_parameters?.watch_number, !isExpired),
46
+ line(`Strong Tornadoes Probability:`, event?.properties?.watch_parameters?.strong_tornadoes_probability ? `${event?.properties?.watch_parameters?.strong_tornadoes_probability}%` : null, !isExpired),
47
+ line(`Additional Tornadoes Probability:`, event?.properties?.watch_parameters?.additional_tornadoes_probability ? `${event?.properties?.watch_parameters?.additional_tornadoes_probability}%` : null, !isExpired),
48
+ line(`Combined Hail/Wind Probability:`, event?.properties?.watch_parameters?.combined_hail_wind_probability ? `${event?.properties?.watch_parameters?.combined_hail_wind_probability}%` : null, !isExpired),
49
+ line(`Severe Hail Probability:`, event?.properties?.watch_parameters?.severe_hail_probability ? `${event?.properties?.watch_parameters?.severe_hail_probability}%` : null, !isExpired),
50
+ line(`Hail >2in Probability:`, event?.properties?.watch_parameters?.hail_2in_probability ? `${event?.properties?.watch_parameters?.hail_2in_probability}%` : null, !isExpired),
51
+ line(`Max Hail Inches:`, event?.properties?.watch_parameters?.max_hail_in, !isExpired),
52
+ line(`Severe Wind Probability:`, event?.properties?.watch_parameters?.severe_wind_probability ? `${event?.properties?.watch_parameters?.severe_wind_probability}%` : null, !isExpired),
53
+ line(`Max Surface Wind:`, event?.properties?.watch_parameters?.max_wind_surface, !isExpired),
54
+ line(`Max Tops (x100 feet):`, event?.properties?.watch_parameters?.max_tops_x100feet, !isExpired),
55
+ line(`Sender:`, event?.properties?.geocode?.office?.name ? `${event?.properties?.geocode?.office?.name} (${event?.properties?.geocode?.office?.office})` : event?.properties?.geocode?.office?.office),
56
+ line(`Tracking:`, event?.properties?.metadata?.tracking),
57
+ ].filter(Boolean).join('\n');
58
+ }
@@ -11,32 +11,32 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
17
17
 
18
18
  */
19
19
 
20
20
  interface GetTextFromProductOptions {
21
- message: string
22
- find: string[]
23
- append?: string
24
- removal?: string[]
21
+ Message: string
22
+ Find: string[]
23
+ Append?: string
24
+ Removal?: string[]
25
25
  }
26
26
 
27
- export const getTextFromProduct = (options: GetTextFromProductOptions): string => {
28
- const lines = options.message.split(`\n`);
27
+ export const GetTextFromProduct = ({ Message, Find, Append, Removal }: GetTextFromProductOptions): string => {
28
+ const lines = Message.split(`\n`);
29
29
  for (const line of lines) {
30
- const matchedFind = options.find.find((find) => line.includes(find));
30
+ const matchedFind = Find.find((find) => line.includes(find));
31
31
  if (matchedFind) {
32
32
  let result = line.slice(line.indexOf(matchedFind) + matchedFind.length).trim();
33
- if (options.removal) {
34
- for (const str of options.removal) {
33
+ if (Removal) {
34
+ for (const str of Removal) {
35
35
  result = result.toLowerCase().split(str.toLowerCase()).join('');
36
36
  }
37
37
  result = result.replace(matchedFind, '').replace('<', '').trim();
38
38
  }
39
- return result.toUpperCase() + (options?.append ?? ``);
39
+ return result.toUpperCase() + (Append ?? ``);
40
40
  }
41
41
  }
42
42
  return null;
@@ -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: https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Independent Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { Bootstrap } from "@Bootstrap"
21
+
22
+ export const GetCache = (key: string) => {
23
+ return Bootstrap.Cache.UGC.get(key);
24
+ };
@@ -11,13 +11,13 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
17
17
 
18
18
  */
19
19
 
20
- export const getExpiry = (message: string): string | null => {
20
+ export const GetExpiry = (message: string): string | null => {
21
21
  const match = message.match(/\b(\d{6})-/);
22
22
  if (!match) {
23
23
  return null;
@@ -11,18 +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 { regExp } from "../../@dictionaries/dictionaries.regExp"
20
+ import { EnumExpressions } from "@Enums/Expressions"
21
21
 
22
- export const getUGCHeader = (message: string): string | null => {
23
- const start = message.search(regExp.ugc1)
22
+ export const GetHeader = (message: string): string | null => {
23
+ const start = message.search(EnumExpressions.ugc1)
24
24
  const sub = message.substring(start)
25
- const end = sub.search(regExp.ugc2)
25
+ const end = sub.search(EnumExpressions.ugc2)
26
26
  const fin = sub.substring(0, end)
27
27
  .replace(/\s+/g, '')
28
28
  .slice(0, -1);
@@ -0,0 +1,57 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Independent Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { Bootstrap } from "@Bootstrap"
21
+ import { GetCache } from "@ParsingUGC/GetCache"
22
+ import { SetCache } from "@ParsingUGC/SetCache"
23
+
24
+ export const GetLocations = async (zones: string[]): Promise<string[]> => {
25
+ const uniqueZones = Array.from(new Set(zones));
26
+
27
+ const results: string[] = [];
28
+ const missing: string[] = [];
29
+
30
+ for (let i = 0; i < uniqueZones.length; i++) {
31
+ const zone = uniqueZones[i];
32
+ const cached = GetCache(zone);
33
+
34
+ if (cached) {
35
+ for (let j = 0; j < cached.length; j++) {
36
+ results.push(cached[j]);
37
+ }
38
+ } else {
39
+ missing.push(zone);
40
+ }
41
+ }
42
+
43
+ if (missing.length > 0) {
44
+ const rows = await Bootstrap.Database
45
+ .prepare(
46
+ `SELECT id, location FROM shapefiles WHERE id IN (${missing.map(() => '?').join(',')})`
47
+ )
48
+ .all(...missing);
49
+
50
+ for (let i = 0; i < rows.length; i++) {
51
+ const r = rows[i] as any;
52
+ SetCache({ Key: r.id, Value: [r.location] });
53
+ results.push(r.location);
54
+ }
55
+ }
56
+ return Array.from(new Set(results));
57
+ };
@@ -0,0 +1,73 @@
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 { CreateQuery } from "@Database/CreateQuery"
21
+ import { GetUnionPolygon } from "@Utilities/GetUnionPolygon"
22
+ import { createHash } from "crypto";
23
+
24
+ interface CoordinatesOptions {
25
+ Zones: string[]
26
+ Union: boolean
27
+ }
28
+
29
+ interface CoordinatesResponse {
30
+ type: `Polygon` | `MultiPolygon`
31
+ coordinates: any[]
32
+ }
33
+
34
+ export const GetZonePolygon = ({ Zones, Union }: CoordinatesOptions): CoordinatesResponse | null => {
35
+ const list = [...new Set(Zones.map(z => z.trim()))].filter(z => z === 'XX000' ? false : true);
36
+ if (list.length === 0) return null;
37
+
38
+ const placeholders = list.map(() => "?").join(",");
39
+ const rows = CreateQuery({
40
+ Query: `SELECT geometry FROM shapefiles WHERE id IN (${placeholders})`,
41
+ Parameters: list
42
+ });
43
+ const polygons: any[] = [];
44
+ const geometryHashes = new Set<string>();
45
+ for (const row of rows) {
46
+ if (!row?.geometry) continue;
47
+ const geometryHash = createHash("sha256").update(row.geometry).digest("hex");
48
+ if (geometryHashes.has(geometryHash)) continue;
49
+ geometryHashes.add(geometryHash);
50
+ const geom = JSON.parse(row.geometry);
51
+ if (geom?.type === "Polygon") {
52
+ polygons.push(geom.coordinates);
53
+ }
54
+ if (geom?.type === "MultiPolygon") {
55
+ for (const poly of geom.coordinates) {
56
+ polygons.push(poly);
57
+ }
58
+ }
59
+ }
60
+ if (polygons.length === 0) return null;
61
+ if (Union) {
62
+ return GetUnionPolygon({ Polygons: polygons });
63
+ } else {
64
+ const multi: any[] = [];
65
+ for (const polyCoords of polygons) {
66
+ if (Array.isArray(polyCoords) && Array.isArray(polyCoords[0])) {
67
+ multi.push(polyCoords);
68
+ }
69
+ }
70
+ if (multi.length === 0) return null;
71
+ return {type: "MultiPolygon", coordinates: multi};
72
+ }
73
+ }
@@ -11,13 +11,13 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
17
17
 
18
18
  */
19
19
 
20
- export const getZones = (header: string): string[] => {
20
+ export const GetZones = (header: string): string[] => {
21
21
  const splits = header.split('-');
22
22
  const zones: string[] = [];
23
23
  let state = splits[0].substring(0, 2);
@@ -11,20 +11,23 @@
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 { bootstrap } from "../../bootstrap"
20
+ import { Bootstrap } from "@Bootstrap"
21
21
 
22
- interface SetListenerOptions {
23
- event: string,
24
- callback: () => void
22
+ interface SetCacheOptions {
23
+ Key: string
24
+ Value: string[]
25
25
  }
26
26
 
27
- export const setListener = (options: SetListenerOptions): (() => void) => {
28
- bootstrap.listener.on(options.event, options.callback)
29
- return () => { void bootstrap.listener.off(options.event, options.callback) };
30
- }
27
+ export const SetCache = ({ Key, Value }: SetCacheOptions) => {
28
+ if (Bootstrap.Cache.UGC.size >= 5000) {
29
+ const firstKey = Bootstrap.Cache.UGC.keys().next().value;
30
+ Bootstrap.Cache.UGC.delete(firstKey);
31
+ }
32
+ Bootstrap.Cache.UGC.set(Key, Value);
33
+ };
@@ -11,27 +11,27 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
17
17
 
18
18
  */
19
19
 
20
- import { 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";
20
+ import { TypeUGC } from "Types/UGC"
21
+ import { GetHeader } from "@ParsingUGC/GetHeader"
22
+ import { GetZones } from "@ParsingUGC/GetZones"
23
+ import { GetExpiry } from "@ParsingUGC/GetExpiry"
24
+ import { GetLocations } from "@ParsingUGC/GetLocations"
25
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)
26
+ export const UGCExtract = async (message: string): Promise<TypeUGC> => {
27
+ const expires = GetExpiry(message)
28
+ const head = GetHeader(message);
29
+ const ugcs = GetZones(head);
30
+ const areas = await GetLocations(ugcs)
31
31
  if (!head || ugcs?.length == 0) return;
32
32
  return {
33
- zones: ugcs,
34
- locations: areas,
35
- expires: expires
33
+ Zones: ugcs,
34
+ Locations: areas,
35
+ Expires: expires
36
36
  }
37
37
  }
@@ -11,13 +11,13 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
17
17
 
18
18
  */
19
19
 
20
- export const getExpiry = (dates: string[]): string => {
20
+ export const GetExpiry = (dates: string[]): string => {
21
21
  if (dates?.[1] == `000000T0000Z`) return 'Invalid Date Format'
22
22
  const expires = `${new Date().getFullYear().toString().substring(0, 2)}${dates[1].substring(0, 2)}-${dates[1].substring(2, 4)}-${dates[1].substring(4, 6)}T${dates[1].substring(7, 9)}:${dates[1].substring(9, 11)}:00`;
23
23
  const local = new Date(new Date(expires).getTime() - 4 * 60 * 60000);
@@ -0,0 +1,49 @@
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 { TypeVTEC } from "Types/VTEC"
21
+ import { EnumExpressions } from "@Enums/Expressions"
22
+ import { EnumProducts } from "@Enums/Products"
23
+ import { EnumEvents } from "@Enums/Events"
24
+ import { EnumActions } from "@Enums/Actions"
25
+ import { EnumStatus } from "@Enums/Status"
26
+ import { GetExpiry } from "@ParsingVTEC/GetExpiry"
27
+
28
+ export const VTECExtract = (message: string): TypeVTEC[] | null => {
29
+ if (!message) return null;
30
+ const getVTECs = message.match(EnumExpressions.vtec) ?? [];
31
+ const vtecs: TypeVTEC[] = [];
32
+ for (const vtec of getVTECs) {
33
+ const sub = vtec.split(`.`);
34
+ if (sub?.length < 7) continue;
35
+ const dates = sub[6]?.split(`-`);
36
+ vtecs.push({
37
+ Raw: vtec,
38
+ ProductType: EnumProducts[sub[0]],
39
+ Tracking: `${sub[2]}.${sub[3]}.${sub[4]}.${sub[5]}`,
40
+ Event: `${EnumEvents[sub[3]]} ${EnumActions[sub[4]]}`,
41
+ Status: EnumStatus[sub[1]],
42
+ WMO: message.match(EnumExpressions.wmo)?.[0] ?? null,
43
+ Expires: GetExpiry(dates),
44
+ Watch: (sub[4] == `A` || sub[4] == `Y`) && (sub[3] == `TO` || sub[3] == `SV`),
45
+ PredictionCenter: sub[2] == `KWNS` ? true : false
46
+ })
47
+ }
48
+ return vtecs.length > 0 ? vtecs : null;
49
+ }
@@ -11,13 +11,12 @@
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
-
21
20
  export type TypeAttributes = {
22
21
  xmlns: string
23
22
  id: string
@@ -11,20 +11,20 @@
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 { TypeEventProperties as BaseTypeEventProperties } from "./type.properties";
21
- import { TypeHVTEC } from "../@types/types.hvtec";
22
- import { TypePVTEC } from "./types.pvtec";
20
+ import { TypeEventProperties as BaseTypeEventProperties } from "StaticTypes/Properties"
21
+ import { TypeHVTEC } from "Types/HVTEC"
22
+ import { TypeVTEC } from "Types/VTEC"
23
23
 
24
24
  export type TypeEvent = {
25
25
  type: string
26
26
  geometry: {
27
- type: string
27
+ type: "Polygon" | "MultiPolygon"
28
28
  coordinates: number[][]
29
29
  }
30
30
  properties: {
@@ -33,6 +33,7 @@ export type TypeEvent = {
33
33
  status: string
34
34
  issued: string
35
35
  expires: string
36
+ theme: string
36
37
  status_metadata?: {
37
38
  is_issued?: boolean
38
39
  is_updated?: boolean
@@ -46,8 +47,8 @@ export type TypeEvent = {
46
47
  tracking: string
47
48
  hash?: string
48
49
  header: string
49
- vtec: TypePVTEC | null
50
- hvtec: TypeHVTEC[]
50
+ vtec?: TypeVTEC | null
51
+ hvtec?: TypeHVTEC[] | null
51
52
  nodes?: {
52
53
  id?: string | number
53
54
  coordinates: [number, number]
@@ -63,6 +64,8 @@ export type TypeEvent = {
63
64
  issued: string
64
65
  status: string
65
66
  }[]
67
+ attachments?: { name: string; link: string }[]
68
+ raw: string
66
69
  }
67
70
  } & BaseTypeEventProperties
68
71
  }