@atmosx/event-product-parser 3.0.44 → 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 (62) hide show
  1. package/README.md +66 -31
  2. package/SUPPORTED_EVENTS.md +369 -0
  3. package/dist/cjs/index.cjs +476 -373
  4. package/dist/esm/index.mjs +454 -352
  5. package/dist/index.d.mts +42 -24
  6. package/dist/index.d.ts +42 -24
  7. package/package.json +1 -1
  8. package/src/@building/{building.outlooks.ts → building.attachments.ts} +7 -1
  9. package/src/@building/building.enhance.ts +7 -3
  10. package/src/@building/building.office.ts +2 -2
  11. package/src/@building/building.properties.ts +11 -11
  12. package/src/@building/building.signature.ts +11 -11
  13. package/src/@building/building.tags.ts +2 -2
  14. package/src/@building/building.tracking.ts +3 -3
  15. package/src/@building/building.validate.ts +2 -2
  16. package/src/@core/core.createEvent.ts +82 -0
  17. package/src/@dictionaries/{dictionaries.eventActions.ts → dictionaries.actions.ts} +1 -1
  18. package/src/@dictionaries/{dictionaries.eventAwipAbreviations.ts → dictionaries.awips.ts} +1 -1
  19. package/src/@dictionaries/{dictionaries.eventCancelMessages.ts → dictionaries.cancellation.ts} +1 -1
  20. package/src/@dictionaries/{dictionaries.eventCauses.ts → dictionaries.causes.ts} +1 -1
  21. package/src/@dictionaries/{dictionaries.statusCorrelationText.ts → dictionaries.correlations.ts} +1 -1
  22. package/src/@dictionaries/{dictionaries.betterEventNames.ts → dictionaries.enhanced.ts} +13 -2
  23. package/src/@dictionaries/{dictionaries.eventTypes.ts → dictionaries.events.ts} +1 -1
  24. package/src/@dictionaries/{dictionaries.regExp.ts → dictionaries.expressions.ts} +1 -1
  25. package/src/@dictionaries/{dictionaries.hailStrings.ts → dictionaries.hail.ts} +4 -1
  26. package/src/@dictionaries/{dictionaries.officeICAOs.ts → dictionaries.icao.ts} +1 -1
  27. package/src/@dictionaries/{dictionaries.eventsMatchText.ts → dictionaries.matches.ts} +1 -1
  28. package/src/@dictionaries/{dictionaries.eventProducts.ts → dictionaries.products.ts} +1 -1
  29. package/src/@dictionaries/{dictionaries.eventRecords.ts → dictionaries.records.ts} +1 -1
  30. package/src/@dictionaries/{dictionaries.eventSeverity.ts → dictionaries.severity.ts} +1 -1
  31. package/src/@dictionaries/{dictionaries.shapefileLinks.ts → dictionaries.shapefiles.ts} +1 -1
  32. package/src/@dictionaries/{dictionaries.eventStatus.ts → dictionaries.status.ts} +1 -1
  33. package/src/@dictionaries/{dictionaries.eventTags.ts → dictionaries.tags.ts} +1 -1
  34. package/src/@dictionaries/{dictionaries.testSignatures.ts → dictionaries.test.ts} +3 -2
  35. package/src/@events/events.api.ts +17 -15
  36. package/src/@events/events.text.ts +2 -2
  37. package/src/@events/events.ugc.ts +2 -2
  38. package/src/@manager/manager.mkEvent.ts +3 -3
  39. package/src/@manager/manager.rmEvent.ts +3 -2
  40. package/src/@manager/manager.updateListener.ts +124 -0
  41. package/src/@modules/@database/database.shapefiles.ts +2 -2
  42. package/src/@modules/@eas/eas.getCleanDescription.ts +2 -0
  43. package/src/@modules/@eas/eas.getTTS.ts +19 -8
  44. package/src/@modules/@eas/eas.setEasTone.ts +15 -10
  45. package/src/@modules/@stanza/stanza.getAwipsType.ts +2 -2
  46. package/src/@modules/@stanza/stanza.validate.ts +3 -3
  47. package/src/@modules/@utilities/utilities.setCronSchedule.ts +4 -2
  48. package/src/@parsers/@hvtec/hvtec.extract.ts +8 -8
  49. package/src/@parsers/@pvtec/pvtec.extract.ts +12 -12
  50. package/src/@parsers/@text/text.getDescriptionFromProduct.ts +2 -2
  51. package/src/@parsers/@text/text.getEmbed.ts +60 -0
  52. package/src/@parsers/@ugc/ugc.header.ts +3 -3
  53. package/src/@types/type.event.ts +2 -2
  54. package/src/@types/{type.webhook.ts → type.listener.ts} +11 -7
  55. package/src/@types/type.properties.ts +9 -9
  56. package/src/@types/type.settings.ts +7 -6
  57. package/src/bootstrap.ts +7 -6
  58. package/src/index.ts +2 -1
  59. package/test.js +19 -19
  60. package/src/@manager/manager.createWebhook.ts +0 -129
  61. package/src/@manager/manager.updateWebhooks.ts +0 -49
  62. package/src/@modules/@utilities/utilities.isImageReady.ts +0 -27
package/dist/index.d.mts CHANGED
@@ -1,11 +1,16 @@
1
- type TypeWebhook = {
2
- webhook: string;
3
- title: string;
4
- message: string;
5
- upload: boolean;
6
- eas: boolean;
7
- rate: number;
1
+ type TypeListener = {
8
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
+ };
9
14
  };
10
15
 
11
16
  type TypeSettings = {
@@ -46,7 +51,7 @@ type TypeSettings = {
46
51
  ShapefileSkipPoints: number;
47
52
  NodeTTL: number;
48
53
  NodeMinDistance: number;
49
- WebhookSettings?: TypeWebhook;
54
+ ListenerSettings?: TypeListener[];
50
55
  EventFiltering: {
51
56
  ListeningEvents: string[];
52
57
  ListeningICAO: string[];
@@ -57,10 +62,11 @@ type TypeSettings = {
57
62
  NodeLocationFiltering: boolean;
58
63
  IgnoreTestProducts: boolean;
59
64
  };
60
- EASSettings: {
61
- ArchiveTTL: number;
62
- ArchiveDirectory: string;
63
- IntroWavFile: string;
65
+ ArchiveSettings: {
66
+ TTL: number;
67
+ TextDirectory: string;
68
+ EasDirectory: string;
69
+ EasToneout: string;
64
70
  };
65
71
  };
66
72
  };
@@ -79,7 +85,7 @@ type TypeAttributes = {
79
85
  type TypeEventProperties = {
80
86
  locations: string;
81
87
  description: string;
82
- attributes: TypeAttributes;
88
+ attributes?: TypeAttributes;
83
89
  geocode: {
84
90
  office: {
85
91
  name: string;
@@ -90,7 +96,7 @@ type TypeEventProperties = {
90
96
  polygon: string;
91
97
  polygon_generated: boolean;
92
98
  };
93
- parameters: {
99
+ parameters?: {
94
100
  tags: string[];
95
101
  instructions: string;
96
102
  source: string;
@@ -123,13 +129,13 @@ type TypeEventProperties = {
123
129
  max_tops_x100feet: string;
124
130
  pds_watch: boolean;
125
131
  };
126
- spc_parameters: {
127
- spc_number: string;
128
- spc_concerning: string;
129
- spc_max_tornado: string;
130
- spc_max_hail: string;
131
- spc_max_wind: string;
132
- 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;
133
139
  };
134
140
  };
135
141
 
@@ -177,8 +183,8 @@ type TypeEvent = {
177
183
  tracking: string;
178
184
  hash?: string;
179
185
  header: string;
180
- vtec: TypePVTEC | null;
181
- hvtec: TypeHVTEC[];
186
+ vtec?: TypePVTEC | null;
187
+ hvtec?: TypeHVTEC[] | null;
182
188
  nodes?: {
183
189
  id?: string | number;
184
190
  coordinates: [number, number];
@@ -215,6 +221,7 @@ declare const stopService: () => Promise<void>;
215
221
  interface GenerateEASOptions {
216
222
  message: string;
217
223
  header: string;
224
+ title: string;
218
225
  }
219
226
  declare const setEasTone: (options: GenerateEASOptions) => Promise<string>;
220
227
 
@@ -232,6 +239,17 @@ declare const getEvents: () => any;
232
239
 
233
240
  declare const getNodes: () => any;
234
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
+
235
253
  declare const getRandomEvent: () => any;
236
254
 
237
255
  type TypeStanza = {
@@ -267,4 +285,4 @@ declare class Manager {
267
285
  trycatch(): void;
268
286
  }
269
287
 
270
- 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,11 +1,16 @@
1
- type TypeWebhook = {
2
- webhook: string;
3
- title: string;
4
- message: string;
5
- upload: boolean;
6
- eas: boolean;
7
- rate: number;
1
+ type TypeListener = {
8
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
+ };
9
14
  };
10
15
 
11
16
  type TypeSettings = {
@@ -46,7 +51,7 @@ type TypeSettings = {
46
51
  ShapefileSkipPoints: number;
47
52
  NodeTTL: number;
48
53
  NodeMinDistance: number;
49
- WebhookSettings?: TypeWebhook;
54
+ ListenerSettings?: TypeListener[];
50
55
  EventFiltering: {
51
56
  ListeningEvents: string[];
52
57
  ListeningICAO: string[];
@@ -57,10 +62,11 @@ type TypeSettings = {
57
62
  NodeLocationFiltering: boolean;
58
63
  IgnoreTestProducts: boolean;
59
64
  };
60
- EASSettings: {
61
- ArchiveTTL: number;
62
- ArchiveDirectory: string;
63
- IntroWavFile: string;
65
+ ArchiveSettings: {
66
+ TTL: number;
67
+ TextDirectory: string;
68
+ EasDirectory: string;
69
+ EasToneout: string;
64
70
  };
65
71
  };
66
72
  };
@@ -79,7 +85,7 @@ type TypeAttributes = {
79
85
  type TypeEventProperties = {
80
86
  locations: string;
81
87
  description: string;
82
- attributes: TypeAttributes;
88
+ attributes?: TypeAttributes;
83
89
  geocode: {
84
90
  office: {
85
91
  name: string;
@@ -90,7 +96,7 @@ type TypeEventProperties = {
90
96
  polygon: string;
91
97
  polygon_generated: boolean;
92
98
  };
93
- parameters: {
99
+ parameters?: {
94
100
  tags: string[];
95
101
  instructions: string;
96
102
  source: string;
@@ -123,13 +129,13 @@ type TypeEventProperties = {
123
129
  max_tops_x100feet: string;
124
130
  pds_watch: boolean;
125
131
  };
126
- spc_parameters: {
127
- spc_number: string;
128
- spc_concerning: string;
129
- spc_max_tornado: string;
130
- spc_max_hail: string;
131
- spc_max_wind: string;
132
- 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;
133
139
  };
134
140
  };
135
141
 
@@ -177,8 +183,8 @@ type TypeEvent = {
177
183
  tracking: string;
178
184
  hash?: string;
179
185
  header: string;
180
- vtec: TypePVTEC | null;
181
- hvtec: TypeHVTEC[];
186
+ vtec?: TypePVTEC | null;
187
+ hvtec?: TypeHVTEC[] | null;
182
188
  nodes?: {
183
189
  id?: string | number;
184
190
  coordinates: [number, number];
@@ -215,6 +221,7 @@ declare const stopService: () => Promise<void>;
215
221
  interface GenerateEASOptions {
216
222
  message: string;
217
223
  header: string;
224
+ title: string;
218
225
  }
219
226
  declare const setEasTone: (options: GenerateEASOptions) => Promise<string>;
220
227
 
@@ -232,6 +239,17 @@ declare const getEvents: () => any;
232
239
 
233
240
  declare const getNodes: () => any;
234
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
+
235
253
  declare const getRandomEvent: () => any;
236
254
 
237
255
  type TypeStanza = {
@@ -267,4 +285,4 @@ declare class Manager {
267
285
  trycatch(): void;
268
286
  }
269
287
 
270
- 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.44",
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",
@@ -22,11 +22,17 @@ import { getLatestIssuance } from "../@modules/@utilities/utilities.getLatestIss
22
22
 
23
23
  export const getEventAttachments = (event: TypeEvent): string[] | null => {
24
24
  const latestTime = getLatestIssuance();
25
+ const spcNumber = event?.properties?.discussion_parameters?.discussion_number;
26
+ const watchNumber = event?.properties?.watch_parameters?.watch_number;
25
27
  const validEvents = [
26
28
  { target: "Day 1", attachment: `https://www.spc.noaa.gov/products/outlook/day1otlk_${latestTime}.png` },
27
29
  { target: "Day 2", attachment: `https://www.spc.noaa.gov/products/outlook/day2otlk.png` },
28
30
  { target: "Day 3", attachment: `https://www.spc.noaa.gov/products/outlook/day3otlk.png` },
29
- { target: "Mesoscale Discussion", attachment: `https://www.spc.noaa.gov/products/md/mcd${event?.properties?.spc_parameters?.spc_number}.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` }
30
36
  ]
31
37
  const isValid = validEvents.find(outlook => outlook.target == event.properties.event);
32
38
  if (isValid) {
@@ -20,7 +20,7 @@
20
20
  import { TypeEvent } from "../@types/type.event";
21
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;
@@ -19,7 +19,7 @@
19
19
 
20
20
  import { TypeAttributes } from "../@types/type.attributes";
21
21
  import { TypePVTEC } from "../@types/type.pvtec";
22
- import { officeICAOs } from "../@dictionaries/dictionaries.officeICAOs";
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
  }
@@ -22,7 +22,7 @@ import { TypeAttributes } from "../@types/type.attributes";
22
22
  import { TypeUGC } from "../@types/type.ugc";
23
23
  import { TypePVTEC } from "../@types/type.pvtec";
24
24
  import { TypeHVTEC } from "../@types/type.hvtec";
25
- import { regExp } from "../@dictionaries/dictionaries.regExp";
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,16 +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_number: getTextFromProduct({ message: options.message, find: [`Mesoscale Discussion `], removal: [`Mesoscale Discussion`, `Number`, `...`] }) ?? null,
70
- spc_concerning: getTextFromProduct({ message: options.message, find: [`Concerning...`] }) ?? null,
71
- spc_max_tornado: getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK TORNADO INTENSITY...`] }) ?? null,
72
- spc_max_hail: getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK HAIL SIZE...`] }) ?? null,
73
- spc_max_wind: getTextFromProduct({ message: options.message, find: [`MOST PROBABLE PEAK WIND GUST...`] }) ?? null,
74
- 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,
75
75
  },
76
76
  watch_parameters: {
77
- 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),
78
78
  watch_type: options.message.includes(`TORNADO WATCH`) ? `Tornado` : options?.message.includes(`SEVERE`) ? `Severe` : null,
79
79
  additional_tornadoes_probability: getTextFromProduct({ message: options.message, find: [`PROB OF 2 OR MORE TORNADOES`], removal: [`%`, `<`, `:`] }) ?? null,
80
80
  strong_tornadoes_probability: getTextFromProduct({ message: options.message, find: [`PROB OF 1 OR MORE STRONG /EF2-EF5/ TORNADOES`], removal: [`%`, `<`, `:`] }) ?? null,
@@ -85,7 +85,7 @@ export const properties = (options: GetPropertiesOptions): TypeEventProperties =
85
85
  max_hail_in: getTextFromProduct({ message: options.message, find: [`MAX HAIL /INCHES/`], removal: [`%`, `<`, `:`] }) ?? null,
86
86
  max_wind_surface: getTextFromProduct({ message: options.message, find: [`MAX WIND GUSTS SURFACE /KNOTS/`], removal: [`%`, `<`, `:`] }) ?? null,
87
87
  max_tops_x100feet: getTextFromProduct({ message: options.message, find: [`MAX TOPS /X 100 FEET/`], removal: [`%`, `<`, `:`] }) ?? null,
88
- 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)
89
89
  }
90
90
  }
91
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
  }
@@ -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
  }
@@ -26,7 +26,7 @@ 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.outlooks";
29
+ import { getEventAttachments } from "./building.attachments";
30
30
  import { updateNode } from "../@manager/manager.updateNodes";
31
31
  import { setEventEmit } from "../@modules/@utilities/utilities.setEventEmit";
32
32
 
@@ -67,7 +67,7 @@ export const validateEvents = async (events: TypeEvent[]): Promise<void> => {
67
67
  return false;
68
68
  }
69
69
 
70
- if (properties.metadata?.vtec?.is_watch) {
70
+ if (properties.metadata?.vtec?.is_watch && properties.metadata.source != `events.api`) {
71
71
  const isSPC = properties.metadata?.vtec?.prediction_center;
72
72
  setEventEmit({ event: isSPC ? `onStormPredictionWatch` : `onNonStormPredictionWatch`, metadata: define })
73
73
  if (bools?.SPCWatchesOnly && !isSPC) {
@@ -0,0 +1,82 @@
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 { validateEvents } from "../@building/building.validate";
21
+ import { dict_correlations } from "../@dictionaries/dictionaries.correlations";
22
+
23
+ interface CreateEventOptions {
24
+ event: string
25
+ status: string
26
+ issued: Date
27
+ expires: Date
28
+ locations: string
29
+ description: string
30
+ coordinates: number[][]
31
+ }
32
+
33
+ export const createEvent = (options: CreateEventOptions): void => {
34
+ const tick = performance.now()
35
+ validateEvents([{
36
+ type: `Feature`,
37
+ geometry: {
38
+ type: `Point`,
39
+ coordinates: options.coordinates
40
+ },
41
+ properties: {
42
+ event: options.event,
43
+ parent: options.event,
44
+ status: options.status,
45
+ issued: options.issued.toISOString(),
46
+ expires: options.expires.toISOString(),
47
+ locations: options.locations,
48
+ description: options.description,
49
+ geocode: {
50
+ office: {
51
+ office: `ATMX`,
52
+ name: `AtmosphericX Manual Event`,
53
+ },
54
+ organization: `AtmosphericX`,
55
+ ugc: [],
56
+ polygon: options.coordinates.length > 0 ? Buffer.from(JSON.stringify([options.coordinates[0]])).toString('base64') : null,
57
+ polygon_generated: options.coordinates.length > 0 ? true : false,
58
+ },
59
+ status_metadata: {
60
+ is_issued: options.status == `Issued`,
61
+ is_updated: options.status == `Updated`,
62
+ is_expired: options.status == `Expired`,
63
+ is_test: options.status == `Test`,
64
+ is_statement: options.status == `Statement`
65
+ },
66
+ metadata: {
67
+ ms: performance.now() - tick,
68
+ source: `events.manual`,
69
+ tracking: `ATMX-M-W-01`,
70
+ header: `ZCZC-ATMOSX-ATMX-M-W-01`,
71
+ raw: options.description,
72
+ history: [
73
+ {
74
+ description: options.description,
75
+ issued: options.issued.toISOString(),
76
+ status: options.status ?? null,
77
+ }
78
+ ]
79
+ }
80
+ }
81
+ }])
82
+ }
@@ -17,7 +17,7 @@
17
17
 
18
18
  */
19
19
 
20
- export const eventActions: Record<string, string> = {
20
+ export const dict_actions: Record<string, string> = {
21
21
  "W": "Warning",
22
22
  "F": "Forecast",
23
23
  "A": "Watch",
@@ -17,7 +17,7 @@
17
17
 
18
18
  */
19
19
 
20
- export const eventAwipAbreviations: Record<string, string> = {
20
+ export const dict_awips: Record<string, string> = {
21
21
  ABV: `rawinsonde-data-above-100-millibars`,
22
22
  ADA: `alarm-alert-administrative-message`,
23
23
  ADM: `alert-administrative-message`,
@@ -17,7 +17,7 @@
17
17
 
18
18
  */
19
19
 
20
- export const eventCancelMessages: string[] = [
20
+ export const dict_cancellation: string[] = [
21
21
  "has been cancelled",
22
22
  "subsided sufficiently for the advisory to be cancelled",
23
23
  "has been cancelled",
@@ -17,7 +17,7 @@
17
17
 
18
18
  */
19
19
 
20
- export const eventCauses : Record<string, string> = {
20
+ export const dict_causes: Record<string, string> = {
21
21
  "SM": "Snow Melt",
22
22
  "RS": "Rain/Snow Melt",
23
23
  "ER": "Excessive Rain",
@@ -26,7 +26,7 @@ type TypeCorrelations = {
26
26
  isStatement: boolean
27
27
  }
28
28
 
29
- export const statusCorrelationText: TypeCorrelations[] = [
29
+ export const dict_correlations: TypeCorrelations[] = [
30
30
  {type: "Statement", name: "Statement", isCancel: false, isUpdate: false, isIssued: true, isStatement: true},
31
31
  {type: "Update", name: "Updated", isCancel: false, isUpdate: true, isIssued: false, isStatement: false},
32
32
  {type: "Cancel", name: "Cancelled", isCancel: true, isUpdate: false, isIssued: false, isStatement: false},
@@ -22,9 +22,10 @@ type EnhancedEventType = {
22
22
  append?: boolean
23
23
  tornado?: string
24
24
  damage?: string
25
+ pdswatch?: boolean
25
26
  }
26
27
 
27
- export const betterEventNames: Record<string, Record<string, EnhancedEventType>> = {
28
+ export const dict_enhanced: Record<string, Record<string, EnhancedEventType>> = {
28
29
  "Tornado Warning": {
29
30
  "Tornado Emergency": {
30
31
  description: "tornado emergency"
@@ -42,6 +43,11 @@ export const betterEventNames: Record<string, Record<string, EnhancedEventType>>
42
43
  },
43
44
  "Radar Indicated Tornado Warning": { },
44
45
  },
46
+ "Fire Weather Warning": {
47
+ "PDS Fire Weather Warning": {
48
+ description: "particularly dangerous situation",
49
+ },
50
+ },
45
51
  "Blizzard Warning": {
46
52
  "PDS Blizzard Warning": {
47
53
  description: "particularly dangerous situation",
@@ -59,7 +65,12 @@ export const betterEventNames: Record<string, Record<string, EnhancedEventType>>
59
65
  },
60
66
  "Tornado Watch": {
61
67
  "PDS Tornado Watch": {
62
- description: "particularly dangerous situation"
68
+ pdswatch: true,
69
+ }
70
+ },
71
+ "Severe Thunderstorm Watch": {
72
+ "PDS Severe Thunderstorm Watch": {
73
+ pdswatch: true
63
74
  }
64
75
  },
65
76
  "Flash Flood Warning": {