easyoref 1.11.0 → 1.11.2
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/dist/agent/auth.d.ts +11 -0
- package/dist/agent/auth.d.ts.map +1 -0
- package/dist/agent/auth.js +54 -0
- package/dist/agent/auth.js.map +1 -0
- package/dist/agent/dry-run.d.ts +12 -0
- package/dist/agent/dry-run.d.ts.map +1 -0
- package/dist/agent/dry-run.js +229 -0
- package/dist/agent/dry-run.js.map +1 -0
- package/dist/agent/gramjs-monitor.d.ts +13 -0
- package/dist/agent/gramjs-monitor.d.ts.map +1 -0
- package/dist/agent/gramjs-monitor.js +193 -0
- package/dist/agent/gramjs-monitor.js.map +1 -0
- package/dist/agent/graph.d.ts +44 -0
- package/dist/agent/graph.d.ts.map +1 -0
- package/dist/agent/graph.js +707 -0
- package/dist/agent/graph.js.map +1 -0
- package/dist/agent/queue.d.ts +15 -0
- package/dist/agent/queue.d.ts.map +1 -0
- package/dist/agent/queue.js +40 -0
- package/dist/agent/queue.js.map +1 -0
- package/dist/agent/redis.d.ts +8 -0
- package/dist/agent/redis.d.ts.map +1 -0
- package/dist/agent/redis.js +33 -0
- package/dist/agent/redis.js.map +1 -0
- package/dist/agent/store.d.ts +39 -0
- package/dist/agent/store.d.ts.map +1 -0
- package/dist/agent/store.js +52 -0
- package/dist/agent/store.js.map +1 -0
- package/dist/agent/types.d.ts +102 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +3 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/agent/worker.d.ts +10 -0
- package/dist/agent/worker.d.ts.map +1 -0
- package/dist/agent/worker.js +69 -0
- package/dist/agent/worker.js.map +1 -0
- package/dist/bin.d.ts +17 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +82 -0
- package/dist/bin.js.map +1 -0
- package/dist/bot.d.ts +16 -0
- package/dist/bot.d.ts.map +1 -0
- package/dist/bot.js +557 -0
- package/dist/bot.js.map +1 -0
- package/dist/config.d.ts +116 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +145 -0
- package/dist/config.js.map +1 -0
- package/dist/gif-state.d.ts +17 -0
- package/dist/gif-state.d.ts.map +1 -0
- package/dist/gif-state.js +67 -0
- package/dist/gif-state.js.map +1 -0
- package/dist/i18n.d.ts +49 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +229 -0
- package/dist/i18n.js.map +1 -0
- package/dist/init.d.ts +7 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +163 -0
- package/dist/init.js.map +1 -0
- package/dist/logger.d.ts +14 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +45 -0
- package/dist/logger.js.map +1 -0
- package/dist/service.d.ts +19 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +165 -0
- package/dist/service.js.map +1 -0
- package/package.json +3 -3
package/dist/bot.js
ADDED
|
@@ -0,0 +1,557 @@
|
|
|
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 { startMonitor, stopMonitor } from "./agent/gramjs-monitor.js";
|
|
18
|
+
import { enqueueEnrich } from "./agent/queue.js";
|
|
19
|
+
import { closeRedis } from "./agent/redis.js";
|
|
20
|
+
import { clearActiveAlert, saveAlertMeta } from "./agent/store.js";
|
|
21
|
+
import { startEnrichWorker, stopEnrichWorker } from "./agent/worker.js";
|
|
22
|
+
import { config } from "./config.js";
|
|
23
|
+
import { initGifState, pickGif } from "./gif-state.js";
|
|
24
|
+
import { getLanguagePack, initTranslations, resolveCityIds, translateAreas, } from "./i18n.js";
|
|
25
|
+
import * as logger from "./logger.js";
|
|
26
|
+
const langPack = getLanguagePack(config.language);
|
|
27
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
28
|
+
// Area Filter (configurable via AREAS env var)
|
|
29
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
30
|
+
/** Check if alert data contains any of our monitored areas. */
|
|
31
|
+
function isRelevantArea(alertAreas) {
|
|
32
|
+
for (const monitored of config.areas) {
|
|
33
|
+
if (alertAreas.includes(monitored))
|
|
34
|
+
return true;
|
|
35
|
+
if (alertAreas.some((a) => a.startsWith(monitored) || monitored.startsWith(a)))
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
/** Return human-readable area label for messages */
|
|
41
|
+
function matchedAreaLabel(alertAreas) {
|
|
42
|
+
const matched = alertAreas.filter((a) => config.areas.some((m) => a.startsWith(m) || m.startsWith(a) || a === m));
|
|
43
|
+
return matched.length > 0
|
|
44
|
+
? matched.join(", ")
|
|
45
|
+
: alertAreas.slice(0, 3).join(", ");
|
|
46
|
+
}
|
|
47
|
+
/** Map internal AlertType → YAML config key */
|
|
48
|
+
const ALERT_TYPE_TO_CONFIG = {
|
|
49
|
+
early_warning: "early",
|
|
50
|
+
siren: "siren",
|
|
51
|
+
resolved: "resolved",
|
|
52
|
+
};
|
|
53
|
+
function classifyAlertType(title) {
|
|
54
|
+
if (title.includes("האירוע הסתיים"))
|
|
55
|
+
return "resolved";
|
|
56
|
+
if (title.includes("בדקות הקרובות") || title.includes("צפויות להתקבל"))
|
|
57
|
+
return "early_warning";
|
|
58
|
+
return "siren";
|
|
59
|
+
}
|
|
60
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
61
|
+
// Cooldown / Dedup
|
|
62
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
63
|
+
const COOLDOWN_EARLY_MS = 2 * 60 * 1000; // 2 min (Oref sends multiple IDs per wave)
|
|
64
|
+
const COOLDOWN_SIREN_MS = 90 * 1000; // 1.5 min (no prior early warning)
|
|
65
|
+
const COOLDOWN_SIREN_AFTER_EARLY_MS = 3 * 60 * 1000; // 3 min (early warning already sent)
|
|
66
|
+
const COOLDOWN_RESOLVED_MS = 5 * 60 * 1000; // 5 min
|
|
67
|
+
const lastSent = {
|
|
68
|
+
early_warning: 0,
|
|
69
|
+
siren: 0,
|
|
70
|
+
resolved: 0,
|
|
71
|
+
};
|
|
72
|
+
function shouldSend(type) {
|
|
73
|
+
const elapsed = Date.now() - lastSent[type];
|
|
74
|
+
switch (type) {
|
|
75
|
+
case "early_warning":
|
|
76
|
+
return elapsed >= COOLDOWN_EARLY_MS;
|
|
77
|
+
case "resolved":
|
|
78
|
+
return elapsed >= COOLDOWN_RESOLVED_MS;
|
|
79
|
+
case "siren": {
|
|
80
|
+
// If early warning was already sent this cycle → longer cooldown (user already informed)
|
|
81
|
+
const sirenCd = lastSent.early_warning > 0
|
|
82
|
+
? COOLDOWN_SIREN_AFTER_EARLY_MS
|
|
83
|
+
: COOLDOWN_SIREN_MS;
|
|
84
|
+
return elapsed >= sirenCd;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function markSent(type) {
|
|
89
|
+
const now = Date.now();
|
|
90
|
+
lastSent[type] = now;
|
|
91
|
+
// After resolved → reset ALL others (new attack cycle)
|
|
92
|
+
if (type === "resolved") {
|
|
93
|
+
lastSent.early_warning = 0;
|
|
94
|
+
lastSent.siren = 0;
|
|
95
|
+
}
|
|
96
|
+
// After siren → allow new early_warning (next wave) and resolved
|
|
97
|
+
if (type === "siren") {
|
|
98
|
+
lastSent.early_warning = 0;
|
|
99
|
+
lastSent.resolved = 0;
|
|
100
|
+
}
|
|
101
|
+
// After early_warning → allow resolved
|
|
102
|
+
if (type === "early_warning")
|
|
103
|
+
lastSent.resolved = 0;
|
|
104
|
+
}
|
|
105
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
106
|
+
// Oref Poller
|
|
107
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
108
|
+
const seenAlerts = new Set();
|
|
109
|
+
async function fetchAlerts() {
|
|
110
|
+
const t0 = Date.now();
|
|
111
|
+
try {
|
|
112
|
+
const res = await fetch(config.orefApiUrl, {
|
|
113
|
+
headers: {
|
|
114
|
+
"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",
|
|
115
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
116
|
+
Referer: "https://www.oref.org.il/",
|
|
117
|
+
Accept: "application/json, text/plain, */*",
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
const ms = Date.now() - t0;
|
|
121
|
+
if (!res.ok) {
|
|
122
|
+
logger.warn("Oref API error", { status: res.status, ms });
|
|
123
|
+
return [];
|
|
124
|
+
}
|
|
125
|
+
const text = await res.text();
|
|
126
|
+
if (!text.trim()) {
|
|
127
|
+
logger.debug("Oref poll — quiet", { status: res.status, ms, raw: text });
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
const parsed = JSON.parse(text);
|
|
131
|
+
if (Array.isArray(parsed)) {
|
|
132
|
+
logger.info("Oref poll — alerts received", {
|
|
133
|
+
count: parsed.length,
|
|
134
|
+
ms,
|
|
135
|
+
raw: text.slice(0, 2000),
|
|
136
|
+
});
|
|
137
|
+
return parsed;
|
|
138
|
+
}
|
|
139
|
+
if (parsed && typeof parsed === "object" && "id" in parsed) {
|
|
140
|
+
logger.info("Oref poll — single alert", {
|
|
141
|
+
ms,
|
|
142
|
+
raw: text.slice(0, 2000),
|
|
143
|
+
});
|
|
144
|
+
return [parsed];
|
|
145
|
+
}
|
|
146
|
+
logger.warn("Oref unexpected response", { raw: text.slice(0, 500), ms });
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
logger.warn("Oref fetch failed", {
|
|
151
|
+
error: String(err),
|
|
152
|
+
ms: Date.now() - t0,
|
|
153
|
+
});
|
|
154
|
+
return [];
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
158
|
+
// GIF Pools by Mode
|
|
159
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
160
|
+
// ── funny_cats ────────────────────────────────────────
|
|
161
|
+
const CATS_EARLY_WARNING = [
|
|
162
|
+
"https://media.giphy.com/media/wQI5H4jtqZEPK/giphy.gif",
|
|
163
|
+
"https://media.giphy.com/media/pD83kYQkhuhgY/giphy.gif",
|
|
164
|
+
"https://media.giphy.com/media/W2FXGIVejFptc6CSxY/giphy.gif",
|
|
165
|
+
"https://media1.tenor.com/m/iM6XLBMUKNcAAAAd/cat-kitty.mp4",
|
|
166
|
+
"https://media1.tenor.com/m/fZ-SvpmkgSUAAAAd/uni-unico.mp4",
|
|
167
|
+
];
|
|
168
|
+
const CATS_EARLY_WARNING_NIGHT = [
|
|
169
|
+
"https://media.giphy.com/media/5UH2PJ8VIEuMqN8V6R/giphy.gif",
|
|
170
|
+
"https://media.tenor.com/4gH8RagrsjAAAAPo/wake-up-viralhog.mp4",
|
|
171
|
+
"https://media1.tenor.com/m/4NJKe0rdz9AAAAAd/cat-kitty.mp4",
|
|
172
|
+
];
|
|
173
|
+
const CATS_SIREN = [
|
|
174
|
+
"https://media1.tenor.com/m/9vcHsGLyJmgAAAAd/cat-alarm-alarm.mp4",
|
|
175
|
+
"https://media.tenor.com/Wx3bGh80AWkAAAPo/siren-cat.mp4",
|
|
176
|
+
"https://media.giphy.com/media/WLGJGG9JjpUrmUWkYf/giphy.gif",
|
|
177
|
+
"https://media1.tenor.com/m/0XHXUdzJ9KIAAAAd/cat-meme.mp4",
|
|
178
|
+
"https://media1.tenor.com/m/J3sih0hnKLwAAAAC/borzoi-siren.mp4",
|
|
179
|
+
];
|
|
180
|
+
const CATS_RESOLVED = [
|
|
181
|
+
"https://media.tenor.com/eRGgvoRJNqAAAAPo/cat-silly.mp4",
|
|
182
|
+
"https://media.tenor.com/aePEdx5RyFcAAAPo/cat-petsure.mp4",
|
|
183
|
+
"https://media.tenor.com/wP_lARteJosAAAPo/cat-box.mp4",
|
|
184
|
+
"https://media1.tenor.com/m/Td6hJ6AayEgAAAAd/cats-leave.mp4",
|
|
185
|
+
"https://media1.tenor.com/m/eaLwOMoptpcAAAAd/rexi-im-out.mp4",
|
|
186
|
+
];
|
|
187
|
+
// ── assertive ─────────────────────────────────────────
|
|
188
|
+
const ASSERTIVE_EARLY_WARNING = [
|
|
189
|
+
"https://media.giphy.com/media/3o7TKxOhkp8gO0LXMI/giphy.gif", // radar
|
|
190
|
+
"https://media.giphy.com/media/l0HlQXlQ3nHyLMvte/giphy.gif", // alert screen
|
|
191
|
+
];
|
|
192
|
+
const ASSERTIVE_SIREN = [
|
|
193
|
+
"https://media.giphy.com/media/3o7TKVfu4JSwmSqiMo/giphy.gif", // flashing red
|
|
194
|
+
"https://media.giphy.com/media/l0MYt5jPR6QX5APm0/giphy.gif", // warning sign
|
|
195
|
+
];
|
|
196
|
+
const ASSERTIVE_RESOLVED = [
|
|
197
|
+
"https://media.giphy.com/media/XreQmk7ETCak0/giphy.gif", // thumbs up
|
|
198
|
+
"https://media.giphy.com/media/3oKIPf3C7HGx1NWIJ2/giphy.gif", // all clear
|
|
199
|
+
];
|
|
200
|
+
const GIF_POOLS = {
|
|
201
|
+
funny_cats: {
|
|
202
|
+
early: CATS_EARLY_WARNING,
|
|
203
|
+
earlyNight: [...CATS_EARLY_WARNING, ...CATS_EARLY_WARNING_NIGHT],
|
|
204
|
+
siren: CATS_SIREN,
|
|
205
|
+
resolved: CATS_RESOLVED,
|
|
206
|
+
},
|
|
207
|
+
assertive: {
|
|
208
|
+
early: ASSERTIVE_EARLY_WARNING,
|
|
209
|
+
earlyNight: ASSERTIVE_EARLY_WARNING,
|
|
210
|
+
siren: ASSERTIVE_SIREN,
|
|
211
|
+
resolved: ASSERTIVE_RESOLVED,
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
/** Is it nighttime in Israel? (03:00–10:59) */
|
|
215
|
+
function isNightInIsrael() {
|
|
216
|
+
const h = Number(new Date().toLocaleTimeString("en-US", {
|
|
217
|
+
hour: "numeric",
|
|
218
|
+
hour12: false,
|
|
219
|
+
timeZone: "Asia/Jerusalem",
|
|
220
|
+
}));
|
|
221
|
+
return h >= 3 && h < 11;
|
|
222
|
+
}
|
|
223
|
+
function getGifUrl(alertType) {
|
|
224
|
+
const mode = config.gifMode;
|
|
225
|
+
// pikud_haoref and none → no GIFs
|
|
226
|
+
if (mode === "none" || mode === "pikud_haoref")
|
|
227
|
+
return null;
|
|
228
|
+
const pools = GIF_POOLS[mode];
|
|
229
|
+
if (!pools)
|
|
230
|
+
return null;
|
|
231
|
+
switch (alertType) {
|
|
232
|
+
case "early_warning": {
|
|
233
|
+
const pool = isNightInIsrael() ? pools.earlyNight : pools.early;
|
|
234
|
+
return pickGif(pool, isNightInIsrael() ? `${mode}_early_night` : `${mode}_early`);
|
|
235
|
+
}
|
|
236
|
+
case "siren":
|
|
237
|
+
return pickGif(pools.siren, `${mode}_siren`);
|
|
238
|
+
case "resolved":
|
|
239
|
+
return pickGif(pools.resolved, `${mode}_resolved`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
243
|
+
// Telegram
|
|
244
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
245
|
+
let bot = null;
|
|
246
|
+
function initBot() {
|
|
247
|
+
if (!config.botToken) {
|
|
248
|
+
logger.error("BOT_TOKEN not set — Telegram DISABLED");
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
if (!config.chatId) {
|
|
252
|
+
logger.error("CHAT_ID not set — Telegram DISABLED");
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
logger.info("Bot initialized", {
|
|
256
|
+
chat_id: config.chatId.slice(0, -4) + "****",
|
|
257
|
+
language: config.language,
|
|
258
|
+
areas: config.areas,
|
|
259
|
+
gif_mode: config.gifMode,
|
|
260
|
+
});
|
|
261
|
+
return new Bot(config.botToken);
|
|
262
|
+
}
|
|
263
|
+
function nowHHMM() {
|
|
264
|
+
return new Date().toLocaleTimeString("he-IL", {
|
|
265
|
+
hour: "2-digit",
|
|
266
|
+
minute: "2-digit",
|
|
267
|
+
timeZone: "Asia/Jerusalem",
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
function formatMessage(alertType, areas) {
|
|
271
|
+
const time = nowHHMM();
|
|
272
|
+
const localAreas = translateAreas(areas, config.language);
|
|
273
|
+
const cfgKey = ALERT_TYPE_TO_CONFIG[alertType];
|
|
274
|
+
const defaults = langPack.alerts[cfgKey];
|
|
275
|
+
const labels = langPack.labels;
|
|
276
|
+
const emoji = config.emojiOverride[cfgKey] ?? defaults.emoji;
|
|
277
|
+
const title = config.titleOverride[cfgKey] ?? defaults.title;
|
|
278
|
+
const desc = config.descriptionOverride[cfgKey] ?? defaults.description;
|
|
279
|
+
const lines = [`<b>${emoji} ${title}</b>`];
|
|
280
|
+
if (desc)
|
|
281
|
+
lines.push(desc);
|
|
282
|
+
lines.push("");
|
|
283
|
+
lines.push(`<b>${labels.area}:</b> ${localAreas}`);
|
|
284
|
+
if (alertType === "early_warning") {
|
|
285
|
+
lines.push(`<b>${labels.timeToImpact}:</b> ${labels.earlyEta}`);
|
|
286
|
+
lines.push(`<b>${labels.time}:</b> ${time}`);
|
|
287
|
+
}
|
|
288
|
+
else if (alertType === "siren") {
|
|
289
|
+
lines.push(`<b>${labels.timeToImpact}:</b> ${labels.sirenEta}`);
|
|
290
|
+
lines.push(`<b>${labels.time}:</b> ${time}`);
|
|
291
|
+
}
|
|
292
|
+
else if (alertType === "resolved") {
|
|
293
|
+
lines.push(`<b>${labels.time}:</b> ${time}`);
|
|
294
|
+
}
|
|
295
|
+
return lines.join("\n");
|
|
296
|
+
}
|
|
297
|
+
/** Send message and return {messageId, isCaption} for agent editing */
|
|
298
|
+
async function sendTelegram(alertType, text) {
|
|
299
|
+
if (!bot || !config.chatId) {
|
|
300
|
+
logger.error("Telegram unavailable", {
|
|
301
|
+
bot_exists: !!bot,
|
|
302
|
+
chat_id: config.chatId,
|
|
303
|
+
});
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
const gifUrl = getGifUrl(alertType);
|
|
307
|
+
// No GIF mode → send text only
|
|
308
|
+
if (!gifUrl) {
|
|
309
|
+
try {
|
|
310
|
+
const msg = await bot.api.sendMessage(config.chatId, text, {
|
|
311
|
+
parse_mode: "HTML",
|
|
312
|
+
});
|
|
313
|
+
logger.info("Alert sent via Telegram (text)", { type: alertType });
|
|
314
|
+
return { messageId: msg.message_id, isCaption: false };
|
|
315
|
+
}
|
|
316
|
+
catch (err) {
|
|
317
|
+
logger.error("Telegram send failed", {
|
|
318
|
+
error: String(err),
|
|
319
|
+
type: alertType,
|
|
320
|
+
});
|
|
321
|
+
return null;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
// GIF mode → try animation, fall back to text
|
|
325
|
+
try {
|
|
326
|
+
const msg = await bot.api.sendAnimation(config.chatId, gifUrl, {
|
|
327
|
+
caption: text,
|
|
328
|
+
parse_mode: "HTML",
|
|
329
|
+
});
|
|
330
|
+
logger.info("Alert sent via Telegram (GIF)", {
|
|
331
|
+
type: alertType,
|
|
332
|
+
gif_url: gifUrl,
|
|
333
|
+
});
|
|
334
|
+
return { messageId: msg.message_id, isCaption: true };
|
|
335
|
+
}
|
|
336
|
+
catch (err) {
|
|
337
|
+
logger.warn("GIF send failed, falling back to text", {
|
|
338
|
+
error: String(err),
|
|
339
|
+
gif_url: gifUrl,
|
|
340
|
+
});
|
|
341
|
+
try {
|
|
342
|
+
const msg = await bot.api.sendMessage(config.chatId, text, {
|
|
343
|
+
parse_mode: "HTML",
|
|
344
|
+
});
|
|
345
|
+
logger.info("Alert sent via Telegram (text fallback)", {
|
|
346
|
+
type: alertType,
|
|
347
|
+
});
|
|
348
|
+
return { messageId: msg.message_id, isCaption: false };
|
|
349
|
+
}
|
|
350
|
+
catch (err2) {
|
|
351
|
+
logger.error("Telegram send failed completely", {
|
|
352
|
+
error: String(err2),
|
|
353
|
+
type: alertType,
|
|
354
|
+
});
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
360
|
+
// Alert Processing
|
|
361
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
362
|
+
async function processAlert(alert) {
|
|
363
|
+
if (!isRelevantArea(alert.data)) {
|
|
364
|
+
logger.info("Alert — not in our area", {
|
|
365
|
+
alert_id: alert.id,
|
|
366
|
+
areas_he: alert.data,
|
|
367
|
+
});
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const alertType = classifyAlertType(alert.title);
|
|
371
|
+
// Filter by configured alert types
|
|
372
|
+
const cfgKey = ALERT_TYPE_TO_CONFIG[alertType];
|
|
373
|
+
if (!config.alertTypes.includes(cfgKey)) {
|
|
374
|
+
logger.info("Alert type filtered out by config", {
|
|
375
|
+
alert_id: alert.id,
|
|
376
|
+
type: alertType,
|
|
377
|
+
config_key: cfgKey,
|
|
378
|
+
});
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
const areas = matchedAreaLabel(alert.data);
|
|
382
|
+
logger.info("Alert — RELEVANT", {
|
|
383
|
+
alert_id: alert.id,
|
|
384
|
+
type: alertType,
|
|
385
|
+
areas_he: alert.data,
|
|
386
|
+
});
|
|
387
|
+
if (!shouldSend(alertType)) {
|
|
388
|
+
logger.info("Cooldown active, skipping Telegram", {
|
|
389
|
+
alert_id: alert.id,
|
|
390
|
+
type: alertType,
|
|
391
|
+
});
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
markSent(alertType);
|
|
395
|
+
const message = formatMessage(alertType, areas);
|
|
396
|
+
// Only monitor early + siren alerts with the agent (not resolved)
|
|
397
|
+
const shouldEnrich = config.agent.enabled &&
|
|
398
|
+
(alertType === "early_warning" || alertType === "siren");
|
|
399
|
+
try {
|
|
400
|
+
const sent = await sendTelegram(alertType, message);
|
|
401
|
+
// Clear active alert on resolved (stop monitoring)
|
|
402
|
+
if (alertType === "resolved") {
|
|
403
|
+
await clearActiveAlert();
|
|
404
|
+
logger.info("Agent monitoring stopped (resolved alert)", {
|
|
405
|
+
alert_id: alert.id,
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
// Store alert meta + enqueue enrichment job
|
|
409
|
+
if (sent && shouldEnrich && config.chatId) {
|
|
410
|
+
const alertTs = Date.now();
|
|
411
|
+
await saveAlertMeta({
|
|
412
|
+
alertId: alert.id,
|
|
413
|
+
messageId: sent.messageId,
|
|
414
|
+
chatId: config.chatId,
|
|
415
|
+
isCaption: sent.isCaption,
|
|
416
|
+
alertTs,
|
|
417
|
+
alertType,
|
|
418
|
+
alertAreas: alert.data,
|
|
419
|
+
currentText: message,
|
|
420
|
+
});
|
|
421
|
+
await enqueueEnrich(alert.id, alertTs);
|
|
422
|
+
// Start timeout timer — clear active alert after 15min if not resolved
|
|
423
|
+
const timeoutMs = config.agent.timeoutMinutes * 60 * 1000;
|
|
424
|
+
setTimeout(async () => {
|
|
425
|
+
try {
|
|
426
|
+
await clearActiveAlert();
|
|
427
|
+
logger.info("Agent monitoring stopped (timeout)", {
|
|
428
|
+
alert_id: alert.id,
|
|
429
|
+
timeout_minutes: config.agent.timeoutMinutes,
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
catch (err) {
|
|
433
|
+
logger.warn("Timeout clearActiveAlert failed", {
|
|
434
|
+
error: String(err),
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
}, timeoutMs);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
catch (err) {
|
|
441
|
+
logger.error("Alert send/store failed", {
|
|
442
|
+
error: String(err),
|
|
443
|
+
alert_id: alert.id,
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
448
|
+
// Health Server
|
|
449
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
450
|
+
function startHealthServer() {
|
|
451
|
+
const server = createServer((req, res) => {
|
|
452
|
+
if (req.url === "/health") {
|
|
453
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
454
|
+
res.end(JSON.stringify({
|
|
455
|
+
status: "ok",
|
|
456
|
+
service: "easyoref",
|
|
457
|
+
uptime: process.uptime(),
|
|
458
|
+
seen_alerts: seenAlerts.size,
|
|
459
|
+
language: config.language,
|
|
460
|
+
gif_mode: config.gifMode,
|
|
461
|
+
areas: config.areas,
|
|
462
|
+
}));
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
res.writeHead(404);
|
|
466
|
+
res.end("Not Found");
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
server.listen(config.healthPort, () => {
|
|
470
|
+
logger.info("Health server started", { port: config.healthPort });
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
474
|
+
// Main
|
|
475
|
+
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
476
|
+
async function main() {
|
|
477
|
+
logger.info("EasyOref starting", {
|
|
478
|
+
poll_interval_ms: config.pollIntervalMs,
|
|
479
|
+
telegram: config.botToken ? "enabled" : "disabled",
|
|
480
|
+
language: config.language,
|
|
481
|
+
gif_mode: config.gifMode,
|
|
482
|
+
areas: config.areas,
|
|
483
|
+
});
|
|
484
|
+
await initTranslations();
|
|
485
|
+
// Resolve YAML city_ids → Hebrew area names for Oref API matching
|
|
486
|
+
if (config.cityIds.length > 0) {
|
|
487
|
+
config.areas = resolveCityIds(config.cityIds);
|
|
488
|
+
logger.info("Resolved city IDs to area names", {
|
|
489
|
+
city_ids: config.cityIds,
|
|
490
|
+
areas: config.areas,
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
else if (process.env.AREAS) {
|
|
494
|
+
// Legacy fallback: AREAS env var (comma-separated Hebrew names)
|
|
495
|
+
config.areas = process.env.AREAS.split(",")
|
|
496
|
+
.map((s) => s.trim())
|
|
497
|
+
.filter(Boolean);
|
|
498
|
+
logger.info("Using legacy AREAS env var", { areas: config.areas });
|
|
499
|
+
}
|
|
500
|
+
if (config.areas.length === 0) {
|
|
501
|
+
logger.warn("No areas configured — bot will not filter alerts by area");
|
|
502
|
+
}
|
|
503
|
+
initGifState(config.dataDir);
|
|
504
|
+
bot = initBot();
|
|
505
|
+
startHealthServer();
|
|
506
|
+
// Start agent subsystems if enabled
|
|
507
|
+
if (config.agent.enabled) {
|
|
508
|
+
startEnrichWorker();
|
|
509
|
+
await startMonitor();
|
|
510
|
+
logger.info("Agent subsystems started", {
|
|
511
|
+
model: config.agent.model,
|
|
512
|
+
provider: "openrouter.ai",
|
|
513
|
+
channels: 14, // MONITORED_CHANNELS length (hardcoded)
|
|
514
|
+
enrich_delay_ms: config.agent.enrichDelayMs,
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
// Poll loop
|
|
518
|
+
setInterval(async () => {
|
|
519
|
+
try {
|
|
520
|
+
const alerts = await fetchAlerts();
|
|
521
|
+
for (const alert of alerts) {
|
|
522
|
+
if (seenAlerts.has(alert.id))
|
|
523
|
+
continue;
|
|
524
|
+
seenAlerts.add(alert.id);
|
|
525
|
+
await processAlert(alert);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
catch (err) {
|
|
529
|
+
logger.error("Poll error", { error: String(err) });
|
|
530
|
+
}
|
|
531
|
+
}, config.pollIntervalMs);
|
|
532
|
+
// Heartbeat — flush Logtail buffer every 30s
|
|
533
|
+
setInterval(async () => {
|
|
534
|
+
logger.debug("heartbeat", {
|
|
535
|
+
uptime_s: Math.round(process.uptime()),
|
|
536
|
+
seen_alerts: seenAlerts.size,
|
|
537
|
+
});
|
|
538
|
+
await logger.flush();
|
|
539
|
+
}, 30_000);
|
|
540
|
+
// Graceful shutdown
|
|
541
|
+
for (const sig of ["SIGINT", "SIGTERM"]) {
|
|
542
|
+
process.on(sig, async () => {
|
|
543
|
+
logger.info(`Shutting down (${sig})`);
|
|
544
|
+
await stopMonitor();
|
|
545
|
+
await stopEnrichWorker();
|
|
546
|
+
await closeRedis();
|
|
547
|
+
await logger.flush();
|
|
548
|
+
process.exit(0);
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
main().catch(async (err) => {
|
|
553
|
+
logger.error("Fatal error", { error: String(err) });
|
|
554
|
+
await logger.flush();
|
|
555
|
+
process.exit(1);
|
|
556
|
+
});
|
|
557
|
+
//# sourceMappingURL=bot.js.map
|
package/dist/bot.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot.js","sourceRoot":"","sources":["../src/bot.ts"],"names":[],"mappings":"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"}
|