Spaces:
Sleeping
Sleeping
Sasha commited on
Commit Β·
7c10755
1
Parent(s): fdc7871
feat: add Better Stack webhook receiver for Telegram alerts
Browse files- server/server.js +57 -0
server/server.js
CHANGED
|
@@ -901,6 +901,63 @@ app.post('/api/streams/sync-vod-direct', authenticateWorker, async (req, res) =>
|
|
| 901 |
}
|
| 902 |
});
|
| 903 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 904 |
// Periodic Twitch Stream Status Polling
|
| 905 |
async function pollTwitchStreamStatus() {
|
| 906 |
const clientId = process.env.TWITCH_CLIENT_ID;
|
|
|
|
| 901 |
}
|
| 902 |
});
|
| 903 |
|
| 904 |
+
// Outgoing Webhook receiver from Better Stack to forward alerts to Telegram bot
|
| 905 |
+
app.post('/api/betterstack-webhook', async (req, res) => {
|
| 906 |
+
console.log('[Better Stack Webhook] Received webhook payload:', req.body);
|
| 907 |
+
|
| 908 |
+
const botToken = process.env.TELEGRAM_BOT_TOKEN;
|
| 909 |
+
const chatId = process.env.TELEGRAM_CHAT_ID;
|
| 910 |
+
|
| 911 |
+
if (!botToken || !chatId) {
|
| 912 |
+
console.warn('[Better Stack Webhook] Missing TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID in environment');
|
| 913 |
+
return res.status(200).json({ success: false, error: 'Telegram credentials missing' });
|
| 914 |
+
}
|
| 915 |
+
|
| 916 |
+
try {
|
| 917 |
+
const event = req.body.event || 'incident.updated';
|
| 918 |
+
const data = req.body.data || {};
|
| 919 |
+
const attributes = data.attributes || {};
|
| 920 |
+
|
| 921 |
+
const monitorName = attributes.name || 'Unknown Monitor';
|
| 922 |
+
const url = attributes.url || '';
|
| 923 |
+
const cause = attributes.cause || 'No cause provided';
|
| 924 |
+
const status = attributes.status || '';
|
| 925 |
+
|
| 926 |
+
let statusEmoji = 'β οΈ';
|
| 927 |
+
let statusText = 'UPDATED';
|
| 928 |
+
|
| 929 |
+
if (status === 'ongoing') {
|
| 930 |
+
statusEmoji = 'π΄';
|
| 931 |
+
statusText = 'DOWN (CRITICAL)';
|
| 932 |
+
} else if (status === 'resolved') {
|
| 933 |
+
statusEmoji = 'π’';
|
| 934 |
+
statusText = 'RESOLVED (UP)';
|
| 935 |
+
}
|
| 936 |
+
|
| 937 |
+
const message =
|
| 938 |
+
`π¨ *[Better Stack Alert]*\n\n` +
|
| 939 |
+
`π₯οΈ *Monitor:* ${monitorName}\n` +
|
| 940 |
+
`π *Status:* ${statusEmoji} ${statusText}\n` +
|
| 941 |
+
`β *Cause:* ${cause}\n` +
|
| 942 |
+
`π *URL:* ${url || 'N/A'}\n` +
|
| 943 |
+
`π *Event:* \`${event}\``;
|
| 944 |
+
|
| 945 |
+
// Send to Telegram Bot API
|
| 946 |
+
await axios.post(`https://api.telegram.org/bot${botToken}/sendMessage`, {
|
| 947 |
+
chat_id: chatId,
|
| 948 |
+
text: message,
|
| 949 |
+
parse_mode: 'Markdown'
|
| 950 |
+
});
|
| 951 |
+
|
| 952 |
+
console.log('[Better Stack Webhook] Successfully forwarded alert to Telegram');
|
| 953 |
+
return res.json({ success: true });
|
| 954 |
+
} catch (err) {
|
| 955 |
+
console.error('[Better Stack Webhook] Error sending message to Telegram:', err.message);
|
| 956 |
+
// Return 200 to Better Stack so it doesn't retry infinitely on transport failures, but log the error
|
| 957 |
+
return res.status(200).json({ success: false, error: err.message });
|
| 958 |
+
}
|
| 959 |
+
});
|
| 960 |
+
|
| 961 |
// Periodic Twitch Stream Status Polling
|
| 962 |
async function pollTwitchStreamStatus() {
|
| 963 |
const clientId = process.env.TWITCH_CLIENT_ID;
|