@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.
- package/README.md +66 -31
- package/SUPPORTED_EVENTS.md +369 -0
- package/dist/cjs/index.cjs +476 -373
- package/dist/esm/index.mjs +454 -352
- package/dist/index.d.mts +42 -24
- package/dist/index.d.ts +42 -24
- package/package.json +1 -1
- package/src/@building/{building.outlooks.ts → building.attachments.ts} +7 -1
- package/src/@building/building.enhance.ts +7 -3
- package/src/@building/building.office.ts +2 -2
- package/src/@building/building.properties.ts +11 -11
- package/src/@building/building.signature.ts +11 -11
- package/src/@building/building.tags.ts +2 -2
- package/src/@building/building.tracking.ts +3 -3
- package/src/@building/building.validate.ts +2 -2
- package/src/@core/core.createEvent.ts +82 -0
- package/src/@dictionaries/{dictionaries.eventActions.ts → dictionaries.actions.ts} +1 -1
- package/src/@dictionaries/{dictionaries.eventAwipAbreviations.ts → dictionaries.awips.ts} +1 -1
- package/src/@dictionaries/{dictionaries.eventCancelMessages.ts → dictionaries.cancellation.ts} +1 -1
- package/src/@dictionaries/{dictionaries.eventCauses.ts → dictionaries.causes.ts} +1 -1
- package/src/@dictionaries/{dictionaries.statusCorrelationText.ts → dictionaries.correlations.ts} +1 -1
- package/src/@dictionaries/{dictionaries.betterEventNames.ts → dictionaries.enhanced.ts} +13 -2
- package/src/@dictionaries/{dictionaries.eventTypes.ts → dictionaries.events.ts} +1 -1
- package/src/@dictionaries/{dictionaries.regExp.ts → dictionaries.expressions.ts} +1 -1
- package/src/@dictionaries/{dictionaries.hailStrings.ts → dictionaries.hail.ts} +4 -1
- package/src/@dictionaries/{dictionaries.officeICAOs.ts → dictionaries.icao.ts} +1 -1
- package/src/@dictionaries/{dictionaries.eventsMatchText.ts → dictionaries.matches.ts} +1 -1
- package/src/@dictionaries/{dictionaries.eventProducts.ts → dictionaries.products.ts} +1 -1
- package/src/@dictionaries/{dictionaries.eventRecords.ts → dictionaries.records.ts} +1 -1
- package/src/@dictionaries/{dictionaries.eventSeverity.ts → dictionaries.severity.ts} +1 -1
- package/src/@dictionaries/{dictionaries.shapefileLinks.ts → dictionaries.shapefiles.ts} +1 -1
- package/src/@dictionaries/{dictionaries.eventStatus.ts → dictionaries.status.ts} +1 -1
- package/src/@dictionaries/{dictionaries.eventTags.ts → dictionaries.tags.ts} +1 -1
- package/src/@dictionaries/{dictionaries.testSignatures.ts → dictionaries.test.ts} +3 -2
- package/src/@events/events.api.ts +17 -15
- package/src/@events/events.text.ts +2 -2
- package/src/@events/events.ugc.ts +2 -2
- package/src/@manager/manager.mkEvent.ts +3 -3
- package/src/@manager/manager.rmEvent.ts +3 -2
- package/src/@manager/manager.updateListener.ts +124 -0
- package/src/@modules/@database/database.shapefiles.ts +2 -2
- package/src/@modules/@eas/eas.getCleanDescription.ts +2 -0
- package/src/@modules/@eas/eas.getTTS.ts +19 -8
- package/src/@modules/@eas/eas.setEasTone.ts +15 -10
- package/src/@modules/@stanza/stanza.getAwipsType.ts +2 -2
- package/src/@modules/@stanza/stanza.validate.ts +3 -3
- package/src/@modules/@utilities/utilities.setCronSchedule.ts +4 -2
- package/src/@parsers/@hvtec/hvtec.extract.ts +8 -8
- package/src/@parsers/@pvtec/pvtec.extract.ts +12 -12
- package/src/@parsers/@text/text.getDescriptionFromProduct.ts +2 -2
- package/src/@parsers/@text/text.getEmbed.ts +60 -0
- package/src/@parsers/@ugc/ugc.header.ts +3 -3
- package/src/@types/type.event.ts +2 -2
- package/src/@types/{type.webhook.ts → type.listener.ts} +11 -7
- package/src/@types/type.properties.ts +9 -9
- package/src/@types/type.settings.ts +7 -6
- package/src/bootstrap.ts +7 -6
- package/src/index.ts +2 -1
- package/test.js +19 -19
- package/src/@manager/manager.createWebhook.ts +0 -129
- package/src/@manager/manager.updateWebhooks.ts +0 -49
- package/src/@modules/@utilities/utilities.isImageReady.ts +0 -27
package/dist/index.d.mts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
type
|
|
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
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
|
181
|
-
hvtec
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
|
181
|
-
hvtec
|
|
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.
|
|
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${
|
|
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 {
|
|
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
|
|
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(
|
|
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 {
|
|
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 =
|
|
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 {
|
|
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(
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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 {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
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 =
|
|
31
|
+
const status = dict_correlations
|
|
32
32
|
.find((c: { type: string }) => c.type === properties?.status);
|
|
33
|
-
const csig =
|
|
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
|
|
37
|
-
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 =
|
|
50
|
-
if (isTestProduct ||
|
|
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 {
|
|
20
|
+
import { dict_tags } from "../@dictionaries/dictionaries.tags";
|
|
21
21
|
|
|
22
22
|
export const getEventTags = (message: string): string[] => {
|
|
23
|
-
return Object.entries(
|
|
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?.[
|
|
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.
|
|
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
|
|
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`,
|
package/src/@dictionaries/{dictionaries.statusCorrelationText.ts → dictionaries.correlations.ts}
RENAMED
|
@@ -26,7 +26,7 @@ type TypeCorrelations = {
|
|
|
26
26
|
isStatement: boolean
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export const
|
|
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
|
|
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
|
-
|
|
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": {
|