@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.
- package/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +1 -1
- package/.github/README.md +163 -0
- package/.github/SUPPORTED_EVENTS.md +370 -0
- package/.github/docs/docs-functions.md +30 -0
- package/.github/docs/docs-general-configurations.md +209 -0
- package/.github/docs/docs-integrations.md +37 -0
- package/.github/docs/docs-listeners.md +28 -0
- package/.github/docs/docs-source-configuration.md +218 -0
- package/.github/docs/docs-technical.md +50 -0
- package/.github/logo.png +0 -0
- package/.github/samples/SAMPLE_EAS_GENERATION.wav +0 -0
- package/.github/samples/SAMPLE_GEOJSON.json +204 -0
- package/.github/samples/SAMPLE_TEXT_PRODUCT.txt +119 -0
- package/dist/cjs/index.cjs +4677 -13422
- package/dist/esm/index.mjs +3159 -11906
- package/package.json +3 -9
- package/src/@building/{building.create.ts → CreateEvent.ts} +25 -11
- package/src/@building/{building.clean.ts → GetCleanedEvent.ts} +2 -2
- package/src/@building/GetEventAttachments.ts +86 -0
- package/src/@building/{building.enhance.ts → GetEventEnhancedName.ts} +11 -12
- package/src/@building/{building.geometry.ts → GetEventGeometry.ts} +7 -7
- package/src/@building/{building.headers.ts → GetEventHeader.ts} +3 -3
- package/src/@building/{building.polygon.ts → GetEventNodes.ts} +13 -11
- package/src/@building/{building.office.ts → GetEventOffice.ts} +6 -6
- package/src/@building/GetEventProperties.ts +96 -0
- package/src/@building/{building.signature.ts → GetEventSignature.ts} +14 -15
- package/src/@building/{building.tags.ts → GetEventTags.ts} +9 -4
- package/src/@building/{building.tracking.ts → GetEventTracking.ts} +15 -15
- package/src/@building/{building.validate.ts → ValidateEvents.ts} +67 -60
- package/src/@core/{core.clearEvents.ts → ClearEvents.ts} +3 -4
- package/src/@core/{core.createListener.ts → CreateListener.ts} +3 -3
- package/src/@core/{core.getEvents.ts → GetEvents.ts} +1 -2
- package/src/@core/{core.getNodes.ts → GetNodes.ts} +1 -2
- package/src/@core/{core.getRandomEvent.ts → GetRandomEvent.ts} +1 -2
- package/src/@core/{core.getVersion.ts → GetVersion.ts} +1 -2
- package/src/@core/ManualEvent.ts +56 -0
- package/src/@core/QueryStanza.ts +39 -0
- package/src/@core/{core.setNode.ts → SetNode.ts} +8 -8
- package/src/@core/{core.start.ts → StartService.ts} +21 -21
- package/src/@core/{core.stop.ts → StopService.ts} +1 -1
- package/src/@enums/AWIPS.ts +366 -0
- package/src/{@dictionaries/dictionaries.eventActions.ts → @enums/Actions.ts} +1 -1
- package/src/{@dictionaries/dictionaries.eventCancelMessages.ts → @enums/Cancellation.ts} +2 -1
- package/src/{@dictionaries/dictionaries.eventCauses.ts → @enums/Causes.ts} +1 -1
- package/src/{@dictionaries/dictionaries.statusCorrelationText.ts → @enums/Correlations.ts} +1 -1
- package/src/@enums/Enhanced.ts +70 -0
- package/src/{@dictionaries/dictionaries.eventTypes.ts → @enums/Events.ts} +1 -1
- package/src/{@dictionaries/dictionaries.regExp.ts → @enums/Expressions.ts} +2 -1
- package/src/@enums/GlobalFilter.ts +24 -0
- package/src/{@dictionaries/dictionaries.hailStrings.ts → @enums/Hail.ts} +7 -2
- package/src/{@dictionaries/dictionaries.officeICAOs.ts → @enums/ICAO.ts} +3 -1
- package/src/@enums/Matches.ts +55 -0
- package/src/{@dictionaries/dictionaries.eventProducts.ts → @enums/Products.ts} +1 -1
- package/src/{@dictionaries/dictionaries.eventRecords.ts → @enums/Records.ts} +1 -1
- package/src/{@dictionaries/dictionaries.eventSeverity.ts → @enums/Severity.ts} +1 -1
- package/src/{@dictionaries/dictionaries.shapefileLinks.ts → @enums/Shapefiles.ts} +1 -1
- package/src/@enums/States.ts +72 -0
- package/src/{@dictionaries/dictionaries.eventStatus.ts → @enums/Status.ts} +1 -1
- package/src/@enums/Strings.ts +22 -0
- package/src/@enums/Tags.ts +167 -0
- package/src/{@dictionaries/dictionaries.testSignatures.ts → @enums/Testing.ts} +3 -2
- package/src/@events/{events.api.ts → ParseAPI.ts} +42 -38
- package/src/@events/{events.text.ts → ParseText.ts} +25 -18
- package/src/@events/{events.ugc.ts → ParseUGC.ts} +28 -19
- package/src/@events/{events.vtec.ts → ParseVTEC.ts} +21 -21
- package/src/@manager/CreateActions.ts +213 -0
- package/src/@manager/{manager.mkEvent.ts → MakeEvent.ts} +34 -31
- package/src/@manager/RemoveEvent.ts +70 -0
- package/src/@manager/{manager.setHash.ts → SetHash.ts} +8 -9
- package/src/@manager/{manager.updateEvents.ts → UpdateEvents.ts} +9 -9
- package/src/@manager/{manager.updateNodes.ts → UpdateNode.ts} +24 -17
- package/src/@modules/@database/{database.cache.ts → GetCachedEvents.ts} +10 -8
- package/src/@modules/@database/ImportBroadcastify.ts +70 -0
- package/src/@modules/@database/{database.shapefiles.ts → ImportShapefiles.ts} +17 -20
- package/src/@modules/@database/{database.stanza.ts → ImportStanza.ts} +5 -6
- package/src/@modules/@database/{database.init.ts → InitializeDatabase.ts} +25 -11
- package/src/@modules/@eas/GenerateEASMessage.ts +144 -0
- package/src/@modules/@eas/GetCleanDescription.ts +91 -0
- package/src/@modules/@eas/{eas.getFloatPCM16.ts → GetFloatPCM16.ts} +1 -1
- package/src/@modules/@eas/{eas.getMergedPCM16.ts → GetMergedPCM16.ts} +1 -1
- package/src/@modules/@eas/{eas.getPCM16.ts → GetPCM16.ts} +1 -1
- package/src/@modules/@eas/{eas.getPCMToFloat.ts → GetPCMToFloat.ts} +1 -1
- package/src/@modules/@eas/{eas.getSampledPCM16.ts → GetSampledPCM16.ts} +1 -1
- package/src/@modules/@eas/GetTTS.ts +54 -0
- package/src/@modules/@eas/{eas.getWavPCM16.ts → GetWavPCM16.ts} +1 -1
- package/src/@modules/@eas/{eas.setAFSK.ts → SetAFSK.ts} +1 -2
- package/src/@modules/@eas/{eas.setAsciiToBits.ts → SetAsciiToBits.ts} +1 -2
- package/src/@modules/@eas/{eas.setAttentionTone.ts → SetAttentionTone.ts} +1 -1
- package/src/@modules/@eas/{eas.setNoise.ts → SetNoise.ts} +6 -5
- package/src/@modules/@eas/{eas.setRadioEffect.ts → SetRadioEffect.ts} +6 -5
- package/src/@modules/@eas/{eas.setSameHeader.ts → SetSameHeader.ts} +7 -8
- package/src/@modules/@stanza/{stanza.getAwipsType.ts → GetAwipsType.ts} +11 -9
- package/src/@modules/@stanza/{stanza.validate.ts → ValidateStanza.ts} +9 -9
- package/src/@modules/@utilities/CreateHttp.ts +83 -0
- package/src/@modules/@utilities/{utilities.getFormattedTime.ts → GetFormattedTime.ts} +1 -1
- package/src/@modules/@utilities/GetLatestIssuance.ts +32 -0
- package/src/@modules/@utilities/GetMatched.ts +33 -0
- package/src/@modules/@utilities/{utilities.getSettings.ts → GetSettings.ts} +2 -2
- package/src/@modules/@utilities/{utilities.getShapeNearestPoint.ts → GetShapeNearestPoint.ts} +1 -1
- package/src/@modules/@utilities/{utilities.setCronSchedule.ts → SetCronSchedule.ts} +41 -12
- package/src/{@types/types.webhook.ts → @modules/@utilities/SetDebug.ts} +16 -6
- package/src/@modules/@utilities/{utilities.setEventEmit.ts → SetEventEmit.ts} +5 -5
- package/src/@modules/@utilities/{utilities.setListener.ts → SetListener.ts} +1 -1
- package/src/@modules/@utilities/{utilities.setSettings.ts → SetSettings.ts} +2 -2
- package/src/@modules/@utilities/{utilities.setSleep.ts → SetSleep.ts} +1 -1
- package/src/@modules/@utilities/{utilities.setTimeoutAction.ts → SetTimeoutAction.ts} +8 -3
- package/src/@modules/@utilities/{utilities.setWarning.ts → SetWarning.ts} +2 -2
- package/src/@modules/@xmpp/{xmpp.xDeploy.ts → DeployXMPP.ts} +13 -14
- package/src/@modules/@xmpp/{xmpp.xError.ts → ErrorXMPP.ts} +1 -3
- package/src/@modules/@xmpp/{xmpp.xOffline.ts → OfflineXMPP.ts} +3 -4
- package/src/@modules/@xmpp/{xmpp.xOnline.ts → OnlineXMPP.ts} +6 -5
- package/src/@modules/@xmpp/{xmpp.xReconnect.ts → ReconnectXMPP.ts} +8 -8
- package/src/@modules/@xmpp/{xmpp.xStanza.ts → StanzaXMPP.ts} +11 -11
- package/src/@parsers/@hvtec/{hvtec.extract.ts → HVExtract.ts} +10 -10
- package/src/@parsers/@pvtec/{pvtec.expires.ts → GetExpiry.ts} +1 -1
- package/src/@parsers/@pvtec/{pvtec.extract.ts → VTECExtract.ts} +17 -17
- package/src/@parsers/@text/{text.getDescriptionFromProduct.ts → GetDescriptionFromProduct.ts} +12 -5
- package/src/@parsers/@text/GetEmbededText.ts +56 -0
- package/src/@parsers/@text/{text.getPolygonFromProduct.ts → GetPolygonFromProduct.ts} +31 -10
- package/src/@parsers/@text/GetStringText.ts +58 -0
- package/src/@parsers/@text/{text.getTextFromProduct.ts → GetTextFromProduct.ts} +1 -1
- package/src/@parsers/@text/{text.getXML.ts → GetXML.ts} +1 -1
- package/src/@parsers/@ugc/GetCache.ts +24 -0
- package/src/@parsers/@ugc/{ugc.expiry.ts → GetExpiry.ts} +1 -1
- package/src/@parsers/@ugc/{ugc.locations.ts → GetLocations.ts} +35 -7
- package/src/@parsers/@ugc/{ugc.header.ts → GetUGCHeader.ts} +3 -3
- package/src/@parsers/@ugc/{ugc.coordinates.ts → GetZonePolygon.ts} +4 -3
- package/src/@parsers/@ugc/SetCache.ts +28 -0
- package/src/@parsers/@ugc/{ugc.extract.ts → UGCExtract.ts} +6 -6
- package/src/@types/Actions.ts +37 -0
- package/src/@types/{type.event.ts → Event.ts} +7 -5
- package/src/@types/{type.properties.ts → Properties.ts} +11 -8
- package/src/@types/{types.settings.ts → Settings.ts} +31 -7
- package/src/@types/{types.compiled.ts → StanzaCompiled.ts} +2 -1
- package/src/bootstrap.ts +33 -9
- package/src/index.ts +26 -24
- package/tsup.config.ts +1 -1
- package/README.md +0 -349
- package/dist/index.d.mts +0 -239
- package/dist/index.d.ts +0 -239
- package/src/@building/building.properties.ts +0 -89
- package/src/@dictionaries/dictionaries.betterEventNames.ts +0 -99
- package/src/@dictionaries/dictionaries.eventAwipAbreviations.ts +0 -364
- package/src/@dictionaries/dictionaries.eventTags.ts +0 -93
- package/src/@dictionaries/dictionaries.eventsMatchText.ts +0 -36
- package/src/@dictionaries/dictionaries.transcribedMessageReplacements.ts +0 -68
- package/src/@manager/manager.rmEvent.ts +0 -49
- package/src/@manager/manager.updateWebhooks.ts +0 -50
- package/src/@modules/@eas/eas.setEasTone.ts +0 -137
- package/src/@modules/@utilities/utilities.createHttp.ts +0 -85
- package/src/@modules/@utilities/utilities.createWebhook.ts +0 -115
- package/test.js +0 -91
- /package/{CODE_OF_CONDUCT.md → .github/CODE_OF_CONDUCT.md} +0 -0
- /package/{LICENSE → .github/LICENSE} +0 -0
- /package/{SECURITY.md → .github/SECURITY.md} +0 -0
- /package/src/@parsers/@ugc/{ugc.zones.ts → GetZones.ts} +0 -0
- /package/src/@types/{types.attributes.ts → Attributes.ts} +0 -0
- /package/src/@types/{types.hvtec.ts → HVTEC.ts} +0 -0
- /package/src/@types/{types.hash.ts → Hash.ts} +0 -0
- /package/src/@types/{types.stanza.ts → Stanza.ts} +0 -0
- /package/src/@types/{types.ugc.ts → UGC.ts} +0 -0
- /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
|
-
|
|
19
|
+
|
|
20
20
|
import { bootstrap } from "../../bootstrap";
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
21
|
+
import { SetEventEmit } from '../@utilities/SetEventEmit';
|
|
22
|
+
import { xml } from '@xmpp/client'
|
|
23
23
|
|
|
24
|
-
export const
|
|
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
|
-
|
|
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/
|
|
20
|
+
import { TypeSettings } from "../../@types/Settings";
|
|
21
21
|
import { bootstrap } from "../../bootstrap"
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
22
|
+
import { SetEventEmit } from "../@utilities/SetEventEmit";
|
|
23
|
+
import { SetWarning } from "../@utilities/SetWarning";
|
|
24
24
|
|
|
25
|
-
export const
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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/
|
|
20
|
+
import { TypeStanza } from "../../@types/Stanza";
|
|
21
21
|
import { bootstrap } from "../../bootstrap";
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
|
47
|
-
await
|
|
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
|
-
|
|
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/
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
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
|
|
27
|
-
const getHVTECs = message.match(
|
|
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:
|
|
35
|
-
cause:
|
|
36
|
-
record:
|
|
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
|
|
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/
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
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
|
|
29
|
-
|
|
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:
|
|
38
|
-
tracking: `${sub[2]}
|
|
39
|
-
event: `${
|
|
40
|
-
status:
|
|
41
|
-
organization: message.match(
|
|
42
|
-
expires:
|
|
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;
|
package/src/@parsers/@text/{text.getDescriptionFromProduct.ts → GetDescriptionFromProduct.ts}
RENAMED
|
@@ -17,21 +17,28 @@
|
|
|
17
17
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import {
|
|
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
|
|
27
|
+
export const GetDescriptionFromProduct = (options: GetDescriptionFromProductOptions): string => {
|
|
28
28
|
let message = options.message;
|
|
29
|
-
const
|
|
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
|
|
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
|
|
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: [
|
|
22
|
-
const match = message.match(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
|
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
|
|
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
|
+
};
|
|
@@ -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
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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 {
|
|
20
|
+
import { EnumExpressions } from "../../@enums/Expressions"
|
|
21
21
|
|
|
22
22
|
export const getUGCHeader = (message: string): string | null => {
|
|
23
|
-
const start = message.search(
|
|
23
|
+
const start = message.search(EnumExpressions.ugc1)
|
|
24
24
|
const sub = message.substring(start)
|
|
25
|
-
const end = sub.search(
|
|
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)
|
|
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)
|
|
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
|
+
};
|