@atmosx/event-product-parser 3.0.62 → 3.0.75
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/.github/docs/docs-functions.md +1 -1
- package/.github/docs/docs-general-configurations.md +1 -11
- package/.github/docs/docs-integrations.md +3 -2
- package/README.md +10 -8
- package/dist/cjs/index.cjs +24482 -7207
- package/dist/esm/index.mjs +24275 -7003
- package/package.json +56 -47
- package/pnpm-workspace.yaml +4 -0
- package/src/bootstrap.ts +65 -48
- package/src/{@building → building}/CreateEvent.ts +22 -24
- package/src/{@building → building}/GetCleanedEvent.ts +2 -2
- package/src/{@building → building}/GetEventAttachments.ts +14 -12
- package/src/building/GetEventDirection.ts +28 -0
- package/src/{@building → building}/GetEventEnhancedName.ts +5 -8
- package/src/{@building → building}/GetEventGeometry.ts +19 -13
- package/src/{@building → building}/GetEventHeader.ts +13 -13
- package/src/{@building → building}/GetEventNodes.ts +22 -20
- package/src/{@building → building}/GetEventOffice.ts +13 -13
- package/src/building/GetEventPopulation.ts +58 -0
- package/src/building/GetEventProperties.ts +106 -0
- package/src/{@building → building}/GetEventSignature.ts +9 -9
- package/src/{@building → building}/GetEventTags.ts +3 -3
- package/src/building/GetEventTheme.ts +26 -0
- package/src/building/GetEventTracking.ts +64 -0
- package/src/components/audio/GenerateAudioMessage.ts +149 -0
- package/src/{@modules/@eas → components/audio/components}/GetCleanDescription.ts +2 -2
- package/src/{@modules/@eas → components/audio/components}/GetFloatPCM16.ts +2 -2
- package/src/{@modules/@eas → components/audio/components}/GetMergedPCM16.ts +2 -2
- package/src/{@modules/@eas → components/audio/components}/GetPCM16.ts +13 -8
- package/src/{@modules/@eas → components/audio/components}/GetPCMToFloat.ts +2 -2
- package/src/{@modules/@eas → components/audio/components}/GetSampledPCM16.ts +14 -8
- package/src/{@modules/@eas → components/audio/components}/GetTTS.ts +17 -10
- package/src/{@modules/@eas → components/audio/components}/GetWavPCM16.ts +7 -7
- package/src/{@modules/@eas → components/audio/components}/SetAFSK.ts +13 -8
- package/src/{@modules/@eas → components/audio/components}/SetAsciiToBits.ts +2 -2
- package/src/{@modules/@eas → components/audio/components}/SetAttentionTone.ts +11 -6
- package/src/{@modules/@eas → components/audio/components}/SetNoise.ts +12 -7
- package/src/{@modules/@eas → components/audio/components}/SetRadioEffect.ts +12 -7
- package/src/{@modules/@eas → components/audio/components}/SetSameHeader.ts +22 -14
- package/src/{@modules/@utilities/SetWarning.ts → components/database/CreateQuery.ts} +18 -13
- package/src/{@modules/@database → components/database}/GetCachedEvents.ts +18 -15
- package/src/components/database/ImportBoundaries.ts +168 -0
- package/src/{@modules/@database → components/database}/ImportBroadcastify.ts +14 -24
- package/src/components/database/ImportCities.ts +87 -0
- package/src/{@modules/@database → components/database}/ImportShapefiles.ts +23 -26
- package/src/{@modules/@database → components/database}/ImportStanza.ts +15 -19
- package/src/components/database/InitializeDatabase.ts +71 -0
- package/src/components/images/GenerateGraphic.ts +242 -0
- package/src/components/images/components/CreateRectangle.ts +22 -0
- package/src/components/images/components/CreateText.ts +22 -0
- package/src/components/images/modules/CreateSVG.ts +37 -0
- package/src/components/images/modules/GetGeographicalBoundaries.ts +72 -0
- package/src/components/images/modules/GetGeographicalCities.ts +58 -0
- package/src/components/images/modules/GetGeographicalEvents.ts +48 -0
- package/src/components/images/modules/GetGeometryBounds.ts +82 -0
- package/src/components/images/modules/GetParsedBoundary.ts +58 -0
- package/src/components/images/modules/GetSVGPath.ts +53 -0
- package/src/components/images/modules/NormalizePolygon.ts +57 -0
- package/src/{@modules/@stanza → components/stanza}/GetAwipsType.ts +16 -17
- package/src/{@modules/@stanza → components/stanza}/ValidateStanza.ts +27 -15
- package/src/{@modules/@utilities → components/utilities}/CreateHttp.ts +26 -26
- package/src/{@parsers/@text → components/utilities}/GetEmbededText.ts +8 -6
- package/src/{@modules/@utilities → components/utilities}/GetFormattedTime.ts +2 -2
- package/src/{@modules/@utilities → components/utilities}/GetLatestIssuance.ts +2 -2
- package/src/{@modules/@utilities → components/utilities}/GetMatched.ts +10 -5
- package/src/{@modules/@utilities → components/utilities}/GetShapeNearestPoint.ts +24 -19
- package/src/{@parsers/@text → components/utilities}/GetStringText.ts +9 -9
- package/src/components/utilities/GetUnionPolygon.ts +36 -0
- package/src/components/utilities/QueueManager.ts +70 -0
- package/src/components/utilities/SetCronSchedule.ts +106 -0
- package/src/{@modules/@utilities → components/utilities}/SetDebug.ts +12 -12
- package/src/components/utilities/SetEventEmit.ts +42 -0
- package/src/{@modules/@utilities → components/utilities}/SetSettings.ts +7 -7
- package/src/{@modules/@utilities → components/utilities}/SetSleep.ts +5 -5
- package/src/components/utilities/SetTimeoutAction.ts +64 -0
- package/src/components/utilities/SetWarning.ts +47 -0
- package/src/{@modules/@xmpp → components/xmpp}/DeployXMPP.ts +20 -20
- package/src/{@core/CreateListener.ts → components/xmpp/ErrorXMPP.ts} +8 -5
- package/src/{@modules/@xmpp → components/xmpp}/OfflineXMPP.ts +13 -13
- package/src/{@modules/@xmpp → components/xmpp}/OnlineXMPP.ts +18 -18
- package/src/components/xmpp/ReconnectXMPP.ts +64 -0
- package/src/{@modules/@xmpp → components/xmpp}/StanzaXMPP.ts +25 -25
- package/src/{@core → core}/ClearEvents.ts +9 -9
- package/src/{@core → core}/GetEvents.ts +4 -4
- package/src/{@core → core}/GetNodes.ts +4 -4
- package/src/{@core → core}/GetRandomEvent.ts +4 -4
- package/src/{@core → core}/GetVersion.ts +4 -4
- package/src/{@core → core}/ManualEvent.ts +23 -24
- package/src/{@core → core}/QueryStanza.ts +12 -11
- package/src/core/SetNode.ts +87 -0
- package/src/{@core → core}/StartService.ts +21 -20
- package/src/{@core → core}/StopService.ts +10 -10
- package/src/{@enums → enums}/AWIPS.ts +2 -2
- package/src/{@enums → enums}/Actions.ts +2 -2
- package/src/{@enums → enums}/Cancellation.ts +2 -2
- package/src/{@enums → enums}/Causes.ts +2 -2
- package/src/{@enums → enums}/Correlations.ts +2 -2
- package/src/{@enums → enums}/Enhanced.ts +4 -3
- package/src/{@enums → enums}/Events.ts +2 -2
- package/src/{@enums → enums}/Expressions.ts +3 -3
- package/src/{@enums → enums}/GlobalFilter.ts +2 -2
- package/src/{@enums → enums}/Hail.ts +2 -2
- package/src/{@enums → enums}/ICAO.ts +2 -2
- package/src/{@enums → enums}/Matches.ts +8 -3
- package/src/{@enums → enums}/Products.ts +2 -2
- package/src/{@enums → enums}/Records.ts +2 -2
- package/src/{@enums → enums}/Severity.ts +2 -2
- package/src/{@enums → enums}/Shapefiles.ts +2 -2
- package/src/{@enums → enums}/States.ts +68 -4
- package/src/{@enums → enums}/Status.ts +2 -2
- package/src/{@enums → enums}/Strings.ts +2 -2
- package/src/{@enums → enums}/Tags.ts +9 -4
- package/src/{@enums → enums}/Testing.ts +2 -2
- package/src/enums/Themes.ts +70 -0
- package/src/events/ParseAPI.ts +133 -0
- package/src/{@events → events}/ParseText.ts +24 -22
- package/src/{@events → events}/ParseUGC.ts +27 -26
- package/src/{@events → events}/ParseVTEC.ts +38 -37
- package/src/index.ts +57 -37
- package/src/{@manager → manager}/MakeEvents.ts +38 -47
- package/src/manager/RemoveEvent.ts +74 -0
- package/src/{@manager → manager}/SetHash.ts +18 -13
- package/src/{@manager → manager}/UpdateEvents.ts +12 -12
- package/src/{@manager → manager}/UpdateNode.ts +14 -14
- package/src/{@manager → manager}/ValidateEvents.ts +55 -45
- package/src/{@parsers/@hvtec → parsers/hvtec}/HVExtract.ts +11 -11
- package/src/{@parsers/@text → parsers/text}/GetDescriptionFromProduct.ts +20 -21
- package/src/parsers/text/GetPolygonFromProduct.ts +71 -0
- package/src/{@parsers/@text → parsers/text}/GetTextFromProduct.ts +12 -12
- package/src/parsers/ugc/GetCache.ts +24 -0
- package/src/{@parsers/@ugc → parsers/ugc}/GetExpiry.ts +2 -2
- package/src/{@parsers/@ugc/GetUGCHeader.ts → parsers/ugc/GetHeader.ts} +4 -4
- package/src/{@parsers/@ugc → parsers/ugc}/GetLocations.ts +10 -10
- package/src/parsers/ugc/GetZonePolygon.ts +73 -0
- package/src/{@parsers/@ugc → parsers/ugc}/GetZones.ts +3 -3
- package/src/{@parsers/@ugc → parsers/ugc}/SetCache.ts +13 -8
- package/src/{@parsers/@ugc → parsers/ugc}/UGCExtract.ts +14 -14
- package/src/{@parsers/@pvtec → parsers/vtec}/GetExpiry.ts +2 -2
- package/src/parsers/vtec/VTECExtract.ts +49 -0
- package/src/{@types → static}/Attributes.ts +2 -3
- package/src/{@types → static}/Event.ts +8 -7
- package/src/{@types → static}/Properties.ts +17 -3
- package/src/{@types → static}/Stanza.ts +2 -2
- package/src/tasks/CreateTasks.ts +116 -0
- package/src/tasks/TaskGenerateJSON.ts +34 -0
- package/src/tasks/TaskGenerateText.ts +34 -0
- package/src/tasks/TaskSendNTFY.ts +95 -0
- package/src/tasks/TaskSendWebhook.ts +107 -0
- package/src/{@types → types}/Actions.ts +3 -3
- package/src/{@types → types}/HVTEC.ts +6 -6
- package/src/{@types → types}/Hash.ts +5 -5
- package/src/types/Nodes.ts +29 -0
- package/src/{@types → types}/Settings.ts +17 -8
- package/src/{@types → types}/StanzaCompiled.ts +15 -15
- package/src/{@types → types}/UGC.ts +5 -5
- package/src/{@modules/@utilities/GetSettings.ts → types/VTEC.ts} +12 -7
- package/tools/build.js +47 -0
- package/tsconfig.json +28 -1
- package/src/@building/GetEventProperties.ts +0 -96
- package/src/@building/GetEventTracking.ts +0 -68
- package/src/@core/SetNode.ts +0 -81
- package/src/@events/ParseAPI.ts +0 -117
- package/src/@manager/RemoveEvent.ts +0 -70
- package/src/@manager/Tasks.ts +0 -246
- package/src/@modules/@database/InitializeDatabase.ts +0 -59
- package/src/@modules/@eas/GenerateEASMessage.ts +0 -144
- package/src/@modules/@utilities/SetCronSchedule.ts +0 -94
- package/src/@modules/@utilities/SetEventEmit.ts +0 -41
- package/src/@modules/@utilities/SetListener.ts +0 -30
- package/src/@modules/@utilities/SetTimeoutAction.ts +0 -64
- package/src/@modules/@xmpp/ErrorXMPP.ts +0 -27
- package/src/@modules/@xmpp/ReconnectXMPP.ts +0 -64
- package/src/@parsers/@pvtec/VTECExtract.ts +0 -49
- package/src/@parsers/@text/GetPolygonFromProduct.ts +0 -53
- package/src/@parsers/@text/GetXML.ts +0 -61
- package/src/@parsers/@ugc/GetCache.ts +0 -24
- package/src/@parsers/@ugc/GetZonePolygon.ts +0 -111
- package/src/@types/VTEC.ts +0 -30
- package/tsup.config.ts +0 -16
|
@@ -11,15 +11,15 @@
|
|
|
11
11
|
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
12
|
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
13
|
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
-
Documentation:
|
|
14
|
+
Documentation: https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Independent Package: @atmosx/event-product-parser
|
|
17
17
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { TypeEvent } from "
|
|
20
|
+
import { TypeEvent } from "StaticTypes/Event"
|
|
21
21
|
|
|
22
|
-
export const
|
|
22
|
+
export const GetEmbededText = (event: TypeEvent): string => {
|
|
23
23
|
const line = (label: string, value: unknown, condition = true) => condition && value ? `${label} ${value}` : null;
|
|
24
24
|
const isStatement = event.properties.status_metadata.is_statement;
|
|
25
25
|
const isExpired = event.properties.status_metadata.is_expired;
|
|
@@ -30,8 +30,9 @@ export const GetEmebedText = (event: TypeEvent): string => {
|
|
|
30
30
|
line(`**Damage Threat:**`, event?.properties?.parameters?.damage_threat, !isExpired),
|
|
31
31
|
line(`**Flood Threat:**`, event?.properties?.parameters?.flood_threat, !isExpired),
|
|
32
32
|
line(`**Tornado Threat:**`, event?.properties?.parameters?.tornado_threat, !isExpired),
|
|
33
|
-
line(`**
|
|
34
|
-
line(`**
|
|
33
|
+
line(`**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(`**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(`**Direction:**`, event?.properties?.parameters?.direction, !isExpired && event?.properties?.parameters?.direction != null),
|
|
35
36
|
line(`**Discussion:**`, event?.properties?.discussion_parameters?.discussion_number, !isExpired),
|
|
36
37
|
line(`**Concern:**`, event?.properties?.discussion_parameters?.discussion_concerning, !isExpired),
|
|
37
38
|
line(`**SPC Max Tornado Threat:**`, event?.properties?.discussion_parameters?.discussion_max_tornado, !isExpired),
|
|
@@ -50,6 +51,7 @@ export const GetEmebedText = (event: TypeEvent): string => {
|
|
|
50
51
|
line(`**Max Tops (x100 feet):**`, event?.properties?.watch_parameters?.max_tops_x100feet, !isExpired),
|
|
51
52
|
line(`**Tags:**`, event?.properties?.parameters?.tags?.length > 0 ? event?.properties?.parameters?.tags.join(', ') : null, !isExpired),
|
|
52
53
|
line(`**Sender:**`, event?.properties?.geocode?.office?.name ? `${event?.properties?.geocode?.office?.name} (${event?.properties?.geocode?.office?.office})` : event?.properties?.geocode?.office?.office),
|
|
54
|
+
line(`**Population:**`, event?.properties?.geocode?.census?.population, !isExpired),
|
|
53
55
|
line(`**Tracking:**`, event?.properties?.metadata?.tracking),
|
|
54
56
|
line(`**Logs:**`, event?.properties?.metadata?.history?.length > 0 ? event?.properties?.metadata?.history.length : null),
|
|
55
57
|
].filter(Boolean).join('\n');
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
12
|
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
13
|
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
-
Documentation:
|
|
14
|
+
Documentation: https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Independent Package: @atmosx/event-product-parser
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
*/
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
12
|
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
13
|
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
-
Documentation:
|
|
14
|
+
Documentation: https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Independent Package: @atmosx/event-product-parser
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
*/
|
|
@@ -11,17 +11,22 @@
|
|
|
11
11
|
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
12
|
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
13
|
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
-
Documentation:
|
|
14
|
+
Documentation: https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Independent Package: @atmosx/event-product-parser
|
|
17
17
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
interface GetMatchedOptions {
|
|
21
|
+
Strings: string[]
|
|
22
|
+
String: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const GetMatched = ({ Strings, String }: GetMatchedOptions): boolean => {
|
|
26
|
+
const isMatched = Strings.some(pattern => {
|
|
22
27
|
if (!pattern) return false;
|
|
23
28
|
const lowerP = pattern.toLowerCase();
|
|
24
|
-
const lowerS =
|
|
29
|
+
const lowerS = String.toLowerCase()
|
|
25
30
|
if (lowerP === "*" || lowerP === lowerS) return true;
|
|
26
31
|
if (lowerP.includes("*")) {
|
|
27
32
|
const regex = "^" + lowerP.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$";
|
|
@@ -11,23 +11,28 @@
|
|
|
11
11
|
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
12
|
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
13
|
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
-
Documentation:
|
|
14
|
+
Documentation: https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Independent Package: @atmosx/event-product-parser
|
|
17
17
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
+
interface GetShapeNearestPointOptions {
|
|
21
|
+
Coordinates: number[][]
|
|
22
|
+
Point: [number, number]
|
|
23
|
+
}
|
|
24
|
+
|
|
20
25
|
interface GetShapeNearestPointResponse {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
Proximity: boolean
|
|
27
|
+
Point: [number, number]
|
|
28
|
+
Distance: number | null
|
|
29
|
+
DistanceKm?: number | null
|
|
30
|
+
DistanceMeters?: number | null
|
|
26
31
|
}
|
|
27
32
|
|
|
28
|
-
export const GetShapeNearestPoint = (
|
|
29
|
-
if (!
|
|
30
|
-
return {
|
|
33
|
+
export const GetShapeNearestPoint = ({ Coordinates, Point }: GetShapeNearestPointOptions): GetShapeNearestPointResponse => {
|
|
34
|
+
if (!Coordinates || !Point) {
|
|
35
|
+
return { Proximity: false, Point: [0, 0], Distance: null }
|
|
31
36
|
}
|
|
32
37
|
const normalize = (coords: any): any[] => {
|
|
33
38
|
if (!Array.isArray(coords)) return [];
|
|
@@ -43,10 +48,10 @@ export const GetShapeNearestPoint = (coordinates: number[][], point: [number, nu
|
|
|
43
48
|
}
|
|
44
49
|
return [];
|
|
45
50
|
}
|
|
46
|
-
const polys = normalize(
|
|
47
|
-
if (polys.length === 0) return {
|
|
48
|
-
const lon =
|
|
49
|
-
const lat =
|
|
51
|
+
const polys = normalize(Coordinates);
|
|
52
|
+
if (polys.length === 0) return { Proximity: false, Point: [0, 0], Distance: null };
|
|
53
|
+
const lon = Point[0];
|
|
54
|
+
const lat = Point[1];
|
|
50
55
|
const pointInRing = (pt: [number, number], ring: number[][]): boolean => {
|
|
51
56
|
let x = pt[0], y = pt[1];
|
|
52
57
|
let inside = false;
|
|
@@ -76,13 +81,13 @@ export const GetShapeNearestPoint = (coordinates: number[][], point: [number, nu
|
|
|
76
81
|
for (const poly of polys) {
|
|
77
82
|
const outer = poly[0];
|
|
78
83
|
const holes = poly.slice(1);
|
|
79
|
-
if (pointInRing(
|
|
84
|
+
if (pointInRing(Point, outer)) {
|
|
80
85
|
let inHole = false;
|
|
81
86
|
for (const hole of holes) {
|
|
82
|
-
if (pointInRing(
|
|
87
|
+
if (pointInRing(Point, hole)) { inHole = true; break; }
|
|
83
88
|
}
|
|
84
89
|
if (!inHole) {
|
|
85
|
-
return {
|
|
90
|
+
return { Proximity: true, Point, Distance: 0 };
|
|
86
91
|
}
|
|
87
92
|
}
|
|
88
93
|
for (const ring of poly) {
|
|
@@ -105,10 +110,10 @@ export const GetShapeNearestPoint = (coordinates: number[][], point: [number, nu
|
|
|
105
110
|
}
|
|
106
111
|
}
|
|
107
112
|
if (!isFinite(minDistance) || closestPoint == null) {
|
|
108
|
-
return {
|
|
113
|
+
return { Proximity: false, Point: [0,0], Distance: null };
|
|
109
114
|
}
|
|
110
115
|
const distanceMiles = minDistance;
|
|
111
116
|
const distanceKm = Number((distanceMiles * 1.609344).toFixed(3));
|
|
112
117
|
const distanceMeters = Math.round(distanceKm * 1000);
|
|
113
|
-
return {
|
|
118
|
+
return { Proximity: distanceMiles === 0, Point: closestPoint, Distance: distanceMiles, DistanceKm: distanceKm, DistanceMeters: distanceMeters };
|
|
114
119
|
}
|
|
@@ -11,19 +11,17 @@
|
|
|
11
11
|
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
12
|
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
13
|
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
-
Documentation:
|
|
14
|
+
Documentation: https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Independent Package: @atmosx/event-product-parser
|
|
17
17
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { TypeEvent } from "
|
|
21
|
-
import {
|
|
22
|
-
import { bootstrap } from "../../bootstrap";
|
|
20
|
+
import { TypeEvent } from "StaticTypes/Event"
|
|
21
|
+
import { Bootstrap } from "@Bootstrap"
|
|
23
22
|
|
|
24
23
|
export const GetStringText = (event: TypeEvent): string => {
|
|
25
|
-
const
|
|
26
|
-
const timezone = settings.NotifyServer.Timezone ?? `UTC`;
|
|
24
|
+
const timezone = Bootstrap.Settings.Timezone ?? `UTC`;
|
|
27
25
|
const line = (label: string, value: unknown, condition = true) => condition && value ? `${label} ${value}` : null;
|
|
28
26
|
const isStatement = event.properties.status_metadata.is_statement;
|
|
29
27
|
const isExpired = event.properties.status_metadata.is_expired;
|
|
@@ -34,8 +32,9 @@ export const GetStringText = (event: TypeEvent): string => {
|
|
|
34
32
|
line(`Damage Threat:`, event?.properties?.parameters?.damage_threat, !isExpired),
|
|
35
33
|
line(`Flood Threat:`, event?.properties?.parameters?.flood_threat, !isExpired),
|
|
36
34
|
line(`Tornado Threat:`, event?.properties?.parameters?.tornado_threat, !isExpired),
|
|
37
|
-
line(`
|
|
38
|
-
line(`
|
|
35
|
+
line(`Wind Gusts:`, `${event?.properties?.parameters?.estimated_wind_gusts} ${event?.properties?.parameters?.wind_threat ? ` (${event?.properties?.parameters?.wind_threat})` : ''}`, !isExpired && event?.properties?.parameters?.estimated_wind_gusts != null),
|
|
36
|
+
line(`Hail Size:`, `${event?.properties?.parameters?.estimated_hail_size} ${event?.properties?.parameters?.hail_threat ? ` (${event?.properties?.parameters?.hail_threat})` : ''}`, !isExpired && event?.properties?.parameters?.estimated_hail_size != null),
|
|
37
|
+
line(`Direction:`, event?.properties?.parameters?.direction, !isExpired && event?.properties?.parameters?.direction != null),
|
|
39
38
|
line(`Discussion:`, event?.properties?.discussion_parameters?.discussion_number, !isExpired),
|
|
40
39
|
line(`Concern:`, event?.properties?.discussion_parameters?.discussion_concerning, !isExpired),
|
|
41
40
|
line(`SPC Max Tornado Threat:`, event?.properties?.discussion_parameters?.discussion_max_tornado, !isExpired),
|
|
@@ -53,6 +52,7 @@ export const GetStringText = (event: TypeEvent): string => {
|
|
|
53
52
|
line(`Max Surface Wind:`, event?.properties?.watch_parameters?.max_wind_surface, !isExpired),
|
|
54
53
|
line(`Max Tops (x100 feet):`, event?.properties?.watch_parameters?.max_tops_x100feet, !isExpired),
|
|
55
54
|
line(`Sender:`, event?.properties?.geocode?.office?.name ? `${event?.properties?.geocode?.office?.name} (${event?.properties?.geocode?.office?.office})` : event?.properties?.geocode?.office?.office),
|
|
55
|
+
line(`Population:`, event?.properties?.geocode?.census?.population, !isExpired),
|
|
56
56
|
line(`Tracking:`, event?.properties?.metadata?.tracking),
|
|
57
57
|
].filter(Boolean).join('\n');
|
|
58
58
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
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: https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Independent Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { union } from "polygon-clipping";
|
|
21
|
+
|
|
22
|
+
interface GetUnionPolygonOptions {
|
|
23
|
+
Polygons: number[][][][] | null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const GetUnionPolygon = ({ Polygons }: GetUnionPolygonOptions): GeoJSON.MultiPolygon | null => {
|
|
27
|
+
if (!Polygons || Polygons.length === 0) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const unionFn = union as unknown as (...polygons: number[][][][]) => number[][][][];
|
|
31
|
+
const unioned = unionFn(...Polygons)
|
|
32
|
+
return {
|
|
33
|
+
type: `MultiPolygon`,
|
|
34
|
+
coordinates: unioned
|
|
35
|
+
}
|
|
36
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
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: https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Independent Package: @atmosx/event-product-parser
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export type QueueTask = () => Promise<void>;
|
|
20
|
+
|
|
21
|
+
export interface QueueManagerOptions {
|
|
22
|
+
Concurrency?: number;
|
|
23
|
+
Error?: (error: unknown) => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class QueueManager {
|
|
27
|
+
private readonly queue: QueueTask[] = [];
|
|
28
|
+
private readonly concurrency: number;
|
|
29
|
+
private readonly onError: (error: unknown) => void;
|
|
30
|
+
|
|
31
|
+
private running = 0;
|
|
32
|
+
private draining = false;
|
|
33
|
+
|
|
34
|
+
public constructor({ Concurrency, Error }: QueueManagerOptions = {}) {
|
|
35
|
+
this.concurrency = Concurrency ?? 1;
|
|
36
|
+
this.onError = Error ?? ((error) => {
|
|
37
|
+
console.error("[QueueManager] Task failed:", error);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public enqueue(task: QueueTask): void {
|
|
42
|
+
this.queue.push(task);
|
|
43
|
+
this.drain();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private drain(): void {
|
|
47
|
+
if (this.draining) { return; }
|
|
48
|
+
this.draining = true;
|
|
49
|
+
while (this.running < this.concurrency && this.queue.length > 0) {
|
|
50
|
+
const task = this.queue.shift();
|
|
51
|
+
if (!task) { continue; }
|
|
52
|
+
this.running++;
|
|
53
|
+
void this.execute(task);
|
|
54
|
+
}
|
|
55
|
+
this.draining = false;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private async execute(task: QueueTask): Promise<void> {
|
|
59
|
+
try {
|
|
60
|
+
await task();
|
|
61
|
+
} catch (error) {
|
|
62
|
+
try {
|
|
63
|
+
this.onError(error);
|
|
64
|
+
} catch (handlerError) {}
|
|
65
|
+
} finally {
|
|
66
|
+
this.running--;
|
|
67
|
+
this.drain();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
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: https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Independent Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { TypeSettings } from "Types/Settings"
|
|
22
|
+
import { ReconnectXMPP } from "@XMPP/ReconnectXMPP"
|
|
23
|
+
import { Bootstrap } from "@Bootstrap"
|
|
24
|
+
import { CreateHttp } from "@Utilities/CreateHttp"
|
|
25
|
+
import { SetEventEmit } from "@Utilities/SetEventEmit"
|
|
26
|
+
import { CreateEvent } from "@Building/CreateEvent"
|
|
27
|
+
import { readdirSync, unlinkSync, statSync, rmdirSync, existsSync } from "fs"
|
|
28
|
+
import { join } from "path"
|
|
29
|
+
|
|
30
|
+
export const SetCronSchedule = async (): Promise<void> => {
|
|
31
|
+
const settings = Bootstrap.Settings as TypeSettings;
|
|
32
|
+
|
|
33
|
+
const TTL = settings.GlobalSettings.ArchiveSettings.TTL
|
|
34
|
+
const TTLCUT = Date.now() - TTL * 1000;
|
|
35
|
+
|
|
36
|
+
const walk = (dir: string, deleteFolder = false): void => {
|
|
37
|
+
if (!existsSync(dir)) return;
|
|
38
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
39
|
+
for (const entry of entries) {
|
|
40
|
+
const fullPath = join(dir, entry.name);
|
|
41
|
+
if (entry.isDirectory()) {
|
|
42
|
+
walk(fullPath, deleteFolder);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const stats = statSync(fullPath);
|
|
46
|
+
if (stats.mtime.getTime() < TTLCUT) {
|
|
47
|
+
try {
|
|
48
|
+
unlinkSync(fullPath);
|
|
49
|
+
} catch (err) {
|
|
50
|
+
console.error(`Failed to delete ${fullPath}:`, err);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (deleteFolder) {
|
|
55
|
+
try {
|
|
56
|
+
if (readdirSync(dir).length === 0 && statSync(dir).mtime.getTime() < TTLCUT) {
|
|
57
|
+
rmdirSync(dir);
|
|
58
|
+
}
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.error(`Failed to delete directory ${dir}:`, err);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
walk(settings.GlobalSettings.ArchiveSettings.TextDirectory, true)
|
|
65
|
+
walk(settings.GlobalSettings.ArchiveSettings.AudioDirectory, true)
|
|
66
|
+
walk(settings.GlobalSettings.ArchiveSettings.JSONDirectory, true)
|
|
67
|
+
walk(settings.GlobalSettings.ArchiveSettings.ImageDirectory, true)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
if (settings.EnableWireService) {
|
|
72
|
+
if (settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.Enabled) {
|
|
73
|
+
void ReconnectXMPP(settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval)
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
const response = await CreateHttp({
|
|
77
|
+
URL: settings.NationalWeatherServiceSettings.EventsEndpoint,
|
|
78
|
+
Headers: {
|
|
79
|
+
"User-Agent": "@atmosx/event-product-parser"
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
if (response.error) {
|
|
83
|
+
return SetEventEmit({
|
|
84
|
+
Event: `onServiceStatus`,
|
|
85
|
+
Metadata: {
|
|
86
|
+
type: "fetch-api",
|
|
87
|
+
message: `Failed to fetch latest events from National Weather Service API - ${response.message}`,
|
|
88
|
+
data: {},
|
|
89
|
+
error: true
|
|
90
|
+
},
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
SetEventEmit({
|
|
94
|
+
Event: `onServiceStatus`,
|
|
95
|
+
Metadata: {
|
|
96
|
+
Message: `Fetched latest events from National Weather Service API`,
|
|
97
|
+
Data: {},
|
|
98
|
+
Type: "fetch-api",
|
|
99
|
+
Error: false
|
|
100
|
+
},
|
|
101
|
+
})
|
|
102
|
+
await CreateEvent({ Message: response.message, NWWS: false })
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
@@ -11,27 +11,27 @@
|
|
|
11
11
|
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
12
|
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
13
|
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
-
Documentation:
|
|
14
|
+
Documentation: https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Independent Package: @atmosx/event-product-parser
|
|
17
17
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { TypeSettings } from "
|
|
21
|
-
import {
|
|
20
|
+
import { TypeSettings } from "Types/Settings"
|
|
21
|
+
import { Bootstrap } from "@Bootstrap"
|
|
22
22
|
|
|
23
23
|
interface SetDebugOptions {
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
Title?: string
|
|
25
|
+
Message: string
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export const SetDebug = (
|
|
29
|
-
const settings =
|
|
30
|
-
|
|
31
|
-
message:
|
|
32
|
-
function:
|
|
28
|
+
export const SetDebug = ({ Title, Message }: SetDebugOptions): void => {
|
|
29
|
+
const settings = Bootstrap.Settings as TypeSettings;
|
|
30
|
+
Bootstrap.Listener.emit(`debug`, {
|
|
31
|
+
message: Message,
|
|
32
|
+
function: Title ?? `debug`,
|
|
33
33
|
})
|
|
34
34
|
if (settings.EnableDebugging) {
|
|
35
|
-
console.log(`[${
|
|
35
|
+
console.log(`[${Bootstrap.Colors.Blue}${Title ?? `debug`}${Bootstrap.Colors.Reset}] ${Message}`)
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
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: https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Independent Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { Bootstrap } from "@Bootstrap"
|
|
21
|
+
import { SetTimeoutAction } from "@Utilities/SetTimeoutAction"
|
|
22
|
+
import { SetWarning } from "@Utilities/SetWarning"
|
|
23
|
+
|
|
24
|
+
interface SetEventEmitOptions {
|
|
25
|
+
Event: string
|
|
26
|
+
Metadata: any
|
|
27
|
+
Message?: string
|
|
28
|
+
Limited?: boolean
|
|
29
|
+
Tree?: string[]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const SetEventEmit = ({ Event, Metadata, Message, Limited, Tree }: SetEventEmitOptions): void => {
|
|
33
|
+
if (Limited) {
|
|
34
|
+
const isTimeout = SetTimeoutAction({ Identifier: `event.${Event}`, AddTime: true, Max: 1, Interval: 1 })
|
|
35
|
+
if (isTimeout.Limited) return;
|
|
36
|
+
}
|
|
37
|
+
Bootstrap.Listener.emit(Event, Metadata)
|
|
38
|
+
if (Event != `log`) { Bootstrap.Listener.emit(`*`, {event: Event, data: Metadata}) }
|
|
39
|
+
if (Message) {
|
|
40
|
+
SetWarning({ Message: Message, Tree: Tree })
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -11,17 +11,17 @@
|
|
|
11
11
|
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
12
|
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
13
|
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
-
Documentation:
|
|
14
|
+
Documentation: https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Independent Package: @atmosx/event-product-parser
|
|
17
17
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { TypeSettings } from
|
|
21
|
-
import {
|
|
20
|
+
import { TypeSettings } from "Types/Settings"
|
|
21
|
+
import { Bootstrap } from "@Bootstrap"
|
|
22
22
|
|
|
23
|
-
export const SetSettings = (
|
|
24
|
-
const settings =
|
|
23
|
+
export const SetSettings = (imported: TypeSettings): TypeSettings => {
|
|
24
|
+
const settings = Bootstrap.Settings as Record<string, unknown>;
|
|
25
25
|
const merge = (target: Record<string, unknown>, source: Record<string, unknown>) => {
|
|
26
26
|
for (const key in source) {
|
|
27
27
|
if (!Object.prototype.hasOwnProperty.call(source, key)) continue;
|
|
@@ -37,6 +37,6 @@ export const SetSettings = (newSettings: TypeSettings): TypeSettings => {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
|
-
merge(settings,
|
|
40
|
+
merge(settings, imported as Record<string, unknown>);
|
|
41
41
|
return settings as TypeSettings;
|
|
42
42
|
}
|
|
@@ -11,22 +11,22 @@
|
|
|
11
11
|
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
12
|
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
13
|
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
-
Documentation:
|
|
14
|
+
Documentation: https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Independent Package: @atmosx/event-product-parser
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
interface SetSleepOptions {
|
|
22
|
-
|
|
22
|
+
Timeout: number
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export const SetSleep = async (
|
|
25
|
+
export const SetSleep = async ({ Timeout }: SetSleepOptions): Promise<void> => {
|
|
26
26
|
return new Promise((resolve) => {
|
|
27
27
|
setTimeout(() => {
|
|
28
28
|
resolve();
|
|
29
|
-
},
|
|
29
|
+
}, Timeout);
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -0,0 +1,64 @@
|
|
|
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: https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Independent Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { Bootstrap } from "@Bootstrap"
|
|
21
|
+
|
|
22
|
+
interface SetTimeoutActionOptions {
|
|
23
|
+
Identifier: string
|
|
24
|
+
AddTime?: boolean
|
|
25
|
+
Max?: number
|
|
26
|
+
Interval?: number
|
|
27
|
+
Expire?: boolean
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
type SetTimeoutActionResponse = {
|
|
31
|
+
Limited: boolean
|
|
32
|
+
Remaining?: number
|
|
33
|
+
Response?: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const SetTimeoutAction = ({ Identifier, AddTime, Max, Interval, Expire }: SetTimeoutActionOptions): SetTimeoutActionResponse => {
|
|
37
|
+
let target = Bootstrap?.Ratelimits?.[Identifier];
|
|
38
|
+
if (!target) {
|
|
39
|
+
Bootstrap.Ratelimits[Identifier] = [];
|
|
40
|
+
target = Bootstrap.Ratelimits[Identifier];
|
|
41
|
+
}
|
|
42
|
+
if (Expire) {
|
|
43
|
+
delete Bootstrap.Ratelimits[Identifier];
|
|
44
|
+
return { Limited: false };
|
|
45
|
+
}
|
|
46
|
+
if (target?.length > 0) {
|
|
47
|
+
Bootstrap.Ratelimits[Identifier] = target.filter((ts: number) => Date.now() - ts < Interval * 1000);
|
|
48
|
+
target = Bootstrap.Ratelimits[Identifier];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const oldestTimestamp = target?.[0];
|
|
52
|
+
const getWait = oldestTimestamp ? Math.ceil((Interval * 1000) - (Date.now() - oldestTimestamp)) : 0;
|
|
53
|
+
const max = Max ?? 1;
|
|
54
|
+
|
|
55
|
+
if (target?.length >= max && getWait > 0) {
|
|
56
|
+
return {
|
|
57
|
+
Limited: true,
|
|
58
|
+
Remaining: getWait,
|
|
59
|
+
Response: `You are being rate limited, please wait ${(getWait / 1e3).toFixed(1)} second(s) before performing this action again.`
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
Bootstrap.Ratelimits[Identifier].push(Date.now());
|
|
63
|
+
return { Limited: false };
|
|
64
|
+
}
|