@atmosx/event-product-parser 3.0.53 → 3.0.55
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/.github/README.md +25 -107
- package/dist/cjs/index.cjs +93 -75
- package/dist/esm/index.mjs +93 -75
- package/package.json +1 -1
- package/src/@building/building.validate.ts +5 -3
- package/src/@dictionaries/dictionaries.enhanced.ts +3 -0
- package/src/@dictionaries/dictionaries.strings.ts +22 -0
- package/src/@manager/manager.rmEvent.ts +34 -19
- package/src/@manager/manager.updateEvents.ts +6 -4
- package/src/@manager/manager.updateListener.ts +43 -43
- package/src/@modules/@utilities/utilities.setTimeoutAction.ts +1 -0
- package/src/@parsers/@text/{text.getEmbed.ts → text.getEmbedText.ts} +1 -1
- package/src/@parsers/@text/{text.getRaw.ts → text.getStringText.ts} +1 -1
- package/src/@types/type.listener.ts +13 -12
- package/src/bootstrap.ts +1 -1
- package/testing/init.js +26 -41
|
@@ -22,8 +22,8 @@ import { TypeListener } from "../@types/type.listener";
|
|
|
22
22
|
import { bootstrap } from "../bootstrap"
|
|
23
23
|
import { setEasTone } from "../@modules/@eas/eas.setEasTone"
|
|
24
24
|
import { setTimeoutAction } from "../@modules/@utilities/utilities.setTimeoutAction";
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
25
|
+
import { getEmebedText } from "../@parsers/@text/text.getEmbedText";
|
|
26
|
+
import { getStringText } from "../@parsers/@text/text.getStringText";
|
|
27
27
|
import { getCleanedEvent } from "../@building/building.clean"
|
|
28
28
|
import { createHttp } from "../@modules/@utilities/utilities.createHttp";
|
|
29
29
|
import { setDebug } from "../@modules/@utilities/utilities.setDebug";
|
|
@@ -50,13 +50,14 @@ export const updateListener = async (event: TypeEvent): Promise<void> => {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
for (const listener of listeners) {
|
|
53
|
-
const events = listener?.
|
|
54
|
-
const webhook = listener?.
|
|
55
|
-
const
|
|
53
|
+
const events = listener?.Events;
|
|
54
|
+
const webhook = listener?.Webhook;
|
|
55
|
+
const notify = listener?.NotificationServer;
|
|
56
|
+
const uploads = listener?.Uploads
|
|
56
57
|
const isMatched = getMatched(events ?? [], metadata.name)
|
|
57
58
|
|
|
58
59
|
if (events?.length == 0 || isMatched) {
|
|
59
|
-
if (uploads?.
|
|
60
|
+
if (uploads?.EAS) {
|
|
60
61
|
metadata.eas = await setEasTone({
|
|
61
62
|
title: `${metadata.name}_${metadata.status}_${metadata.tracking}`,
|
|
62
63
|
message: metadata.description,
|
|
@@ -64,13 +65,13 @@ export const updateListener = async (event: TypeEvent): Promise<void> => {
|
|
|
64
65
|
});
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
if (uploads?.
|
|
68
|
+
if (uploads?.File) {
|
|
68
69
|
const fDestination = settings.GlobalSettings.ArchiveSettings.TextDirectory;
|
|
69
70
|
if (fDestination) {
|
|
70
|
-
const file = (`${fDestination}/${metadata.name}_${metadata.
|
|
71
|
+
const file = (`${fDestination}/${metadata.name}_${metadata.tracking}.txt`).replace(/[\\:*?"<>|]/g, "_").replace(/\s+/g, " ").trim();
|
|
71
72
|
if (!existsSync(fDestination)) { mkdirSync(fDestination, { recursive: true }); }
|
|
72
73
|
if (existsSync(file)) {
|
|
73
|
-
appendFileSync(file, metadata.raw);
|
|
74
|
+
appendFileSync(file, `${(`\n`).repeat(10)}${metadata.raw}`);
|
|
74
75
|
} else {
|
|
75
76
|
writeFileSync(file, metadata.raw);
|
|
76
77
|
}
|
|
@@ -78,50 +79,49 @@ export const updateListener = async (event: TypeEvent): Promise<void> => {
|
|
|
78
79
|
metadata.file = metadata.raw;
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
if (uploads?.
|
|
82
|
+
if (uploads?.JSON) {
|
|
82
83
|
const eDestination = settings.GlobalSettings.ArchiveSettings.EventDirectory;
|
|
83
84
|
if (eDestination) {
|
|
84
|
-
const file = (`${eDestination}/${metadata.name}_${metadata.
|
|
85
|
+
const file = (`${eDestination}/${metadata.name}_${metadata.tracking}.json`).replace(/[\\:*?"<>|]/g, "_").replace(/\s+/g, " ").trim();
|
|
85
86
|
if (!existsSync(eDestination)) { mkdirSync(eDestination, { recursive: true }); }
|
|
86
87
|
writeFileSync(file, JSON.stringify(getCleanedEvent(event), null, 2));
|
|
87
88
|
}
|
|
88
89
|
metadata.json = JSON.stringify(getCleanedEvent(event), null, 2);
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
if (settings
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
})
|
|
92
|
+
if (settings?.NotifyServer?.Enabled && notify?.Enabled && notify?.Topic) {
|
|
93
|
+
const server = settings?.NotifyServer;
|
|
94
|
+
const auth = server?.Credentials?.Username && server?.Credentials?.Password ? { username: settings?.NotifyServer?.Credentials?.Username, password: server?.Credentials?.Password } : undefined;
|
|
95
|
+
const attachment = metadata.eas && server?.Attachments ? `${server?.Attachments}/${metadata.name}_${metadata.status}_${metadata.tracking}.wav` : undefined;
|
|
96
|
+
const isRatelimited = setTimeoutAction({ identifier: metadata.tracking + `notify.server`, interval: 1, max: 1, addTime: true })
|
|
97
|
+
if (!isRatelimited.limited) {
|
|
98
|
+
await createHttp({
|
|
99
|
+
url: `${server?.Server?.replace(/\/$/, "")}/${listener?.NotificationServer?.Topic}`,
|
|
100
|
+
timeout: 15_000,
|
|
101
|
+
method: "POST",
|
|
102
|
+
...(auth && { auth }),
|
|
103
|
+
headers: {
|
|
104
|
+
"Title": `${metadata.name} (${metadata.status})`,
|
|
105
|
+
"Tags": properties.parameters.tags?.join(",") ?? "N/A",
|
|
106
|
+
"Expires": new Date(properties.expires).getTime(),
|
|
107
|
+
"Priority": notify?.Priority ? notify.Priority.toString() : "5",
|
|
108
|
+
... (attachment && { "Attach": attachment }),
|
|
109
|
+
},
|
|
110
|
+
body: getStringText(event)
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
if (webhook?.
|
|
116
|
-
const isRatelimited = setTimeoutAction({ identifier: webhook.
|
|
115
|
+
if (webhook?.Enabled && webhook?.Destination) {
|
|
116
|
+
const isRatelimited = setTimeoutAction({ identifier: webhook.Destination, interval: (webhook.Ratelimit ?? 2) * 2, max: (webhook.Ratelimit ?? 2), addTime: true })
|
|
117
117
|
const form = new FormData();
|
|
118
118
|
const embed = {
|
|
119
119
|
title: `${metadata.name} (${metadata.status})`,
|
|
120
|
-
description:
|
|
120
|
+
description: getEmebedText(event),
|
|
121
121
|
fields: [],
|
|
122
122
|
color: 16711680,
|
|
123
123
|
timestamp: new Date().toISOString(),
|
|
124
|
-
footer: { text: webhook.
|
|
124
|
+
footer: { text: webhook.Title ?? `AtmosphericX` }
|
|
125
125
|
};
|
|
126
126
|
|
|
127
127
|
if (isRatelimited.limited) { return }
|
|
@@ -146,15 +146,15 @@ export const updateListener = async (event: TypeEvent): Promise<void> => {
|
|
|
146
146
|
});
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
if (uploads?.
|
|
149
|
+
if (uploads?.File) {
|
|
150
150
|
form.append("fUpload", new Blob([Buffer.from(metadata.file)], {type: "application/text"}), `${properties.event}_${properties.status}_${properties.metadata.tracking}.txt`)
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
if (uploads?.
|
|
153
|
+
if (uploads?.JSON) {
|
|
154
154
|
form.append("fUpload2", new Blob([Buffer.from(metadata.json)], {type: "application/json"}), `${properties.event}_${properties.status}_${properties.metadata.tracking}.json`)
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
if (uploads?.
|
|
157
|
+
if (uploads?.EAS) {
|
|
158
158
|
if (metadata.eas) {
|
|
159
159
|
const file = readFileSync(metadata.eas)
|
|
160
160
|
form.append("fEas", new Blob([Buffer.from(file)], { type: "audio/mpeg" }), `${properties.event}_${properties.status}_${properties.metadata.tracking}_eas.mp3`)
|
|
@@ -162,13 +162,13 @@ export const updateListener = async (event: TypeEvent): Promise<void> => {
|
|
|
162
162
|
}
|
|
163
163
|
|
|
164
164
|
form.append("payload_json", JSON.stringify({
|
|
165
|
-
username: webhook.
|
|
166
|
-
content: webhook.
|
|
165
|
+
username: webhook.Title ?? "AtmosphericX",
|
|
166
|
+
content: webhook.Message ?? "",
|
|
167
167
|
embeds: [embed]
|
|
168
168
|
}));
|
|
169
169
|
|
|
170
170
|
await createHttp({
|
|
171
|
-
url: webhook.
|
|
171
|
+
url: webhook.Destination,
|
|
172
172
|
timeout: 15e3,
|
|
173
173
|
method: `POST`,
|
|
174
174
|
body: form
|
|
@@ -41,6 +41,7 @@ export const setTimeoutAction = (options: SetTimeoutActionOptions): SetTimeoutAc
|
|
|
41
41
|
}
|
|
42
42
|
if (options?.expire) {
|
|
43
43
|
delete bootstrap.ratelimits[options?.identifier];
|
|
44
|
+
return { limited: false };
|
|
44
45
|
}
|
|
45
46
|
if (target?.length > 0) {
|
|
46
47
|
bootstrap.ratelimits[options?.identifier] = target.filter((ts: number) => Date.now() - ts < options?.interval * 1000);
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
import { TypeEvent } from "../../@types/type.event"
|
|
21
21
|
|
|
22
|
-
export const
|
|
22
|
+
export const getEmebedText = (event: TypeEvent): string => {
|
|
23
23
|
const line = (label: string, value: unknown, condition = true) => condition && value ? `${label} ${value}` : null;
|
|
24
24
|
const isStatement = event.properties.status_metadata.is_statement;
|
|
25
25
|
const isExpired = event.properties.status_metadata.is_expired;
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
import { TypeEvent } from "../../@types/type.event"
|
|
21
21
|
|
|
22
|
-
export const
|
|
22
|
+
export const getStringText = (event: TypeEvent): string => {
|
|
23
23
|
const line = (label: string, value: unknown, condition = true) => condition && value ? `${label} ${value}` : null;
|
|
24
24
|
const isStatement = event.properties.status_metadata.is_statement;
|
|
25
25
|
const isExpired = event.properties.status_metadata.is_expired;
|
|
@@ -18,20 +18,21 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
export type TypeListener = {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
Events: string[]
|
|
22
|
+
Webhook?: {
|
|
23
|
+
Enabled: boolean
|
|
24
|
+
Destination: string
|
|
25
|
+
Ratelimit: number
|
|
26
|
+
Title: string
|
|
27
|
+
Message: string
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
NotificationServer?: {
|
|
30
|
+
Enabled: boolean
|
|
31
|
+
Topic: string
|
|
32
|
+
Priority?: 1 | 2 | 3 | 4 | 5 | void
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
Uploads?: {
|
|
35
|
+
File?: boolean, EAS?: boolean, JSON?: boolean
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
}
|
package/src/bootstrap.ts
CHANGED
package/testing/init.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { Manager } = require(`../dist/cjs/index.cjs`)
|
|
2
2
|
|
|
3
3
|
const Client = new Manager({
|
|
4
|
-
Database: `
|
|
4
|
+
Database: `event-product-parser.db`,
|
|
5
5
|
EnableWireService: false,
|
|
6
6
|
EnableJournal: true,
|
|
7
7
|
EnableDebugging: false,
|
|
@@ -17,8 +17,8 @@ const Client = new Manager({
|
|
|
17
17
|
},
|
|
18
18
|
CacheSettings: {
|
|
19
19
|
Enabled: true,
|
|
20
|
-
MaxDatabaseHistory:
|
|
21
|
-
MaxRetentionHistory:
|
|
20
|
+
MaxDatabaseHistory: 50000,
|
|
21
|
+
MaxRetentionHistory: 1500,
|
|
22
22
|
},
|
|
23
23
|
StanzaSettings: {
|
|
24
24
|
DisableUGC: false,
|
|
@@ -32,12 +32,13 @@ const Client = new Manager({
|
|
|
32
32
|
},
|
|
33
33
|
BroadcastifySettings: {
|
|
34
34
|
BroadcastifyAttachments: true,
|
|
35
|
+
BroadcastifyDatabase: `https://scriptkitty.cafe/ftp/@atmosphericx/assets/broadcastify.json`,
|
|
35
36
|
BroadcastifyTags: [`Public Safety`, `Amateur Radio`, `Other`, `Rail`, `Aviation`, `Marine`, `Disaster Event`, `Special Event`]
|
|
36
37
|
},
|
|
37
38
|
NotifyServer: {
|
|
38
39
|
Enabled: false,
|
|
39
|
-
Server: "https://ntfy.
|
|
40
|
-
Attachments: "https://
|
|
40
|
+
Server: "https://ntfy.scriptkitty.cafe",
|
|
41
|
+
Attachments: "https://scriptkitty.cafe/ftp/@bucket/EAS/encoded",
|
|
41
42
|
Credentials: {
|
|
42
43
|
Username: "username",
|
|
43
44
|
Password: "password"
|
|
@@ -45,22 +46,16 @@ const Client = new Manager({
|
|
|
45
46
|
},
|
|
46
47
|
ListenerSettings: [
|
|
47
48
|
{
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
message: "<@&XXXXXXXXXXXXXXXXXXXXX>",
|
|
54
|
-
ratelimit: 1
|
|
49
|
+
Events: ["*Extreme Heat Warning*"],
|
|
50
|
+
NotificationServer: {
|
|
51
|
+
Enabled: false,
|
|
52
|
+
Topic: "heat-warnings",
|
|
53
|
+
Priority: 5
|
|
55
54
|
},
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
uploads: {
|
|
61
|
-
eas: true,
|
|
62
|
-
file: true,
|
|
63
|
-
event: true
|
|
55
|
+
Uploads: {
|
|
56
|
+
EAS: true,
|
|
57
|
+
File: true,
|
|
58
|
+
JSON: true
|
|
64
59
|
}
|
|
65
60
|
}
|
|
66
61
|
],
|
|
@@ -72,35 +67,25 @@ const Client = new Manager({
|
|
|
72
67
|
SPCWatchesOnly: true,
|
|
73
68
|
ShapefileSkipPoints: 0,
|
|
74
69
|
NodeTTL: 60,
|
|
75
|
-
NodeMinDistance:
|
|
70
|
+
NodeMinDistance: 125,
|
|
76
71
|
EventFiltering: {
|
|
77
72
|
ListeningEvents: [
|
|
78
|
-
|
|
79
|
-
"*Blizzard*", "*Ice Storm*", "*Winter Storm*", "*Snow Squall*",
|
|
80
|
-
"Tornado Emergency", "*Tornado Warning*",
|
|
81
|
-
"Special Weather Statement", "Marine Weather Statement",
|
|
82
|
-
"*Tsunami*", "*Hurricane*", "*Tropical Storm*", "*Special Marine*",
|
|
83
|
-
"*Flash Flood Warning*", "*Flash Flood Watch*", "*Flash Flood Advisory*",
|
|
84
|
-
"Mesoscale Discussion",
|
|
85
|
-
"*Storm Prediction Center*",
|
|
86
|
-
"PDS Tornado Watch", "Tornado Watch", "Severe Thunderstorm Watch", "Flash Flood Watch", "PDS Severe Thunderstorm Watch",
|
|
87
|
-
"*Administrative*", "National Weather Service Policy",
|
|
88
|
-
"Fire Weather Warning", "Fire Weather Watch", "Fire Weather Advisory",
|
|
73
|
+
"*Warning*"
|
|
89
74
|
],
|
|
90
|
-
ListeningICAO: [
|
|
75
|
+
ListeningICAO: [],
|
|
76
|
+
ListeningUGC: [],
|
|
77
|
+
ListeningStates: [],
|
|
91
78
|
IgnoredICAO: [],
|
|
92
79
|
IgnoredEvents: [],
|
|
93
|
-
ListeningUGC: [`WIC001`],
|
|
94
|
-
ListeningStates: [`MO`, `IA`],
|
|
95
80
|
NodeLocationFiltering: false,
|
|
96
81
|
IgnoreTestProducts: true,
|
|
97
82
|
},
|
|
98
83
|
ArchiveSettings: {
|
|
99
|
-
TTL:
|
|
100
|
-
EventDirectory:
|
|
101
|
-
TextDirectory:
|
|
102
|
-
EasDirectory:
|
|
103
|
-
EasToneout: `
|
|
84
|
+
TTL: 30,
|
|
85
|
+
EventDirectory: `@bucket/ParsedProducts`,
|
|
86
|
+
TextDirectory: `@bucket/RawTextProducts`,
|
|
87
|
+
EasDirectory: `@bucket/EAS`,
|
|
88
|
+
EasToneout: `eas-toneout.wav`,
|
|
104
89
|
}
|
|
105
90
|
}
|
|
106
|
-
})
|
|
91
|
+
})
|