# Telegram Watchdog Implementation Plan > **For agentic workers:** Stappen gebruiken checkbox (`- [ ]`) syntax voor tracking. **Goal:** Apart Telegram bot process dat de admin waarschuwt als WhatsApp API of dienst-bot plat ligt. **Architecture:** `telegramBot.js` draait als apart systemd process op nextcloud, gebruikt Telegram Bot API via axios. Dienst-bot roept `POST /notify` aan als WhatsApp notificatie faalt. Periodieke health checks naar beide services. **Tech Stack:** Node.js, Express, axios, dotenv (bestaande dependencies, geen nieuwe) --- ### Task 1: Create `src/telegramBot.js` - [ ] **Create `src/telegramBot.js`** ```js require('dotenv').config() const express = require('express') const axios = require('axios') const BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN const ADMIN_CHAT_ID = process.env.TELEGRAM_ADMIN_CHAT_ID const PORT = process.env.TELEGRAM_BOT_PORT || 3004 const DIENST_BOT_HEALTH = process.env.DIENST_BOT_HEALTH_URL || 'http://localhost:3002/health' const WWEBJS_SESSION = process.env.WWEBJS_API_SESSION_URL || 'http://192.168.5.252:3001/session/status/EdGpt' const CHECK_INTERVAL = parseInt(process.env.HEALTH_CHECK_INTERVAL_MS || '300000', 10) const app = express() app.use(express.json()) let dienstBotOk = true let wwebjsOk = true function sendTelegram(text) { return axios.post(`https://api.telegram.org/bot${BOT_TOKEN}/sendMessage`, { chat_id: ADMIN_CHAT_ID, text, parse_mode: 'Markdown' }, { timeout: 10000 }) } async function startupNotification() { try { await sendTelegram('✅ Telegram watchdog online — gezondheidschecks actief') console.log('Startup notification sent') } catch (err) { console.error('Failed to send startup notification:', err.message) } } async function checkHealth() { let currentDienstBotOk = true let currentWwebjsOk = true try { await axios.get(DIENST_BOT_HEALTH, { timeout: 5000 }) } catch { currentDienstBotOk = false } try { const res = await axios.get(WWEBJS_SESSION, { timeout: 5000 }) currentWwebjsOk = res.data?.state === 'CONNECTED' } catch { currentWwebjsOk = false } if (dienstBotOk !== currentDienstBotOk) { const icon = currentDienstBotOk ? '✅' : '❌' const status = currentDienstBotOk ? 'weer online' : 'niet bereikbaar' try { await sendTelegram(`${icon} dienst-bot ${status}`) } catch (err) { console.error('Failed to send dienst-bot status:', err.message) } dienstBotOk = currentDienstBotOk } if (wwebjsOk !== currentWwebjsOk) { const icon = currentWwebjsOk ? '✅' : '❌' const status = currentWwebjsOk ? 'weer online' : 'niet bereikbaar' try { await sendTelegram(`${icon} wwebjs-api ${status}`) } catch (err) { console.error('Failed to send wwebjs-api status:', err.message) } wwebjsOk = currentWwebjsOk } console.log(`Health check: dienst-bot=${currentDienstBotOk ? 'UP' : 'DOWN'}, wwebjs-api=${currentWwebjsOk ? 'UP' : 'DOWN'}`) } app.post('/notify', async (req, res) => { const { text } = req.body if (!text) { return res.status(400).json({ success: false, error: 'missing text' }) } try { await sendTelegram(`⚠️ ${text}`) res.json({ success: true }) } catch (err) { console.error('Failed to forward notification:', err.message) res.status(500).json({ success: false, error: err.message }) } }) app.get('/health', (req, res) => { res.json({ status: 'ok', services: { dienstBot: dienstBotOk, wwebjsApi: wwebjsOk } }) }) startupNotification() setInterval(checkHealth, CHECK_INTERVAL) checkHealth() app.listen(PORT, () => { console.log(`telegram-bot listening on port ${PORT}`) }) ``` - [ ] **Update `.env.example` — add Telegram variables** ``` # Telegram watchdog TELEGRAM_BOT_TOKEN= TELEGRAM_ADMIN_CHAT_ID= TELEGRAM_BOT_PORT=3004 DIENST_BOT_HEALTH_URL=http://localhost:3002/health WWEBJS_API_SESSION_URL=http://192.168.5.252:3001/session/status/EdGpt HEALTH_CHECK_INTERVAL_MS=300000 ``` ### Task 2: Update `src/whatsappApi.js` — add Telegram fallback - [ ] **Modify `notifyAdmin()` in `src/whatsappApi.js`** Replace: ```js async function notifyAdmin(errorText) { const adminNumber = process.env.ADMIN_NUMBER if (!adminNumber) { console.error('ADMIN_NUMBER not configured, skipping admin notification') return } try { await sendTextMessage(adminNumber, `[dienst-bot fout] ${errorText}`) } catch (err) { console.error('Failed to notify admin:', err.message) } } ``` With: ```js async function notifyAdmin(errorText) { const adminNumber = process.env.ADMIN_NUMBER if (!adminNumber) { console.error('ADMIN_NUMBER not configured, skipping admin notification') return } try { await sendTextMessage(adminNumber, `[dienst-bot fout] ${errorText}`) } catch (err) { console.error('WhatsApp admin notification failed, falling back to Telegram:', err.message) try { const telegramUrl = process.env.TELEGRAM_BOT_URL if (telegramUrl) { await axios.post(`${telegramUrl}/notify`, { text: errorText }, { timeout: 5000 }) } } catch (telegramErr) { console.error('Telegram notification also failed:', telegramErr.message) } } } ``` - [ ] **Update `.env.example` — add TELEGRAM_BOT_URL to dienst-bot section** ``` # Telegram watchdog (fallback when WhatsApp API is down) TELEGRAM_BOT_URL=http://localhost:3004 ``` ### Task 3: Update AGENTS.md - [ ] **Add telegram-bot to tables and commands** Add rows: - Systemd service: `telegram-bot.service` - Poort: `3004` - Health check: `curl http://localhost:3004/health` - Commands for status/restart/logs - [ ] **Update release-proces** — add step for restarting telegram-bot ### Task 4: Deploy & verify on nextcloud - [ ] `ssh aiaiaiaiagent@nextcloud` — create systemd service - [ ] Add TELEGRAM_* vars to .env on nextcloud - [ ] `sudo systemctl daemon-reload && sudo systemctl enable --now telegram-bot` - [ ] Check status & logs - [ ] Update release-proces: rsync + restart beide services