@atmosx/event-product-parser 3.0.4 → 3.0.42

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.
@@ -47,7 +47,7 @@ export const startService = async (configurations: TypeSettings): Promise<void>
47
47
  await setCronSchedule()
48
48
  let scheduleInterval = !settings.EnableWireService ? settings.NationalWeatherServiceSettings.CallbackInterval : 1;
49
49
  if (!settings.EnableWireService && scheduleInterval < 15) {
50
- setWarning({ message: `Schedule Interval of ${scheduleInterval} seconds is too low, setting to 15 seconds` })
50
+ setWarning({ message: `Schedule interval of ${scheduleInterval} seconds is too low, setting to 15 seconds` })
51
51
  bootstrap.settings.NationalWeatherServiceSettings.CallbackInterval = 15;
52
52
  scheduleInterval = 15;
53
53
  }
@@ -18,6 +18,7 @@
18
18
  */
19
19
 
20
20
  export const officeICAOs: Record<string, string> = {
21
+ "KLUB": "Lubbock, TX",
21
22
  "KLCH": "Lake Charles, LA",
22
23
  "TSTL": "St. Louis, MO",
23
24
  "PABC": "Bethel, AK",
@@ -253,5 +254,6 @@ export const officeICAOs: Record<string, string> = {
253
254
  "KCAR": "Caribou, ME",
254
255
  "KMFR": "Medford, OR",
255
256
  "PGUM": "Guam, GU",
257
+ "PACR": "Cordova, AK",
256
258
  "PAJK": "Juneau, AK"
257
259
  };
@@ -17,11 +17,11 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeEvent } from "../../@types/type.event";
21
- import { setTimeoutAction } from "./utilities.setTimeoutAction"
22
- import { createHttp } from "./utilities.createHttp"
23
- import { TypeWebhook } from "../../@types/types.webhook";
24
- import { getCleanedEvent } from "../../@building/building.clean";
20
+ import { TypeEvent } from "../@types/type.event";
21
+ import { setTimeoutAction } from "../@modules/@utilities/utilities.setTimeoutAction"
22
+ import { createHttp } from "../@modules/@utilities/utilities.createHttp"
23
+ import { TypeWebhook } from "../@types/types.webhook";
24
+ import { getCleanedEvent } from "../@building/building.clean";
25
25
  import FormData from "form-data";
26
26
 
27
27
  interface CreateWebhookOptions {
@@ -35,7 +35,7 @@ export const createWebhook = async (options: CreateWebhookOptions): Promise<void
35
35
 
36
36
  let body = [
37
37
  event.locations ? `**Locations**: ${event.locations.slice(0,100)}` : null,
38
- event.issued ? `**Issued**: <t:${Math.floor(new Date(event.issued).getTime()/1000)}:R>` : null,
38
+ event.issued && event.status != `Expired` ? `**Issued**: <t:${Math.floor(new Date(event.issued).getTime()/1000)}:R>` : null,
39
39
  event.expires && event.status != `Statement` ? `**Expires**: <t:${Math.floor(new Date(event.expires).getTime()/1000)}:R>` : null,
40
40
  (() => {
41
41
  const val = event.parameters.estimated_wind_gusts ?? null
@@ -46,7 +46,7 @@ export const createWebhook = async (options: CreateWebhookOptions): Promise<void
46
46
  (() => {
47
47
  const val = event.parameters.estimated_hail_size ?? null
48
48
  const th = event.parameters.hail_threat ?? null
49
- return (val || th) ? `**Hail Threat**: ${val} ${th ? `(${th})` : ''}` : null;
49
+ return (val ?? th) ? `**Hail Threat**: ${val} ${th ? `(${th})` : ''}` : null;
50
50
  })(),
51
51
  event.parameters.damage_threat ? `**Damage Threat**: ${event.parameters.damage_threat}` : null,
52
52
  event.parameters.flood_threat ? `**Flood Threat**: ${event.parameters.flood_threat}` : null,
@@ -69,11 +69,13 @@ export const createWebhook = async (options: CreateWebhookOptions): Promise<void
69
69
  (() => {
70
70
  const val = event.geocode?.office?.name ?? `N/A`
71
71
  const th = event.geocode?.office?.office ?? null
72
- return (val || th) ? `**Sender**: ${val} ${th ? `(${th})` : ''}` : null;
72
+ return (val ?? th) ? `**Sender**: ${val} ${th ? `(${th})` : ''}` : null;
73
73
  })(),
74
74
  event.metadata?.tracking ? `**Tracking**: ${event.metadata.tracking}` : null,
75
+ event.metadata.history?.length > 0 ? `**Logs**: ${event.metadata.history.length}` : null,
75
76
  (() => {
76
- const desc = (event.description || '').split('\n').map(l => l.trim()).filter(Boolean).join('\n');
77
+ if (event.status == `Expired`) { return null }
78
+ const desc = (event.description ?? '').split('\n').map(l => l.trim()).filter(Boolean).join('\n');
77
79
  return desc ? '```' + '\n' + desc + '\n' + '```' : null;
78
80
  })(),
79
81
  ].filter(Boolean).join('\n');
@@ -83,7 +85,7 @@ export const createWebhook = async (options: CreateWebhookOptions): Promise<void
83
85
 
84
86
  if (body.length > 1900) {
85
87
  body = body.substring(0, 1900) + "\n\n[Message truncated due to length]";
86
- const blocks = (body.match(/```/g) || []).length;
88
+ const blocks = (body.match(/```/g) ?? []).length;
87
89
  if (blocks % 2 !== 0) body += "```";
88
90
  }
89
91
  const form = new FormData();
@@ -28,22 +28,15 @@ import { TypeSettings } from "../@types/types.settings";
28
28
  export const mkEvent = async (event: TypeEvent): Promise<void> => {
29
29
  const settings = bootstrap.settings as TypeSettings;
30
30
  const features = bootstrap.cache.events.features;
31
- const map = new Map<string, typeof features[0]>();
32
-
33
- for (const f of features) {
34
- const key = f?.properties?.metadata?.tracking;
35
- if (!key) continue;
36
- map.set(key, f);
37
- }
38
-
31
+
39
32
  const getHash = event.properties.metadata.hash;
40
33
  const getTracking = event.properties.metadata.tracking;
41
34
  const isEntry = bootstrap.cache.hashes?.find(hash => hash.tracking === getTracking)
42
35
  const isHashed = isEntry?.hashes?.includes(getHash) ?? false;
43
- const getFeature = map.get(getTracking);
44
-
36
+ const getFeature = features.find(feature => feature.properties.metadata.tracking === getTracking);
45
37
  if (isHashed || event.properties.status_metadata.is_expired) return
46
- await setHash(event, isEntry)
38
+ setHash(event, isEntry)
39
+
47
40
  const isFilteredLocation = await updateNode(event).then(() => event.properties.metadata.filtered_proximity);
48
41
  if (!isFilteredLocation && settings.GlobalSettings.EventFiltering.NodeLocationFiltering) { return }
49
42
 
@@ -67,7 +60,7 @@ export const mkEvent = async (event: TypeEvent): Promise<void> => {
67
60
  const iLocations = event.properties?.locations?.split(";").map((l: string) => l.trim()) ?? [];
68
61
  const iUgc = event.properties?.geocode?.ugc ?? [];
69
62
 
70
- const mHistory = [...cHistory, ...iHistory].filter((v, i, a) => a.indexOf(v) === i);
63
+ const mHistory = [...cHistory, ...iHistory].filter((v, i, a) => a.indexOf(v) === i).filter((v, i, a) => a.findIndex(h => h.description === v.description && h.issued === v.issued) === i);
71
64
  const mLocations = [...cLocations, ...iLocations].filter((v, i, a) => a.indexOf(v) === i).join('; ');
72
65
  const mUgc = [...cUgc, ...iUgc].filter((v, i, a) => a.indexOf(v) === i);
73
66
 
@@ -22,7 +22,7 @@ import { TypeHash } from "../@types/types.hash"
22
22
  import { bootstrap } from "../bootstrap"
23
23
 
24
24
 
25
- export const setHash = async (event: TypeEvent, entry: TypeHash): Promise<void> => {
25
+ export const setHash = (event: TypeEvent, entry: TypeHash): void => {
26
26
  if (entry) {
27
27
  entry.hashes.push(event.properties.metadata.hash);
28
28
  entry.expires = event.properties.expires;
@@ -17,12 +17,11 @@
17
17
 
18
18
  */
19
19
 
20
- import { createWebhook } from "../@modules/@utilities/utilities.createWebhook";
20
+ import { createWebhook } from "./manager.createWebhook";
21
21
  import { TypeEvent } from "../@types/type.event";
22
22
  import { TypeWebhook } from "../@types/types.webhook";
23
23
  import { bootstrap } from "../bootstrap"
24
24
 
25
-
26
25
  export const updateWebhooks = async (event: TypeEvent): Promise<void> => {
27
26
  const settings = bootstrap.settings;
28
27
  const webhooks = settings.WebhookSettings as TypeWebhook[];
@@ -45,7 +45,7 @@ export const setTimeoutAction = (options: SetTimeoutActionOptions): SetTimeoutAc
45
45
 
46
46
  const oldestTimestamp = target?.[0];
47
47
  const getWait = oldestTimestamp ? Math.ceil((options?.interval * 1000) - (Date.now() - oldestTimestamp)) : 0;
48
- const max = options?.max || 1;
48
+ const max = options?.max ?? 1;
49
49
 
50
50
  if (target?.length >= max && getWait > 0) {
51
51
  return {
@@ -26,7 +26,7 @@ export const xReconnect = async (interval: number): Promise<void> => {
26
26
  const settings = bootstrap.settings as TypeSettings;
27
27
  const lastStanza = Date.now() - bootstrap.cache.lastStanza
28
28
  if (interval < 15) {
29
- setWarning({ message: `Reconnection Interval of ${interval} seconds is too low, setting to 15 seconds` })
29
+ setWarning({ message: `Reconnection interval of ${interval} seconds is too low, setting to 15 seconds` })
30
30
  interval = 15;
31
31
  bootstrap.settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval = 15;
32
32
  }
@@ -35,7 +35,7 @@ export const pvExtract = (message: string): TypePVTEC[] | null => {
35
35
  vtecs.push({
36
36
  vtec: vtec,
37
37
  product: eventProducts[sub[0]],
38
- tracking: `${sub[2]}-${sub[3]}-${sub[4]}-${sub[5]}`,
38
+ tracking: `${sub[2]}.${sub[3]}.${sub[4]}.${sub[5]}`,
39
39
  event: `${eventTypes[sub[3]]} ${eventActions[sub[4]]}`,
40
40
  status: eventStatus[sub[1]],
41
41
  organization: message.match(regExp.wmo)?.[0] ?? null,
@@ -70,7 +70,7 @@ export const getZonePolygon = (options: CoordinatesOptions): CoordinatesResponse
70
70
  }
71
71
  if (!bestPoly || bestPoly.length === 0) return null;
72
72
  const outerRing = bestPoly[0];
73
- const skip = Math.max(1, parseInt(String(bootstrap.settings.GlobalSettings.ShapefileSkipPoints), 10) || 1);
73
+ const skip = Math.max(1, parseInt(String(bootstrap.settings.GlobalSettings.ShapefileSkipPoints), 10) ?? 1);
74
74
  let skipped = outerRing.filter((_: any, idx: number) => idx % skip === 0);
75
75
  if (skipped.length < 4) {
76
76
  skipped = outerRing.slice();
@@ -89,7 +89,7 @@ export const getZonePolygon = (options: CoordinatesOptions): CoordinatesResponse
89
89
  }
90
90
  }
91
91
  if (multi.length === 0) return null;
92
- const skip = Math.max(1, parseInt(String(bootstrap.settings.GlobalSettings.ShapefileSkipPoints), 10) || 1);
92
+ const skip = Math.max(1, parseInt(String(bootstrap.settings.GlobalSettings.ShapefileSkipPoints), 10) ?? 1);
93
93
  if (skip > 1) {
94
94
  for (let p = 0; p < multi.length; p++) {
95
95
  for (let r = 0; r < multi[p].length; r++) {
package/src/bootstrap.ts CHANGED
@@ -21,7 +21,7 @@ import path from 'path'
21
21
  import { EventEmitter } from 'node:events';
22
22
 
23
23
  export const bootstrap = {
24
- version: `3.0.3`,
24
+ version: `3.0.42`,
25
25
  isReady: true,
26
26
  ratelimits: {},
27
27
  session_xmpp: null,
package/src/index.ts CHANGED
@@ -31,6 +31,7 @@ import { setNode } from "./@core/core.setNode"
31
31
  import { getEvents } from "./@core/core.getEvents"
32
32
  import { getNodes } from "./@core/core.getNodes"
33
33
  import { getRandomEvent } from './@core/core.getRandomEvent';
34
+ import { query } from './@core/core.query';
34
35
  import { clearEvents } from './@core/core.clearEvents';
35
36
 
36
37
  export class Manager {
@@ -55,7 +56,7 @@ export class Manager {
55
56
  })
56
57
  return;
57
58
  }
58
- setWarning({message: `Uncaught Exception: ${err instanceof Error ? err.stack || err.message : String(err)}`})
59
+ setWarning({message: `Uncaught Exception: ${err instanceof Error ? err.stack ?? err.message : String(err)}`})
59
60
  })
60
61
  }
61
62
  }
@@ -66,7 +67,7 @@ export {
66
67
  setSettings, getEventGeometry,
67
68
  getCleanedEvent, stopService, clearEvents,
68
69
  startService, setNode, getRandomEvent,
69
- getEvents, getNodes, setEasTone
70
+ getEvents, getNodes, setEasTone, query
70
71
  }
71
72
 
72
73