@atmosx/event-product-parser 3.0.622 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/.github/CHANGELOGS.md +52 -0
  2. package/.github/CODE_OF_CONDUCT.md +24 -1
  3. package/.github/CONTRIBUTING.md +22 -3
  4. package/.github/FUNDING.yaml +3 -0
  5. package/.github/LICENSE +24 -1
  6. package/.github/SECURITY.md +25 -6
  7. package/.github/docs/chapters/general-configurations.md +109 -0
  8. package/.github/docs/chapters/sources-and-attributes.md +219 -0
  9. package/README.md +56 -148
  10. package/dist/{cjs/index.cjs → index.cjs} +4486 -1471
  11. package/package.json +13 -8
  12. package/pnpm-workspace.yaml +1 -0
  13. package/src/bootstrap.ts +66 -51
  14. package/src/components/audio/GenerateAudioMessage.ts +149 -0
  15. package/src/{@modules/@eas → components/audio/components}/GetCleanDescription.ts +2 -2
  16. package/src/{@modules/@eas → components/audio/components}/GetFloatPCM16.ts +2 -2
  17. package/src/{@modules/@eas → components/audio/components}/GetMergedPCM16.ts +2 -2
  18. package/src/{@modules/@eas → components/audio/components}/GetPCM16.ts +13 -8
  19. package/src/{@modules/@eas → components/audio/components}/GetPCMToFloat.ts +2 -2
  20. package/src/{@modules/@eas → components/audio/components}/GetSampledPCM16.ts +14 -8
  21. package/src/{@modules/@eas → components/audio/components}/GetTTS.ts +15 -8
  22. package/src/{@modules/@eas → components/audio/components}/GetWavPCM16.ts +7 -7
  23. package/src/{@modules/@eas → components/audio/components}/SetAFSK.ts +13 -8
  24. package/src/{@modules/@eas → components/audio/components}/SetAsciiToBits.ts +2 -2
  25. package/src/{@modules/@eas → components/audio/components}/SetAttentionTone.ts +11 -6
  26. package/src/{@modules/@eas → components/audio/components}/SetNoise.ts +12 -7
  27. package/src/{@modules/@eas → components/audio/components}/SetRadioEffect.ts +12 -7
  28. package/src/{@modules/@eas → components/audio/components}/SetSameHeader.ts +22 -14
  29. package/src/components/database/CreateQuery.ts +39 -0
  30. package/src/components/database/InitializeDatabase.ts +71 -0
  31. package/src/components/database/imports/Boundaires.ts +168 -0
  32. package/src/{@modules/@database/ImportBroadcastify.ts → components/database/imports/Broadcastify.ts} +15 -25
  33. package/src/components/database/imports/Census.ts +87 -0
  34. package/src/{@modules/@database/ImportShapefiles.ts → components/database/imports/Shapefiles.ts} +18 -21
  35. package/src/{@modules/@database/ImportStanza.ts → components/database/imports/Stanza.ts} +15 -19
  36. package/src/components/events/CreateEvents.ts +88 -0
  37. package/src/components/events/FilterEvents.ts +149 -0
  38. package/src/{@building/CreateEvent.ts → components/events/ProcessStanza.ts} +22 -22
  39. package/src/components/events/RemoveEvents.ts +74 -0
  40. package/src/{@building → components/events/components}/GetCleanedEvent.ts +2 -2
  41. package/src/{@building → components/events/components}/GetEventAttachments.ts +14 -12
  42. package/src/components/events/components/GetEventDirection.ts +28 -0
  43. package/src/{@building → components/events/components}/GetEventEnhancedName.ts +5 -6
  44. package/src/{@building → components/events/components}/GetEventGeometry.ts +19 -13
  45. package/src/{@building → components/events/components}/GetEventHeader.ts +13 -13
  46. package/src/components/events/components/GetEventMerged.ts +51 -0
  47. package/src/{@building → components/events/components}/GetEventNodes.ts +20 -18
  48. package/src/{@building → components/events/components}/GetEventOffice.ts +13 -13
  49. package/src/components/events/components/GetEventPopulation.ts +58 -0
  50. package/src/components/events/components/GetEventProperties.ts +106 -0
  51. package/src/{@building → components/events/components}/GetEventSignature.ts +9 -9
  52. package/src/{@building → components/events/components}/GetEventTags.ts +3 -3
  53. package/src/{@core/CreateListener.ts → components/events/components/GetEventTheme.ts} +8 -6
  54. package/src/components/events/components/GetEventTracking.ts +64 -0
  55. package/src/{@modules/@database → components/events/utilities}/GetCachedEvents.ts +18 -14
  56. package/src/{@manager → components/events/utilities}/SetHash.ts +18 -13
  57. package/src/{@manager → components/events/utilities}/UpdateEvents.ts +12 -12
  58. package/src/{@manager → components/events/utilities}/UpdateNode.ts +14 -14
  59. package/src/{@parsers/@text → components/formatting}/GetEmbededText.ts +12 -6
  60. package/src/{@parsers/@text → components/formatting}/GetStringText.ts +13 -9
  61. package/src/{@modules/@utilities → components/geometry}/GetShapeNearestPoint.ts +24 -19
  62. package/src/components/geometry/GetUnionPolygon.ts +36 -0
  63. package/src/components/images/GenerateGraphic.ts +242 -0
  64. package/src/components/images/components/CreateRectangle.ts +22 -0
  65. package/src/components/images/components/CreateText.ts +22 -0
  66. package/src/components/images/modules/CreateSVG.ts +37 -0
  67. package/src/components/images/modules/GetGeographicalBoundaries.ts +72 -0
  68. package/src/components/images/modules/GetGeographicalCities.ts +58 -0
  69. package/src/components/images/modules/GetGeographicalEvents.ts +48 -0
  70. package/src/components/images/modules/GetGeometryBounds.ts +82 -0
  71. package/src/components/images/modules/GetParsedBoundary.ts +58 -0
  72. package/src/components/images/modules/GetSVGPath.ts +53 -0
  73. package/src/components/images/modules/NormalizePolygon.ts +57 -0
  74. package/src/{@modules/@stanza → components/stanza}/GetAwipsType.ts +16 -17
  75. package/src/{@modules/@stanza → components/stanza}/ValidateStanza.ts +27 -15
  76. package/src/{@modules/@utilities → components/utilities}/CreateHttp.ts +26 -26
  77. package/src/components/utilities/EmitThread.ts +97 -0
  78. package/src/{@modules/@utilities → components/utilities}/GetLatestIssuance.ts +2 -2
  79. package/src/{@modules/@utilities → components/utilities}/GetMatched.ts +10 -5
  80. package/src/{@modules/@utilities → components/utilities}/QueueManager.ts +7 -8
  81. package/src/{@modules/@utilities → components/utilities}/SetDebug.ts +13 -13
  82. package/src/components/utilities/SetEventEmit.ts +42 -0
  83. package/src/{@modules/@utilities → components/utilities}/SetSettings.ts +7 -7
  84. package/src/{@modules/@utilities → components/utilities}/SetSleep.ts +5 -5
  85. package/src/components/utilities/SetTimeoutAction.ts +64 -0
  86. package/src/components/utilities/SetWarning.ts +47 -0
  87. package/src/{@modules/@xmpp → components/xmpp}/DeployXMPP.ts +20 -20
  88. package/src/{@modules/@xmpp → components/xmpp}/ErrorXMPP.ts +6 -6
  89. package/src/{@modules/@xmpp → components/xmpp}/OfflineXMPP.ts +13 -13
  90. package/src/{@modules/@xmpp → components/xmpp}/OnlineXMPP.ts +18 -18
  91. package/src/components/xmpp/ReconnectXMPP.ts +64 -0
  92. package/src/{@modules/@xmpp → components/xmpp}/StanzaXMPP.ts +26 -26
  93. package/src/{@enums → enums}/AWIPS.ts +2 -2
  94. package/src/{@enums → enums}/Actions.ts +2 -2
  95. package/src/{@enums → enums}/Cancellation.ts +2 -2
  96. package/src/{@enums → enums}/Causes.ts +2 -2
  97. package/src/{@enums → enums}/Correlations.ts +2 -2
  98. package/src/{@enums → enums}/Enhanced.ts +4 -3
  99. package/src/{@enums → enums}/Events.ts +2 -2
  100. package/src/{@enums → enums}/Expressions.ts +3 -3
  101. package/src/{@enums → enums}/GlobalFilter.ts +2 -2
  102. package/src/{@enums → enums}/Hail.ts +2 -2
  103. package/src/{@enums → enums}/ICAO.ts +2 -2
  104. package/src/{@enums → enums}/Matches.ts +8 -3
  105. package/src/{@enums → enums}/Products.ts +2 -2
  106. package/src/{@enums → enums}/Records.ts +2 -2
  107. package/src/{@enums → enums}/Severity.ts +2 -2
  108. package/src/{@enums → enums}/Shapefiles.ts +2 -2
  109. package/src/{@enums → enums}/States.ts +68 -4
  110. package/src/{@enums → enums}/Status.ts +2 -2
  111. package/src/{@enums → enums}/Strings.ts +2 -2
  112. package/src/{@enums → enums}/Tags.ts +8 -3
  113. package/src/{@enums → enums}/Testing.ts +2 -2
  114. package/src/enums/Themes.ts +70 -0
  115. package/src/events/ParseAPI.ts +133 -0
  116. package/src/{@events → events}/ParseText.ts +24 -22
  117. package/src/{@events → events}/ParseUGC.ts +27 -26
  118. package/src/{@events → events}/ParseVTEC.ts +37 -36
  119. package/src/{@core → exports}/ClearEvents.ts +9 -9
  120. package/src/{@core → exports}/GetEvents.ts +4 -4
  121. package/src/exports/GetNearestCity.ts +45 -0
  122. package/src/{@core → exports}/GetNodes.ts +4 -4
  123. package/src/{@core → exports}/GetRandomEvent.ts +4 -4
  124. package/src/{@core → exports}/GetVersion.ts +4 -4
  125. package/src/{@core → exports}/ManualEvent.ts +24 -24
  126. package/src/{@core → exports}/QueryStanza.ts +12 -11
  127. package/src/exports/SetNode.ts +100 -0
  128. package/src/{@core → exports}/StartService.ts +22 -21
  129. package/src/{@core → exports}/StopService.ts +10 -10
  130. package/src/index.ts +55 -37
  131. package/src/{@parsers/@hvtec → parsers/hvtec}/HVExtract.ts +7 -7
  132. package/src/{@parsers/@text → parsers/text}/GetDescriptionFromProduct.ts +20 -21
  133. package/src/parsers/text/GetPolygonFromProduct.ts +71 -0
  134. package/src/{@parsers/@text → parsers/text}/GetTextFromProduct.ts +12 -12
  135. package/src/parsers/ugc/GetCache.ts +24 -0
  136. package/src/{@parsers/@ugc → parsers/ugc}/GetExpiry.ts +2 -2
  137. package/src/{@parsers/@ugc/GetUGCHeader.ts → parsers/ugc/GetHeader.ts} +4 -4
  138. package/src/{@parsers/@ugc → parsers/ugc}/GetLocations.ts +10 -10
  139. package/src/parsers/ugc/GetZonePolygon.ts +73 -0
  140. package/src/{@parsers/@ugc → parsers/ugc}/GetZones.ts +3 -3
  141. package/src/{@parsers/@ugc → parsers/ugc}/SetCache.ts +13 -8
  142. package/src/{@parsers/@ugc → parsers/ugc}/UGCExtract.ts +14 -14
  143. package/src/{@parsers/@pvtec → parsers/vtec}/GetExpiry.ts +2 -2
  144. package/src/{@parsers/@pvtec → parsers/vtec}/VTECExtract.ts +17 -17
  145. package/src/tasks/CreateTasks.ts +116 -0
  146. package/src/{@tasks → tasks}/TaskGenerateJSON.ts +10 -11
  147. package/src/{@tasks → tasks}/TaskGenerateText.ts +11 -12
  148. package/src/tasks/TaskSendNTFY.ts +96 -0
  149. package/src/tasks/TaskSendWebhook.ts +107 -0
  150. package/src/{@types → types/event}/Attributes.ts +2 -3
  151. package/src/{@types → types/event}/Event.ts +8 -7
  152. package/src/{@types → types/event}/HVTEC.ts +2 -2
  153. package/src/{@types → types/event}/Properties.ts +17 -4
  154. package/src/{@types → types/event}/Stanza.ts +2 -2
  155. package/src/{@types → types/event}/VTEC.ts +8 -8
  156. package/src/{@types → types/standard}/Actions.ts +3 -3
  157. package/src/{@types → types/standard}/Hash.ts +5 -5
  158. package/src/{@modules/@utilities/GetSettings.ts → types/standard/Nodes.ts} +15 -7
  159. package/src/{@types → types/standard}/Settings.ts +19 -12
  160. package/src/{@types → types/standard}/StanzaCompiled.ts +15 -15
  161. package/src/{@types → types/standard}/UGC.ts +5 -5
  162. package/tools/build.js +2 -15
  163. package/tsconfig.json +29 -17
  164. package/.github/SUPPORTED_EVENTS.md +0 -370
  165. package/.github/docs/docs-functions.md +0 -30
  166. package/.github/docs/docs-general-configurations.md +0 -209
  167. package/.github/docs/docs-integrations.md +0 -37
  168. package/.github/docs/docs-listeners.md +0 -28
  169. package/.github/docs/docs-source-configuration.md +0 -218
  170. package/.github/docs/docs-technical.md +0 -50
  171. package/.github/logo.png +0 -0
  172. package/.github/samples/SAMPLE_EAS_GENERATION.wav +0 -0
  173. package/.github/samples/SAMPLE_GEOJSON.json +0 -204
  174. package/.github/samples/SAMPLE_TEXT_PRODUCT.txt +0 -119
  175. package/dist/esm/index.mjs +0 -22298
  176. package/src/@building/GetEventProperties.ts +0 -101
  177. package/src/@building/GetEventTracking.ts +0 -68
  178. package/src/@core/SetNode.ts +0 -87
  179. package/src/@events/ParseAPI.ts +0 -122
  180. package/src/@manager/MakeEvents.ts +0 -109
  181. package/src/@manager/RemoveEvent.ts +0 -70
  182. package/src/@manager/ValidateEvents.ts +0 -141
  183. package/src/@modules/@database/InitializeDatabase.ts +0 -59
  184. package/src/@modules/@eas/GenerateEASMessage.ts +0 -152
  185. package/src/@modules/@utilities/GetFormattedTime.ts +0 -43
  186. package/src/@modules/@utilities/SetCronSchedule.ts +0 -94
  187. package/src/@modules/@utilities/SetEventEmit.ts +0 -41
  188. package/src/@modules/@utilities/SetListener.ts +0 -30
  189. package/src/@modules/@utilities/SetTimeoutAction.ts +0 -64
  190. package/src/@modules/@utilities/SetWarning.ts +0 -34
  191. package/src/@modules/@xmpp/ReconnectXMPP.ts +0 -64
  192. package/src/@parsers/@text/GetPolygonFromProduct.ts +0 -53
  193. package/src/@parsers/@text/GetXML.ts +0 -61
  194. package/src/@parsers/@ugc/GetCache.ts +0 -24
  195. package/src/@parsers/@ugc/GetZonePolygon.ts +0 -111
  196. package/src/@tasks/CreateTasks.ts +0 -110
  197. package/src/@tasks/TaskGenerateAudio.ts +0 -35
  198. package/src/@tasks/TaskSendNTFY.ts +0 -93
  199. package/src/@tasks/TaskSendWebhook.ts +0 -101
@@ -1,141 +0,0 @@
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
- import { GetEventEnhancedName } from "@building/GetEventEnhancedName"
24
- import { GetEventSignature } from "@building/GetEventSignature"
25
- import { MakeEvents } from "@manager/MakeEvents"
26
- import { RemoveEvent } from "@manager/RemoveEvent"
27
- import { GetEventAttachments } from "@building/GetEventAttachments"
28
- import { SetEventEmit } from "@utilities/SetEventEmit"
29
- import { SetDebug } from "@utilities/SetDebug"
30
- import { GetMatched } from "@utilities/GetMatched"
31
- import { GetEventGeometry } from "@building/GetEventGeometry"
32
- import { createHash } from "crypto"
33
-
34
- export const ValidateEvents = async (events: TypeEvent[]): Promise<void> => {
35
- const tick = performance.now();
36
- if (events.length === 0) return
37
- const configurations = bootstrap.settings as TypeSettings
38
- const sets = {} as Record<string, Set<string>>;
39
- const bools = {} as Record<string, boolean>;
40
- const megered = {...configurations.GlobalSettings, ...configurations.GlobalSettings.EventFiltering}
41
- for (const key in megered) {
42
- const setting = megered[key];
43
- if (Array.isArray(setting)) { sets[key] = new Set(setting.map(item => item.toLowerCase())); }
44
- if (typeof setting === 'boolean') { bools[key] = setting; }
45
- }
46
-
47
- const isFiltered = (define: TypeEvent): boolean => {
48
- const properties = define.properties;
49
- const zones = properties.geocode.ugc;
50
- const icao = properties.geocode.office.office
51
-
52
- if (properties.status_metadata.is_test) {
53
- SetEventEmit({ event: `onTestProduct`, metadata: define })
54
- if (bools?.IgnoreTestProducts) return true;
55
- }
56
-
57
- if (properties.status_metadata.is_expired) {
58
- SetEventEmit({ event: `onExpiredProduct`, metadata: define })
59
- RemoveEvent(define, false)
60
- return true;
61
- }
62
-
63
- if (properties.metadata?.vtec?.is_watch && properties.metadata.source != `events.api`) {
64
- const isSPC = properties.metadata?.vtec?.prediction_center;
65
- SetEventEmit({ event: isSPC ? `onStormPredictionWatch` : `onNonStormPredictionWatch`, metadata: define })
66
- if (bools?.SPCWatchesOnly && !isSPC) {
67
- return true;
68
- }
69
- if ((!bools?.SPCWatchesOnly) && isSPC) {
70
- return true
71
- }
72
- }
73
-
74
- for (const key in sets) {
75
- const setting = sets[key]
76
- const values = [...setting];
77
- if (key === 'ListeningEvents' && setting.size > 0 && !GetMatched(values, define.properties.event)) {
78
- SetEventEmit({
79
- event: `onFilteredEvent`,
80
- metadata: define
81
- });
82
- return true
83
- }
84
- if (key === 'IgnoredEvents' && setting.size > 0 && GetMatched(values, define.properties.event)) {
85
- SetEventEmit({
86
- event: `onIgnoredEvent`,
87
- metadata: define
88
- });
89
- return true
90
- }
91
- if (key === 'ListeningICAO' && setting.size > 0 && icao != null && !setting.has(icao.toLowerCase())) {
92
- SetEventEmit({
93
- event: `onFilteredICAO`,
94
- metadata: define
95
- });
96
- return true
97
- }
98
- if (key === 'IgnoredICAO' && setting.size > 0 && icao != null && setting.has(icao.toLowerCase())) {
99
- SetEventEmit({
100
- event: `onIgnoredICAO`,
101
- metadata: define
102
- });
103
- return true
104
- }
105
- if (key === 'ListeningUGC' && setting.size > 0 && zones.length > 0 && !zones.some((ugc: string) => setting.has(ugc.toLowerCase()))) {
106
- SetEventEmit({
107
- event: `onFilteredUGC`,
108
- metadata: define
109
- });
110
- return true
111
- }
112
- if (key === 'ListeningStates' && setting.size > 0 && zones.length > 0 && !zones.some((ugc: string) => setting.has(ugc.substring(0, 2).toLowerCase()))) {
113
- SetEventEmit({
114
- event: `onFilteredState`,
115
- metadata: define
116
- });
117
- return true
118
- }
119
- }
120
- return false
121
- }
122
-
123
- const filtering = events.filter((event: TypeEvent) => {
124
- bootstrap.cache.processed = bootstrap.cache.processed.filter((e) => e !== event);
125
- const define = GetEventSignature(event) as TypeEvent;
126
- const pre = {...define,properties: {...define.properties, metadata: {...define.properties.metadata }}};
127
- const properties = define.properties; delete pre.properties.metadata.ms; delete pre.properties.metadata.header;
128
- const enhanced = properties.event = GetEventEnhancedName(event)
129
- const filtered = isFiltered(define)
130
- if (!filtered) {
131
- event.geometry = !bools?.DisableGeometryParsing ? GetEventGeometry(event) : null;
132
- properties.metadata.attachments = GetEventAttachments(event)
133
- }
134
- properties.metadata.hash = createHash("sha256").update(JSON.stringify(pre)).digest("hex")
135
- SetEventEmit({ event: `onProductType${enhanced.replace(/\s+/g, '')}`, metadata: define });
136
- return !filtered
137
- })
138
-
139
- SetDebug({ title: `ValidateEvents (${filtering.length}/${events.length})`, message: `${Math.round(performance.now() - tick)}ms` })
140
- await MakeEvents(filtering)
141
- }
@@ -1,59 +0,0 @@
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
-
21
- import { TypeSettings } from "types/Settings"
22
- import { bootstrap } from "@bootstrap"
23
- import { SetWarning } from "@utilities/SetWarning"
24
- import { ImportShapefiles } from "@database/ImportShapefiles"
25
- import { ImportBroadcastify } from "@database/ImportBroadcastify"
26
- import { existsSync, writeFileSync } from "fs"
27
- import sqlite3 from "better-sqlite3"
28
-
29
- export const InitializeDatabase = async (): Promise<void> => {
30
- const settings = bootstrap.settings as TypeSettings;
31
- try {
32
- if (!existsSync(settings.Database)) {
33
- writeFileSync(settings.Database, '')
34
- SetWarning({ message: `Creating new database at ${settings.Database}` })
35
- }
36
- bootstrap.database = new sqlite3(settings.Database);
37
- bootstrap.database
38
- .prepare(`CREATE TABLE IF NOT EXISTS stanzas ( id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT, issued TEXT, stanza TEXT )`)
39
- .run();
40
- bootstrap.database
41
- .prepare(`CREATE TABLE IF NOT EXISTS shapefiles (id TEXT PRIMARY KEY, location TEXT, geometry TEXT)`)
42
- .run();
43
- const isNeedingShapefiles = bootstrap.database
44
- .prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='shapefiles';`)
45
- .get();
46
- const isNeedingBroadcastify = bootstrap.database
47
- .prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='broadcastify';`)
48
- .get();
49
-
50
- if (!isNeedingShapefiles || !isNeedingBroadcastify) {
51
- SetWarning({message: `Required database tables are currently building, please ${bootstrap.ansi_colors.RED}DO NOT${bootstrap.ansi_colors.RESET} close your terminal. The building will not finish and will remain incomplete. If you do mess up, you will need to delete ${settings.Database} and restart the application.` })
52
- await ImportBroadcastify();
53
- await ImportShapefiles();
54
- SetWarning({ message: `Building has completed, you can now continue or close the terminal`})
55
- }
56
- } catch (error) {
57
- SetWarning({ message: `An error occurred while initializing the database: ${error.message}` })
58
- }
59
- }
@@ -1,152 +0,0 @@
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/Settings"
21
- import { bootstrap } from "@bootstrap"
22
- import { GetWavPCM16 } from "@eas/GetWavPCM16"
23
- import { GetSampledPCM16 } from "@eas/GetSampledPCM16"
24
- import { SetRadioEffect } from "@eas/SetRadioEffect"
25
- import { SetSameHeader } from "@eas/SetSameHeader"
26
- import { SetAttentionTone } from "@eas/SetAttentionTone"
27
- import { GetMergedPCM16 } from "@eas/GetMergedPCM16"
28
- import { SetNoise } from "@eas/SetNoise"
29
- import { GetPCM16 } from "@eas/GetPCM16"
30
- import { GetTTS } from "@eas/GetTTS"
31
- import { GetCleanDescription } from "@eas/GetCleanDescription"
32
- import { SetWarning } from "@utilities/SetWarning"
33
- import { SetDebug } from "@utilities/SetDebug"
34
- import { join } from "path"
35
- import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs"
36
- import { execSync } from "child_process"
37
- import { platform } from "os"
38
-
39
-
40
- interface GenerateEASMessageOptions {
41
- message: string
42
- header: string
43
- title: string
44
- }
45
-
46
- export const GenerateEASMessage = async (options: GenerateEASMessageOptions): Promise<string> => {
47
- const tick = performance.now()
48
- const settings = bootstrap.settings as TypeSettings;
49
- const directory = settings.GlobalSettings.ArchiveSettings.EasDirectory;
50
- const prefix = settings.GlobalSettings.ArchiveSettings.EasToneout;
51
- let message = options.message;
52
- let header = options.header;
53
- let title = (options.title ?? `${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, '')}`).replace(/[\\:*?"<>|]/g, "_").replace(/\s+/g, " ").trim();
54
- if (!message || !header) {
55
- SetWarning({
56
- title: `EAS`,
57
- message: `Message and header are required to generate an EAS tone.`
58
- })
59
- return null;
60
- }
61
- let buffTTS: Buffer;
62
- let buffRadio: any;
63
- let buffFull: any[] = [];
64
-
65
- if (!directory) {
66
- SetWarning({
67
- title: `EAS`,
68
- message: `EAS directory is not set in the settings. Please set it to generate EAS tones.`
69
- });
70
- return null;
71
- }
72
-
73
- if (!existsSync(directory)) {
74
- mkdirSync(directory, { recursive: true });
75
- }
76
- const tmpTTS = join(directory, `/${title}-tts.wav`)
77
- const outTTS = join(directory, `/${title}.wav`)
78
- const vPlatform = platform();
79
-
80
- if (vPlatform === 'darwin') {
81
- SetWarning({
82
- title: `EAS`,
83
- message: `EAS tone generation is not supported on macOS.`
84
- });
85
- return null
86
- }
87
-
88
-
89
- await new Promise<void>((resolve, reject) => {
90
- const tMsg = GetCleanDescription(message)
91
- GetTTS(tMsg, tmpTTS).then(() => {
92
- resolve();
93
- });
94
- });
95
- if (!existsSync(tmpTTS)) {
96
- return null;
97
- }
98
- buffTTS = readFileSync(tmpTTS);
99
- const vWav = GetWavPCM16(buffTTS);
100
- const vSamples = GetSampledPCM16(vWav.samples, vWav.sampleRate, 8000)
101
- const vRadio = SetRadioEffect(vSamples, 8000)
102
-
103
- if (existsSync(prefix)) {
104
- let tBuffer = readFileSync(prefix);
105
- let tWav = GetWavPCM16(tBuffer);
106
-
107
- if (tWav == null) {
108
- try {
109
- const converted = join(directory, `/${title}-tts-fixed.wav`)
110
- execSync(`ffmpeg -y -i "${prefix}" -ar 8000 -ac 1 -sample_fmt s16 "${converted}"`, { stdio: 'ignore' })
111
- if (existsSync(converted)) {
112
- tBuffer = readFileSync(converted)
113
- tWav = GetWavPCM16(tBuffer)
114
- try { unlinkSync(converted) } catch {}
115
- }
116
- } catch (e) {}
117
- }
118
-
119
- if (tWav == null) {
120
- SetWarning({ title: `EAS`, message: `Intro tone isn't a valid .WAV file or isn't in PCM 16-bit format. Converted attempt failed; please convert it then try again.` })
121
- return null;
122
- }
123
-
124
- const tSamples = (tWav.sampleRate != 8000 ? GetSampledPCM16(tWav.samples, tWav.sampleRate, 8000) : tWav.samples)
125
- buffRadio = SetRadioEffect(tSamples, 8000)
126
- }
127
-
128
- buffFull = buffRadio != null ? [buffRadio, new Int16Array(Math.floor(0.5 * 8000))] : [];
129
- buffFull.push(
130
- SetSameHeader(header, 3, 8000, {
131
- preMarkSec: 1.1,
132
- gapSec: 0.5,
133
- }),
134
- new Int16Array(Math.floor(0.5 * 8000)),
135
- SetAttentionTone(8, 8000),
136
- new Int16Array(Math.floor(0.5 * 8000)),
137
- vRadio
138
- )
139
- for (let i = 0; i < 3; i++) {
140
- buffFull.push(SetSameHeader(header, 1, 8000, { preMarkSec: 0.5, gapSec: 0.1 }))
141
- buffFull.push(new Int16Array(Math.floor(0.5 * 8000)));
142
- }
143
- const aSamples = GetMergedPCM16(buffFull);
144
- const aFinal = SetNoise(aSamples, 0.002);
145
- const aBuffer = GetPCM16(Array.from(aFinal).map(v => ({ value: v })), 8000);
146
- writeFileSync(outTTS, aBuffer)
147
- try{ unlinkSync(tmpTTS) } catch {}
148
- SetDebug({ title: `GenerateEASMessage`, message: `${Math.round(performance.now() - tick)}ms` })
149
- return outTTS;
150
- }
151
-
152
-
@@ -1,43 +0,0 @@
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
-
21
- export const GetFormattedTime = (date: string): string => {
22
- const now = Date.now();
23
- const then = typeof date === "number" ? date : new Date(date).getTime()
24
- const seconds = Math.floor((now - then) / 1000);
25
- const absSeconds = Math.abs(seconds);
26
- const isPast = seconds > 0;
27
- const units: [string, number][] = [
28
- ["year", 31536000], ["month", 2592000],
29
- ["day", 86400], ["hour", 3600],
30
- ["minute", 60], ["second", 1],
31
- ];
32
- for (const [name, value] of units) {
33
- const interval = Math.floor(absSeconds / value);
34
- if (interval >= 1) {
35
- return isPast
36
- ? `${interval} ${name}${interval > 1 ? "s" : ""} ago`
37
- : `in ${interval} ${name}${interval > 1 ? "s" : ""}`;
38
- }
39
- }
40
- return "just now";
41
- }
42
-
43
-
@@ -1,94 +0,0 @@
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
-
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, 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): void => {
37
- if (existsSync(dir)) {
38
- const entries = readdirSync(dir, { withFileTypes: true });
39
- for (const entry of entries) {
40
- const fullPath = join(dir, entry.name);
41
- if (entry.isDirectory()) { walk(fullPath); continue; }
42
- const stats = statSync(fullPath);
43
- if (stats.mtime.getTime() < TTLCUT) {
44
- try {
45
- unlinkSync(fullPath);
46
- } catch (err) {
47
- console.error(`Failed to delete ${fullPath}:`, err);
48
- }
49
- }
50
- }
51
- }
52
- };
53
- walk(settings.GlobalSettings.ArchiveSettings.TextDirectory)
54
- walk(settings.GlobalSettings.ArchiveSettings.EasDirectory)
55
- walk(settings.GlobalSettings.ArchiveSettings.JSONDirectory)
56
-
57
-
58
-
59
- if (settings.EnableWireService) {
60
- if (settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.Enabled) {
61
- void ReconnectXMPP(settings.NOAAWeatherWireServiceSettings.ReconnectionSettings.ReconnectionInterval)
62
- }
63
- } else {
64
- const response = await CreateHttp({
65
- url: settings.NationalWeatherServiceSettings.EventsEndpoint,
66
- headers: {
67
- "User-Agent": "@atmosx/event-product-parser"
68
- }
69
- })
70
- if (response.error) {
71
- return SetEventEmit({
72
- event: `onServiceStatus`,
73
- metadata: {
74
- type: "fetch-api",
75
- message: `Failed to fetch latest events from National Weather Service API - ${response.message}`,
76
- data: {},
77
- error: true
78
- },
79
- })
80
- }
81
- SetEventEmit({
82
- event: `onServiceStatus`,
83
- metadata: {
84
- message: `Fetched latest events from National Weather Service API`,
85
- data: {},
86
- type: "fetch-api",
87
- error: false
88
- },
89
- })
90
- await CreateEvent({ message: response.message, isNWWS: false })
91
- }
92
- }
93
-
94
-
@@ -1,41 +0,0 @@
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
- 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
- }
30
-
31
- export const SetEventEmit = (options: SetEventEmitOptions): void => {
32
- if (options.limited) {
33
- const isTimeout = SetTimeoutAction({ identifier: `event.${options.event}`, addTime: true, max: 1, interval: 1 })
34
- if (isTimeout.limited) return;
35
- }
36
- bootstrap.listener.emit(options.event, options.metadata)
37
- if (options.event != `log`) { bootstrap.listener.emit(`*`, {event: options.event, data: options.metadata}) }
38
- if (options.message) {
39
- SetWarning({ message: options.message })
40
- }
41
- }
@@ -1,30 +0,0 @@
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
- interface SetListenerOptions {
23
- event: string,
24
- callback: () => void
25
- }
26
-
27
- export const SetListener = (options: SetListenerOptions): (() => void) => {
28
- bootstrap.listener.on(options.event, options.callback)
29
- return () => { void bootstrap.listener.off(options.event, options.callback) };
30
- }
@@ -1,64 +0,0 @@
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
- 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 = (options: SetTimeoutActionOptions): SetTimeoutActionResponse => {
37
- let target = bootstrap?.ratelimits?.[options?.identifier];
38
- if (!target) {
39
- bootstrap.ratelimits[options?.identifier] = [];
40
- target = bootstrap.ratelimits[options?.identifier];
41
- }
42
- if (options?.expire) {
43
- delete bootstrap.ratelimits[options?.identifier];
44
- return { limited: false };
45
- }
46
- if (target?.length > 0) {
47
- bootstrap.ratelimits[options?.identifier] = target.filter((ts: number) => Date.now() - ts < options?.interval * 1000);
48
- target = bootstrap.ratelimits[options?.identifier];
49
- }
50
-
51
- const oldestTimestamp = target?.[0];
52
- const getWait = oldestTimestamp ? Math.ceil((options?.interval * 1000) - (Date.now() - oldestTimestamp)) : 0;
53
- const max = options?.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[options?.identifier].push(Date.now());
63
- return { limited: false };
64
- }
@@ -1,34 +0,0 @@
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
- import { TypeSettings } from "types/Settings"
22
-
23
- interface SetWarningOptions {
24
- title?: string
25
- message: string
26
- }
27
-
28
- export const SetWarning = (options: SetWarningOptions): void => {
29
- const settings = bootstrap.settings as TypeSettings;
30
- bootstrap.listener.emit(`log`, `${options.title ?? `[${bootstrap.ansi_colors.YELLOW}@atmosx/product-parser${bootstrap.ansi_colors.RESET}]`} ${options.message}`)
31
- if (settings.EnableJournal) {
32
- console.log(`${options.title ?? `[${bootstrap.ansi_colors.YELLOW}@atmosx/product-parser${bootstrap.ansi_colors.RESET}]`} ${options.message}`)
33
- }
34
- }