easyoref 1.5.0 → 1.7.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "easyoref",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "description": "Real-time Israeli civil defense alerts → Telegram, filtered by your location",
5
5
  "type": "module",
6
6
  "bin": {
@@ -32,14 +32,24 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@inquirer/prompts": "^7.0.0",
35
+ "@langchain/core": "^0.3.0",
36
+ "@langchain/google-genai": "^0.1.12",
37
+ "@langchain/langgraph": "^0.2.0",
35
38
  "@logtail/node": "^0.5.6",
39
+ "bullmq": "^5.0.0",
36
40
  "chalk": "^5.3.0",
37
41
  "grammy": "^1.35.0",
38
- "js-yaml": "^4.1.1"
42
+ "input": "^1.0.1",
43
+ "ioredis": "^5.3.0",
44
+ "js-yaml": "^4.1.1",
45
+ "qrcode-terminal": "^0.12.0",
46
+ "telegram": "^2.26.0"
39
47
  },
40
48
  "devDependencies": {
49
+ "@types/ioredis": "^4.28.10",
41
50
  "@types/js-yaml": "^4.0.9",
42
51
  "@types/node": "^22.0.0",
52
+ "@types/qrcode-terminal": "^0.12.2",
43
53
  "eslint": "^9.0.0",
44
54
  "tsx": "^4.19.0",
45
55
  "typescript": "^5.7.0"
package/dist/bin.d.ts DELETED
@@ -1,17 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * EasyOref CLI entrypoint.
4
- *
5
- * easyoref — run the bot (foreground)
6
- * easyoref run — same as above
7
- * easyoref init — interactive setup wizard
8
- * easyoref install — create systemd service + start
9
- * easyoref uninstall — remove systemd service
10
- * easyoref start — start service (install if needed)
11
- * easyoref stop — stop service
12
- * easyoref restart — restart service
13
- * easyoref status — show service status
14
- * easyoref logs — follow service logs
15
- */
16
- export {};
17
- //# sourceMappingURL=bin.d.ts.map
package/dist/bin.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;GAaG"}
package/dist/bin.js DELETED
@@ -1,82 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * EasyOref CLI entrypoint.
4
- *
5
- * easyoref — run the bot (foreground)
6
- * easyoref run — same as above
7
- * easyoref init — interactive setup wizard
8
- * easyoref install — create systemd service + start
9
- * easyoref uninstall — remove systemd service
10
- * easyoref start — start service (install if needed)
11
- * easyoref stop — stop service
12
- * easyoref restart — restart service
13
- * easyoref status — show service status
14
- * easyoref logs — follow service logs
15
- */
16
- const command = process.argv[2];
17
- switch (command) {
18
- case "init": {
19
- const { init } = await import("./init.js");
20
- await init();
21
- break;
22
- }
23
- case "install": {
24
- const svc = await import("./service.js");
25
- svc.install();
26
- break;
27
- }
28
- case "uninstall": {
29
- const svc = await import("./service.js");
30
- svc.uninstall();
31
- break;
32
- }
33
- case "start": {
34
- const svc = await import("./service.js");
35
- svc.start();
36
- break;
37
- }
38
- case "stop": {
39
- const svc = await import("./service.js");
40
- svc.stop();
41
- break;
42
- }
43
- case "restart": {
44
- const svc = await import("./service.js");
45
- svc.restart();
46
- break;
47
- }
48
- case "status": {
49
- const svc = await import("./service.js");
50
- svc.status();
51
- break;
52
- }
53
- case "logs": {
54
- const svc = await import("./service.js");
55
- svc.logs();
56
- break;
57
- }
58
- case "--help":
59
- case "-h":
60
- console.log(`
61
- EasyOref — Telegram alert bot for Israeli civil defense
62
-
63
- Usage:
64
- easyoref Run the bot (foreground)
65
- easyoref init Interactive setup wizard
66
-
67
- Service management:
68
- easyoref install Create systemd service & start
69
- easyoref uninstall Remove systemd service
70
- easyoref start Start service (auto-install if needed)
71
- easyoref stop Stop service
72
- easyoref restart Restart service
73
- easyoref status Show service status
74
- easyoref logs Follow service logs
75
- `);
76
- break;
77
- case "run":
78
- default:
79
- await import("./bot.js");
80
- }
81
- export {};
82
- //# sourceMappingURL=bin.js.map
package/dist/bin.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;GAaG;AAEH,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEhC,QAAQ,OAAO,EAAE,CAAC;IAChB,KAAK,MAAM,CAAC,CAAC,CAAC;QACZ,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;QAC3C,MAAM,IAAI,EAAE,CAAC;QACb,MAAM;IACR,CAAC;IAED,KAAK,SAAS,CAAC,CAAC,CAAC;QACf,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QACzC,GAAG,CAAC,OAAO,EAAE,CAAC;QACd,MAAM;IACR,CAAC;IAED,KAAK,WAAW,CAAC,CAAC,CAAC;QACjB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QACzC,GAAG,CAAC,SAAS,EAAE,CAAC;QAChB,MAAM;IACR,CAAC;IAED,KAAK,OAAO,CAAC,CAAC,CAAC;QACb,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QACzC,GAAG,CAAC,KAAK,EAAE,CAAC;QACZ,MAAM;IACR,CAAC;IAED,KAAK,MAAM,CAAC,CAAC,CAAC;QACZ,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QACzC,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,MAAM;IACR,CAAC;IAED,KAAK,SAAS,CAAC,CAAC,CAAC;QACf,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QACzC,GAAG,CAAC,OAAO,EAAE,CAAC;QACd,MAAM;IACR,CAAC;IAED,KAAK,QAAQ,CAAC,CAAC,CAAC;QACd,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QACzC,GAAG,CAAC,MAAM,EAAE,CAAC;QACb,MAAM;IACR,CAAC;IAED,KAAK,MAAM,CAAC,CAAC,CAAC;QACZ,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QACzC,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,MAAM;IACR,CAAC;IAED,KAAK,QAAQ,CAAC;IACd,KAAK,IAAI;QACP,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;CAef,CAAC,CAAC;QACC,MAAM;IAER,KAAK,KAAK,CAAC;IACX;QACE,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;AAC7B,CAAC"}
package/dist/bot.d.ts DELETED
@@ -1,16 +0,0 @@
1
- /**
2
- * EasyOref — Real-time Israeli Red Alert Filter Bot
3
- *
4
- * Architecture:
5
- * oref.org.il API → local filter (area map) → Telegram (grammY)
6
- *
7
- * Flow:
8
- * 1. Poll oref.org.il every 2 seconds for active alerts
9
- * 2. Match areas against configured regions (Hebrew names)
10
- * 3. Classify alert type: early warning / siren / incident over
11
- * 4. If relevant → send calm message to family Telegram chat
12
- *
13
- * No LLM needed — purely deterministic matching for <1s latency.
14
- */
15
- export {};
16
- //# sourceMappingURL=bot.d.ts.map
package/dist/bot.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"bot.d.ts","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
package/dist/bot.js DELETED
@@ -1,477 +0,0 @@
1
- /**
2
- * EasyOref — Real-time Israeli Red Alert Filter Bot
3
- *
4
- * Architecture:
5
- * oref.org.il API → local filter (area map) → Telegram (grammY)
6
- *
7
- * Flow:
8
- * 1. Poll oref.org.il every 2 seconds for active alerts
9
- * 2. Match areas against configured regions (Hebrew names)
10
- * 3. Classify alert type: early warning / siren / incident over
11
- * 4. If relevant → send calm message to family Telegram chat
12
- *
13
- * No LLM needed — purely deterministic matching for <1s latency.
14
- */
15
- import { Bot } from "grammy";
16
- import { createServer } from "node:http";
17
- import { config } from "./config.js";
18
- import { initGifState, pickGif } from "./gif-state.js";
19
- import { getLanguagePack, initTranslations, resolveCityIds, translateAreas, } from "./i18n.js";
20
- import * as logger from "./logger.js";
21
- const langPack = getLanguagePack(config.language);
22
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
23
- // Area Filter (configurable via AREAS env var)
24
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
25
- /** Check if alert data contains any of our monitored areas. */
26
- function isRelevantArea(alertAreas) {
27
- for (const monitored of config.areas) {
28
- if (alertAreas.includes(monitored))
29
- return true;
30
- if (alertAreas.some((a) => a.startsWith(monitored) || monitored.startsWith(a)))
31
- return true;
32
- }
33
- return false;
34
- }
35
- /** Return human-readable area label for messages */
36
- function matchedAreaLabel(alertAreas) {
37
- const matched = alertAreas.filter((a) => config.areas.some((m) => a.startsWith(m) || m.startsWith(a) || a === m));
38
- return matched.length > 0
39
- ? matched.join(", ")
40
- : alertAreas.slice(0, 3).join(", ");
41
- }
42
- /** Map internal AlertType → YAML config key */
43
- const ALERT_TYPE_TO_CONFIG = {
44
- early_warning: "early",
45
- siren: "siren",
46
- resolved: "resolved",
47
- };
48
- function classifyAlertType(title) {
49
- if (title.includes("האירוע הסתיים"))
50
- return "resolved";
51
- if (title.includes("בדקות הקרובות") || title.includes("צפויות להתקבל"))
52
- return "early_warning";
53
- return "siren";
54
- }
55
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
56
- // Cooldown / Dedup
57
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
58
- const COOLDOWN_EARLY_MS = 2 * 60 * 1000; // 2 min (Oref sends multiple IDs per wave)
59
- const COOLDOWN_SIREN_MS = 90 * 1000; // 1.5 min
60
- const COOLDOWN_RESOLVED_MS = 5 * 60 * 1000; // 5 min
61
- const lastSent = {
62
- early_warning: 0,
63
- siren: 0,
64
- resolved: 0,
65
- };
66
- function shouldSend(type) {
67
- const elapsed = Date.now() - lastSent[type];
68
- switch (type) {
69
- case "early_warning":
70
- return elapsed >= COOLDOWN_EARLY_MS;
71
- case "resolved":
72
- return elapsed >= COOLDOWN_RESOLVED_MS;
73
- case "siren":
74
- return elapsed >= COOLDOWN_SIREN_MS;
75
- }
76
- }
77
- function markSent(type) {
78
- const now = Date.now();
79
- lastSent[type] = now;
80
- // After resolved → reset ALL others (new attack cycle)
81
- if (type === "resolved") {
82
- lastSent.early_warning = 0;
83
- lastSent.siren = 0;
84
- }
85
- // After siren → allow new early_warning (next wave) and resolved
86
- if (type === "siren") {
87
- lastSent.early_warning = 0;
88
- lastSent.resolved = 0;
89
- }
90
- // After early_warning → allow resolved
91
- if (type === "early_warning")
92
- lastSent.resolved = 0;
93
- }
94
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
95
- // Oref Poller
96
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
97
- const seenAlerts = new Set();
98
- async function fetchAlerts() {
99
- const t0 = Date.now();
100
- try {
101
- const res = await fetch(config.orefApiUrl, {
102
- headers: {
103
- "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
104
- "X-Requested-With": "XMLHttpRequest",
105
- Referer: "https://www.oref.org.il/",
106
- Accept: "application/json, text/plain, */*",
107
- },
108
- });
109
- const ms = Date.now() - t0;
110
- if (!res.ok) {
111
- logger.warn("Oref API error", { status: res.status, ms });
112
- return [];
113
- }
114
- const text = await res.text();
115
- if (!text.trim()) {
116
- logger.debug("Oref poll — quiet", { status: res.status, ms, raw: text });
117
- return [];
118
- }
119
- const parsed = JSON.parse(text);
120
- if (Array.isArray(parsed)) {
121
- logger.info("Oref poll — alerts received", {
122
- count: parsed.length,
123
- ms,
124
- raw: text.slice(0, 2000),
125
- });
126
- return parsed;
127
- }
128
- if (parsed && typeof parsed === "object" && "id" in parsed) {
129
- logger.info("Oref poll — single alert", {
130
- ms,
131
- raw: text.slice(0, 2000),
132
- });
133
- return [parsed];
134
- }
135
- logger.warn("Oref unexpected response", { raw: text.slice(0, 500), ms });
136
- return [];
137
- }
138
- catch (err) {
139
- logger.warn("Oref fetch failed", {
140
- error: String(err),
141
- ms: Date.now() - t0,
142
- });
143
- return [];
144
- }
145
- }
146
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
147
- // GIF Pools by Mode
148
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
149
- // ── funny_cats ────────────────────────────────────────
150
- const CATS_EARLY_WARNING = [
151
- "https://media.giphy.com/media/wQI5H4jtqZEPK/giphy.gif",
152
- "https://media.giphy.com/media/pD83kYQkhuhgY/giphy.gif",
153
- "https://media.giphy.com/media/W2FXGIVejFptc6CSxY/giphy.gif",
154
- "https://media1.tenor.com/m/iM6XLBMUKNcAAAAd/cat-kitty.mp4",
155
- "https://media1.tenor.com/m/fZ-SvpmkgSUAAAAd/uni-unico.mp4",
156
- ];
157
- const CATS_EARLY_WARNING_NIGHT = [
158
- "https://media.giphy.com/media/5UH2PJ8VIEuMqN8V6R/giphy.gif",
159
- "https://media.tenor.com/4gH8RagrsjAAAAPo/wake-up-viralhog.mp4",
160
- "https://media1.tenor.com/m/4NJKe0rdz9AAAAAd/cat-kitty.mp4",
161
- ];
162
- const CATS_SIREN = [
163
- "https://media1.tenor.com/m/9vcHsGLyJmgAAAAd/cat-alarm-alarm.mp4",
164
- "https://media.tenor.com/Wx3bGh80AWkAAAPo/siren-cat.mp4",
165
- "https://media.giphy.com/media/WLGJGG9JjpUrmUWkYf/giphy.gif",
166
- "https://media1.tenor.com/m/0XHXUdzJ9KIAAAAd/cat-meme.mp4",
167
- "https://media1.tenor.com/m/J3sih0hnKLwAAAAC/borzoi-siren.mp4",
168
- ];
169
- const CATS_RESOLVED = [
170
- "https://media.tenor.com/eRGgvoRJNqAAAAPo/cat-silly.mp4",
171
- "https://media.tenor.com/aePEdx5RyFcAAAPo/cat-petsure.mp4",
172
- "https://media.tenor.com/wP_lARteJosAAAPo/cat-box.mp4",
173
- "https://media1.tenor.com/m/Td6hJ6AayEgAAAAd/cats-leave.mp4",
174
- "https://media1.tenor.com/m/eaLwOMoptpcAAAAd/rexi-im-out.mp4",
175
- ];
176
- // ── assertive ─────────────────────────────────────────
177
- const ASSERTIVE_EARLY_WARNING = [
178
- "https://media.giphy.com/media/3o7TKxOhkp8gO0LXMI/giphy.gif", // radar
179
- "https://media.giphy.com/media/l0HlQXlQ3nHyLMvte/giphy.gif", // alert screen
180
- ];
181
- const ASSERTIVE_SIREN = [
182
- "https://media.giphy.com/media/3o7TKVfu4JSwmSqiMo/giphy.gif", // flashing red
183
- "https://media.giphy.com/media/l0MYt5jPR6QX5APm0/giphy.gif", // warning sign
184
- ];
185
- const ASSERTIVE_RESOLVED = [
186
- "https://media.giphy.com/media/XreQmk7ETCak0/giphy.gif", // thumbs up
187
- "https://media.giphy.com/media/3oKIPf3C7HGx1NWIJ2/giphy.gif", // all clear
188
- ];
189
- const GIF_POOLS = {
190
- funny_cats: {
191
- early: CATS_EARLY_WARNING,
192
- earlyNight: [...CATS_EARLY_WARNING, ...CATS_EARLY_WARNING_NIGHT],
193
- siren: CATS_SIREN,
194
- resolved: CATS_RESOLVED,
195
- },
196
- assertive: {
197
- early: ASSERTIVE_EARLY_WARNING,
198
- earlyNight: ASSERTIVE_EARLY_WARNING,
199
- siren: ASSERTIVE_SIREN,
200
- resolved: ASSERTIVE_RESOLVED,
201
- },
202
- };
203
- /** Is it nighttime in Israel? (03:00–10:59) */
204
- function isNightInIsrael() {
205
- const h = Number(new Date().toLocaleTimeString("en-US", {
206
- hour: "numeric",
207
- hour12: false,
208
- timeZone: "Asia/Jerusalem",
209
- }));
210
- return h >= 3 && h < 11;
211
- }
212
- function getGifUrl(alertType) {
213
- const mode = config.gifMode;
214
- // pikud_haoref and none → no GIFs
215
- if (mode === "none" || mode === "pikud_haoref")
216
- return null;
217
- const pools = GIF_POOLS[mode];
218
- if (!pools)
219
- return null;
220
- switch (alertType) {
221
- case "early_warning": {
222
- const pool = isNightInIsrael() ? pools.earlyNight : pools.early;
223
- return pickGif(pool, isNightInIsrael() ? `${mode}_early_night` : `${mode}_early`);
224
- }
225
- case "siren":
226
- return pickGif(pools.siren, `${mode}_siren`);
227
- case "resolved":
228
- return pickGif(pools.resolved, `${mode}_resolved`);
229
- }
230
- }
231
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
232
- // Telegram
233
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
234
- let bot = null;
235
- function initBot() {
236
- if (!config.botToken) {
237
- logger.error("BOT_TOKEN not set — Telegram DISABLED");
238
- return null;
239
- }
240
- if (!config.chatId) {
241
- logger.error("CHAT_ID not set — Telegram DISABLED");
242
- return null;
243
- }
244
- logger.info("Bot initialized", {
245
- chat_id: config.chatId.slice(0, -4) + "****",
246
- language: config.language,
247
- areas: config.areas,
248
- gif_mode: config.gifMode,
249
- });
250
- return new Bot(config.botToken);
251
- }
252
- function nowHHMM() {
253
- return new Date().toLocaleTimeString("he-IL", {
254
- hour: "2-digit",
255
- minute: "2-digit",
256
- timeZone: "Asia/Jerusalem",
257
- });
258
- }
259
- function formatMessage(alertType, areas) {
260
- const time = nowHHMM();
261
- const localAreas = translateAreas(areas, config.language);
262
- const cfgKey = ALERT_TYPE_TO_CONFIG[alertType];
263
- const defaults = langPack.alerts[cfgKey];
264
- const labels = langPack.labels;
265
- const emoji = config.emojiOverride[cfgKey] ?? defaults.emoji;
266
- const title = config.titleOverride[cfgKey] ?? defaults.title;
267
- const desc = config.descriptionOverride[cfgKey] ?? defaults.description;
268
- const lines = [`<b>${emoji} ${title}</b>`];
269
- if (desc)
270
- lines.push(desc);
271
- lines.push("");
272
- lines.push(`<b>${labels.area}:</b> ${localAreas}`);
273
- if (alertType === "early_warning") {
274
- lines.push(`<b>${labels.timeToImpact}:</b> ${labels.earlyEta}`);
275
- lines.push(`<b>${labels.time}:</b> ${time}`);
276
- }
277
- else if (alertType === "siren") {
278
- lines.push(`<b>${labels.timeToImpact}:</b> ${labels.sirenEta}`);
279
- lines.push(`<b>${labels.time}:</b> ${time}`);
280
- }
281
- else if (alertType === "resolved") {
282
- lines.push(`<b>${labels.time}:</b> ${time}`);
283
- }
284
- return lines.join("\n");
285
- }
286
- async function sendTelegram(alertType, text) {
287
- if (!bot || !config.chatId) {
288
- logger.error("Telegram unavailable", {
289
- bot_exists: !!bot,
290
- chat_id: config.chatId,
291
- });
292
- return;
293
- }
294
- const gifUrl = getGifUrl(alertType);
295
- // No GIF mode → send text only
296
- if (!gifUrl) {
297
- try {
298
- await bot.api.sendMessage(config.chatId, text, { parse_mode: "HTML" });
299
- logger.info("Alert sent via Telegram (text)", { type: alertType });
300
- }
301
- catch (err) {
302
- logger.error("Telegram send failed", {
303
- error: String(err),
304
- type: alertType,
305
- });
306
- }
307
- return;
308
- }
309
- // GIF mode → try animation, fall back to text
310
- try {
311
- await bot.api.sendAnimation(config.chatId, gifUrl, {
312
- caption: text,
313
- parse_mode: "HTML",
314
- });
315
- logger.info("Alert sent via Telegram (GIF)", {
316
- type: alertType,
317
- gif_url: gifUrl,
318
- });
319
- }
320
- catch (err) {
321
- logger.warn("GIF send failed, falling back to text", {
322
- error: String(err),
323
- gif_url: gifUrl,
324
- });
325
- try {
326
- await bot.api.sendMessage(config.chatId, text, { parse_mode: "HTML" });
327
- logger.info("Alert sent via Telegram (text fallback)", {
328
- type: alertType,
329
- });
330
- }
331
- catch (err2) {
332
- logger.error("Telegram send failed completely", {
333
- error: String(err2),
334
- type: alertType,
335
- });
336
- }
337
- }
338
- }
339
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
340
- // Alert Processing
341
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
342
- function processAlert(alert) {
343
- if (!isRelevantArea(alert.data)) {
344
- logger.info("Alert — not in our area", {
345
- alert_id: alert.id,
346
- areas_he: alert.data,
347
- });
348
- return;
349
- }
350
- const alertType = classifyAlertType(alert.title);
351
- // Filter by configured alert types
352
- const cfgKey = ALERT_TYPE_TO_CONFIG[alertType];
353
- if (!config.alertTypes.includes(cfgKey)) {
354
- logger.info("Alert type filtered out by config", {
355
- alert_id: alert.id,
356
- type: alertType,
357
- config_key: cfgKey,
358
- });
359
- return;
360
- }
361
- const areas = matchedAreaLabel(alert.data);
362
- logger.info("Alert — RELEVANT", {
363
- alert_id: alert.id,
364
- type: alertType,
365
- areas_he: alert.data,
366
- });
367
- if (!shouldSend(alertType)) {
368
- logger.info("Cooldown active, skipping Telegram", {
369
- alert_id: alert.id,
370
- type: alertType,
371
- });
372
- return;
373
- }
374
- markSent(alertType);
375
- const message = formatMessage(alertType, areas);
376
- sendTelegram(alertType, message).catch((err) => logger.error("Telegram send failed", {
377
- error: String(err),
378
- alert_id: alert.id,
379
- }));
380
- }
381
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
382
- // Health Server
383
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
384
- function startHealthServer() {
385
- const server = createServer((req, res) => {
386
- if (req.url === "/health") {
387
- res.writeHead(200, { "Content-Type": "application/json" });
388
- res.end(JSON.stringify({
389
- status: "ok",
390
- service: "easyoref",
391
- uptime: process.uptime(),
392
- seen_alerts: seenAlerts.size,
393
- language: config.language,
394
- gif_mode: config.gifMode,
395
- areas: config.areas,
396
- }));
397
- }
398
- else {
399
- res.writeHead(404);
400
- res.end("Not Found");
401
- }
402
- });
403
- server.listen(config.healthPort, () => {
404
- logger.info("Health server started", { port: config.healthPort });
405
- });
406
- }
407
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
408
- // Main
409
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
410
- async function main() {
411
- logger.info("EasyOref starting", {
412
- poll_interval_ms: config.pollIntervalMs,
413
- telegram: config.botToken ? "enabled" : "disabled",
414
- language: config.language,
415
- gif_mode: config.gifMode,
416
- areas: config.areas,
417
- });
418
- await initTranslations();
419
- // Resolve YAML city_ids → Hebrew area names for Oref API matching
420
- if (config.cityIds.length > 0) {
421
- config.areas = resolveCityIds(config.cityIds);
422
- logger.info("Resolved city IDs to area names", {
423
- city_ids: config.cityIds,
424
- areas: config.areas,
425
- });
426
- }
427
- else if (process.env.AREAS) {
428
- // Legacy fallback: AREAS env var (comma-separated Hebrew names)
429
- config.areas = process.env.AREAS.split(",")
430
- .map((s) => s.trim())
431
- .filter(Boolean);
432
- logger.info("Using legacy AREAS env var", { areas: config.areas });
433
- }
434
- if (config.areas.length === 0) {
435
- logger.warn("No areas configured — bot will not filter alerts by area");
436
- }
437
- initGifState(config.dataDir);
438
- bot = initBot();
439
- startHealthServer();
440
- // Poll loop
441
- setInterval(async () => {
442
- try {
443
- const alerts = await fetchAlerts();
444
- for (const alert of alerts) {
445
- if (seenAlerts.has(alert.id))
446
- continue;
447
- seenAlerts.add(alert.id);
448
- processAlert(alert);
449
- }
450
- }
451
- catch (err) {
452
- logger.error("Poll error", { error: String(err) });
453
- }
454
- }, config.pollIntervalMs);
455
- // Heartbeat — flush Logtail buffer every 30s
456
- setInterval(async () => {
457
- logger.debug("heartbeat", {
458
- uptime_s: Math.round(process.uptime()),
459
- seen_alerts: seenAlerts.size,
460
- });
461
- await logger.flush();
462
- }, 30_000);
463
- // Graceful shutdown
464
- for (const sig of ["SIGINT", "SIGTERM"]) {
465
- process.on(sig, async () => {
466
- logger.info(`Shutting down (${sig})`);
467
- await logger.flush();
468
- process.exit(0);
469
- });
470
- }
471
- }
472
- main().catch(async (err) => {
473
- logger.error("Fatal error", { error: String(err) });
474
- await logger.flush();
475
- process.exit(1);
476
- });
477
- //# sourceMappingURL=bot.js.map
package/dist/bot.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"bot.js","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"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"}