@atmosx/event-product-parser 2.0.16 → 3.0.1
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/README.md +248 -187
- package/dist/cjs/index.cjs +12218 -3139
- package/dist/esm/index.mjs +12401 -3327
- package/dist/index.d.mts +235 -0
- package/dist/index.d.ts +235 -0
- package/package.json +6 -4
- package/src/@building/building.clean.ts +30 -0
- package/src/@building/building.create.ts +42 -0
- package/src/@building/building.enhance.ts +56 -0
- package/src/@building/building.geometry.ts +48 -0
- package/src/@building/building.headers.ts +37 -0
- package/src/@building/building.office.ts +43 -0
- package/src/@building/building.polygon.ts +71 -0
- package/src/@building/building.properties.ts +89 -0
- package/src/@building/building.signature.ts +61 -0
- package/src/@building/building.tags.ts +24 -0
- package/src/@building/building.tracking.ts +68 -0
- package/src/@building/building.validate.ts +147 -0
- package/src/@core/core.getEvents.ts +25 -0
- package/src/@core/core.getNodes.ts +25 -0
- package/src/@core/core.getRandomEvent.ts +25 -0
- package/src/@core/core.getVersion.ts +25 -0
- package/src/@core/core.listener.ts +24 -0
- package/src/@core/core.setNode.ts +81 -0
- package/src/@core/core.start.ts +59 -0
- package/src/@core/core.stop.ts +32 -0
- package/src/@dictionaries/dictionaries.betterEventNames.ts +89 -0
- package/src/@dictionaries/dictionaries.eventActions.ts +28 -0
- package/src/@dictionaries/{awips.ts → dictionaries.eventAwipAbreviations.ts} +13 -7
- package/src/@dictionaries/dictionaries.eventCancelMessages.ts +30 -0
- package/src/@dictionaries/dictionaries.eventCauses.ts +36 -0
- package/src/@dictionaries/dictionaries.eventProducts.ts +25 -0
- package/src/@dictionaries/dictionaries.eventRecords.ts +25 -0
- package/src/@dictionaries/dictionaries.eventSeverity.ts +27 -0
- package/src/@dictionaries/dictionaries.eventStatus.ts +31 -0
- package/src/@dictionaries/{signatures.ts → dictionaries.eventTags.ts} +13 -68
- package/src/@dictionaries/dictionaries.eventTypes.ts +82 -0
- package/src/@dictionaries/dictionaries.eventsOffshore.ts +31 -0
- package/src/@dictionaries/dictionaries.hailStrings.ts +33 -0
- package/src/@dictionaries/{icao.ts → dictionaries.officeICAOs.ts} +13 -6
- package/src/@dictionaries/dictionaries.regExp.ts +28 -0
- package/src/@dictionaries/dictionaries.shapefileLinks.ts +36 -0
- package/src/@dictionaries/dictionaries.statusCorrelationText.ts +40 -0
- package/src/@dictionaries/dictionaries.testSignatures.ts +24 -0
- package/src/@dictionaries/dictionaries.transcribedMessageReplacements.ts +68 -0
- package/src/@events/events.api.ts +113 -0
- package/src/@events/events.text.ts +79 -0
- package/src/@events/events.ugc.ts +83 -0
- package/src/@events/events.vtec.ts +87 -0
- package/src/@manager/manager.mkEvent.ts +95 -0
- package/src/@manager/manager.rmEvent.ts +46 -0
- package/src/@manager/manager.setHash.ts +37 -0
- package/src/@manager/manager.updateNodes.ts +55 -0
- package/src/@manager/manager.updateWebhooks.ts +50 -0
- package/src/@modules/@database/database.cache.ts +48 -0
- package/src/@modules/@database/database.init.ts +45 -0
- package/src/@modules/@database/database.shapefiles.ts +96 -0
- package/src/@modules/@database/database.stanza.ts +48 -0
- package/src/@modules/@eas/eas.getFloatPCM16.ts +29 -0
- package/src/@modules/@eas/eas.getMergedPCM16.ts +32 -0
- package/src/@modules/@eas/eas.getPCM16.ts +52 -0
- package/src/@modules/@eas/eas.getPCMToFloat.ts +26 -0
- package/src/@modules/@eas/eas.getSampledPCM16.ts +36 -0
- package/src/@modules/@eas/eas.getWavPCM16.ts +52 -0
- package/src/@modules/@eas/eas.setAFSK.ts +52 -0
- package/src/@modules/@eas/eas.setAsciiToBits.ts +32 -0
- package/src/@modules/@eas/eas.setAttentionTone.ts +40 -0
- package/src/@modules/@eas/eas.setEasTone.ts +137 -0
- package/src/@modules/@eas/eas.setNoise.ts +31 -0
- package/src/@modules/@eas/eas.setRadioEffect.ts +49 -0
- package/src/@modules/@eas/eas.setSameHeader.ts +45 -0
- package/src/@modules/@stanza/stanza.getAwipsType.ts +46 -0
- package/src/@modules/@stanza/stanza.validate.ts +50 -0
- package/src/@modules/@utilities/utilities.createHttp.ts +85 -0
- package/src/@modules/@utilities/utilities.createWebhook.ts +100 -0
- package/src/@modules/@utilities/utilities.getFormattedTime.ts +43 -0
- package/src/@modules/@utilities/utilities.getSettings.ts +25 -0
- package/src/@modules/@utilities/utilities.getShapeNearestPoint.ts +114 -0
- package/src/@modules/@utilities/utilities.setCronSchedule.ts +65 -0
- package/src/@modules/@utilities/utilities.setEventEmit.ts +41 -0
- package/src/@modules/@utilities/utilities.setListener.ts +30 -0
- package/src/@modules/@utilities/utilities.setSettings.ts +42 -0
- package/src/@modules/@utilities/utilities.setSleep.ts +33 -0
- package/src/@modules/@utilities/utilities.setTimeoutAction.ts +59 -0
- package/src/@modules/@utilities/utilities.setWarning.ts +34 -0
- package/src/@modules/@xmpp/xmpp.xDeploy.ts +58 -0
- package/src/@modules/@xmpp/xmpp.xError.ts +29 -0
- package/src/@modules/@xmpp/xmpp.xOffline.ts +38 -0
- package/src/@modules/@xmpp/xmpp.xOnline.ts +45 -0
- package/src/@modules/@xmpp/xmpp.xReconnect.ts +64 -0
- package/src/@modules/@xmpp/xmpp.xStanza.ts +63 -0
- package/src/@parsers/@hvtec/hvtec.extract.ts +40 -0
- package/src/@parsers/@pvtec/pvtec.expires.ts +26 -0
- package/src/@parsers/@pvtec/pvtec.extract.ts +49 -0
- package/src/@parsers/@text/text.getDescriptionFromProduct.ts +53 -0
- package/src/@parsers/@text/text.getPolygonFromProduct.ts +32 -0
- package/src/@parsers/@text/text.getTextFromProduct.ts +43 -0
- package/src/@parsers/@text/text.getXML.ts +61 -0
- package/src/@parsers/@ugc/ugc.coordinates.ts +110 -0
- package/src/@parsers/@ugc/ugc.expiry.ts +32 -0
- package/src/@parsers/@ugc/ugc.extract.ts +37 -0
- package/src/@parsers/@ugc/ugc.header.ts +30 -0
- package/src/@parsers/@ugc/ugc.locations.ts +29 -0
- package/src/@parsers/@ugc/ugc.zones.ts +52 -0
- package/src/@types/type.event.ts +67 -0
- package/src/@types/type.properties.ts +75 -0
- package/src/@types/types.attributes.ts +28 -0
- package/src/@types/types.compiled.ts +35 -0
- package/src/@types/types.hash.ts +24 -0
- package/src/@types/types.hvtec.ts +25 -0
- package/src/@types/types.pvtec.ts +30 -0
- package/src/@types/types.settings.ts +76 -0
- package/src/@types/types.stanza.ts +37 -0
- package/src/@types/types.ugc.ts +24 -0
- package/src/@types/types.webhook.ts +26 -0
- package/src/bootstrap.ts +85 -163
- package/src/index.ts +47 -216
- package/test.js +78 -51
- package/tsup.config.ts +1 -0
- package/src/@dictionaries/events.ts +0 -168
- package/src/@parsers/@events/api.ts +0 -146
- package/src/@parsers/@events/cap.ts +0 -123
- package/src/@parsers/@events/text.ts +0 -104
- package/src/@parsers/@events/ugc.ts +0 -107
- package/src/@parsers/@events/vtec.ts +0 -76
- package/src/@parsers/events.ts +0 -392
- package/src/@parsers/hvtec.ts +0 -46
- package/src/@parsers/pvtec.ts +0 -72
- package/src/@parsers/stanza.ts +0 -97
- package/src/@parsers/text.ts +0 -165
- package/src/@parsers/ugc.ts +0 -247
- package/src/@submodules/database.ts +0 -201
- package/src/@submodules/eas.ts +0 -490
- package/src/@submodules/utils.ts +0 -191
- package/src/@submodules/xmpp.ts +0 -142
- package/src/types.ts +0 -259
|
@@ -0,0 +1,83 @@
|
|
|
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 { TypeAttributes } from "../@types/types.attributes";
|
|
21
|
+
import { TypeStanzaCompiled } from "../@types/types.compiled"
|
|
22
|
+
import { TypeEvent } from "../@types/type.event";
|
|
23
|
+
import { eventsOffshore } from "../@dictionaries/dictionaries.eventsOffshore";
|
|
24
|
+
import { ugcExtract } from "../@parsers/@ugc/ugc.extract";
|
|
25
|
+
import { properties } from "../@building/building.properties";
|
|
26
|
+
import { getEventHeader } from "../@building/building.headers";
|
|
27
|
+
import { getEventTracking } from "../@building/building.tracking";
|
|
28
|
+
import { validateEvents } from "../@building/building.validate";
|
|
29
|
+
|
|
30
|
+
export const ugc = async (stanza: TypeStanzaCompiled): Promise<void> => {
|
|
31
|
+
let processed: TypeEvent[] = [];
|
|
32
|
+
const getMessages = stanza?.message
|
|
33
|
+
?.split(/(?=\$\$)/g)
|
|
34
|
+
?.map(message => message.trim())
|
|
35
|
+
?.filter(message => message && message !== "$$");
|
|
36
|
+
if (!getMessages || getMessages?.length == 0 ) return;
|
|
37
|
+
for (const message of getMessages) {
|
|
38
|
+
const tick = performance.now();
|
|
39
|
+
const attributes = stanza?.attributes as TypeAttributes
|
|
40
|
+
const ugc = await ugcExtract(message)
|
|
41
|
+
if (ugc != null ) {
|
|
42
|
+
const props = properties({ message, attributes, ugc: ugc })
|
|
43
|
+
const issued = new Date(attributes.issue)
|
|
44
|
+
const expires = new Date(issued.getTime() + 12 * 60 * 60 * 1000)
|
|
45
|
+
const header = getEventHeader({properties: props, getType: stanza.getType })
|
|
46
|
+
let event = Object.keys(eventsOffshore).find(event => message.toLowerCase().includes(event.toLowerCase()));
|
|
47
|
+
if (!event) {
|
|
48
|
+
event = stanza.getType.type.split(`-`).map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(` `)
|
|
49
|
+
}
|
|
50
|
+
processed.push({
|
|
51
|
+
type: `Feature`,
|
|
52
|
+
geometry: {
|
|
53
|
+
type: `Point`,
|
|
54
|
+
coordinates: []
|
|
55
|
+
},
|
|
56
|
+
properties: {
|
|
57
|
+
event: event,
|
|
58
|
+
parent: event,
|
|
59
|
+
status: `Issued`,
|
|
60
|
+
issued: (!isNaN(issued.getTime())) ? issued.toISOString() : new Date().toISOString(),
|
|
61
|
+
expires: (!isNaN(expires.getTime())) ? expires.toISOString() : new Date(Date.now() + 60 * 60 * 1000).toISOString(),
|
|
62
|
+
...props,
|
|
63
|
+
metadata: {
|
|
64
|
+
ms: performance.now() - tick,
|
|
65
|
+
source: `events.ugc`,
|
|
66
|
+
tracking: getEventTracking({ type: `RAW`, stanza, attributes, properties: props }),
|
|
67
|
+
header: header,
|
|
68
|
+
vtec: null,
|
|
69
|
+
hvtec: null,
|
|
70
|
+
history: [
|
|
71
|
+
{
|
|
72
|
+
description: props.description,
|
|
73
|
+
issued: (!isNaN(issued.getTime())) ? issued.toISOString() : new Date().toISOString(),
|
|
74
|
+
status: `Issued`
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
validateEvents(processed)
|
|
83
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
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 { TypeAttributes } from "../@types/types.attributes";
|
|
21
|
+
import { TypeStanzaCompiled } from "../@types/types.compiled"
|
|
22
|
+
import { TypeEvent } from "../@types/type.event";
|
|
23
|
+
import { TypePVTEC } from "../@types/types.pvtec";
|
|
24
|
+
import { TypeHVTEC } from "../@types/types.hvtec";
|
|
25
|
+
import { pvExtract } from "../@parsers/@pvtec/pvtec.extract";
|
|
26
|
+
import { hvExtract } from "../@parsers/@hvtec/hvtec.extract";
|
|
27
|
+
import { ugcExtract } from "../@parsers/@ugc/ugc.extract";
|
|
28
|
+
import { properties } from "../@building/building.properties";
|
|
29
|
+
import { getEventHeader } from "../@building/building.headers";
|
|
30
|
+
import { getEventTracking } from "../@building/building.tracking";
|
|
31
|
+
import { validateEvents } from "../@building/building.validate";
|
|
32
|
+
|
|
33
|
+
export const vtec = async (stanza: TypeStanzaCompiled): Promise<void> => {
|
|
34
|
+
let processed: TypeEvent[] = [];
|
|
35
|
+
const getMessages = stanza?.message
|
|
36
|
+
?.split(/(?=\$\$)/g)
|
|
37
|
+
?.map(message => message.trim())
|
|
38
|
+
?.filter(message => message && message !== "$$");
|
|
39
|
+
if (!getMessages || getMessages?.length == 0 ) return;
|
|
40
|
+
for (const message of getMessages) {
|
|
41
|
+
const tick = performance.now();
|
|
42
|
+
const attributes = stanza?.attributes as TypeAttributes
|
|
43
|
+
const pVtec = pvExtract(message) as TypePVTEC[];
|
|
44
|
+
const hVtec = hvExtract(message) as TypeHVTEC[];
|
|
45
|
+
const ugc = await ugcExtract(message)
|
|
46
|
+
if (pVtec != null && ugc != null ) {
|
|
47
|
+
for (const pv of pVtec) {
|
|
48
|
+
const vtec = pv;
|
|
49
|
+
const props = properties({ message, attributes, ugc, pVtec: vtec })
|
|
50
|
+
const header = getEventHeader({properties: props, getType: stanza.getType, vtec: vtec})
|
|
51
|
+
const issued = new Date(attributes.issue)?? new Date()
|
|
52
|
+
const expires = new Date(vtec.expires)
|
|
53
|
+
processed.push({
|
|
54
|
+
type: `Feature`,
|
|
55
|
+
geometry: {
|
|
56
|
+
type: `Point`,
|
|
57
|
+
coordinates: []
|
|
58
|
+
},
|
|
59
|
+
properties: {
|
|
60
|
+
event: pv.event,
|
|
61
|
+
parent: pv.event,
|
|
62
|
+
status: pv.status,
|
|
63
|
+
issued: (!isNaN(issued.getTime())) ? issued.toISOString() : new Date().toISOString(),
|
|
64
|
+
expires: (!isNaN(expires.getTime())) ? expires.toISOString() : ugc.expires ?? new Date(issued.getTime() + 60 * 60 * 1000).toISOString(),
|
|
65
|
+
...props,
|
|
66
|
+
metadata: {
|
|
67
|
+
ms: performance.now() - tick,
|
|
68
|
+
source: `events.vtec`,
|
|
69
|
+
tracking: getEventTracking({ type: `VTEC`, stanza, attributes, properties: props, vtec }),
|
|
70
|
+
header: header,
|
|
71
|
+
vtec: pv,
|
|
72
|
+
hvtec: hVtec,
|
|
73
|
+
history: [
|
|
74
|
+
{
|
|
75
|
+
description: props.description,
|
|
76
|
+
issued: (!isNaN(issued.getTime())) ? issued.toISOString() : new Date().toISOString(),
|
|
77
|
+
status: pv.status
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
validateEvents(processed)
|
|
87
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
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 { setEventEmit } from "../@modules/@utilities/utilities.setEventEmit";
|
|
21
|
+
import { TypeEvent } from "../@types/type.event";
|
|
22
|
+
import { bootstrap } from "../bootstrap"
|
|
23
|
+
import { setHash } from "./manager.setHash";
|
|
24
|
+
import { updateWebhooks } from "./manager.updateWebhooks";
|
|
25
|
+
import { updateNode } from "./manager.updateNodes";
|
|
26
|
+
import { TypeSettings } from "../@types/types.settings";
|
|
27
|
+
|
|
28
|
+
export const mkEvent = async (event: TypeEvent): Promise<void> => {
|
|
29
|
+
const settings = bootstrap.settings as TypeSettings;
|
|
30
|
+
const features = bootstrap.cache.events.features;
|
|
31
|
+
const map = new Map<string, typeof features[0]>();
|
|
32
|
+
|
|
33
|
+
for (const f of features) {
|
|
34
|
+
const key = f?.properties?.metadata?.tracking;
|
|
35
|
+
if (!key) continue;
|
|
36
|
+
map.set(key, f);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const getHash = event.properties.metadata.hash;
|
|
40
|
+
const getTracking = event.properties.metadata.tracking;
|
|
41
|
+
const isEntry = bootstrap.cache.hashes?.find(hash => hash.tracking === getTracking)
|
|
42
|
+
const isHashed = isEntry?.hashes?.includes(getHash) ?? false;
|
|
43
|
+
const getFeature = map.get(getTracking);
|
|
44
|
+
|
|
45
|
+
if (isHashed || event.properties.status_metadata.is_expired) return
|
|
46
|
+
await setHash(event, isEntry)
|
|
47
|
+
const isFilteredLocation = await updateNode(event).then(() => event.properties.metadata.filtered_proximity);
|
|
48
|
+
if (!isFilteredLocation && settings.GlobalSettings.EventFiltering.NodeLocationFiltering) { return }
|
|
49
|
+
|
|
50
|
+
setEventEmit({
|
|
51
|
+
event: `onEventStatus`,
|
|
52
|
+
metadata: {
|
|
53
|
+
type: getFeature ? `Updated` : `New`,
|
|
54
|
+
event: event
|
|
55
|
+
},
|
|
56
|
+
message: `[${getFeature ? 'Updated' : 'New'}] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
|
|
57
|
+
})
|
|
58
|
+
if (settings.GlobalSettings.EventManagement) {
|
|
59
|
+
if (event.properties.status_metadata.is_issued || event.properties.status_metadata.is_updated) {
|
|
60
|
+
if (getFeature) {
|
|
61
|
+
const getIndex = features.indexOf(getFeature);
|
|
62
|
+
const cHistory = getFeature?.properties?.metadata?.history ?? [];
|
|
63
|
+
const cLocations = getFeature?.properties?.locations?.split(";").map((l: string) => l.trim()) ?? [];
|
|
64
|
+
const cUgc = getFeature?.properties?.geocode?.ugc ?? [];
|
|
65
|
+
|
|
66
|
+
const iHistory = event.properties?.metadata?.history ?? [];
|
|
67
|
+
const iLocations = event.properties?.locations?.split(";").map((l: string) => l.trim()) ?? [];
|
|
68
|
+
const iUgc = event.properties?.geocode?.ugc ?? [];
|
|
69
|
+
|
|
70
|
+
const mHistory = [...cHistory, ...iHistory].filter((v, i, a) => a.indexOf(v) === i);
|
|
71
|
+
const mLocations = [...cLocations, ...iLocations].filter((v, i, a) => a.indexOf(v) === i).join('; ');
|
|
72
|
+
const mUgc = [...cUgc, ...iUgc].filter((v, i, a) => a.indexOf(v) === i);
|
|
73
|
+
|
|
74
|
+
bootstrap.cache.events.features[getIndex] = {
|
|
75
|
+
...event,
|
|
76
|
+
properties: {
|
|
77
|
+
...event.properties,
|
|
78
|
+
metadata: {
|
|
79
|
+
...event?.properties?.metadata,
|
|
80
|
+
history: mHistory
|
|
81
|
+
},
|
|
82
|
+
locations: mLocations,
|
|
83
|
+
geocode: {
|
|
84
|
+
...event?.properties?.geocode,
|
|
85
|
+
ugc: mUgc
|
|
86
|
+
},
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
} else {
|
|
90
|
+
features.push(event)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
updateWebhooks(event)
|
|
95
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
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 { setEventEmit } from "../@modules/@utilities/utilities.setEventEmit";
|
|
21
|
+
import { TypeEvent } from "../@types/type.event";
|
|
22
|
+
import { bootstrap } from "../bootstrap"
|
|
23
|
+
import { updateWebhooks } from "./manager.updateWebhooks";
|
|
24
|
+
|
|
25
|
+
export const rmEvent = (event: TypeEvent): void => {
|
|
26
|
+
const getEvent = bootstrap.cache.events.features.find(f => f?.properties?.metadata?.tracking === event?.properties?.metadata?.tracking);
|
|
27
|
+
if (getEvent) {
|
|
28
|
+
setEventEmit({
|
|
29
|
+
event: `onEventStatus`,
|
|
30
|
+
metadata: {
|
|
31
|
+
type: `Removed`,
|
|
32
|
+
event: event
|
|
33
|
+
},
|
|
34
|
+
message: `[Removed] ${event.properties.event} (${event.properties.status}) (${event.properties.metadata.tracking})`
|
|
35
|
+
})
|
|
36
|
+
setEventEmit({ event: `onExpiredProduct`, metadata: event })
|
|
37
|
+
updateWebhooks(event)
|
|
38
|
+
bootstrap.cache.events.features.splice(bootstrap.cache.events.features.indexOf(getEvent), 1);
|
|
39
|
+
bootstrap.cache.hashes = bootstrap.cache.hashes.filter(hash => hash.tracking !== event.properties.metadata.tracking);
|
|
40
|
+
}
|
|
41
|
+
setEventEmit({
|
|
42
|
+
event: `onEventCache`,
|
|
43
|
+
metadata: bootstrap.cache.events,
|
|
44
|
+
limited: true
|
|
45
|
+
})
|
|
46
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ _ _ __ __
|
|
3
|
+
/\ | | | | (_) \ \ / /
|
|
4
|
+
/ \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
|
|
5
|
+
/ /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
|
|
6
|
+
/ ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
|
|
7
|
+
/_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
|
|
8
|
+
| |
|
|
9
|
+
|_|
|
|
10
|
+
|
|
11
|
+
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
|
+
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
|
+
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
+
Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Internal Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { TypeEvent } from "../@types/type.event";
|
|
21
|
+
import { TypeHash } from "../@types/types.hash"
|
|
22
|
+
import { bootstrap } from "../bootstrap"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
export const setHash = async (event: TypeEvent, entry: TypeHash): Promise<void> => {
|
|
26
|
+
if (entry) {
|
|
27
|
+
entry.hashes.push(event.properties.metadata.hash);
|
|
28
|
+
entry.expires = event.properties.expires;
|
|
29
|
+
} else {
|
|
30
|
+
bootstrap.cache.hashes.push({
|
|
31
|
+
tracking: event.properties.metadata.tracking,
|
|
32
|
+
hashes: [event.properties.metadata.hash],
|
|
33
|
+
expires: event.properties.expires
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
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 { getEventNodes } from "../@building/building.polygon";
|
|
21
|
+
import { setEventEmit } from "../@modules/@utilities/utilities.setEventEmit";
|
|
22
|
+
import { TypeEvent } from "../@types/type.event";
|
|
23
|
+
import { bootstrap } from "../bootstrap"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
export const updateNode = async (selectedEvent?: TypeEvent): Promise<void> => {
|
|
27
|
+
const events = bootstrap.cache.events.features;
|
|
28
|
+
const ttl = bootstrap.settings.GlobalSettings.NodeTTL * 1e3;
|
|
29
|
+
let total = 0;
|
|
30
|
+
|
|
31
|
+
async function update(evt: TypeEvent) {
|
|
32
|
+
const lastUpdate = evt?.properties?.metadata?.updated ?? null;
|
|
33
|
+
if (lastUpdate != null && (Date.now() - lastUpdate) < ttl) {
|
|
34
|
+
return evt;
|
|
35
|
+
}
|
|
36
|
+
const node = await getEventNodes(evt);
|
|
37
|
+
if (node.nodes.length > 0) {
|
|
38
|
+
total++
|
|
39
|
+
}
|
|
40
|
+
evt.properties.metadata.nodes = node.nodes
|
|
41
|
+
evt.properties.metadata.filtered_proximity = node.filtered
|
|
42
|
+
evt.properties.metadata.updated = node.updated
|
|
43
|
+
}
|
|
44
|
+
if (!selectedEvent) { await Promise.all(events.map(async (evt) => { await update(evt) })) }
|
|
45
|
+
if (selectedEvent) { await update(selectedEvent) }
|
|
46
|
+
if (total > 0) {
|
|
47
|
+
setEventEmit({
|
|
48
|
+
event: `onNodeUpdate`,
|
|
49
|
+
metadata: {
|
|
50
|
+
type: `global-update`,
|
|
51
|
+
updated: total
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
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 { createWebhook } from "../@modules/@utilities/utilities.createWebhook";
|
|
21
|
+
import { TypeEvent } from "../@types/type.event";
|
|
22
|
+
import { TypeWebhook } from "../@types/types.webhook";
|
|
23
|
+
import { bootstrap } from "../bootstrap"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
export const updateWebhooks = async (event: TypeEvent): Promise<void> => {
|
|
27
|
+
const settings = bootstrap.settings;
|
|
28
|
+
const webhooks = settings.WebhookSettings as TypeWebhook[];
|
|
29
|
+
const eventName = event.properties.event;
|
|
30
|
+
for (const socket of webhooks) {
|
|
31
|
+
const events = socket.events;
|
|
32
|
+
if (!events || events.length === 0) {
|
|
33
|
+
await createWebhook({ webhook: socket, event });
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const matched = events.some(pattern => {
|
|
37
|
+
if (!pattern) return false;
|
|
38
|
+
if (pattern === "*" || pattern === eventName) return true;
|
|
39
|
+
if (pattern.includes("*")) {
|
|
40
|
+
const regex = "^" +
|
|
41
|
+
pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$";
|
|
42
|
+
return new RegExp(regex).test(eventName);
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
});
|
|
46
|
+
if (matched) {
|
|
47
|
+
await createWebhook({ webhook: socket, event });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
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/types.settings"
|
|
21
|
+
import { bootstrap } from '../../bootstrap'
|
|
22
|
+
import { setWarning } from '../@utilities/utilities.setWarning';
|
|
23
|
+
import { createEvent } from '../../@building/building.create';
|
|
24
|
+
|
|
25
|
+
export const getCachedEvents = async (): Promise<void> => {
|
|
26
|
+
try {
|
|
27
|
+
const settings = bootstrap.settings as TypeSettings;
|
|
28
|
+
const tick = performance.now();
|
|
29
|
+
if (settings.NOAAWeatherWireServiceSettings.CacheSettings.Enabled) {
|
|
30
|
+
const max = settings.NOAAWeatherWireServiceSettings.CacheSettings.MaxRetentionHistory ?? 500;
|
|
31
|
+
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
|
+
let events = get.map((row) => JSON.parse(row.stanza))
|
|
34
|
+
.filter(stanza => {
|
|
35
|
+
if (!stanza) { return }
|
|
36
|
+
const isSkippable = stanza.isIgnored ||
|
|
37
|
+
(stanza.isCapEvent) ||
|
|
38
|
+
(stanza.isCapEvent && !stanza.isCapAreaDescription)
|
|
39
|
+
return !isSkippable
|
|
40
|
+
});
|
|
41
|
+
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` })
|
|
44
|
+
}
|
|
45
|
+
} catch (error) {
|
|
46
|
+
setWarning({ message: `An error occurred while fetching cached events: ${error.message} -> ${error.stack}` })
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
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 fs from 'fs'
|
|
21
|
+
import sqlite3 from 'better-sqlite3'
|
|
22
|
+
import { TypeSettings } from "../../@types/types.settings"
|
|
23
|
+
import { bootstrap } from "../../bootstrap"
|
|
24
|
+
import { setWarning } from '../@utilities/utilities.setWarning'
|
|
25
|
+
import { importShapefiles } from './database.shapefiles'
|
|
26
|
+
|
|
27
|
+
export const initializeDatabase = async (): Promise<void> => {
|
|
28
|
+
const settings = bootstrap.settings as TypeSettings;
|
|
29
|
+
try {
|
|
30
|
+
if (!fs.existsSync(settings.Database)) {
|
|
31
|
+
fs.writeFileSync(settings.Database, '')
|
|
32
|
+
setWarning({ message: `Creating new database at ${settings.Database}` })
|
|
33
|
+
}
|
|
34
|
+
bootstrap.database = new sqlite3(settings.Database);
|
|
35
|
+
bootstrap.database
|
|
36
|
+
.prepare(`CREATE TABLE IF NOT EXISTS stanzas ( id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT, issued TEXT, stanza TEXT )`)
|
|
37
|
+
.run();
|
|
38
|
+
bootstrap.database
|
|
39
|
+
.prepare(`CREATE TABLE IF NOT EXISTS shapefiles (id TEXT PRIMARY KEY, location TEXT, geometry TEXT)`)
|
|
40
|
+
.run();
|
|
41
|
+
await importShapefiles();
|
|
42
|
+
} catch (error) {
|
|
43
|
+
setWarning({ message: `An error occurred while initializing the database: ${error.message}` })
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
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 fs from 'fs'
|
|
21
|
+
import { resolve, extname} from 'path'
|
|
22
|
+
import { loadAsync } from 'jszip'
|
|
23
|
+
import { read } from 'shapefile'
|
|
24
|
+
import { TypeSettings } from "../../@types/types.settings"
|
|
25
|
+
import { bootstrap } from "../../bootstrap"
|
|
26
|
+
import { setSleep } from '../@utilities/utilities.setSleep'
|
|
27
|
+
import { setWarning } from '../@utilities/utilities.setWarning'
|
|
28
|
+
import { shapefileLinks } from '../../@dictionaries/dictionaries.shapefileLinks'
|
|
29
|
+
|
|
30
|
+
export const importShapefiles = async (): Promise<void> => {
|
|
31
|
+
const settings = bootstrap.settings as TypeSettings;
|
|
32
|
+
try {
|
|
33
|
+
const tShapefiles = bootstrap.database
|
|
34
|
+
.prepare(`SELECT COUNT(*) AS count FROM shapefiles`)
|
|
35
|
+
.get().count;
|
|
36
|
+
if (tShapefiles === 0) {
|
|
37
|
+
await setSleep({timeout: 1e3});
|
|
38
|
+
setWarning({ message: `Shapefiles are currently building, please DO NOT close your terminal. The shapefiles will not finish and will remain incomplete. If you do mess up, you will need to delete ${settings.Database} and restart the application.` })
|
|
39
|
+
for (const shapefile of shapefileLinks) {
|
|
40
|
+
const response = await fetch(shapefile.link);
|
|
41
|
+
const arrayBuff = await response.arrayBuffer();
|
|
42
|
+
const content = await loadAsync(arrayBuff);
|
|
43
|
+
const directory = resolve(__dirname, `../../shapefiles`);
|
|
44
|
+
if (!fs.existsSync(directory)) {
|
|
45
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
46
|
+
}
|
|
47
|
+
for (const file of Object.keys(content.files)) {
|
|
48
|
+
if (file.endsWith('.shp') || file.endsWith('.dbf')) {
|
|
49
|
+
const data = await content.files[file].async(`nodebuffer`)
|
|
50
|
+
const output = resolve(directory, `${shapefile?.name ?? ``}_${shapefile?.id ?? ``}${extname(file)}`)
|
|
51
|
+
fs.writeFileSync(output, data)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const filepath = resolve(__dirname, '../../shapefiles', shapefile.name + '_' + shapefile.id)
|
|
55
|
+
const { features } = await read(
|
|
56
|
+
filepath,
|
|
57
|
+
filepath,
|
|
58
|
+
);
|
|
59
|
+
setWarning({ message: `Importing ${features.length} features from ${shapefile.name}_${shapefile.id}` })
|
|
60
|
+
const insert = bootstrap.database
|
|
61
|
+
.prepare(`INSERT OR REPLACE INTO shapefiles (id, location, geometry) VALUES (?, ?, ?)`)
|
|
62
|
+
const transaction = bootstrap.database.transaction((entries: any[]) => {
|
|
63
|
+
for (const entry of entries) {
|
|
64
|
+
const { properties, geometry } = entry;
|
|
65
|
+
let final: string, location: string;
|
|
66
|
+
if (properties.FIPS) {
|
|
67
|
+
final = `${properties.STATE}${shapefile.id}${properties.FIPS.substring(2)}`;
|
|
68
|
+
location = `${properties.COUNTYNAME}, ${properties.STATE}`;
|
|
69
|
+
}
|
|
70
|
+
else if (properties.FULLSTAID) {
|
|
71
|
+
final = `${properties.ST}${shapefile.id}${properties.WFO}`;
|
|
72
|
+
location = `${properties.CITY}, ${properties.STATE}`;
|
|
73
|
+
}
|
|
74
|
+
else if (properties.STATE) {
|
|
75
|
+
final = `${properties.STATE}${shapefile.id}${properties.ZONE ?? properties.SITE_ID}`;
|
|
76
|
+
location = `${properties.NAME ?? `${properties.RFC_NAME} ${properties.RFC_CITY}`}, ${properties.STATE}`;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
final = properties.ID ?? properties.WFO
|
|
80
|
+
location = properties.NAME;
|
|
81
|
+
}
|
|
82
|
+
insert.run(final, location, JSON.stringify(geometry));
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
fs.unlinkSync(`${filepath}.shp`)
|
|
86
|
+
fs.unlinkSync(`${filepath}.dbf`)
|
|
87
|
+
setWarning({ message: `Cleaned up temporary files for ${shapefile.name}_${shapefile.id}` })
|
|
88
|
+
transaction(features)
|
|
89
|
+
}
|
|
90
|
+
setWarning({ message: `Shapefiles have finished compiling, you can now continue and close this terminal` })
|
|
91
|
+
fs.rm(resolve(__dirname, '../../shapefiles'), { recursive: true, force: true }, () => {});
|
|
92
|
+
}
|
|
93
|
+
} catch (error) {
|
|
94
|
+
setWarning( {message: `An error occurred while compiling shapefiles: ${error.message}` })
|
|
95
|
+
}
|
|
96
|
+
}
|