@atmosx/event-product-parser 3.0.48 → 3.0.51

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 (57) hide show
  1. package/README.md +48 -21
  2. package/dist/cjs/index.cjs +1895 -1812
  3. package/dist/esm/index.mjs +1898 -1815
  4. package/package.json +2 -2
  5. package/src/@building/building.attachments.ts +5 -5
  6. package/src/@building/building.create.ts +19 -5
  7. package/src/@building/building.enhance.ts +1 -1
  8. package/src/@building/building.geometry.ts +1 -1
  9. package/src/@building/building.polygon.ts +1 -2
  10. package/src/@building/building.signature.ts +0 -1
  11. package/src/@building/building.tracking.ts +4 -4
  12. package/src/@building/building.validate.ts +11 -6
  13. package/src/@core/core.clearEvents.ts +0 -1
  14. package/src/@core/core.createEvent.ts +0 -1
  15. package/src/@core/core.getEvents.ts +0 -1
  16. package/src/@core/core.getNodes.ts +0 -1
  17. package/src/@core/core.getRandomEvent.ts +0 -1
  18. package/src/@core/core.getVersion.ts +0 -1
  19. package/src/@dictionaries/dictionaries.awips.ts +3 -3
  20. package/src/@events/events.api.ts +7 -9
  21. package/src/@events/events.text.ts +5 -6
  22. package/src/@events/events.ugc.ts +5 -5
  23. package/src/@events/events.vtec.ts +4 -5
  24. package/src/@manager/manager.mkEvent.ts +17 -12
  25. package/src/@manager/manager.rmEvent.ts +5 -3
  26. package/src/@manager/manager.setHash.ts +0 -1
  27. package/src/@manager/manager.updateEvents.ts +1 -3
  28. package/src/@manager/manager.updateListener.ts +22 -27
  29. package/src/@manager/manager.updateNodes.ts +2 -3
  30. package/src/@modules/@database/database.cache.ts +6 -4
  31. package/src/@modules/@database/database.init.ts +5 -4
  32. package/src/@modules/@database/database.shapefiles.ts +11 -11
  33. package/src/@modules/@database/database.stanza.ts +2 -3
  34. package/src/@modules/@eas/eas.setAFSK.ts +0 -1
  35. package/src/@modules/@eas/eas.setAsciiToBits.ts +0 -1
  36. package/src/@modules/@eas/eas.setEasTone.ts +6 -2
  37. package/src/@modules/@eas/eas.setNoise.ts +1 -0
  38. package/src/@modules/@eas/eas.setRadioEffect.ts +1 -0
  39. package/src/@modules/@eas/eas.setSameHeader.ts +0 -1
  40. package/src/@modules/@utilities/utilities.getMatched.ts +33 -0
  41. package/src/@modules/@utilities/utilities.setDebug.ts +38 -0
  42. package/src/@modules/@utilities/utilities.setTimeoutAction.ts +5 -1
  43. package/src/@modules/@xmpp/xmpp.xDeploy.ts +1 -2
  44. package/src/@modules/@xmpp/xmpp.xError.ts +0 -2
  45. package/src/@modules/@xmpp/xmpp.xOffline.ts +0 -1
  46. package/src/@modules/@xmpp/xmpp.xOnline.ts +2 -2
  47. package/src/@parsers/@text/text.getEmbed.ts +0 -2
  48. package/src/@parsers/@ugc/ugc.coordinates.ts +2 -1
  49. package/src/@parsers/@ugc/ugc.getCache.ts +24 -0
  50. package/src/@parsers/@ugc/ugc.locations.ts +35 -7
  51. package/src/@parsers/@ugc/ugc.setCache.ts +28 -0
  52. package/src/@types/type.settings.ts +1 -0
  53. package/src/bootstrap.ts +4 -1
  54. package/test.js +15 -21
  55. package/tsup.config.ts +1 -1
  56. package/dist/index.d.mts +0 -299
  57. package/dist/index.d.ts +0 -299
@@ -17,7 +17,6 @@
17
17
 
18
18
  */
19
19
 
20
-
21
20
  import { TypeEvent } from "../@types/type.event";
22
21
  import { TypeListener } from "../@types/type.listener";
23
22
  import { bootstrap } from "../bootstrap"
@@ -26,19 +25,19 @@ import { setTimeoutAction } from "../@modules/@utilities/utilities.setTimeoutAct
26
25
  import { getEmebed } from "../@parsers/@text/text.getEmbed";
27
26
  import { getCleanedEvent } from "../@building/building.clean"
28
27
  import { createHttp } from "../@modules/@utilities/utilities.createHttp";
28
+ import { setDebug } from "../@modules/@utilities/utilities.setDebug";
29
+ import { getMatched } from "../@modules/@utilities/utilities.getMatched";
29
30
  import { existsSync, mkdirSync, writeFileSync, readFileSync, appendFileSync } from "fs";
30
- import { setWarning } from "../@modules/@utilities/utilities.setWarning";
31
-
32
-
33
-
34
31
 
35
32
  export const updateListener = async (event: TypeEvent): Promise<void> => {
33
+ const tick = performance.now()
36
34
  const settings = bootstrap.settings;
37
35
  const listeners = settings.ListenerSettings as TypeListener[];
38
36
  const properties = event.properties;
39
37
  const metadata = {
40
38
  file: null,
41
39
  eas: null,
40
+ json: null,
42
41
  name: properties.event,
43
42
  status: properties.status,
44
43
  description: properties.description,
@@ -53,16 +52,7 @@ export const updateListener = async (event: TypeEvent): Promise<void> => {
53
52
  const events = listener?.events;
54
53
  const webhook = listener?.webhook;
55
54
  const uploads = listener?.uploads
56
- const isMatched = events.some(pattern => {
57
- if (!pattern) return false;
58
- if (pattern === "*" || pattern === metadata.name) return true;
59
- if (pattern.includes("*")) {
60
- const regex = "^" +
61
- pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$";
62
- return new RegExp(regex).test(metadata.name);
63
- }
64
- return false;
65
- });
55
+ const isMatched = getMatched(events ?? [], metadata.name)
66
56
 
67
57
  if (events?.length == 0 || isMatched) {
68
58
  if (uploads?.eas) {
@@ -76,11 +66,12 @@ export const updateListener = async (event: TypeEvent): Promise<void> => {
76
66
  if (uploads?.file) {
77
67
  const fDestination = settings.GlobalSettings.ArchiveSettings.TextDirectory;
78
68
  if (fDestination) {
69
+ const file = (`${fDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.txt`).replace(/[\\:*?"<>|]/g, "_").replace(/\s+/g, " ").trim();
79
70
  if (!existsSync(fDestination)) { mkdirSync(fDestination, { recursive: true }); }
80
- if (existsSync(`${fDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.txt`)) {
81
- appendFileSync(`${fDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.txt`, metadata.raw);
71
+ if (existsSync(file)) {
72
+ appendFileSync(file, metadata.raw);
82
73
  } else {
83
- writeFileSync(`${fDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.txt`, metadata.raw);
74
+ writeFileSync(file, metadata.raw);
84
75
  }
85
76
  }
86
77
  metadata.file = metadata.raw;
@@ -89,13 +80,15 @@ export const updateListener = async (event: TypeEvent): Promise<void> => {
89
80
  if (uploads?.event) {
90
81
  const eDestination = settings.GlobalSettings.ArchiveSettings.EventDirectory;
91
82
  if (eDestination) {
83
+ const file = (`${eDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.json`).replace(/[\\:*?"<>|]/g, "_").replace(/\s+/g, " ").trim();
92
84
  if (!existsSync(eDestination)) { mkdirSync(eDestination, { recursive: true }); }
93
- writeFileSync(`${eDestination}/${metadata.name}_${metadata.status}_${metadata.tracking}.json`, JSON.stringify(getCleanedEvent(event), null, 2));
85
+ writeFileSync(file, JSON.stringify(getCleanedEvent(event), null, 2));
94
86
  }
87
+ metadata.json = JSON.stringify(getCleanedEvent(event), null, 2);
95
88
  }
96
89
 
97
- if (webhook.enabled && webhook.destination) {
98
- const ratelimit = setTimeoutAction({ identifier: webhook.destination, interval: webhook.ratelimit * 2, max: webhook.ratelimit, addTime: true })
90
+ if (webhook?.enabled && webhook?.destination) {
91
+ const isRatelimited = setTimeoutAction({ identifier: webhook.destination, interval: (webhook.ratelimit ?? 2) * 2, max: (webhook.ratelimit ?? 2), addTime: true })
99
92
  const form = new FormData();
100
93
  const embed = {
101
94
  title: `${metadata.name} (${metadata.status})`,
@@ -106,7 +99,7 @@ export const updateListener = async (event: TypeEvent): Promise<void> => {
106
99
  footer: { text: webhook.title ?? `AtmosphericX` }
107
100
  };
108
101
 
109
- if (ratelimit.limited) { return }
102
+ if (isRatelimited.limited) { return }
110
103
 
111
104
 
112
105
  if (metadata.description && !metadata.expired) {
@@ -132,6 +125,10 @@ export const updateListener = async (event: TypeEvent): Promise<void> => {
132
125
  form.append("fUpload", new Blob([Buffer.from(metadata.file)], {type: "application/text"}), `${properties.event}_${properties.status}_${properties.metadata.tracking}.txt`)
133
126
  }
134
127
 
128
+ if (uploads?.event) {
129
+ form.append("fUpload2", new Blob([Buffer.from(metadata.json)], {type: "application/json"}), `${properties.event}_${properties.status}_${properties.metadata.tracking}.json`)
130
+ }
131
+
135
132
  if (uploads?.eas) {
136
133
  if (metadata.eas) {
137
134
  const file = readFileSync(metadata.eas)
@@ -145,16 +142,14 @@ export const updateListener = async (event: TypeEvent): Promise<void> => {
145
142
  embeds: [embed]
146
143
  }));
147
144
 
148
- const a = await createHttp({
145
+ await createHttp({
149
146
  url: webhook.destination,
150
- timeout: 5000,
147
+ timeout: 15e3,
151
148
  method: `POST`,
152
149
  body: form
153
150
  })
154
- if (a.error) {
155
- setWarning({ message: `Failed to send webhook: ${a.error.message}` })
156
- }
157
151
  }
158
152
  }
159
153
  }
154
+ setDebug({ title: `@manager.updateListener`, message: `Listener took ${performance.now() - tick} ms` })
160
155
  }
@@ -17,11 +17,10 @@
17
17
 
18
18
  */
19
19
 
20
- import { getEventNodes } from "../@building/building.polygon";
21
- import { setEventEmit } from "../@modules/@utilities/utilities.setEventEmit";
22
20
  import { TypeEvent } from "../@types/type.event";
23
21
  import { bootstrap } from "../bootstrap"
24
-
22
+ import { getEventNodes } from "../@building/building.polygon";
23
+ import { setEventEmit } from "../@modules/@utilities/utilities.setEventEmit";
25
24
 
26
25
  export const updateNode = async (selectedEvent?: TypeEvent): Promise<void> => {
27
26
  const events = bootstrap.cache.events.features;
@@ -21,6 +21,7 @@ import { TypeSettings } from "../../@types/type.settings"
21
21
  import { bootstrap } from '../../bootstrap'
22
22
  import { setWarning } from '../@utilities/utilities.setWarning';
23
23
  import { createEvent } from '../../@building/building.create';
24
+ import { validateEvents } from "../../@building/building.validate";
24
25
 
25
26
  export const getCachedEvents = async (): Promise<void> => {
26
27
  try {
@@ -29,7 +30,7 @@ export const getCachedEvents = async (): Promise<void> => {
29
30
  if (settings.NOAAWeatherWireServiceSettings.CacheSettings.Enabled) {
30
31
  const max = settings.NOAAWeatherWireServiceSettings.CacheSettings.MaxRetentionHistory ?? 500;
31
32
  const get = await bootstrap.database.prepare(`SELECT * FROM stanzas ORDER BY rowid DESC LIMIT ?`).all(max) as { rowid: number; stanza: string }[];
32
- setWarning({ message: `Fetched ${get.length} cached events from the database in ${Math.floor(performance.now() - tick)} ms` })
33
+ setWarning({ message: `Fetched ${get.length} cached stanzas from the database in ${Math.floor(performance.now() - tick)} ms` })
33
34
  let events = get.map((row) => JSON.parse(row.stanza))
34
35
  .filter(stanza => {
35
36
  if (!stanza) { return }
@@ -39,10 +40,11 @@ export const getCachedEvents = async (): Promise<void> => {
39
40
  return !isSkippable
40
41
  });
41
42
  events = events.sort((a, b) => b.issued - a.issued)
42
- await Promise.all(events.map(event => createEvent(event)))
43
- setWarning({ message: `Processed ${events.length} cached events in ${Math.floor(performance.now() - tick)} ms` })
43
+ await Promise.all(events.map(event => createEvent(event, true)))
44
+ setWarning({ message: `Processed ${events.length} cached stanzas in ${Math.floor(performance.now() - tick)} ms` })
45
+ validateEvents(bootstrap.cache.processed)
44
46
  }
45
47
  } catch (error) {
46
- setWarning({ message: `An error occurred while fetching cached events: ${error.message} -> ${error.stack}` })
48
+ setWarning({ message: `An error occurred while fetching cached stanzas: ${error.message} -> ${error.stack}` })
47
49
  }
48
50
  }
@@ -17,19 +17,20 @@
17
17
 
18
18
  */
19
19
 
20
- import fs from 'fs'
21
- import sqlite3 from 'better-sqlite3'
20
+
22
21
  import { TypeSettings } from "../../@types/type.settings"
23
22
  import { bootstrap } from "../../bootstrap"
24
23
  import { setWarning } from '../@utilities/utilities.setWarning'
25
24
  import { importShapefiles } from './database.shapefiles'
26
25
  import { importBroadcastify } from "./database.broadcastify"
26
+ import { existsSync, writeFileSync } from "fs"
27
+ import sqlite3 from 'better-sqlite3'
27
28
 
28
29
  export const initializeDatabase = async (): Promise<void> => {
29
30
  const settings = bootstrap.settings as TypeSettings;
30
31
  try {
31
- if (!fs.existsSync(settings.Database)) {
32
- fs.writeFileSync(settings.Database, '')
32
+ if (!existsSync(settings.Database)) {
33
+ writeFileSync(settings.Database, '')
33
34
  setWarning({ message: `Creating new database at ${settings.Database}` })
34
35
  }
35
36
  bootstrap.database = new sqlite3(settings.Database);
@@ -17,15 +17,15 @@
17
17
 
18
18
  */
19
19
 
20
- import fs from 'fs'
21
- import { resolve, extname} from 'path'
22
- import { loadAsync } from 'jszip'
23
- import { read } from 'shapefile'
24
20
  import { TypeSettings } from "../../@types/type.settings"
21
+ import { dict_shapefiles } from '../../@dictionaries/dictionaries.shapefiles'
25
22
  import { bootstrap } from "../../bootstrap"
26
23
  import { setSleep } from '../@utilities/utilities.setSleep'
27
24
  import { setWarning } from '../@utilities/utilities.setWarning'
28
- import { dict_shapefiles } from '../../@dictionaries/dictionaries.shapefiles'
25
+ import { existsSync, mkdirSync, writeFileSync, unlinkSync, rm } from "fs"
26
+ import { resolve, extname} from 'path'
27
+ import { loadAsync } from 'jszip'
28
+ import { read } from 'shapefile'
29
29
 
30
30
  export const importShapefiles = async (): Promise<void> => {
31
31
  const settings = bootstrap.settings as TypeSettings;
@@ -40,14 +40,14 @@ export const importShapefiles = async (): Promise<void> => {
40
40
  const arrayBuff = await response.arrayBuffer();
41
41
  const content = await loadAsync(arrayBuff);
42
42
  const directory = resolve(__dirname, `../../shapefiles`);
43
- if (!fs.existsSync(directory)) {
44
- fs.mkdirSync(directory, { recursive: true });
43
+ if (!existsSync(directory)) {
44
+ mkdirSync(directory, { recursive: true });
45
45
  }
46
46
  for (const file of Object.keys(content.files)) {
47
47
  if (file.endsWith('.shp') || file.endsWith('.dbf')) {
48
48
  const data = await content.files[file].async(`nodebuffer`)
49
49
  const output = resolve(directory, `${shapefile?.name ?? ``}_${shapefile?.id ?? ``}${extname(file)}`)
50
- fs.writeFileSync(output, data)
50
+ writeFileSync(output, data)
51
51
  }
52
52
  }
53
53
  const filepath = resolve(__dirname, '../../shapefiles', shapefile.name + '_' + shapefile.id)
@@ -81,11 +81,11 @@ export const importShapefiles = async (): Promise<void> => {
81
81
  insert.run(final, location, JSON.stringify(geometry));
82
82
  }
83
83
  })
84
- fs.unlinkSync(`${filepath}.shp`)
85
- fs.unlinkSync(`${filepath}.dbf`)
84
+ unlinkSync(`${filepath}.shp`)
85
+ unlinkSync(`${filepath}.dbf`)
86
86
  transaction(features)
87
87
  }
88
- fs.rm(resolve(__dirname, '../../shapefiles'), { recursive: true, force: true }, () => {});
88
+ rm(resolve(__dirname, '../../shapefiles'), { recursive: true, force: true }, () => {});
89
89
  }
90
90
  } catch (error) {
91
91
  setWarning( {message: `An error occurred while compiling shapefiles: ${error.message}` })
@@ -17,11 +17,10 @@
17
17
 
18
18
  */
19
19
 
20
-
21
- import { bootstrap } from '../../bootstrap'
22
- import { setWarning } from '../@utilities/utilities.setWarning';
23
20
  import { TypeSettings } from "../../@types/type.settings"
24
21
  import { TypeStanzaCompiled } from '../../@types/type.compiled';
22
+ import { bootstrap } from '../../bootstrap'
23
+ import { setWarning } from '../@utilities/utilities.setWarning';
25
24
 
26
25
  export const importStanza = async (stanza: TypeStanzaCompiled): Promise<void> => {
27
26
  const settings = bootstrap.settings as TypeSettings;
@@ -18,7 +18,6 @@
18
18
 
19
19
  */
20
20
 
21
-
22
21
  export const setAFSK = (bits: number[], sampleRate: number): Int16Array => {
23
22
  const baud = 520.83;
24
23
  const markFreq = 2083.3;
@@ -18,7 +18,6 @@
18
18
 
19
19
  */
20
20
 
21
-
22
21
  export const setAsciiToBits = (str: string): number[] => {
23
22
  const bits = [];
24
23
  for (let i = 0; i < str.length; i++) {
@@ -30,11 +30,13 @@ import { setNoise } from "./eas.setNoise";
30
30
  import { getPCM16 } from "./eas.getPCM16";
31
31
  import { getTTS } from "./eas.getTTS";
32
32
  import { getCleanDescription } from "./eas.getCleanDescription";
33
+ import { setDebug } from "../@utilities/utilities.setDebug";
33
34
  import { join } from 'path'
34
35
  import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'fs'
35
36
  import { execSync } from 'child_process'
36
37
  import { platform } from 'os'
37
38
 
39
+
38
40
  interface GenerateEASOptions {
39
41
  message: string
40
42
  header: string
@@ -42,12 +44,13 @@ interface GenerateEASOptions {
42
44
  }
43
45
 
44
46
  export const setEasTone = async (options: GenerateEASOptions): Promise<string> => {
47
+ const tick = performance.now()
45
48
  const settings = bootstrap.settings as TypeSettings;
46
49
  const directory = settings.GlobalSettings.ArchiveSettings.EasDirectory;
47
50
  const prefix = settings.GlobalSettings.ArchiveSettings.EasToneout;
48
51
  let message = options.message;
49
52
  let header = options.header;
50
- let title = options.title ?? `${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, '')}`;
53
+ let title = (options.title ?? `${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, '')}`).replace(/[\\:*?"<>|]/g, "_").replace(/\s+/g, " ").trim();
51
54
  if (!message || !header) {
52
55
  setWarning({
53
56
  title: `EAS`,
@@ -68,7 +71,7 @@ export const setEasTone = async (options: GenerateEASOptions): Promise<string> =
68
71
  if (!existsSync(join(directory, `/encoded`))) {
69
72
  mkdirSync(join(directory, `/encoded`), { recursive: true });
70
73
  }
71
-
74
+
72
75
  const tmpTTS = join(directory, `/tts/${title}.wav`)
73
76
  const outTTS = join(directory, `/encoded/${title}.wav`)
74
77
  const vPlatform = platform();
@@ -141,6 +144,7 @@ export const setEasTone = async (options: GenerateEASOptions): Promise<string> =
141
144
  const aBuffer = getPCM16(Array.from(aFinal).map(v => ({ value: v })), 8000);
142
145
  writeFileSync(outTTS, aBuffer)
143
146
  try{ unlinkSync(tmpTTS) } catch {}
147
+ setDebug({ title: `@eas.setEasTone`, message: `EAS tone generation took ${performance.now() - tick} ms` })
144
148
  return outTTS;
145
149
  }
146
150
 
@@ -17,6 +17,7 @@
17
17
 
18
18
 
19
19
  */
20
+
20
21
  import { getPCMToFloat } from "./eas.getPCMToFloat";
21
22
  import { getFloatPCM16 } from "./eas.getFloatPCM16";
22
23
 
@@ -17,6 +17,7 @@
17
17
 
18
18
 
19
19
  */
20
+
20
21
  import { getPCMToFloat } from "./eas.getPCMToFloat";
21
22
  import { getFloatPCM16 } from "./eas.getFloatPCM16";
22
23
 
@@ -18,7 +18,6 @@
18
18
 
19
19
  */
20
20
 
21
-
22
21
  import { setAFSK } from "./eas.setAFSK";
23
22
  import { setAsciiToBits } from "./eas.setAsciiToBits";
24
23
  import { getMergedPCM16 } from "./eas.getMergedPCM16";
@@ -0,0 +1,33 @@
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 getMatched = (strings: string[], string: string): boolean => {
21
+ const isMatched = strings.some(pattern => {
22
+ if (!pattern) return false;
23
+ const lowerP = pattern.toLowerCase();
24
+ const lowerS = string.toLowerCase()
25
+ if (lowerP === "*" || lowerP === lowerS) return true;
26
+ if (lowerP.includes("*")) {
27
+ const regex = "^" + lowerP.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$";
28
+ return new RegExp(regex).test(lowerS);
29
+ }
30
+ return false;
31
+ });
32
+ return isMatched;
33
+ }
@@ -0,0 +1,38 @@
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 { TypeSettings } from "../../@types/type.settings";
21
+ import { bootstrap } from "../../bootstrap"
22
+
23
+ interface SetDebugOptions {
24
+ title?: string
25
+ message: string
26
+ }
27
+
28
+ export const setDebug = (options: SetDebugOptions): void => {
29
+ const settings = bootstrap.settings as TypeSettings;
30
+ bootstrap.listener.emit(`debug`, {
31
+ message: options.message,
32
+ parent: options?.title?.split(`.`)[0]?.replace(`@`, ``),
33
+ function: options?.title?.split(`.`)[1]
34
+ })
35
+ if (settings.EnableDebugging) {
36
+ console.log(`[${bootstrap.ansi_colors.BLUE}${options.title ?? `debug`}${bootstrap.ansi_colors.RESET}] ${options.message}`)
37
+ }
38
+ }
@@ -23,7 +23,8 @@ interface SetTimeoutActionOptions {
23
23
  identifier: string
24
24
  addTime?: boolean
25
25
  max?: number
26
- interval: number
26
+ interval?: number
27
+ expire?: boolean
27
28
  }
28
29
 
29
30
  type SetTimeoutActionResponse = {
@@ -38,6 +39,9 @@ export const setTimeoutAction = (options: SetTimeoutActionOptions): SetTimeoutAc
38
39
  bootstrap.ratelimits[options?.identifier] = [];
39
40
  target = bootstrap.ratelimits[options?.identifier];
40
41
  }
42
+ if (options?.expire) {
43
+ delete bootstrap.ratelimits[options?.identifier];
44
+ }
41
45
  if (target?.length > 0) {
42
46
  bootstrap.ratelimits[options?.identifier] = target.filter((ts: number) => Date.now() - ts < options?.interval * 1000);
43
47
  target = bootstrap.ratelimits[options?.identifier];
@@ -17,15 +17,14 @@
17
17
 
18
18
  */
19
19
 
20
- import { client } from '@xmpp/client';
21
20
  import { TypeSettings } from "../../@types/type.settings";
22
21
  import { bootstrap } from "../../bootstrap"
23
- import { setWarning } from "../@utilities/utilities.setWarning";
24
22
  import { xOnline } from "./xmpp.xOnline";
25
23
  import { xOffline } from "./xmpp.xOffline";
26
24
  import { xError } from "./xmpp.xError";
27
25
  import { xStanza } from "./xmpp.xStanza";
28
26
  import { setEventEmit } from '../@utilities/utilities.setEventEmit';
27
+ import { client } from '@xmpp/client';
29
28
 
30
29
  export const xDeploy = async (): Promise<void> => {
31
30
  let session;
@@ -18,8 +18,6 @@
18
18
  */
19
19
 
20
20
  import { bootstrap } from "../../bootstrap";
21
- import { setEventEmit } from "../@utilities/utilities.setEventEmit";
22
- import { setWarning } from "../@utilities/utilities.setWarning";
23
21
 
24
22
  export const xError = () => {
25
23
  bootstrap.session_xmpp.on(`error`, async (error: Error) => {
@@ -19,7 +19,6 @@
19
19
 
20
20
  import { bootstrap } from "../../bootstrap";
21
21
  import { setEventEmit } from "../@utilities/utilities.setEventEmit";
22
- import { setWarning } from "../@utilities/utilities.setWarning";
23
22
 
24
23
  export const xOffline = () => {
25
24
  bootstrap.session_xmpp.on(`offline`, async () => {
@@ -16,10 +16,10 @@
16
16
  Internal Package: @atmosx/event-product-parser
17
17
 
18
18
  */
19
- import { xml } from '@xmpp/client'
19
+
20
20
  import { bootstrap } from "../../bootstrap";
21
- import { setSleep } from "../@utilities/utilities.setSleep";
22
21
  import { setEventEmit } from '../@utilities/utilities.setEventEmit';
22
+ import { xml } from '@xmpp/client'
23
23
 
24
24
  export const xOnline = () => {
25
25
  const settings = bootstrap.settings;
@@ -19,8 +19,6 @@
19
19
 
20
20
  import { TypeEvent } from "../../@types/type.event"
21
21
 
22
-
23
-
24
22
  export const getEmebed = (event: TypeEvent): string => {
25
23
  const line = (label: string, value: unknown, condition = true) => condition && value ? `${label} ${value}` : null;
26
24
  const isStatement = event.properties.status_metadata.is_statement;
@@ -16,8 +16,9 @@
16
16
  Internal Package: @atmosx/event-product-parser
17
17
 
18
18
  */
19
- import { union } from "polygon-clipping";
19
+
20
20
  import { bootstrap } from "../../bootstrap";
21
+ import { union } from "polygon-clipping";
21
22
 
22
23
  interface CoordinatesOptions {
23
24
  zones: string[]
@@ -0,0 +1,24 @@
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 { bootstrap } from "../../bootstrap";
21
+
22
+ export const getCache = (key: string) => {
23
+ return bootstrap.cache.ugc.get(key);
24
+ };
@@ -18,12 +18,40 @@
18
18
  */
19
19
 
20
20
  import { bootstrap } from "../../bootstrap";
21
+ import { getCache } from "./ugc.getCache";
22
+ import { setCache } from "./ugc.setCache";
21
23
 
22
24
  export const getLocations = async (zones: string[]): Promise<string[]> => {
23
- const sites = Array.from(new Set(zones));
24
- const placeholders = sites.map(() => '?').join(',');
25
- const rows = await bootstrap.database
26
- .prepare(`SELECT id, location FROM shapefiles WHERE id IN (${placeholders})`)
27
- .all(...sites)
28
- return rows.map((row: any) => row.location).sort();
29
- }
25
+ const uniqueZones = Array.from(new Set(zones));
26
+
27
+ const results: string[] = [];
28
+ const missing: string[] = [];
29
+
30
+ for (let i = 0; i < uniqueZones.length; i++) {
31
+ const zone = uniqueZones[i];
32
+ const cached = getCache(zone);
33
+
34
+ if (cached) {
35
+ for (let j = 0; j < cached.length; j++) {
36
+ results.push(cached[j]);
37
+ }
38
+ } else {
39
+ missing.push(zone);
40
+ }
41
+ }
42
+
43
+ if (missing.length > 0) {
44
+ const rows = await bootstrap.database
45
+ .prepare(
46
+ `SELECT id, location FROM shapefiles WHERE id IN (${missing.map(() => '?').join(',')})`
47
+ )
48
+ .all(...missing);
49
+
50
+ for (let i = 0; i < rows.length; i++) {
51
+ const r = rows[i] as any;
52
+ setCache(r.id, [r.location]);
53
+ results.push(r.location);
54
+ }
55
+ }
56
+ return results;
57
+ };
@@ -0,0 +1,28 @@
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 { bootstrap } from "../../bootstrap";
21
+
22
+ export const setCache = (key: string, value: string[]) => {
23
+ if (bootstrap.cache.ugc.size >= 5000) {
24
+ const firstKey = bootstrap.cache.ugc.keys().next().value;
25
+ bootstrap.cache.ugc.delete(firstKey);
26
+ }
27
+ bootstrap.cache.ugc.set(key, value);
28
+ };
@@ -23,6 +23,7 @@ export type TypeSettings = {
23
23
  Database: string
24
24
  EnableWireService: boolean
25
25
  EnableJournal: boolean
26
+ EnableDebugging: boolean
26
27
  NOAAWeatherWireServiceSettings: {
27
28
  ReconnectionSettings: {
28
29
  Enabled: boolean