@atmosx/event-product-parser 3.0.4 → 3.0.6

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 (162) hide show
  1. package/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +1 -1
  2. package/.github/README.md +163 -0
  3. package/.github/SUPPORTED_EVENTS.md +370 -0
  4. package/.github/docs/docs-functions.md +30 -0
  5. package/.github/docs/docs-general-configurations.md +209 -0
  6. package/.github/docs/docs-integrations.md +37 -0
  7. package/.github/docs/docs-listeners.md +28 -0
  8. package/.github/docs/docs-source-configuration.md +218 -0
  9. package/.github/docs/docs-technical.md +50 -0
  10. package/.github/logo.png +0 -0
  11. package/.github/samples/SAMPLE_EAS_GENERATION.wav +0 -0
  12. package/.github/samples/SAMPLE_GEOJSON.json +204 -0
  13. package/.github/samples/SAMPLE_TEXT_PRODUCT.txt +119 -0
  14. package/dist/cjs/index.cjs +4677 -13422
  15. package/dist/esm/index.mjs +3159 -11906
  16. package/package.json +3 -9
  17. package/src/@building/{building.create.ts → CreateEvent.ts} +25 -11
  18. package/src/@building/{building.clean.ts → GetCleanedEvent.ts} +2 -2
  19. package/src/@building/GetEventAttachments.ts +86 -0
  20. package/src/@building/{building.enhance.ts → GetEventEnhancedName.ts} +11 -12
  21. package/src/@building/{building.geometry.ts → GetEventGeometry.ts} +7 -7
  22. package/src/@building/{building.headers.ts → GetEventHeader.ts} +3 -3
  23. package/src/@building/{building.polygon.ts → GetEventNodes.ts} +13 -11
  24. package/src/@building/{building.office.ts → GetEventOffice.ts} +6 -6
  25. package/src/@building/GetEventProperties.ts +96 -0
  26. package/src/@building/{building.signature.ts → GetEventSignature.ts} +14 -15
  27. package/src/@building/{building.tags.ts → GetEventTags.ts} +9 -4
  28. package/src/@building/{building.tracking.ts → GetEventTracking.ts} +15 -15
  29. package/src/@building/{building.validate.ts → ValidateEvents.ts} +67 -60
  30. package/src/@core/{core.clearEvents.ts → ClearEvents.ts} +3 -4
  31. package/src/@core/{core.createListener.ts → CreateListener.ts} +3 -3
  32. package/src/@core/{core.getEvents.ts → GetEvents.ts} +1 -2
  33. package/src/@core/{core.getNodes.ts → GetNodes.ts} +1 -2
  34. package/src/@core/{core.getRandomEvent.ts → GetRandomEvent.ts} +1 -2
  35. package/src/@core/{core.getVersion.ts → GetVersion.ts} +1 -2
  36. package/src/@core/ManualEvent.ts +56 -0
  37. package/src/@core/QueryStanza.ts +39 -0
  38. package/src/@core/{core.setNode.ts → SetNode.ts} +8 -8
  39. package/src/@core/{core.start.ts → StartService.ts} +21 -21
  40. package/src/@core/{core.stop.ts → StopService.ts} +1 -1
  41. package/src/@enums/AWIPS.ts +366 -0
  42. package/src/{@dictionaries/dictionaries.eventActions.ts → @enums/Actions.ts} +1 -1
  43. package/src/{@dictionaries/dictionaries.eventCancelMessages.ts → @enums/Cancellation.ts} +2 -1
  44. package/src/{@dictionaries/dictionaries.eventCauses.ts → @enums/Causes.ts} +1 -1
  45. package/src/{@dictionaries/dictionaries.statusCorrelationText.ts → @enums/Correlations.ts} +1 -1
  46. package/src/@enums/Enhanced.ts +70 -0
  47. package/src/{@dictionaries/dictionaries.eventTypes.ts → @enums/Events.ts} +1 -1
  48. package/src/{@dictionaries/dictionaries.regExp.ts → @enums/Expressions.ts} +2 -1
  49. package/src/@enums/GlobalFilter.ts +24 -0
  50. package/src/{@dictionaries/dictionaries.hailStrings.ts → @enums/Hail.ts} +7 -2
  51. package/src/{@dictionaries/dictionaries.officeICAOs.ts → @enums/ICAO.ts} +3 -1
  52. package/src/@enums/Matches.ts +55 -0
  53. package/src/{@dictionaries/dictionaries.eventProducts.ts → @enums/Products.ts} +1 -1
  54. package/src/{@dictionaries/dictionaries.eventRecords.ts → @enums/Records.ts} +1 -1
  55. package/src/{@dictionaries/dictionaries.eventSeverity.ts → @enums/Severity.ts} +1 -1
  56. package/src/{@dictionaries/dictionaries.shapefileLinks.ts → @enums/Shapefiles.ts} +1 -1
  57. package/src/@enums/States.ts +72 -0
  58. package/src/{@dictionaries/dictionaries.eventStatus.ts → @enums/Status.ts} +1 -1
  59. package/src/@enums/Strings.ts +22 -0
  60. package/src/@enums/Tags.ts +167 -0
  61. package/src/{@dictionaries/dictionaries.testSignatures.ts → @enums/Testing.ts} +3 -2
  62. package/src/@events/{events.api.ts → ParseAPI.ts} +42 -38
  63. package/src/@events/{events.text.ts → ParseText.ts} +25 -18
  64. package/src/@events/{events.ugc.ts → ParseUGC.ts} +28 -19
  65. package/src/@events/{events.vtec.ts → ParseVTEC.ts} +21 -21
  66. package/src/@manager/CreateActions.ts +213 -0
  67. package/src/@manager/{manager.mkEvent.ts → MakeEvent.ts} +34 -31
  68. package/src/@manager/RemoveEvent.ts +70 -0
  69. package/src/@manager/{manager.setHash.ts → SetHash.ts} +8 -9
  70. package/src/@manager/{manager.updateEvents.ts → UpdateEvents.ts} +9 -9
  71. package/src/@manager/{manager.updateNodes.ts → UpdateNode.ts} +24 -17
  72. package/src/@modules/@database/{database.cache.ts → GetCachedEvents.ts} +10 -8
  73. package/src/@modules/@database/ImportBroadcastify.ts +70 -0
  74. package/src/@modules/@database/{database.shapefiles.ts → ImportShapefiles.ts} +17 -20
  75. package/src/@modules/@database/{database.stanza.ts → ImportStanza.ts} +5 -6
  76. package/src/@modules/@database/{database.init.ts → InitializeDatabase.ts} +25 -11
  77. package/src/@modules/@eas/GenerateEASMessage.ts +144 -0
  78. package/src/@modules/@eas/GetCleanDescription.ts +91 -0
  79. package/src/@modules/@eas/{eas.getFloatPCM16.ts → GetFloatPCM16.ts} +1 -1
  80. package/src/@modules/@eas/{eas.getMergedPCM16.ts → GetMergedPCM16.ts} +1 -1
  81. package/src/@modules/@eas/{eas.getPCM16.ts → GetPCM16.ts} +1 -1
  82. package/src/@modules/@eas/{eas.getPCMToFloat.ts → GetPCMToFloat.ts} +1 -1
  83. package/src/@modules/@eas/{eas.getSampledPCM16.ts → GetSampledPCM16.ts} +1 -1
  84. package/src/@modules/@eas/GetTTS.ts +54 -0
  85. package/src/@modules/@eas/{eas.getWavPCM16.ts → GetWavPCM16.ts} +1 -1
  86. package/src/@modules/@eas/{eas.setAFSK.ts → SetAFSK.ts} +1 -2
  87. package/src/@modules/@eas/{eas.setAsciiToBits.ts → SetAsciiToBits.ts} +1 -2
  88. package/src/@modules/@eas/{eas.setAttentionTone.ts → SetAttentionTone.ts} +1 -1
  89. package/src/@modules/@eas/{eas.setNoise.ts → SetNoise.ts} +6 -5
  90. package/src/@modules/@eas/{eas.setRadioEffect.ts → SetRadioEffect.ts} +6 -5
  91. package/src/@modules/@eas/{eas.setSameHeader.ts → SetSameHeader.ts} +7 -8
  92. package/src/@modules/@stanza/{stanza.getAwipsType.ts → GetAwipsType.ts} +11 -9
  93. package/src/@modules/@stanza/{stanza.validate.ts → ValidateStanza.ts} +9 -9
  94. package/src/@modules/@utilities/CreateHttp.ts +83 -0
  95. package/src/@modules/@utilities/{utilities.getFormattedTime.ts → GetFormattedTime.ts} +1 -1
  96. package/src/@modules/@utilities/GetLatestIssuance.ts +32 -0
  97. package/src/@modules/@utilities/GetMatched.ts +33 -0
  98. package/src/@modules/@utilities/{utilities.getSettings.ts → GetSettings.ts} +2 -2
  99. package/src/@modules/@utilities/{utilities.getShapeNearestPoint.ts → GetShapeNearestPoint.ts} +1 -1
  100. package/src/@modules/@utilities/{utilities.setCronSchedule.ts → SetCronSchedule.ts} +41 -12
  101. package/src/{@types/types.webhook.ts → @modules/@utilities/SetDebug.ts} +16 -6
  102. package/src/@modules/@utilities/{utilities.setEventEmit.ts → SetEventEmit.ts} +5 -5
  103. package/src/@modules/@utilities/{utilities.setListener.ts → SetListener.ts} +1 -1
  104. package/src/@modules/@utilities/{utilities.setSettings.ts → SetSettings.ts} +2 -2
  105. package/src/@modules/@utilities/{utilities.setSleep.ts → SetSleep.ts} +1 -1
  106. package/src/@modules/@utilities/{utilities.setTimeoutAction.ts → SetTimeoutAction.ts} +8 -3
  107. package/src/@modules/@utilities/{utilities.setWarning.ts → SetWarning.ts} +2 -2
  108. package/src/@modules/@xmpp/{xmpp.xDeploy.ts → DeployXMPP.ts} +13 -14
  109. package/src/@modules/@xmpp/{xmpp.xError.ts → ErrorXMPP.ts} +1 -3
  110. package/src/@modules/@xmpp/{xmpp.xOffline.ts → OfflineXMPP.ts} +3 -4
  111. package/src/@modules/@xmpp/{xmpp.xOnline.ts → OnlineXMPP.ts} +6 -5
  112. package/src/@modules/@xmpp/{xmpp.xReconnect.ts → ReconnectXMPP.ts} +8 -8
  113. package/src/@modules/@xmpp/{xmpp.xStanza.ts → StanzaXMPP.ts} +11 -11
  114. package/src/@parsers/@hvtec/{hvtec.extract.ts → HVExtract.ts} +10 -10
  115. package/src/@parsers/@pvtec/{pvtec.expires.ts → GetExpiry.ts} +1 -1
  116. package/src/@parsers/@pvtec/{pvtec.extract.ts → VTECExtract.ts} +17 -17
  117. package/src/@parsers/@text/{text.getDescriptionFromProduct.ts → GetDescriptionFromProduct.ts} +12 -5
  118. package/src/@parsers/@text/GetEmbededText.ts +56 -0
  119. package/src/@parsers/@text/{text.getPolygonFromProduct.ts → GetPolygonFromProduct.ts} +31 -10
  120. package/src/@parsers/@text/GetStringText.ts +58 -0
  121. package/src/@parsers/@text/{text.getTextFromProduct.ts → GetTextFromProduct.ts} +1 -1
  122. package/src/@parsers/@text/{text.getXML.ts → GetXML.ts} +1 -1
  123. package/src/@parsers/@ugc/GetCache.ts +24 -0
  124. package/src/@parsers/@ugc/{ugc.expiry.ts → GetExpiry.ts} +1 -1
  125. package/src/@parsers/@ugc/{ugc.locations.ts → GetLocations.ts} +35 -7
  126. package/src/@parsers/@ugc/{ugc.header.ts → GetUGCHeader.ts} +3 -3
  127. package/src/@parsers/@ugc/{ugc.coordinates.ts → GetZonePolygon.ts} +4 -3
  128. package/src/@parsers/@ugc/SetCache.ts +28 -0
  129. package/src/@parsers/@ugc/{ugc.extract.ts → UGCExtract.ts} +6 -6
  130. package/src/@types/Actions.ts +37 -0
  131. package/src/@types/{type.event.ts → Event.ts} +7 -5
  132. package/src/@types/{type.properties.ts → Properties.ts} +11 -8
  133. package/src/@types/{types.settings.ts → Settings.ts} +31 -7
  134. package/src/@types/{types.compiled.ts → StanzaCompiled.ts} +2 -1
  135. package/src/bootstrap.ts +33 -9
  136. package/src/index.ts +26 -24
  137. package/tsup.config.ts +1 -1
  138. package/README.md +0 -349
  139. package/dist/index.d.mts +0 -239
  140. package/dist/index.d.ts +0 -239
  141. package/src/@building/building.properties.ts +0 -89
  142. package/src/@dictionaries/dictionaries.betterEventNames.ts +0 -99
  143. package/src/@dictionaries/dictionaries.eventAwipAbreviations.ts +0 -364
  144. package/src/@dictionaries/dictionaries.eventTags.ts +0 -93
  145. package/src/@dictionaries/dictionaries.eventsMatchText.ts +0 -36
  146. package/src/@dictionaries/dictionaries.transcribedMessageReplacements.ts +0 -68
  147. package/src/@manager/manager.rmEvent.ts +0 -49
  148. package/src/@manager/manager.updateWebhooks.ts +0 -50
  149. package/src/@modules/@eas/eas.setEasTone.ts +0 -137
  150. package/src/@modules/@utilities/utilities.createHttp.ts +0 -85
  151. package/src/@modules/@utilities/utilities.createWebhook.ts +0 -115
  152. package/test.js +0 -91
  153. /package/{CODE_OF_CONDUCT.md → .github/CODE_OF_CONDUCT.md} +0 -0
  154. /package/{LICENSE → .github/LICENSE} +0 -0
  155. /package/{SECURITY.md → .github/SECURITY.md} +0 -0
  156. /package/src/@parsers/@ugc/{ugc.zones.ts → GetZones.ts} +0 -0
  157. /package/src/@types/{types.attributes.ts → Attributes.ts} +0 -0
  158. /package/src/@types/{types.hvtec.ts → HVTEC.ts} +0 -0
  159. /package/src/@types/{types.hash.ts → Hash.ts} +0 -0
  160. /package/src/@types/{types.stanza.ts → Stanza.ts} +0 -0
  161. /package/src/@types/{types.ugc.ts → UGC.ts} +0 -0
  162. /package/src/@types/{types.pvtec.ts → VTEC.ts} +0 -0
@@ -16,12 +16,12 @@
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
- import { setEventEmit } from '../@utilities/utilities.setEventEmit';
21
+ import { SetEventEmit } from '../@utilities/SetEventEmit';
22
+ import { xml } from '@xmpp/client'
23
23
 
24
- export const xOnline = () => {
24
+ export const OnlineXMPP = () => {
25
25
  const settings = bootstrap.settings;
26
26
  bootstrap.session_xmpp.on(`online`, async (address: string) => {
27
27
  bootstrap.cache.sigHault = false;
@@ -32,7 +32,7 @@ export const xOnline = () => {
32
32
  to: `nwws@conference.nwws-oi.weather.gov/${nickname}`,
33
33
  xmlns: 'http://jabber.org/protocol/muc',
34
34
  }))
35
- setEventEmit({
35
+ SetEventEmit({
36
36
  event: `onServiceStatus`,
37
37
  metadata: {
38
38
  message: `Succesfully connected to NOAA Weather Wire Service as "${nickname}"`,
@@ -40,6 +40,7 @@ export const xOnline = () => {
40
40
  type: `online`,
41
41
  error: false
42
42
  },
43
+ message: `Succesfully connected to NOAA Weather Wire Service as "${nickname}"`,
43
44
  })
44
45
  })
45
46
  }
@@ -17,16 +17,16 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeSettings } from "../../@types/types.settings";
20
+ import { TypeSettings } from "../../@types/Settings";
21
21
  import { bootstrap } from "../../bootstrap"
22
- import { setEventEmit } from "../@utilities/utilities.setEventEmit";
23
- import { setWarning } from "../@utilities/utilities.setWarning";
22
+ import { SetEventEmit } from "../@utilities/SetEventEmit";
23
+ import { SetWarning } from "../@utilities/SetWarning";
24
24
 
25
- export const xReconnect = async (interval: number): Promise<void> => {
25
+ export const ReconnectXMPP = 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
  }
@@ -40,7 +40,7 @@ export const xReconnect = async (interval: number): Promise<void> => {
40
40
  bootstrap.cache.isConnected = false;
41
41
  bootstrap.cache.tReconnects += 1;
42
42
  try {
43
- setEventEmit({
43
+ SetEventEmit({
44
44
  event: `onServiceStatus`,
45
45
  metadata: {
46
46
  message: `Attempting to reconnect to XMPP Service (Reconnect Attempt ${bootstrap.cache.tReconnects})`,
@@ -50,12 +50,12 @@ export const xReconnect = async (interval: number): Promise<void> => {
50
50
  },
51
51
  type: `reconnect`,
52
52
  error: true
53
- },
53
+ }, message: `Attempting to reconnect to XMPP Service (Reconnect Attempt ${bootstrap.cache.tReconnects})`,
54
54
  })
55
55
  await bootstrap.session_xmpp.stop().catch(() => {});
56
56
  await bootstrap.session_xmpp.start().catch(() => {});
57
57
  } catch (error) {
58
- setWarning({ message: `XMPP Reconnect Failed - ${(error as Error).message}` })
58
+ SetWarning({ message: `XMPP Reconnect Failed - ${(error as Error).message}` })
59
59
  } finally {
60
60
  bootstrap.cache.isReconnecting = false;
61
61
  }
@@ -17,18 +17,18 @@
17
17
 
18
18
  */
19
19
 
20
- import { TypeStanza } from "../../@types/types.stanza";
20
+ import { TypeStanza } from "../../@types/Stanza";
21
21
  import { bootstrap } from "../../bootstrap";
22
- import { validate } from "../@stanza/stanza.validate";
23
- import { createEvent } from "../../@building/building.create";
24
- import { importStanza } from "../@database/database.stanza";
25
- import { setEventEmit } from "../@utilities/utilities.setEventEmit";
22
+ import { ValidateStanza } from "../@stanza/ValidateStanza";
23
+ import { CreateEvent } from "../../@building/CreateEvent";
24
+ import { ImportStanza } from "../@database/ImportStanza";
25
+ import { SetEventEmit } from "../@utilities/SetEventEmit";
26
26
 
27
- export const xStanza = () => {
27
+ export const StanzaXMPP = () => {
28
28
  bootstrap.session_xmpp.on(`stanza`, async (stanza: TypeStanza) => {
29
29
  const msgFrom = stanza?.attrs?.from ?? ``
30
30
  const msgType = stanza?.attrs?.type ?? ``
31
- setEventEmit({
31
+ SetEventEmit({
32
32
  event: `onServiceStatus`,
33
33
  metadata: {
34
34
  message: stanza,
@@ -38,18 +38,18 @@ export const xStanza = () => {
38
38
  })
39
39
  bootstrap.cache.lastStanza = Date.now();
40
40
  if (stanza.is(`message`)) {
41
- const result = validate({ stanza });
41
+ const result = ValidateStanza({ stanza });
42
42
  const isSkippable = result.isIgnored ||
43
43
  (result.isCapEvent) ||
44
44
  (result.isCapEvent && !result.isCapAreaDescription)
45
45
  if (isSkippable) { return; }
46
- await createEvent(result);
47
- await importStanza(result);
46
+ await CreateEvent(result);
47
+ await ImportStanza(result);
48
48
  }
49
49
  if (stanza.is(`presence`) && msgFrom.startsWith('nwws@conference.nwws-oi.weather.gov/')) {
50
50
  const getOccupant = msgFrom.split(`/`).slice(1).join(`/`)
51
51
  const getAvailability = msgType === `unavailable`
52
- setEventEmit({
52
+ SetEventEmit({
53
53
  event: `onServiceStatus`,
54
54
  metadata: {
55
55
  message: `Occupant ${getOccupant} has ${getAvailability ? `left` : `joined`} the room`,
@@ -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/HVTEC";
21
+ import { EnumCauses } from "../../@enums/Causes";
22
+ import { EnumRecords } from "../../@enums/Records";
23
+ import { EnumExpressions } from "../../@enums/Expressions";
24
+ import { EnumSeverity } from "../../@enums/Severity";
25
25
 
26
- export const hvExtract = (message: string): TypeHVTEC[] | null => {
27
- const getHVTECs = message.match(regExp.hvtec) ?? [];
26
+ export const HVExtract = (message: string): TypeHVTEC[] | null => {
27
+ const getHVTECs = message.match(EnumExpressions.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: EnumSeverity[sub[1]],
35
+ cause: EnumCauses[sub[2]],
36
+ record: EnumRecords[sub[6]]
37
37
  })
38
38
  }
39
39
  return vtecs.length > 0 ? vtecs : null;
@@ -17,7 +17,7 @@
17
17
 
18
18
  */
19
19
 
20
- export const getExpiry = (dates: string[]): string => {
20
+ export const GetExpiry = (dates: string[]): string => {
21
21
  if (dates?.[1] == `000000T0000Z`) return 'Invalid Date Format'
22
22
  const expires = `${new Date().getFullYear().toString().substring(0, 2)}${dates[1].substring(0, 2)}-${dates[1].substring(2, 4)}-${dates[1].substring(4, 6)}T${dates[1].substring(7, 9)}:${dates[1].substring(9, 11)}:00`;
23
23
  const local = new Date(new Date(expires).getTime() - 4 * 60 * 60000);
@@ -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";
26
- import { getExpiry } from "./pvtec.expires";
20
+ import { TypePVTEC } from "../../@types/VTEC";
21
+ import { EnumExpressions } from "../../@enums/Expressions";
22
+ import { EnumProducts } from "../../@enums/Products";
23
+ import { EnumEvents } from "../../@enums/Events";
24
+ import { EnumActions } from "../../@enums/Actions";
25
+ import { EnumStatus } from "../../@enums/Status";
26
+ import { GetExpiry } from "./GetExpiry";
27
27
 
28
- export const pvExtract = (message: string): TypePVTEC[] | null => {
29
- const getVTECs = message.match(regExp.pvtec) ?? [];
28
+ export const VTECExtract = (message: string): TypePVTEC[] | null => {
29
+ if (!message) return null;
30
+ const getVTECs = message.match(EnumExpressions.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
- 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,
42
- expires: getExpiry(dates),
38
+ product: EnumProducts[sub[0]],
39
+ tracking: `${sub[2]}.${sub[3]}.${sub[4]}.${sub[5]}`,
40
+ event: `${EnumEvents[sub[3]]} ${EnumActions[sub[4]]}`,
41
+ status: EnumStatus[sub[1]],
42
+ organization: message.match(EnumExpressions.wmo)?.[0] ?? null,
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,21 +17,28 @@
17
17
 
18
18
  */
19
19
 
20
- import { regExp } from "../../@dictionaries/dictionaries.regExp";
20
+ import { EnumExpressions } from "../../@enums/Expressions";
21
21
 
22
22
  interface GetDescriptionFromProductOptions {
23
23
  message: string
24
24
  handle?: string
25
25
  }
26
26
 
27
- export const getDescriptionFromProduct = (options: GetDescriptionFromProductOptions): string => {
27
+ export const GetDescriptionFromProduct = (options: GetDescriptionFromProductOptions): string => {
28
28
  let message = options.message;
29
- const dates = Array.from(message.matchAll(regExp.dateline));
29
+ const predefinedEndMarkers = ['&&', 'LAT...'];
30
+ const getEndIndex = (text: string, fromIndex = 0): number => {
31
+ const indices = predefinedEndMarkers
32
+ .map((marker) => text.indexOf(marker, fromIndex))
33
+ .filter((idx) => idx !== -1);
34
+ return indices.length ? Math.min(...indices) : -1;
35
+ };
36
+ const dates = Array.from(message.matchAll(EnumExpressions.dateline));
30
37
  if (dates.length) {
31
38
  const lastMatch = dates[dates.length - 1][0];
32
39
  const sIndx = message.lastIndexOf(lastMatch);
33
40
  if (sIndx !== -1) {
34
- const endIndx = message.indexOf('&&', sIndx);
41
+ const endIndx = getEndIndex(message, sIndx);
35
42
  message = message.substring(sIndx + lastMatch.length, endIndx !== -1 ? endIndx : undefined).trimStart();
36
43
  if (message.startsWith('/')) message = message.slice(1).trimStart();
37
44
  if (options.handle && message.includes(options.handle)) {
@@ -45,7 +52,7 @@ export const getDescriptionFromProduct = (options: GetDescriptionFromProductOpti
45
52
  if (handleIndx !== -1) {
46
53
  let afterHandle = message.substring(handleIndx + options.handle.length).trimStart();
47
54
  if (afterHandle.startsWith('/')) afterHandle = afterHandle.slice(1).trimStart();
48
- const latEnd = afterHandle.indexOf('&&')
55
+ const latEnd = getEndIndex(afterHandle);
49
56
  message = latEnd !== -1 ? afterHandle.substring(0, latEnd).trim() : afterHandle.trim();
50
57
  }
51
58
  }
@@ -0,0 +1,56 @@
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/Event"
21
+
22
+ export const GetEmebedText = (event: TypeEvent): string => {
23
+ const line = (label: string, value: unknown, condition = true) => condition && value ? `${label} ${value}` : null;
24
+ const isStatement = event.properties.status_metadata.is_statement;
25
+ const isExpired = event.properties.status_metadata.is_expired;
26
+ return [
27
+ line(`**Locations:**`, event?.properties?.locations?.slice(0, 100)),
28
+ line(`**Issued:**`, `<t:${Math.floor(new Date(event.properties.issued).getTime() / 1000)}:R>`, !isExpired),
29
+ line(`**Expires:**`, `<t:${Math.floor(new Date(event.properties.expires).getTime() / 1000)}:R>`, !isStatement),
30
+ line(`**Damage Threat:**`, event?.properties?.parameters?.damage_threat, !isExpired),
31
+ line(`**Flood Threat:**`, event?.properties?.parameters?.flood_threat, !isExpired),
32
+ line(`**Tornado Threat:**`, event?.properties?.parameters?.tornado_threat, !isExpired),
33
+ 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),
34
+ 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),
35
+ line(`**Discussion:**`, event?.properties?.discussion_parameters?.discussion_number, !isExpired),
36
+ line(`**Concern:**`, event?.properties?.discussion_parameters?.discussion_concerning, !isExpired),
37
+ line(`**SPC Max Tornado Threat:**`, event?.properties?.discussion_parameters?.discussion_max_tornado, !isExpired),
38
+ line(`**SPC Max Hail Threat:**`, event?.properties?.discussion_parameters?.discussion_max_hail, !isExpired),
39
+ line(`**SPC Max Wind Threat:**`, event?.properties?.discussion_parameters?.discussion_max_wind, !isExpired),
40
+ line(`**SPC Watch Issuance Probability:**`, event?.properties?.discussion_parameters?.discussion_watch_issuance ? `${event?.properties?.discussion_parameters?.discussion_watch_issuance}%` : null, !isExpired),
41
+ line(`**Watch Number:**`, event?.properties?.watch_parameters?.watch_number, !isExpired),
42
+ line(`**Strong Tornadoes Probability:**`, event?.properties?.watch_parameters?.strong_tornadoes_probability ? `${event?.properties?.watch_parameters?.strong_tornadoes_probability}%` : null, !isExpired),
43
+ line(`**Additional Tornadoes Probability:**`, event?.properties?.watch_parameters?.additional_tornadoes_probability ? `${event?.properties?.watch_parameters?.additional_tornadoes_probability}%` : null, !isExpired),
44
+ line(`**Combined Hail/Wind Probability:**`, event?.properties?.watch_parameters?.combined_hail_wind_probability ? `${event?.properties?.watch_parameters?.combined_hail_wind_probability}%` : null, !isExpired),
45
+ line(`**Severe Hail Probability:**`, event?.properties?.watch_parameters?.severe_hail_probability ? `${event?.properties?.watch_parameters?.severe_hail_probability}%` : null, !isExpired),
46
+ line(`**Hail >2in Probability:**`, event?.properties?.watch_parameters?.hail_2in_probability ? `${event?.properties?.watch_parameters?.hail_2in_probability}%` : null, !isExpired),
47
+ line(`**Max Hail Inches:**`, event?.properties?.watch_parameters?.max_hail_in, !isExpired),
48
+ line(`**Severe Wind Probability:**`, event?.properties?.watch_parameters?.severe_wind_probability ? `${event?.properties?.watch_parameters?.severe_wind_probability}%` : null, !isExpired),
49
+ line(`**Max Surface Wind:**`, event?.properties?.watch_parameters?.max_wind_surface, !isExpired),
50
+ line(`**Max Tops (x100 feet):**`, event?.properties?.watch_parameters?.max_tops_x100feet, !isExpired),
51
+ line(`**Tags:**`, event?.properties?.parameters?.tags?.length > 0 ? event?.properties?.parameters?.tags.join(', ') : null, !isExpired),
52
+ line(`**Sender:**`, event?.properties?.geocode?.office?.name ? `${event?.properties?.geocode?.office?.name} (${event?.properties?.geocode?.office?.office})` : event?.properties?.geocode?.office?.office),
53
+ line(`**Tracking:**`, event?.properties?.metadata?.tracking),
54
+ line(`**Logs:**`, event?.properties?.metadata?.history?.length > 0 ? event?.properties?.metadata?.history.length : null),
55
+ ].filter(Boolean).join('\n');
56
+ }
@@ -18,15 +18,36 @@
18
18
  */
19
19
 
20
20
  export const getPolygonFromProduct = (message: string): number[][] => {
21
- const coordinates: [number, number][] = [];
22
- const match = message.match(/LAT\.{3}LON\s+([\d\s]+)/i);
23
- if (!match || !match[1]) return coordinates;
24
- const coordStrings = match[1].replace(/\n/g, ' ').trim().split(/\s+/);
25
- for (let i = 0; i < coordStrings.length - 1; i += 2) {
26
- const lat = parseFloat(coordStrings[i]) / 100;
27
- const lon = -parseFloat(coordStrings[i + 1]) / 100;
28
- if (!isNaN(lat) && !isNaN(lon)) { coordinates.push([lon, lat]); }
21
+ const coordinates: number[][] = [];
22
+ const match = message.match(
23
+ /LAT\.\.\.LON\s+([\s\S]*?)(?=\n[A-Z]{2,}(?:\.\.\.|:)|\$\$|&&|$)/i
24
+ );
25
+ if (!match) return coordinates;
26
+ const text = match[1];
27
+ const values = text.match(/\d{4,8}/g);
28
+ if (!values) return coordinates;
29
+
30
+ if (values.every(v => v.length === 8)) {
31
+ for (const value of values) {
32
+ const lat = parseInt(value.slice(0, 4), 10) / 100;
33
+ const lon = -parseInt(value.slice(4, 8), 10) / 100;
34
+ if (Number.isFinite(lat) && Number.isFinite(lon)) {
35
+ coordinates.push([lon, lat]);
36
+ }
37
+ }
38
+ }
39
+
40
+ else {
41
+ for (let i = 0; i + 1 < values.length; i += 2) {
42
+ const lat = parseInt(values[i], 10) / 100;
43
+ const lon = -parseInt(values[i + 1], 10) / 100;
44
+ if (Number.isFinite(lat) && Number.isFinite(lon)) {
45
+ coordinates.push([lon, lat]);
46
+ }
47
+ }
48
+ }
49
+ if (coordinates.length > 2) {
50
+ coordinates.push([...coordinates[0]]);
29
51
  }
30
- if (coordinates.length > 2) { coordinates.push(coordinates[0]); }
31
52
  return coordinates;
32
- }
53
+ };
@@ -0,0 +1,58 @@
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/Event"
21
+ import { TypeSettings } from "../../@types/Settings";
22
+ import { bootstrap } from "../../bootstrap";
23
+
24
+ export const GetStringText = (event: TypeEvent): string => {
25
+ const settings = bootstrap.settings as TypeSettings;
26
+ const timezone = settings.NotifyServer.Timezone ?? `UTC`;
27
+ const line = (label: string, value: unknown, condition = true) => condition && value ? `${label} ${value}` : null;
28
+ const isStatement = event.properties.status_metadata.is_statement;
29
+ const isExpired = event.properties.status_metadata.is_expired;
30
+ return [
31
+ line(`Locations:`, event?.properties?.locations?.slice(0, 100)),
32
+ line(`Issued:`, `${new Date(event.properties.issued).toLocaleString([], { timeZone: timezone })} (${(timezone.replace(`America/`, ``))})`, !isExpired),
33
+ line(`Expires:`, `${new Date(event.properties.expires).toLocaleString([], { timeZone: timezone })} (${(timezone.replace(`America/`, ``))})`, !isStatement),
34
+ line(`Damage Threat:`, event?.properties?.parameters?.damage_threat, !isExpired),
35
+ line(`Flood Threat:`, event?.properties?.parameters?.flood_threat, !isExpired),
36
+ line(`Tornado Threat:`, event?.properties?.parameters?.tornado_threat, !isExpired),
37
+ 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),
38
+ 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),
39
+ line(`Discussion:`, event?.properties?.discussion_parameters?.discussion_number, !isExpired),
40
+ line(`Concern:`, event?.properties?.discussion_parameters?.discussion_concerning, !isExpired),
41
+ line(`SPC Max Tornado Threat:`, event?.properties?.discussion_parameters?.discussion_max_tornado, !isExpired),
42
+ line(`SPC Max Hail Threat:`, event?.properties?.discussion_parameters?.discussion_max_hail, !isExpired),
43
+ line(`SPC Max Wind Threat:`, event?.properties?.discussion_parameters?.discussion_max_wind, !isExpired),
44
+ line(`SPC Watch Issuance Probability:`, event?.properties?.discussion_parameters?.discussion_watch_issuance ? `${event?.properties?.discussion_parameters?.discussion_watch_issuance}%` : null, !isExpired),
45
+ line(`Watch Number:`, event?.properties?.watch_parameters?.watch_number, !isExpired),
46
+ line(`Strong Tornadoes Probability:`, event?.properties?.watch_parameters?.strong_tornadoes_probability ? `${event?.properties?.watch_parameters?.strong_tornadoes_probability}%` : null, !isExpired),
47
+ line(`Additional Tornadoes Probability:`, event?.properties?.watch_parameters?.additional_tornadoes_probability ? `${event?.properties?.watch_parameters?.additional_tornadoes_probability}%` : null, !isExpired),
48
+ line(`Combined Hail/Wind Probability:`, event?.properties?.watch_parameters?.combined_hail_wind_probability ? `${event?.properties?.watch_parameters?.combined_hail_wind_probability}%` : null, !isExpired),
49
+ line(`Severe Hail Probability:`, event?.properties?.watch_parameters?.severe_hail_probability ? `${event?.properties?.watch_parameters?.severe_hail_probability}%` : null, !isExpired),
50
+ line(`Hail >2in Probability:`, event?.properties?.watch_parameters?.hail_2in_probability ? `${event?.properties?.watch_parameters?.hail_2in_probability}%` : null, !isExpired),
51
+ line(`Max Hail Inches:`, event?.properties?.watch_parameters?.max_hail_in, !isExpired),
52
+ line(`Severe Wind Probability:`, event?.properties?.watch_parameters?.severe_wind_probability ? `${event?.properties?.watch_parameters?.severe_wind_probability}%` : null, !isExpired),
53
+ line(`Max Surface Wind:`, event?.properties?.watch_parameters?.max_wind_surface, !isExpired),
54
+ line(`Max Tops (x100 feet):`, event?.properties?.watch_parameters?.max_tops_x100feet, !isExpired),
55
+ line(`Sender:`, event?.properties?.geocode?.office?.name ? `${event?.properties?.geocode?.office?.name} (${event?.properties?.geocode?.office?.office})` : event?.properties?.geocode?.office?.office),
56
+ line(`Tracking:`, event?.properties?.metadata?.tracking),
57
+ ].filter(Boolean).join('\n');
58
+ }
@@ -24,7 +24,7 @@ interface GetTextFromProductOptions {
24
24
  removal?: string[]
25
25
  }
26
26
 
27
- export const getTextFromProduct = (options: GetTextFromProductOptions): string => {
27
+ export const GetTextFromProduct = (options: GetTextFromProductOptions): string => {
28
28
  const lines = options.message.split(`\n`);
29
29
  for (const line of lines) {
30
30
  const matchedFind = options.find.find((find) => line.includes(find));
@@ -22,7 +22,7 @@ interface GetXMLOptions {
22
22
  targets: string[]
23
23
  }
24
24
 
25
- export const getXML = (options: GetXMLOptions): Record<string, string> => {
25
+ export const GetXML = (options: GetXMLOptions): Record<string, string> => {
26
26
  const extracted: Record<string, any> = {};
27
27
  const findValueByKey = (obj: any, searchKey: string) => {
28
28
  const results = [];
@@ -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
+ };
@@ -17,7 +17,7 @@
17
17
 
18
18
  */
19
19
 
20
- export const getExpiry = (message: string): string | null => {
20
+ export const GetExpiry = (message: string): string | null => {
21
21
  const match = message.match(/\b(\d{6})-/);
22
22
  if (!match) {
23
23
  return null;
@@ -18,12 +18,40 @@
18
18
  */
19
19
 
20
20
  import { bootstrap } from "../../bootstrap";
21
+ import { getCache } from "./GetCache";
22
+ import { setCache } from "./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
+ };
@@ -17,12 +17,12 @@
17
17
 
18
18
  */
19
19
 
20
- import { regExp } from "../../@dictionaries/dictionaries.regExp"
20
+ import { EnumExpressions } from "../../@enums/Expressions"
21
21
 
22
22
  export const getUGCHeader = (message: string): string | null => {
23
- const start = message.search(regExp.ugc1)
23
+ const start = message.search(EnumExpressions.ugc1)
24
24
  const sub = message.substring(start)
25
- const end = sub.search(regExp.ugc2)
25
+ const end = sub.search(EnumExpressions.ugc2)
26
26
  const fin = sub.substring(0, end)
27
27
  .replace(/\s+/g, '')
28
28
  .slice(0, -1);
@@ -16,8 +16,9 @@
16
16
  Internal Package: @atmosx/event-product-parser
17
17
 
18
18
  */
19
+
20
+ import { bootstrap } from "../../bootstrap"
19
21
  import { union } from "polygon-clipping";
20
- import { bootstrap } from "../../bootstrap";
21
22
 
22
23
  interface CoordinatesOptions {
23
24
  zones: string[]
@@ -70,7 +71,7 @@ export const getZonePolygon = (options: CoordinatesOptions): CoordinatesResponse
70
71
  }
71
72
  if (!bestPoly || bestPoly.length === 0) return null;
72
73
  const outerRing = bestPoly[0];
73
- const skip = Math.max(1, parseInt(String(bootstrap.settings.GlobalSettings.ShapefileSkipPoints), 10) || 1);
74
+ const skip = Math.max(1, parseInt(String(bootstrap.settings.GlobalSettings.ShapefileSkipPoints), 10) ?? 1);
74
75
  let skipped = outerRing.filter((_: any, idx: number) => idx % skip === 0);
75
76
  if (skipped.length < 4) {
76
77
  skipped = outerRing.slice();
@@ -89,7 +90,7 @@ export const getZonePolygon = (options: CoordinatesOptions): CoordinatesResponse
89
90
  }
90
91
  }
91
92
  if (multi.length === 0) return null;
92
- const skip = Math.max(1, parseInt(String(bootstrap.settings.GlobalSettings.ShapefileSkipPoints), 10) || 1);
93
+ const skip = Math.max(1, parseInt(String(bootstrap.settings.GlobalSettings.ShapefileSkipPoints), 10) ?? 1);
93
94
  if (skip > 1) {
94
95
  for (let p = 0; p < multi.length; p++) {
95
96
  for (let r = 0; r < multi[p].length; r++) {
@@ -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
+ };