feat: Implement Telegram alerts for catalog updates and failures

This commit is contained in:
2026-10-20 23:14:32 +03:00
parent a95784df93
commit e28d65310d
10 changed files with 541 additions and 43 deletions

View File

@@ -11,6 +11,8 @@ import { createHash } from "node:crypto";
import { timetable } from "./timetable.js";
import { catalogDiagnostics } from "./diagnostics.js";
import { securityHeaders, requestTimeout } from "./protect.js";
import { startWatch, watchOnce, watchStatus } from "./watch.js";
import { telegram } from "./alerts.js";
import {
getIndex,
indexStatus,
@@ -67,8 +69,9 @@ app.use("/api", (_req, res, next) => {
// 7 — /api/diagnostics, cells the parser could not read with confidence;
// 8 — /api/ready, and `ready` in /api/health;
// 9 — a request limit on /api (429 too_many_requests), a 30 s time limit (504 timeout), security headers;
// 10 — parserVersion in /api/catalog.
const API_VERSION = 10;
// 10 — parserVersion in /api/catalog;
// 11 — the catalog is checked by ETag every 5 minutes; `watch`, `telegram` and `catalog.lastCrawl` in /api/health.
const API_VERSION = 11;
/**
* What the server still waits for before it answers from memory: the catalog, the week table
@@ -89,6 +92,9 @@ app.get("/api/health", async (req, res) => {
parserVersion: PARSER_VERSION,
...sources,
directory: indexStatus(),
// The server's own checks of the catalog and its messages to the owner.
watch: watchStatus,
telegram: { enabled: telegram.enabled, sent: telegram.sent, lastSentAt: telegram.lastSentAt, lastError: telegram.lastError },
});
});
// Readiness for Docker and a proxy: 503 until the catalog, the week table and the index are
@@ -309,7 +315,13 @@ export function start(port = Number(process.env.PORT || 3001), host = process.en
console.log(`API и PWA: http://127.0.0.1:${port}`);
// So the first visit and the first search do not wait for the university.
getCalendar().catch((e) => console.error(`Таблица недель: ${e.message}`));
getIndex().catch((e) => console.error(`Индекс: ${e.message}`));
getIndex()
.catch((e) => console.error(`Индекс: ${e.message}`))
// Then the catalog is watched every few minutes, with messages in Telegram if set up.
.finally(() => {
watchOnce();
startWatch();
});
});
// A client must send its headers within 15 s and the whole request (a Word upload of up to
// 10 MB on a slow phone) within two minutes, so slow connections cannot pile up.