@atmosx/event-product-parser 3.0.42 → 3.0.46

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 (87) hide show
  1. package/README.md +70 -22
  2. package/SUPPORTED_EVENTS.md +369 -0
  3. package/dist/cjs/index.cjs +1990 -1758
  4. package/dist/esm/index.mjs +1560 -1329
  5. package/dist/index.d.mts +44 -20
  6. package/dist/index.d.ts +44 -20
  7. package/package.json +1 -1
  8. package/src/@building/building.attachments.ts +42 -0
  9. package/src/@building/building.create.ts +2 -2
  10. package/src/@building/building.enhance.ts +8 -4
  11. package/src/@building/building.geometry.ts +1 -1
  12. package/src/@building/building.headers.ts +1 -1
  13. package/src/@building/building.office.ts +4 -4
  14. package/src/@building/building.properties.ts +15 -13
  15. package/src/@building/building.signature.ts +11 -11
  16. package/src/@building/building.tags.ts +2 -2
  17. package/src/@building/building.tracking.ts +6 -6
  18. package/src/@building/building.validate.ts +5 -3
  19. package/src/@core/core.createEvent.ts +82 -0
  20. package/src/@core/core.query.ts +1 -1
  21. package/src/@core/core.start.ts +1 -1
  22. package/src/@dictionaries/{dictionaries.eventActions.ts → dictionaries.actions.ts} +1 -1
  23. package/src/@dictionaries/{dictionaries.eventAwipAbreviations.ts → dictionaries.awips.ts} +1 -1
  24. package/src/@dictionaries/{dictionaries.eventCancelMessages.ts → dictionaries.cancellation.ts} +1 -1
  25. package/src/@dictionaries/{dictionaries.eventCauses.ts → dictionaries.causes.ts} +1 -1
  26. package/src/@dictionaries/{dictionaries.statusCorrelationText.ts → dictionaries.correlations.ts} +1 -1
  27. package/src/@dictionaries/{dictionaries.betterEventNames.ts → dictionaries.enhanced.ts} +13 -2
  28. package/src/@dictionaries/{dictionaries.eventTypes.ts → dictionaries.events.ts} +1 -1
  29. package/src/@dictionaries/{dictionaries.regExp.ts → dictionaries.expressions.ts} +1 -1
  30. package/src/@dictionaries/{dictionaries.hailStrings.ts → dictionaries.hail.ts} +4 -1
  31. package/src/@dictionaries/{dictionaries.officeICAOs.ts → dictionaries.icao.ts} +1 -1
  32. package/src/@dictionaries/{dictionaries.eventsMatchText.ts → dictionaries.matches.ts} +1 -1
  33. package/src/@dictionaries/{dictionaries.eventProducts.ts → dictionaries.products.ts} +1 -1
  34. package/src/@dictionaries/{dictionaries.eventRecords.ts → dictionaries.records.ts} +1 -1
  35. package/src/@dictionaries/{dictionaries.eventSeverity.ts → dictionaries.severity.ts} +1 -1
  36. package/src/@dictionaries/{dictionaries.shapefileLinks.ts → dictionaries.shapefiles.ts} +1 -1
  37. package/src/@dictionaries/{dictionaries.eventStatus.ts → dictionaries.status.ts} +1 -1
  38. package/src/@dictionaries/{dictionaries.eventTags.ts → dictionaries.tags.ts} +1 -1
  39. package/src/@dictionaries/{dictionaries.testSignatures.ts → dictionaries.test.ts} +3 -2
  40. package/src/@events/events.api.ts +19 -14
  41. package/src/@events/events.text.ts +5 -4
  42. package/src/@events/events.ugc.ts +5 -4
  43. package/src/@events/events.vtec.ts +5 -4
  44. package/src/@manager/manager.mkEvent.ts +4 -4
  45. package/src/@manager/manager.rmEvent.ts +3 -2
  46. package/src/@manager/manager.setHash.ts +1 -1
  47. package/src/@manager/manager.updateListener.ts +124 -0
  48. package/src/@modules/@database/database.cache.ts +1 -1
  49. package/src/@modules/@database/database.init.ts +1 -1
  50. package/src/@modules/@database/database.shapefiles.ts +3 -3
  51. package/src/@modules/@database/database.stanza.ts +2 -2
  52. package/src/@modules/@eas/eas.getCleanDescription.ts +91 -0
  53. package/src/@modules/@eas/eas.getTTS.ts +54 -0
  54. package/src/@modules/@eas/eas.setEasTone.ts +40 -30
  55. package/src/@modules/@stanza/stanza.getAwipsType.ts +3 -3
  56. package/src/@modules/@stanza/stanza.validate.ts +5 -5
  57. package/src/@modules/@utilities/utilities.getLatestIssuance.ts +32 -0
  58. package/src/@modules/@utilities/utilities.getSettings.ts +1 -1
  59. package/src/@modules/@utilities/utilities.setCronSchedule.ts +30 -2
  60. package/src/@modules/@utilities/utilities.setSettings.ts +1 -1
  61. package/src/@modules/@utilities/utilities.setWarning.ts +1 -1
  62. package/src/@modules/@xmpp/xmpp.xDeploy.ts +1 -1
  63. package/src/@modules/@xmpp/xmpp.xReconnect.ts +1 -1
  64. package/src/@modules/@xmpp/xmpp.xStanza.ts +1 -1
  65. package/src/@parsers/@hvtec/hvtec.extract.ts +9 -9
  66. package/src/@parsers/@pvtec/pvtec.extract.ts +13 -13
  67. package/src/@parsers/@text/text.getDescriptionFromProduct.ts +2 -2
  68. package/src/@parsers/@text/text.getEmbed.ts +60 -0
  69. package/src/@parsers/@ugc/ugc.extract.ts +1 -1
  70. package/src/@parsers/@ugc/ugc.header.ts +3 -3
  71. package/src/@types/{types.compiled.ts → type.compiled.ts} +1 -1
  72. package/src/@types/type.event.ts +6 -4
  73. package/src/@types/{types.webhook.ts → type.listener.ts} +11 -6
  74. package/src/@types/type.properties.ts +10 -8
  75. package/src/@types/{types.settings.ts → type.settings.ts} +7 -5
  76. package/src/bootstrap.ts +7 -5
  77. package/src/index.ts +3 -2
  78. package/test.js +19 -19
  79. package/src/@dictionaries/dictionaries.transcribedMessageReplacements.ts +0 -68
  80. package/src/@manager/manager.createWebhook.ts +0 -117
  81. package/src/@manager/manager.updateWebhooks.ts +0 -49
  82. /package/src/@types/{types.attributes.ts → type.attributes.ts} +0 -0
  83. /package/src/@types/{types.hash.ts → type.hash.ts} +0 -0
  84. /package/src/@types/{types.hvtec.ts → type.hvtec.ts} +0 -0
  85. /package/src/@types/{types.pvtec.ts → type.pvtec.ts} +0 -0
  86. /package/src/@types/{types.stanza.ts → type.stanza.ts} +0 -0
  87. /package/src/@types/{types.ugc.ts → type.ugc.ts} +0 -0
package/dist/index.d.mts CHANGED
@@ -1,10 +1,16 @@
1
- type TypeWebhook = {
2
- webhook: string;
3
- title: string;
4
- message: string;
5
- upload: boolean;
6
- rate: number;
1
+ type TypeListener = {
7
2
  events: string[];
3
+ webhook?: {
4
+ enabled: boolean;
5
+ destination: string;
6
+ ratelimit: number;
7
+ title: string;
8
+ message: string;
9
+ };
10
+ uploads?: {
11
+ file?: boolean;
12
+ eas?: boolean;
13
+ };
8
14
  };
9
15
 
10
16
  type TypeSettings = {
@@ -45,7 +51,7 @@ type TypeSettings = {
45
51
  ShapefileSkipPoints: number;
46
52
  NodeTTL: number;
47
53
  NodeMinDistance: number;
48
- WebhookSettings?: TypeWebhook;
54
+ ListenerSettings?: TypeListener[];
49
55
  EventFiltering: {
50
56
  ListeningEvents: string[];
51
57
  ListeningICAO: string[];
@@ -56,9 +62,11 @@ type TypeSettings = {
56
62
  NodeLocationFiltering: boolean;
57
63
  IgnoreTestProducts: boolean;
58
64
  };
59
- EASSettings: {
60
- ArchiveDirectory: string;
61
- IntroWavFile: string;
65
+ ArchiveSettings: {
66
+ TTL: number;
67
+ TextDirectory: string;
68
+ EasDirectory: string;
69
+ EasToneout: string;
62
70
  };
63
71
  };
64
72
  };
@@ -77,7 +85,7 @@ type TypeAttributes = {
77
85
  type TypeEventProperties = {
78
86
  locations: string;
79
87
  description: string;
80
- attributes: TypeAttributes;
88
+ attributes?: TypeAttributes;
81
89
  geocode: {
82
90
  office: {
83
91
  name: string;
@@ -88,7 +96,7 @@ type TypeEventProperties = {
88
96
  polygon: string;
89
97
  polygon_generated: boolean;
90
98
  };
91
- parameters: {
99
+ parameters?: {
92
100
  tags: string[];
93
101
  instructions: string;
94
102
  source: string;
@@ -121,11 +129,13 @@ type TypeEventProperties = {
121
129
  max_tops_x100feet: string;
122
130
  pds_watch: boolean;
123
131
  };
124
- spc_parameters: {
125
- spc_max_tornado: string;
126
- spc_max_hail: string;
127
- spc_max_wind: string;
128
- spc_watch_issuance: string;
132
+ discussion_parameters?: {
133
+ discussion_number: string;
134
+ discussion_concerning: string;
135
+ discussion_max_tornado: string;
136
+ discussion_max_hail: string;
137
+ discussion_max_wind: string;
138
+ discussion_watch_issuance: string;
129
139
  };
130
140
  };
131
141
 
@@ -173,8 +183,8 @@ type TypeEvent = {
173
183
  tracking: string;
174
184
  hash?: string;
175
185
  header: string;
176
- vtec: TypePVTEC | null;
177
- hvtec: TypeHVTEC[];
186
+ vtec?: TypePVTEC | null;
187
+ hvtec?: TypeHVTEC[] | null;
178
188
  nodes?: {
179
189
  id?: string | number;
180
190
  coordinates: [number, number];
@@ -190,6 +200,8 @@ type TypeEvent = {
190
200
  issued: string;
191
201
  status: string;
192
202
  }[];
203
+ attachments?: string[];
204
+ raw: string;
193
205
  };
194
206
  } & TypeEventProperties;
195
207
  };
@@ -209,6 +221,7 @@ declare const stopService: () => Promise<void>;
209
221
  interface GenerateEASOptions {
210
222
  message: string;
211
223
  header: string;
224
+ title: string;
212
225
  }
213
226
  declare const setEasTone: (options: GenerateEASOptions) => Promise<string>;
214
227
 
@@ -226,6 +239,17 @@ declare const getEvents: () => any;
226
239
 
227
240
  declare const getNodes: () => any;
228
241
 
242
+ interface CreateEventOptions {
243
+ event: string;
244
+ status: string;
245
+ issued: Date;
246
+ expires: Date;
247
+ locations: string;
248
+ description: string;
249
+ coordinates: number[][];
250
+ }
251
+ declare const createEvent: (options: CreateEventOptions) => void;
252
+
229
253
  declare const getRandomEvent: () => any;
230
254
 
231
255
  type TypeStanza = {
@@ -261,4 +285,4 @@ declare class Manager {
261
285
  trycatch(): void;
262
286
  }
263
287
 
264
- export { Manager, type TypeEvent, clearEvents, Manager as default, getCleanedEvent, getEventGeometry, getEvents, getNodes, getRandomEvent, query, setEasTone, setNode, setSettings, startService, stopService };
288
+ export { Manager, type TypeEvent, clearEvents, createEvent, Manager as default, getCleanedEvent, getEventGeometry, getEvents, getNodes, getRandomEvent, query, setEasTone, setNode, setSettings, startService, stopService };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,16 @@
1
- type TypeWebhook = {
2
- webhook: string;
3
- title: string;
4
- message: string;
5
- upload: boolean;
6
- rate: number;
1
+ type TypeListener = {
7
2
  events: string[];
3
+ webhook?: {
4
+ enabled: boolean;
5
+ destination: string;
6
+ ratelimit: number;
7
+ title: string;
8
+ message: string;
9
+ };
10
+ uploads?: {
11
+ file?: boolean;
12
+ eas?: boolean;
13
+ };
8
14
  };
9
15
 
10
16
  type TypeSettings = {
@@ -45,7 +51,7 @@ type TypeSettings = {
45
51
  ShapefileSkipPoints: number;
46
52
  NodeTTL: number;
47
53
  NodeMinDistance: number;
48
- WebhookSettings?: TypeWebhook;
54
+ ListenerSettings?: TypeListener[];
49
55
  EventFiltering: {
50
56
  ListeningEvents: string[];
51
57
  ListeningICAO: string[];
@@ -56,9 +62,11 @@ type TypeSettings = {
56
62
  NodeLocationFiltering: boolean;
57
63
  IgnoreTestProducts: boolean;
58
64
  };
59
- EASSettings: {
60
- ArchiveDirectory: string;
61
- IntroWavFile: string;
65
+ ArchiveSettings: {
66
+ TTL: number;
67
+ TextDirectory: string;
68
+ EasDirectory: string;
69
+ EasToneout: string;
62
70
  };
63
71
  };
64
72
  };
@@ -77,7 +85,7 @@ type TypeAttributes = {
77
85
  type TypeEventProperties = {
78
86
  locations: string;
79
87
  description: string;
80
- attributes: TypeAttributes;
88
+ attributes?: TypeAttributes;
81
89
  geocode: {
82
90
  office: {
83
91
  name: string;
@@ -88,7 +96,7 @@ type TypeEventProperties = {
88
96
  polygon: string;
89
97
  polygon_generated: boolean;
90
98
  };
91
- parameters: {
99
+ parameters?: {
92
100
  tags: string[];
93
101
  instructions: string;
94
102
  source: string;
@@ -121,11 +129,13 @@ type TypeEventProperties = {
121
129
  max_tops_x100feet: string;
122
130
  pds_watch: boolean;
123
131
  };
124
- spc_parameters: {
125
- spc_max_tornado: string;
126
- spc_max_hail: string;
127
- spc_max_wind: string;
128
- spc_watch_issuance: string;
132
+ discussion_parameters?: {
133
+ discussion_number: string;
134
+ discussion_concerning: string;
135
+ discussion_max_tornado: string;
136
+ discussion_max_hail: string;
137
+ discussion_max_wind: string;
138
+ discussion_watch_issuance: string;
129
139
  };
130
140
  };
131
141
 
@@ -173,8 +183,8 @@ type TypeEvent = {
173
183
  tracking: string;
174
184
  hash?: string;
175
185
  header: string;
176
- vtec: TypePVTEC | null;
177
- hvtec: TypeHVTEC[];
186
+ vtec?: TypePVTEC | null;
187
+ hvtec?: TypeHVTEC[] | null;
178
188
  nodes?: {
179
189
  id?: string | number;
180
190
  coordinates: [number, number];
@@ -190,6 +200,8 @@ type TypeEvent = {
190
200
  issued: string;
191
201
  status: string;
192
202
  }[];
203
+ attachments?: string[];
204
+ raw: string;
193
205
  };
194
206
  } & TypeEventProperties;
195
207
  };
@@ -209,6 +221,7 @@ declare const stopService: () => Promise<void>;
209
221
  interface GenerateEASOptions {
210
222
  message: string;
211
223
  header: string;
224
+ title: string;
212
225
  }
213
226
  declare const setEasTone: (options: GenerateEASOptions) => Promise<string>;
214
227
 
@@ -226,6 +239,17 @@ declare const getEvents: () => any;
226
239
 
227
240
  declare const getNodes: () => any;
228
241
 
242
+ interface CreateEventOptions {
243
+ event: string;
244
+ status: string;
245
+ issued: Date;
246
+ expires: Date;
247
+ locations: string;
248
+ description: string;
249
+ coordinates: number[][];
250
+ }
251
+ declare const createEvent: (options: CreateEventOptions) => void;
252
+
229
253
  declare const getRandomEvent: () => any;
230
254
 
231
255
  type TypeStanza = {
@@ -261,4 +285,4 @@ declare class Manager {
261
285
  trycatch(): void;
262
286
  }
263
287
 
264
- export { Manager, type TypeEvent, clearEvents, Manager as default, getCleanedEvent, getEventGeometry, getEvents, getNodes, getRandomEvent, query, setEasTone, setNode, setSettings, startService, stopService };
288
+ export { Manager, type TypeEvent, clearEvents, createEvent, Manager as default, getCleanedEvent, getEventGeometry, getEvents, getNodes, getRandomEvent, query, setEasTone, setNode, setSettings, startService, stopService };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atmosx/event-product-parser",
3
- "version": "3.0.42",
3
+ "version": "3.0.46",
4
4
  "description": "NOAA Weather Wire & NWS API Parser - Built for standalone and Project AtmosphericX Integration.",
5
5
  "main": "dist/cjs/index.cjs",
6
6
  "module": "dist/esm/index.mjs",
@@ -0,0 +1,42 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: 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 { getLatestIssuance } from "../@modules/@utilities/utilities.getLatestIssuance";
22
+
23
+ export const getEventAttachments = (event: TypeEvent): string[] | null => {
24
+ const latestTime = getLatestIssuance();
25
+ const spcNumber = event?.properties?.discussion_parameters?.discussion_number;
26
+ const watchNumber = event?.properties?.watch_parameters?.watch_number;
27
+ const validEvents = [
28
+ { target: "Day 1", attachment: `https://www.spc.noaa.gov/products/outlook/day1otlk_${latestTime}.png` },
29
+ { target: "Day 2", attachment: `https://www.spc.noaa.gov/products/outlook/day2otlk.png` },
30
+ { target: "Day 3", attachment: `https://www.spc.noaa.gov/products/outlook/day3otlk.png` },
31
+ { target: "Mesoscale Discussion", attachment: `https://www.spc.noaa.gov/products/md/mcd${spcNumber}.png` },
32
+ { target: "Tornado Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
33
+ { target: "PDS Tornado Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
34
+ { target: "Severe Thunderstorm Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` },
35
+ { target: "PDS Severe Thunderstorm Watch", attachment: `https://www.spc.noaa.gov/products/watch/ww${watchNumber}_radar_big.gif` }
36
+ ]
37
+ const isValid = validEvents.find(outlook => outlook.target == event.properties.event);
38
+ if (isValid) {
39
+ return isValid?.attachment ? [isValid.attachment] : [];
40
+ }
41
+ return null;
42
+ }
@@ -17,8 +17,8 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeStanzaCompiled } from "../@types/types.compiled"
21
- import { TypeSettings } from "../@types/types.settings"
20
+ import { TypeStanzaCompiled } from "../@types/type.compiled"
21
+ import { TypeSettings } from "../@types/type.settings"
22
22
  import { bootstrap } from "../bootstrap"
23
23
  import { text } from "../@events/events.text"
24
24
  import { ugc } from "../@events/events.ugc"
@@ -18,9 +18,9 @@
18
18
  */
19
19
 
20
20
  import { TypeEvent } from "../@types/type.event";
21
- import { TypeSettings } from "../@types/types.settings";
21
+ import { TypeSettings } from "../@types/type.settings";
22
22
  import { bootstrap } from "../bootstrap"
23
- import { betterEventNames } from "../@dictionaries/dictionaries.betterEventNames"
23
+ import { dict_enhanced } from "../@dictionaries/dictionaries.enhanced"
24
24
 
25
25
  export const getEventEnhancedName = (event: TypeEvent): string => {
26
26
  const configurations = bootstrap.settings as TypeSettings
@@ -31,9 +31,10 @@ export const getEventEnhancedName = (event: TypeEvent): string => {
31
31
  }
32
32
 
33
33
  const damage = event?.properties?.parameters?.damage_threat
34
- const tornado = event?.properties?.parameters.tornado_threat;
34
+ const tornado = event?.properties?.parameters?.tornado_threat;
35
+ const pdswatch = event?.properties?.watch_parameters?.pds_watch;
35
36
  const description = event?.properties?.description?.toLowerCase()
36
- for (const [eventKey, eventConfig] of Object.entries(betterEventNames)) {
37
+ for (const [eventKey, eventConfig] of Object.entries(dict_enhanced)) {
37
38
  if (eventKey !== name) continue;
38
39
  for (const [paramKey, paramValue] of Object.entries(eventConfig)) {
39
40
  let matches = true;
@@ -46,6 +47,9 @@ export const getEventEnhancedName = (event: TypeEvent): string => {
46
47
  if (paramValue?.tornado) {
47
48
  if (paramValue.tornado !== tornado) matches = false;
48
49
  }
50
+ if (paramValue?.pdswatch) {
51
+ if (paramValue.pdswatch !== pdswatch) matches = false;
52
+ }
49
53
  if (matches) {
50
54
  name = paramKey;
51
55
  break;
@@ -18,7 +18,7 @@
18
18
  */
19
19
 
20
20
  import { getSettings } from "../@modules/@utilities/utilities.getSettings";
21
- import { TypeSettings } from "../@types/types.settings"
21
+ import { TypeSettings } from "../@types/type.settings"
22
22
  import { TypeEvent } from "../@types/type.event"
23
23
  import { getZonePolygon } from "../@parsers/@ugc/ugc.coordinates";
24
24
 
@@ -17,7 +17,7 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypePVTEC } from "../@types/types.pvtec";
20
+ import { TypePVTEC } from "../@types/type.pvtec";
21
21
  import { TypeEventProperties } from "../@types/type.properties";
22
22
 
23
23
  interface GetHeaderOptions {
@@ -17,9 +17,9 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeAttributes } from "../@types/types.attributes";
21
- import { TypePVTEC } from "../@types/types.pvtec";
22
- import { officeICAOs } from "../@dictionaries/dictionaries.officeICAOs";
20
+ import { TypeAttributes } from "../@types/type.attributes";
21
+ import { TypePVTEC } from "../@types/type.pvtec";
22
+ import { dict_icao } from "../@dictionaries/dictionaries.icao";
23
23
 
24
24
  interface GetOfficeOptions {
25
25
  attributes: TypeAttributes
@@ -38,6 +38,6 @@ export const getEventOffice = (options: GetOfficeOptions): GetOfficeResponse =>
38
38
  (options.organization != null ?
39
39
  (Array.isArray(options.organization) ? options.organization?.[0] : options.organization)
40
40
  : null));
41
- const name = officeICAOs?.[office] ?? null;
41
+ const name = dict_icao?.[office] ?? null;
42
42
  return { office, name };
43
43
  }
@@ -18,11 +18,11 @@
18
18
  */
19
19
 
20
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";
21
+ import { TypeAttributes } from "../@types/type.attributes";
22
+ import { TypeUGC } from "../@types/type.ugc";
23
+ import { TypePVTEC } from "../@types/type.pvtec";
24
+ import { TypeHVTEC } from "../@types/type.hvtec";
25
+ import { dict_expressions } from "../@dictionaries/dictionaries.expressions";
26
26
  import { getDescriptionFromProduct } from "../@parsers/@text/text.getDescriptionFromProduct";
27
27
  import { getPolygonFromProduct } from "../@parsers/@text/text.getPolygonFromProduct";
28
28
  import { getTextFromProduct } from "../@parsers/@text/text.getTextFromProduct";
@@ -38,7 +38,7 @@ interface GetPropertiesOptions {
38
38
  }
39
39
 
40
40
  export const properties = (options: GetPropertiesOptions): TypeEventProperties => {
41
- const organization = options.message.match(regExp.wmo)?.[0] ?? null
41
+ const organization = options.message.match(dict_expressions.wmo)?.[0] ?? null
42
42
  const polygons = getPolygonFromProduct(options.message)
43
43
  const properties = {
44
44
  locations: options?.ugc?.locations?.join(`; `) ?? null,
@@ -65,14 +65,16 @@ export const properties = (options: GetPropertiesOptions): TypeEventProperties =
65
65
  wind_threat: getTextFromProduct({ message: options.message, find: [`WIND THREAT...`]}) ?? null,
66
66
  hail_threat: getTextFromProduct({ message: options.message, find: [`HAIL THREAT...`], removal: []}) ?? null,
67
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,
68
+ discussion_parameters: {
69
+ discussion_number: getTextFromProduct({ message: options.message, find: [`Mesoscale Discussion `], removal: [`Mesoscale Discussion`, `Number`, `...`] })?.toString()?.padStart(4, "0") ?? null,
70
+ discussion_concerning: getTextFromProduct({ message: options.message, find: [`Concerning...`] }) ?? null,
71
+ discussion_max_tornado: getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK TORNADO INTENSITY...`] }) ?? null,
72
+ discussion_max_hail: getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK HAIL SIZE...`] }) ?? null,
73
+ discussion_max_wind: getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK WIND GUST...`] }) ?? null,
74
+ discussion_watch_issuance: getTextFromProduct({ message: options.message, find: [`Probability of Watch Issuance...`], removal: [`percent`]}) ?? null,
73
75
  },
74
76
  watch_parameters: {
75
- watch_number: getTextFromProduct({ message: options.message, find: [`ITIES FOR`, `UPDATE FOR`, `Watch Number `], removal: [`%`, `<`, `:`] })?.replace(/(WT|WS|)/g, '')?.trim() ?? null,
77
+ watch_number: (options?.pVtec?.is_watch) && (getTextFromProduct({ message: options.message, find: [`ITIES FOR`, `UPDATE FOR`, `Watch Number `], removal: [`%`, `<`, `:`] })?.replace(/(WT|WS|)/g, '')?.trim()?.toString()?.padStart(4, "0") ?? options?.pVtec?.tracking?.slice(-4)?.toString()?.padStart(4, "0") ?? null),
76
78
  watch_type: options.message.includes(`TORNADO WATCH`) ? `Tornado` : options?.message.includes(`SEVERE`) ? `Severe` : null,
77
79
  additional_tornadoes_probability: getTextFromProduct({ message: options.message, find: [`PROB OF 2 OR MORE TORNADOES`], removal: [`%`, `<`, `:`] }) ?? null,
78
80
  strong_tornadoes_probability: getTextFromProduct({ message: options.message, find: [`PROB OF 1 OR MORE STRONG /EF2-EF5/ TORNADOES`], removal: [`%`, `<`, `:`] }) ?? null,
@@ -83,7 +85,7 @@ export const properties = (options: GetPropertiesOptions): TypeEventProperties =
83
85
  max_hail_in: getTextFromProduct({ message: options.message, find: [`MAX HAIL /INCHES/`], removal: [`%`, `<`, `:`] }) ?? null,
84
86
  max_wind_surface: getTextFromProduct({ message: options.message, find: [`MAX WIND GUSTS SURFACE /KNOTS/`], removal: [`%`, `<`, `:`] }) ?? null,
85
87
  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`)
88
+ pds_watch: (getTextFromProduct({ message: options.message, find: [`PARTICULARLY DANGEROUS SITUATION`], removal: [`%`, `<`, `:`] }) === `YES` ? true : null)
87
89
  }
88
90
  }
89
91
  if (isNaN(Number(properties.watch_parameters.watch_number))) {
@@ -18,23 +18,23 @@
18
18
  */
19
19
 
20
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"
21
+ import { dict_correlations } from "../@dictionaries/dictionaries.correlations";
22
+ import { dict_cancellation } from "../@dictionaries/dictionaries.cancellation";
23
+ import { dict_testing} from "../@dictionaries/dictionaries.test"
24
+ import { dict_products } from "../@dictionaries/dictionaries.products";
25
+ import { dict_hail } from "../@dictionaries/dictionaries.hail"
26
26
 
27
27
 
28
28
  export const getEventSignature = (event: TypeEvent): TypeEvent => {
29
29
  const properties = event?.properties;
30
30
  const vtec = event?.properties?.metadata?.vtec
31
- const status = statusCorrelationText
31
+ const status = dict_correlations
32
32
  .find((c: { type: string }) => c.type === properties?.status);
33
- const csig = eventCancelMessages.find(sig => properties.description.toLowerCase().includes(sig.toLowerCase()));
33
+ const csig = dict_cancellation.find(sig => properties.description.toLowerCase().includes(sig.toLowerCase()));
34
34
  properties.status_metadata = { ...properties.status_metadata, is_issued: true, is_test: false};
35
35
 
36
- if (properties.parameters.estimated_hail_size) {
37
- properties.parameters.estimated_hail_size += ` (${hailStrings[properties.parameters.estimated_hail_size] ?? '--'})`
36
+ if (properties?.parameters?.estimated_hail_size) {
37
+ properties.parameters.estimated_hail_size += ` (${dict_hail[properties?.parameters?.estimated_hail_size] ?? '--'})`
38
38
  }
39
39
 
40
40
  if (status) {
@@ -46,8 +46,8 @@ export const getEventSignature = (event: TypeEvent): TypeEvent => {
46
46
  }
47
47
 
48
48
  const getProduct = vtec?.vtec?.split(`.`)[0]?.replace(`/`, ``)
49
- const isTestProduct = eventProducts[getProduct] == `Test Product`
50
- if (isTestProduct || testSignatures.some(sig => properties.description?.toLowerCase().includes(sig.toLowerCase()) ?? properties?.parameters?.instructions?.toLowerCase().includes(sig.toLowerCase()))) {
49
+ const isTestProduct = dict_products[getProduct] == `Test Product`
50
+ if (isTestProduct || dict_testing.some(sig => properties.description?.toLowerCase().includes(sig.toLowerCase()) ?? properties?.parameters?.instructions?.toLowerCase().includes(sig.toLowerCase()))) {
51
51
  properties.status_metadata = { ...properties.status_metadata, is_test: true }
52
52
  }
53
53
 
@@ -17,8 +17,8 @@
17
17
 
18
18
  */
19
19
 
20
- import { eventTags } from "../@dictionaries/dictionaries.eventTags";
20
+ import { dict_tags } from "../@dictionaries/dictionaries.tags";
21
21
 
22
22
  export const getEventTags = (message: string): string[] => {
23
- return Object.entries(eventTags).filter(([key]) => message?.toLowerCase().includes(key.toLowerCase())).map(([, value]) => value)
23
+ return Object.entries(dict_tags).filter(([key]) => message?.toLowerCase().includes(key.toLowerCase())).map(([, value]) => value)
24
24
  }
@@ -17,10 +17,10 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeAttributes } from "../@types/types.attributes";
20
+ import { TypeAttributes } from "../@types/type.attributes";
21
21
  import { TypeEventProperties } from "../@types/type.properties";
22
- import { TypeStanzaCompiled } from "../@types/types.compiled";
23
- import { TypePVTEC } from "../@types/types.pvtec";
22
+ import { TypeStanzaCompiled } from "../@types/type.compiled";
23
+ import { TypePVTEC } from "../@types/type.pvtec";
24
24
 
25
25
  interface GetTrackingOptions {
26
26
  type: `RAW` | `VTEC` | `API`
@@ -52,7 +52,7 @@ export const getEventTracking = (options: GetTrackingOptions): string => {
52
52
  if (options.type === `API`) {
53
53
  if (options.vtec) {
54
54
  const vtecValue = Array.isArray(options.vtec)
55
- ? options.vtec[0] : options.vtec;
55
+ ? options.vtec[0].vtec : options.vtec?.vtec;
56
56
  const splitPVTEC = vtecValue.split('.');
57
57
  return `${splitPVTEC[2]}.${splitPVTEC[3]}.${splitPVTEC[4]}.${splitPVTEC[5]}`;
58
58
  }
@@ -60,9 +60,9 @@ export const getEventTracking = (options: GetTrackingOptions): string => {
60
60
  const station = wmoMatch?.[2] ?? 'N/A';
61
61
  if (options.organization.featureId) {
62
62
  const idMatch = options.organization.featureId.match(/([a-f0-9]+)\.(\d+)\.(\d+)$/);
63
- return `${station}.${idMatch?.[1] ?? 'N/A'}`;
63
+ return `${station}.${idMatch?.[0]?.replace(/\./g, '') ?? 'N/A'}`;
64
64
  }
65
65
  const id = wmoMatch?.[1] ?? 'N/A';
66
- return `${station}.${id}`;
66
+ return `${station}.${id?.replace(/\./g, '') ?? 'N/A'}`;
67
67
  }
68
68
  }
@@ -19,13 +19,14 @@
19
19
 
20
20
  import { createHash } from "crypto"
21
21
  import { TypeEvent } from "../@types/type.event";
22
- import { TypeSettings } from "../@types/types.settings";
22
+ import { TypeSettings } from "../@types/type.settings";
23
23
  import { bootstrap } from "../bootstrap"
24
24
  import { getEventEnhancedName } from "./building.enhance";
25
25
  import { getEventSignature } from "./building.signature"
26
26
  import { mkEvent } from "../@manager/manager.mkEvent";
27
27
  import { rmEvent } from "../@manager/manager.rmEvent";
28
28
  import { getEventGeometry } from "./building.geometry";
29
+ import { getEventAttachments } from "./building.attachments";
29
30
  import { updateNode } from "../@manager/manager.updateNodes";
30
31
  import { setEventEmit } from "../@modules/@utilities/utilities.setEventEmit";
31
32
 
@@ -51,7 +52,8 @@ export const validateEvents = async (events: TypeEvent[]): Promise<void> => {
51
52
  delete filteredProperties.metadata.ms;
52
53
  }
53
54
  filteredProperties.metadata = filteredProperties.metadata ?? {} as any;
54
- properties.metadata.hash = createHash("sha256").update(JSON.stringify(filteredProperties)).digest("hex")
55
+ properties.metadata.hash = createHash("sha256").update(JSON.stringify(filteredProperties)).digest("hex")
56
+ properties.metadata.attachments = getEventAttachments(event)
55
57
  setEventEmit({ event: `onProductType${enhancedEventName.replace(/\s+/g, '')}`, metadata: define });
56
58
 
57
59
  if (properties.status_metadata.is_test) {
@@ -65,7 +67,7 @@ export const validateEvents = async (events: TypeEvent[]): Promise<void> => {
65
67
  return false;
66
68
  }
67
69
 
68
- if (properties.metadata?.vtec?.is_watch) {
70
+ if (properties.metadata?.vtec?.is_watch && properties.metadata.source != `events.api`) {
69
71
  const isSPC = properties.metadata?.vtec?.prediction_center;
70
72
  setEventEmit({ event: isSPC ? `onStormPredictionWatch` : `onNonStormPredictionWatch`, metadata: define })
71
73
  if (bools?.SPCWatchesOnly && !isSPC) {