@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
@@ -17,23 +17,23 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeHVTEC } from "../../@types/types.hvtec";
21
- import { eventCauses } from "../../@dictionaries/dictionaries.eventCauses";
22
- import { eventRecords } from "../../@dictionaries/dictionaries.eventRecords";
23
- import { regExp } from "../../@dictionaries/dictionaries.regExp";
24
- import { eventSeverity } from "../../@dictionaries/dictionaries.eventSeverity";
20
+ import { TypeHVTEC } from "../../@types/type.hvtec";
21
+ import { dict_causes } from "../../@dictionaries/dictionaries.causes";
22
+ import { dict_records } from "../../@dictionaries/dictionaries.records";
23
+ import { dict_expressions } from "../../@dictionaries/dictionaries.expressions";
24
+ import { dict_severity } from "../../@dictionaries/dictionaries.severity";
25
25
 
26
26
  export const hvExtract = (message: string): TypeHVTEC[] | null => {
27
- const getHVTECs = message.match(regExp.hvtec) ?? [];
27
+ const getHVTECs = message.match(dict_expressions.hvtec) ?? [];
28
28
  const vtecs: TypeHVTEC[] = [];
29
29
  for (const vtec of getHVTECs) {
30
30
  const sub = vtec.split(`.`);
31
31
  if (sub.length < 7) continue;
32
32
  vtecs.push({
33
33
  hvtec: vtec,
34
- severity: eventSeverity[sub[1]],
35
- cause: eventCauses[sub[2]],
36
- record: eventRecords[sub[6]]
34
+ severity: dict_severity[sub[1]],
35
+ cause: dict_causes[sub[2]],
36
+ record: dict_records[sub[6]]
37
37
  })
38
38
  }
39
39
  return vtecs.length > 0 ? vtecs : null;
@@ -17,16 +17,17 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypePVTEC } from "../../@types/types.pvtec";
21
- import { regExp } from "../../@dictionaries/dictionaries.regExp";
22
- import { eventProducts } from "../../@dictionaries/dictionaries.eventProducts";
23
- import { eventTypes } from "../../@dictionaries/dictionaries.eventTypes";
24
- import { eventActions } from "../../@dictionaries/dictionaries.eventActions";
25
- import { eventStatus } from "../../@dictionaries/dictionaries.eventStatus";
20
+ import { TypePVTEC } from "../../@types/type.pvtec";
21
+ import { dict_expressions } from "../../@dictionaries/dictionaries.expressions";
22
+ import { dict_products } from "../../@dictionaries/dictionaries.products";
23
+ import { dict_events } from "../../@dictionaries/dictionaries.events";
24
+ import { dict_actions } from "../../@dictionaries/dictionaries.actions";
25
+ import { dict_status } from "../../@dictionaries/dictionaries.status";
26
26
  import { getExpiry } from "./pvtec.expires";
27
27
 
28
28
  export const pvExtract = (message: string): TypePVTEC[] | null => {
29
- const getVTECs = message.match(regExp.pvtec) ?? [];
29
+ if (!message) return null;
30
+ const getVTECs = message.match(dict_expressions.pvtec) ?? [];
30
31
  const vtecs: TypePVTEC[] = [];
31
32
  for (const vtec of getVTECs) {
32
33
  const sub = vtec.split(`.`);
@@ -34,15 +35,14 @@ export const pvExtract = (message: string): TypePVTEC[] | null => {
34
35
  const dates = sub[6]?.split(`-`);
35
36
  vtecs.push({
36
37
  vtec: vtec,
37
- product: eventProducts[sub[0]],
38
+ product: dict_products[sub[0]],
38
39
  tracking: `${sub[2]}.${sub[3]}.${sub[4]}.${sub[5]}`,
39
- event: `${eventTypes[sub[3]]} ${eventActions[sub[4]]}`,
40
- status: eventStatus[sub[1]],
41
- organization: message.match(regExp.wmo)?.[0] ?? null,
40
+ event: `${dict_events[sub[3]]} ${dict_actions[sub[4]]}`,
41
+ status: dict_status[sub[1]],
42
+ organization: message.match(dict_expressions.wmo)?.[0] ?? null,
42
43
  expires: getExpiry(dates),
43
44
  is_watch: (sub[4] == `A` || sub[4] == `Y`) && (sub[3] == `TO` || sub[3] == `SV`),
44
- prediction_center: sub[2] == `KWNS`
45
- ? true : false
45
+ prediction_center: sub[2] == `KWNS` ? true : false
46
46
  })
47
47
  }
48
48
  return vtecs.length > 0 ? vtecs : null;
@@ -17,7 +17,7 @@
17
17
 
18
18
  */
19
19
 
20
- import { regExp } from "../../@dictionaries/dictionaries.regExp";
20
+ import { dict_expressions } from "../../@dictionaries/dictionaries.expressions";
21
21
 
22
22
  interface GetDescriptionFromProductOptions {
23
23
  message: string
@@ -26,7 +26,7 @@ interface GetDescriptionFromProductOptions {
26
26
 
27
27
  export const getDescriptionFromProduct = (options: GetDescriptionFromProductOptions): string => {
28
28
  let message = options.message;
29
- const dates = Array.from(message.matchAll(regExp.dateline));
29
+ const dates = Array.from(message.matchAll(dict_expressions.dateline));
30
30
  if (dates.length) {
31
31
  const lastMatch = dates[dates.length - 1][0];
32
32
  const sIndx = message.lastIndexOf(lastMatch);
@@ -0,0 +1,60 @@
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
+
22
+
23
+
24
+ export const getEmebed = (event: TypeEvent): string => {
25
+ const line = (label: string, value: unknown, condition = true) => condition && value ? `${label} ${value}` : null;
26
+ const isStatement = event.properties.status_metadata.is_statement;
27
+ const isExpired = event.properties.status_metadata.is_expired;
28
+ return [
29
+ line(`**Locations:**`, event?.properties?.locations?.slice(0, 100)),
30
+ line(`**Issued:**`, `<t:${Math.floor(new Date(event.properties.issued).getTime() / 1000)}:R>`, !isExpired),
31
+ line(`**Expires:**`, `<t:${Math.floor(new Date(event.properties.expires).getTime() / 1000)}:R>`, !isStatement),
32
+ line(`**Damage Threat:**`, event?.properties?.parameters?.damage_threat, !isExpired),
33
+ line(`**Flood Threat:**`, event?.properties?.parameters?.flood_threat, !isExpired),
34
+ line(`**Tornado Threat:**`, event?.properties?.parameters?.tornado_threat, !isExpired),
35
+ line(`**Estimated Wind Gusts:**`, `${event?.properties?.parameters?.estimated_wind_gusts} ${event?.properties?.parameters?.wind_threat ? ` (${event?.properties?.parameters?.wind_threat})` : ''}`, !isExpired && event?.properties?.parameters?.estimated_wind_gusts != null),
36
+ line(`**Estimated Hail Size:**`, `${event?.properties?.parameters?.estimated_hail_size} ${event?.properties?.parameters?.hail_threat ? ` (${event?.properties?.parameters?.hail_threat})` : ''}`, !isExpired && event?.properties?.parameters?.estimated_hail_size != null),
37
+ line(`**Discussion:**`, event?.properties?.discussion_parameters?.discussion_number, !isExpired),
38
+ line(`**Concern:**`, event?.properties?.discussion_parameters?.discussion_concerning, !isExpired),
39
+ line(`**SPC Max Tornado Threat:**`, event?.properties?.discussion_parameters?.discussion_max_tornado, !isExpired),
40
+ line(`**SPC Max Hail Threat:**`, event?.properties?.discussion_parameters?.discussion_max_hail, !isExpired),
41
+ line(`**SPC Max Wind Threat:**`, event?.properties?.discussion_parameters?.discussion_max_wind, !isExpired),
42
+ line(`**SPC Watch Issuance Probability:**`, event?.properties?.discussion_parameters?.discussion_watch_issuance ? `${event?.properties?.discussion_parameters?.discussion_watch_issuance}%` : null, !isExpired),
43
+ line(`**Watch Number:**`, event?.properties?.watch_parameters?.watch_number, !isExpired),
44
+ line(`**Strong Tornadoes Probability:**`, event?.properties?.watch_parameters?.strong_tornadoes_probability ? `${event?.properties?.watch_parameters?.strong_tornadoes_probability}%` : null, !isExpired),
45
+ line(`**Additional Tornadoes Probability:**`, event?.properties?.watch_parameters?.additional_tornadoes_probability ? `${event?.properties?.watch_parameters?.additional_tornadoes_probability}%` : null, !isExpired),
46
+ line(`**Combined Hail/Wind Probability:**`, event?.properties?.watch_parameters?.combined_hail_wind_probability ? `${event?.properties?.watch_parameters?.combined_hail_wind_probability}%` : null, !isExpired),
47
+ line(`**Severe Hail Probability:**`, event?.properties?.watch_parameters?.severe_hail_probability ? `${event?.properties?.watch_parameters?.severe_hail_probability}%` : null, !isExpired),
48
+ line(`**Hail >2in Probability:**`, event?.properties?.watch_parameters?.hail_2in_probability ? `${event?.properties?.watch_parameters?.hail_2in_probability}%` : null, !isExpired),
49
+ line(`**Max Hail Inches:**`, event?.properties?.watch_parameters?.max_hail_in, !isExpired),
50
+ line(`**Severe Wind Probability:**`, event?.properties?.watch_parameters?.severe_wind_probability ? `${event?.properties?.watch_parameters?.severe_wind_probability}%` : null, !isExpired),
51
+ line(`**Max Surface Wind:**`, event?.properties?.watch_parameters?.max_wind_surface, !isExpired),
52
+ line(`**Max Tops (x100 feet):**`, event?.properties?.watch_parameters?.max_tops_x100feet, !isExpired),
53
+ line(`**Tags:**`, event?.properties?.parameters?.tags?.length > 0 ? event?.properties?.parameters?.tags.join(', ') : null, !isExpired),
54
+ line(`**Sender:**`, event?.properties?.geocode?.office?.name ? `${event?.properties?.geocode?.office?.name} (${event?.properties?.geocode?.office?.office})` : event?.properties?.geocode?.office?.office),
55
+ line(`**Tracking:**`, event?.properties?.metadata?.tracking),
56
+ line(`**Logs:**`, event?.properties?.metadata?.history?.length > 0 ? event?.properties?.metadata?.history.length : null),
57
+ line(``, event?.properties?.metadata?.attachments?.length > 0 ? `**Attachments:** ${event?.properties?.metadata?.attachments.map(attachment => `[Attachment #${event?.properties?.metadata?.attachments.indexOf(attachment) + 1}](${attachment})`).join(' | ')}` : null),
58
+ line(``, event?.properties?.description ? '```' + '\n' + event?.properties?.description.split('\n').map(l => l.trim()).filter(Boolean).join('\n') + '\n' + '```' : null, !isExpired),
59
+ ].filter(Boolean).join('\n');
60
+ }
@@ -17,7 +17,7 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeUGC } from "../../@types/types.ugc";
20
+ import { TypeUGC } from "../../@types/type.ugc";
21
21
  import { getUGCHeader } from "./ugc.header"
22
22
  import { getZones } from "./ugc.zones";
23
23
  import { getExpiry } from './ugc.expiry';
@@ -17,12 +17,12 @@
17
17
 
18
18
  */
19
19
 
20
- import { regExp } from "../../@dictionaries/dictionaries.regExp"
20
+ import { dict_expressions } from "../../@dictionaries/dictionaries.expressions"
21
21
 
22
22
  export const getUGCHeader = (message: string): string | null => {
23
- const start = message.search(regExp.ugc1)
23
+ const start = message.search(dict_expressions.ugc1)
24
24
  const sub = message.substring(start)
25
- const end = sub.search(regExp.ugc2)
25
+ const end = sub.search(dict_expressions.ugc2)
26
26
  const fin = sub.substring(0, end)
27
27
  .replace(/\s+/g, '')
28
28
  .slice(0, -1);
@@ -17,7 +17,7 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeAttributes } from "./types.attributes"
20
+ import { TypeAttributes } from "./type.attributes"
21
21
 
22
22
  export type TypeStanzaCompiled = {
23
23
  message?: string
@@ -18,8 +18,8 @@
18
18
  */
19
19
 
20
20
  import { TypeEventProperties as BaseTypeEventProperties } from "./type.properties";
21
- import { TypeHVTEC } from "../@types/types.hvtec";
22
- import { TypePVTEC } from "./types.pvtec";
21
+ import { TypeHVTEC } from "./type.hvtec";
22
+ import { TypePVTEC } from "./type.pvtec";
23
23
 
24
24
  export type TypeEvent = {
25
25
  type: string
@@ -46,8 +46,8 @@ export type TypeEvent = {
46
46
  tracking: string
47
47
  hash?: string
48
48
  header: string
49
- vtec: TypePVTEC | null
50
- hvtec: TypeHVTEC[]
49
+ vtec?: TypePVTEC | null
50
+ hvtec?: TypeHVTEC[] | null
51
51
  nodes?: {
52
52
  id?: string | number
53
53
  coordinates: [number, number]
@@ -63,6 +63,8 @@ export type TypeEvent = {
63
63
  issued: string
64
64
  status: string
65
65
  }[]
66
+ attachments?: string[]
67
+ raw: string
66
68
  }
67
69
  } & BaseTypeEventProperties
68
70
  }
@@ -17,11 +17,16 @@
17
17
 
18
18
  */
19
19
 
20
- export type TypeWebhook = {
21
- webhook: string
22
- title: string
23
- message: string
24
- upload: boolean
25
- rate: number
20
+ export type TypeListener = {
26
21
  events: string[]
22
+ webhook?: {
23
+ enabled: boolean
24
+ destination: string
25
+ ratelimit: number
26
+ title: string
27
+ message: string
28
+ }
29
+ uploads?: {
30
+ file?: boolean, eas?: boolean
31
+ }
27
32
  }
@@ -17,12 +17,12 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeAttributes } from "./types.attributes";
20
+ import { TypeAttributes } from "./type.attributes";
21
21
 
22
22
  export type TypeEventProperties = {
23
23
  locations: string
24
24
  description: string
25
- attributes: TypeAttributes
25
+ attributes?: TypeAttributes
26
26
  geocode: {
27
27
  office: {
28
28
  name: string
@@ -33,7 +33,7 @@ export type TypeEventProperties = {
33
33
  polygon: string
34
34
  polygon_generated: boolean
35
35
  }
36
- parameters: {
36
+ parameters?: {
37
37
  tags: string[]
38
38
  instructions: string
39
39
  source: string
@@ -66,10 +66,12 @@ export type TypeEventProperties = {
66
66
  max_tops_x100feet: string
67
67
  pds_watch: boolean
68
68
  }
69
- spc_parameters: {
70
- spc_max_tornado: string
71
- spc_max_hail: string
72
- spc_max_wind: string
73
- spc_watch_issuance: string
69
+ discussion_parameters?: {
70
+ discussion_number: string
71
+ discussion_concerning: string
72
+ discussion_max_tornado: string
73
+ discussion_max_hail: string
74
+ discussion_max_wind: string
75
+ discussion_watch_issuance: string
74
76
  }
75
77
  }
@@ -17,7 +17,7 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeWebhook } from "./types.webhook"
20
+ import { TypeListener } from "./type.listener"
21
21
 
22
22
  export type TypeSettings = {
23
23
  Database: string
@@ -57,7 +57,7 @@ export type TypeSettings = {
57
57
  ShapefileSkipPoints: number
58
58
  NodeTTL: number
59
59
  NodeMinDistance: number
60
- WebhookSettings?: TypeWebhook
60
+ ListenerSettings?: TypeListener[]
61
61
  EventFiltering: {
62
62
  ListeningEvents: string[]
63
63
  ListeningICAO: string[]
@@ -68,9 +68,11 @@ export type TypeSettings = {
68
68
  NodeLocationFiltering: boolean
69
69
  IgnoreTestProducts: boolean
70
70
  },
71
- EASSettings: {
72
- ArchiveDirectory: string,
73
- IntroWavFile: string,
71
+ ArchiveSettings: {
72
+ TTL: number,
73
+ TextDirectory: string
74
+ EasDirectory: string
75
+ EasToneout: string
74
76
  }
75
77
  }
76
78
  }
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.42`,
24
+ version: `3.0.46`,
25
25
  isReady: true,
26
26
  ratelimits: {},
27
27
  session_xmpp: null,
@@ -72,7 +72,7 @@ export const bootstrap = {
72
72
  CallbackInterval: 15,
73
73
  EventsEndpoint: `https://api.weather.gov/alerts/active`,
74
74
  },
75
- WebhookSettings: [],
75
+ ListenerSettings: [],
76
76
  GlobalSettings: {
77
77
  EventManagement: true,
78
78
  BetterEventNames: true,
@@ -92,9 +92,11 @@ export const bootstrap = {
92
92
  NodeLocationFiltering: false,
93
93
  IgnoreTestProducts: true,
94
94
  },
95
- EASSettings: {
96
- ArchiveDirectory: null,
97
- IntroWavFile: null,
95
+ ArchiveSettings: {
96
+ TTL: 60,
97
+ TextDirectory: null,
98
+ EasDirectory: null,
99
+ EasToneout: null
98
100
  }
99
101
  }
100
102
  },
package/src/index.ts CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeSettings } from './@types/types.settings'
20
+ import { TypeSettings } from './@types/type.settings'
21
21
  import { setSettings } from "./@modules/@utilities/utilities.setSettings"
22
22
  import { getEventGeometry } from "./@building/building.geometry";
23
23
  import { getCleanedEvent } from "./@building/building.clean"
@@ -30,6 +30,7 @@ import { setEasTone } from './@modules/@eas/eas.setEasTone';
30
30
  import { setNode } from "./@core/core.setNode"
31
31
  import { getEvents } from "./@core/core.getEvents"
32
32
  import { getNodes } from "./@core/core.getNodes"
33
+ import { createEvent } from "./@core/core.createEvent"
33
34
  import { getRandomEvent } from './@core/core.getRandomEvent';
34
35
  import { query } from './@core/core.query';
35
36
  import { clearEvents } from './@core/core.clearEvents';
@@ -64,7 +65,7 @@ export class Manager {
64
65
  export default Manager;
65
66
  export type { TypeEvent } from './@types/type.event';
66
67
  export {
67
- setSettings, getEventGeometry,
68
+ setSettings, getEventGeometry, createEvent,
68
69
  getCleanedEvent, stopService, clearEvents,
69
70
  startService, setNode, getRandomEvent,
70
71
  getEvents, getNodes, setEasTone, query
package/test.js CHANGED
@@ -1,7 +1,7 @@
1
1
  const { Manager, setSettings, getSettings, getListener } = require(`../dist/cjs/index.cjs`)
2
2
 
3
3
  const NOAAWeatherWireService = new Manager({
4
- Database: `shapefile-manager.db`,
4
+ Database: `shapefiles.db`,
5
5
  EnableWireService: false,
6
6
  EnableJournal: true,
7
7
  NOAAWeatherWireServiceSettings: {
@@ -29,22 +29,20 @@ const NOAAWeatherWireService = new Manager({
29
29
  CallbackInterval: 30,
30
30
  EventsEndpoint: `https://api.weather.gov/alerts/active`,
31
31
  },
32
- WebhookSettings: [
32
+ ListenerSettings: [
33
33
  {
34
- webhook: "https://discord.com/api/webhooks/XXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
35
- title: "AtmosphericX - (Severe Weather Events)",
36
- message: `<@user_id>`,
37
- upload: true,
38
- events: [`Severe Thunderstorm Warning`, `Radar Indicated Tornado Warning`],
39
- rate: 1,
40
- },
41
- {
42
- webhook: "https://discord.com/api/webhooks/XXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
43
- title: "AtmosphericX - (All Events)",
44
- message: `<@user_id>`,
45
- upload: false,
46
- events: [],
47
- rate: 5,
34
+ events: [`*Thunderstorm Warning*`, `* Watch`],
35
+ webhook: {
36
+ enabled: true,
37
+ destination: "https://discord.com/api/XXXXXXXXXX/XXXXXXXXXXX",
38
+ title: "AtmosphericX - (Thunderstorm Warnings and Watches)",
39
+ message: "<@&XXXXXXXXXXXXXXXXXXXXX>",
40
+ ratelimit: 1
41
+ },
42
+ uploads: {
43
+ eas: true,
44
+ file: true
45
+ }
48
46
  }
49
47
  ],
50
48
  GlobalSettings: {
@@ -83,9 +81,11 @@ const NOAAWeatherWireService = new Manager({
83
81
  NodeLocationFiltering: false,
84
82
  IgnoreTestProducts: true,
85
83
  },
86
- EASSettings: {
87
- ArchiveDirectory: null,
88
- IntroWavFile: null,
84
+ ArchiveSettings: {
85
+ TTL: 600,
86
+ TextDirectory: `Storage/TextProducts`,
87
+ EasDirectory: `Storage/EasScenarios`,
88
+ EasToneout: `tone.wav`,
89
89
  }
90
90
  }
91
91
  })
@@ -1,68 +0,0 @@
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
- export const transcribedMessageReplacements: { regex: RegExp, replacement: string }[] = [
21
- { regex: /\*/g, replacement: "" },
22
- { regex: /\.{3,}/g, replacement: "" },
23
- { regex: /\bUTC\b/g, replacement: 'Coordinated Universal Time' },
24
- { regex: /\bGMT\b/g, replacement: 'Greenwich Mean Time' },
25
- { regex: /\bEST\b(?!\w)/g, replacement: 'Eastern Standard Time' },
26
- { regex: /\bEDT\b(?!\w)/g, replacement: 'Eastern Daylight Time' },
27
- { regex: /\bCST\b(?!\w)/g, replacement: 'Central Standard Time' },
28
- { regex: /\bCDT\b(?!\w)/g, replacement: 'Central Daylight Time' },
29
- { regex: /\bMST\b(?!\w)/g, replacement: 'Mountain Standard Time' },
30
- { regex: /\bMDT\b(?!\w)/g, replacement: 'Mountain Daylight Time' },
31
- { regex: /\bPST\b(?!\w)/g, replacement: 'Pacific Standard Time' },
32
- { regex: /\bPDT\b(?!\w)/g, replacement: 'Pacific Daylight Time' },
33
- { regex: /\bAKST\b(?!\w)/g, replacement: 'Alaska Standard Time' },
34
- { regex: /\bAKDT\b(?!\w)/g, replacement: 'Alaska Daylight Time' },
35
- { regex: /\bHST\b(?!\w)/g, replacement: 'Hawaii Standard Time' },
36
- { regex: /\bHDT\b(?!\w)/g, replacement: 'Hawaii Daylight Time' },
37
- { regex: /\bmph\b(?!\w)/g, replacement: 'miles per hour' },
38
- { regex: /\bkm\/h\b(?!\w)/g, replacement: 'kilometers per hour' },
39
- { regex: /\bkmh\b(?!\w)/g, replacement: 'kilometers per hour' },
40
- { regex: /\bkt\b(?!\w)/g, replacement: 'knots' },
41
- { regex: /\bNE\b(?!\w)/g, replacement: 'northeast' },
42
- { regex: /\bNW\b(?!\w)/g, replacement: 'northwest' },
43
- { regex: /\bSE\b(?!\w)/g, replacement: 'southeast' },
44
- { regex: /\bSW\b(?!\w)/g, replacement: 'southwest' },
45
- { regex: /\bNM\b(?!\w)/g, replacement: 'nautical miles' },
46
- { regex: /\bdeg\b(?!\w)/g, replacement: 'degrees' },
47
- { regex: /\btstm\b(?!\w)/g, replacement: 'thunderstorm' },
48
- { regex: /\bmm\b(?!\w)/g, replacement: 'millimeters' },
49
- { regex: /\bcm\b(?!\w)/g, replacement: 'centimeters' },
50
- { regex: /\bin.\b(?!\w)/g, replacement: 'inches' },
51
- { regex: /\bft\b(?!\w)/g, replacement: 'feet' },
52
- { regex: /\bmi\b(?!\w)/g, replacement: 'miles' },
53
- { regex: /\bhr\b(?!\w)/g, replacement: 'hour' },
54
- { regex: /\bhourly\b(?!\w)/g, replacement: 'per hour' },
55
- { regex: /\bkg\b(?!\w)/g, replacement: 'kilograms' },
56
- { regex: /\bg\/kg\b(?!\w)/g, replacement: 'grams per kilogram' },
57
- { regex: /\bmb\b(?!\w)/g, replacement: 'millibars' },
58
- { regex: /\bhPa\b(?!\w)/g, replacement: 'hectopascals' },
59
- { regex: /\bPa\b(?!\w)/g, replacement: 'pascals' },
60
- { regex: /\bKPa\b(?!\w)/g, replacement: 'kilopascals' },
61
- { regex: /\bC\/hr\b(?!\w)/g, replacement: 'degrees Celsius per hour' },
62
- { regex: /\bF\/hr\b(?!\w)/g, replacement: 'degrees Fahrenheit per hour' },
63
- { regex: /\bC\/min\b(?!\w)/g, replacement: 'degrees Celsius per minute' },
64
- { regex: /\bF\/min\b(?!\w)/g, replacement: 'degrees Fahrenheit per minute' },
65
- { regex: /\bC\b(?!\w)/g, replacement: 'degrees Celsius' },
66
- { regex: /\bF\b(?!\w)/g, replacement: 'degrees Fahrenheit' },
67
- ];
68
-
@@ -1,117 +0,0 @@
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 { 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
- import FormData from "form-data";
26
-
27
- interface CreateWebhookOptions {
28
- webhook: TypeWebhook
29
- event: TypeEvent
30
- }
31
-
32
- export const createWebhook = async (options: CreateWebhookOptions): Promise<void> => {
33
- const event = options.event.properties;
34
- const settings = options.webhook;
35
-
36
- let body = [
37
- event.locations ? `**Locations**: ${event.locations.slice(0,100)}` : null,
38
- event.issued && event.status != `Expired` ? `**Issued**: <t:${Math.floor(new Date(event.issued).getTime()/1000)}:R>` : null,
39
- event.expires && event.status != `Statement` ? `**Expires**: <t:${Math.floor(new Date(event.expires).getTime()/1000)}:R>` : null,
40
- (() => {
41
- const val = event.parameters.estimated_wind_gusts ?? null
42
- const th = event.parameters.wind_threat ?? null
43
- const combined = [val, th].filter(Boolean).join(' ');
44
- return combined ? `**Wind Gusts**: ${val} ${th ? `(${th})` : ''}` : null;
45
- })(),
46
- (() => {
47
- const val = event.parameters.estimated_hail_size ?? null
48
- const th = event.parameters.hail_threat ?? null
49
- return (val ?? th) ? `**Hail Threat**: ${val} ${th ? `(${th})` : ''}` : null;
50
- })(),
51
- event.parameters.damage_threat ? `**Damage Threat**: ${event.parameters.damage_threat}` : null,
52
- event.parameters.flood_threat ? `**Flood Threat**: ${event.parameters.flood_threat}` : null,
53
- event.parameters.tornado_threat ? `**Tornado Threat**: ${event.parameters.tornado_threat}` : null,
54
- event.spc_parameters.spc_max_tornado ? `**Max Tornado Threat**: ${event.spc_parameters.spc_max_tornado}` : null,
55
- event.spc_parameters.spc_max_hail ? `**Max Hail Threat**: ${event.spc_parameters.spc_max_hail}` : null,
56
- event.spc_parameters.spc_max_wind ? `**Max Wind Threat**: ${event.spc_parameters.spc_max_wind}` : null,
57
- event.spc_parameters.spc_watch_issuance ? `**Watch Issuance**: ${event.spc_parameters.spc_watch_issuance}%` : null,
58
- event.watch_parameters.watch_number ? `**Watch Number**: ${event.watch_parameters.watch_number}` : null,
59
- event.watch_parameters.strong_tornadoes_probability ? `**Strong Tornadoes Probability**: ${event.watch_parameters.strong_tornadoes_probability}%` : null,
60
- event.watch_parameters.additional_tornadoes_probability ? `**Additional Tornadoes Probability**: ${event.watch_parameters.additional_tornadoes_probability}%` : null,
61
- event.watch_parameters.combined_hail_wind_probability ? `**Combined Hail/Wind Probability**: ${event.watch_parameters.combined_hail_wind_probability}%` : null,
62
- event.watch_parameters.severe_hail_probability ? `**Severe Hail Probability**: ${event.watch_parameters.severe_hail_probability}%` : null,
63
- event.watch_parameters.hail_2in_probability ? `**Hail ≥2in Probability**: ${event.watch_parameters.hail_2in_probability}%` : null,
64
- event.watch_parameters.max_hail_in ? `**Max Hail Inches**: ${event.watch_parameters.max_hail_in}` : null,
65
- event.watch_parameters.severe_wind_probability ? `**Severe Wind Probability**: ${event.watch_parameters.severe_wind_probability}%` : null,
66
- event.watch_parameters.max_wind_surface ? `**Max Surface Wind**: ${event.watch_parameters.max_wind_surface}` : null,
67
- event.watch_parameters.max_tops_x100feet ? `**Max Tops (x100 feet)**: ${event.watch_parameters.max_tops_x100feet}` : null,
68
- (event.parameters.tags?.length > 0) ? `**Tags**: ${event.parameters.tags.join(', ')}` : null,
69
- (() => {
70
- const val = event.geocode?.office?.name ?? `N/A`
71
- const th = event.geocode?.office?.office ?? null
72
- return (val ?? th) ? `**Sender**: ${val} ${th ? `(${th})` : ''}` : null;
73
- })(),
74
- event.metadata?.tracking ? `**Tracking**: ${event.metadata.tracking}` : null,
75
- event.metadata.history?.length > 0 ? `**Logs**: ${event.metadata.history.length}` : null,
76
- (() => {
77
- if (event.status == `Expired`) { return null }
78
- const desc = (event.description ?? '').split('\n').map(l => l.trim()).filter(Boolean).join('\n');
79
- return desc ? '```' + '\n' + desc + '\n' + '```' : null;
80
- })(),
81
- ].filter(Boolean).join('\n');
82
-
83
- const isLimited = setTimeoutAction({ identifier: options.webhook.webhook, interval: options.webhook.rate, max: options.webhook.rate, addTime: true })
84
- if (isLimited.limited) { return }
85
-
86
- if (body.length > 1900) {
87
- body = body.substring(0, 1900) + "\n\n[Message truncated due to length]";
88
- const blocks = (body.match(/```/g) ?? []).length;
89
- if (blocks % 2 !== 0) body += "```";
90
- }
91
- const form = new FormData();
92
- const embed = {
93
- title: `${event.event} (${event.status})`,
94
- description: body,
95
- color: 16711680,
96
- timestamp: new Date().toISOString(),
97
- footer: { text: settings.title }
98
- };
99
- form.append("payload_json", JSON.stringify({
100
- username: settings.title ?? "AtmosphericX",
101
- content: settings.message ?? "",
102
- embeds: [embed]
103
- }));
104
- if (settings.upload) {
105
- form.append("file", Buffer.from(JSON.stringify((getCleanedEvent(event)), null, 2)), {
106
- filename: `${event.event}_${event.status}_${event.metadata.tracking}.json`,
107
- contentType: "application/json"
108
- });
109
- }
110
- await createHttp({
111
- url: settings.webhook,
112
- timeout: 2000,
113
- method: `POST`,
114
- headers: form.getHeaders(),
115
- body: form
116
- })
117
- }