如何在外部应用中检测Discord.js机器人的在线状态?
如何在外部应用中检测Discord.js机器人的在线状态?
嘿,我明白你的需求啦——想在自己的状态网站上用JavaScript检测Discord机器人的在线状态,而且不想依赖另一个机器人来做这事,对吧?我给你两个实用的方案,都是可以直接在前端或前后端配合实现的:
方案一:给机器人加健康检查接口
这个思路很直接:让你的Discord机器人启动一个简单的HTTP服务器,对外暴露一个健康检查端点。当机器人在线时,这个端点会返回成功响应;如果机器人离线,请求就会失败。前端只需要定期请求这个端点,就能判断状态了。
机器人端代码(Node.js + Discord.js)
const { Client, GatewayIntentBits } = require('discord.js'); const http = require('http'); // 初始化Discord客户端 const client = new Client({ intents: [GatewayIntentBits.Guilds] }); // 启动HTTP服务器处理健康检查请求 const healthServer = http.createServer((req, res) => { // 只处理/health路径的请求 if (req.url === '/health') { // 检查机器人是否已登录就绪 if (client.isReady()) { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ status: 'online' })); } else { res.writeHead(503, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ status: 'offline' })); } } else { res.writeHead(404); res.end(); } }); // 监听3001端口(可以自定义,记得在服务器防火墙开放这个端口) healthServer.listen(3001, () => { console.log('健康检查服务已启动,端口3001'); }); // 机器人登录成功后的回调 client.on('ready', () => { console.log(`已登录为 ${client.user.tag}`); }); // 替换成你的机器人TOKEN client.login('你的机器人TOKEN');
前端状态页面代码
// 检测机器人状态的函数 async function checkBotStatus() { const statusElement = document.getElementById('bot-status'); try { // 替换成你的机器人服务器IP和端口 const response = await fetch('http://你的机器人服务器IP:3001/health'); if (response.ok) { const data = await response.json(); console.log('机器人状态:', data.status); statusElement.textContent = '在线'; statusElement.style.color = '#2ecc71'; } else { throw new Error('机器人未就绪'); } } catch (error) { console.error('状态检测失败:', error); statusElement.textContent = '离线'; statusElement.style.color = '#e74c3c'; } } // 页面加载时检测一次,之后每5分钟轮询一次 window.addEventListener('load', checkBotStatus); setInterval(checkBotStatus, 5 * 60 * 1000);
方案二:心跳机制(无需开放额外端口)
如果不想给机器人开放额外端口,可以让机器人定期向你的状态页面后端发送“心跳”请求,后端记录最后一次心跳的时间。前端通过查询后端接口,判断最后一次心跳是否在合理时间内(比如10分钟),来确定机器人是否在线。
机器人端心跳代码
const { Client, GatewayIntentBits } = require('discord.js'); const axios = require('axios'); const client = new Client({ intents: [GatewayIntentBits.Guilds] }); // 发送心跳到状态页面后端的函数 async function sendHeartbeat() { try { // 替换成你的状态页面后端接口地址 await axios.post('https://你的状态页面域名/api/bot-heartbeat', { botId: client.user.id }); console.log('心跳发送成功'); } catch (error) { console.error('心跳发送失败:', error); } } client.on('ready', () => { console.log(`已登录为 ${client.user.tag}`); // 登录成功后立即发一次心跳,之后每5分钟发一次 sendHeartbeat(); setInterval(sendHeartbeat, 5 * 60 * 1000); }); client.login('你的机器人TOKEN');
状态页面后端代码(Node.js + Express)
const express = require('express'); const app = express(); app.use(express.json()); // 存储机器人最后一次心跳时间(生产环境建议用数据库持久化) const botHeartbeats = {}; // 接收机器人心跳的接口 app.post('/api/bot-heartbeat', (req, res) => { const { botId } = req.body; botHeartbeats[botId] = Date.now(); res.status(200).json({ success: true }); }); // 提供给前端查询状态的接口 app.get('/api/bot-status', (req, res) => { const { botId } = req.query; const lastHeartbeat = botHeartbeats[botId]; if (!lastHeartbeat) { return res.json({ status: 'offline' }); } // 判断最后一次心跳是否在10分钟内(600000毫秒) const isOnline = Date.now() - lastHeartbeat < 600000; res.json({ status: isOnline ? 'online' : 'offline' }); }); app.listen(3000, () => { console.log('状态页面后端服务已启动,端口3000'); });
前端状态页面代码
async function checkBotStatus() { const statusElement = document.getElementById('bot-status'); try { // 替换成你的后端接口地址和机器人ID const response = await fetch('https://你的状态页面域名/api/bot-status?botId=你的机器人ID'); const data = await response.json(); if (data.status === 'online') { statusElement.textContent = '在线'; statusElement.style.color = '#2ecc71'; } else { statusElement.textContent = '离线'; statusElement.style.color = '#e74c3c'; } } catch (error) { console.error('状态检测失败:', error); statusElement.textContent = '离线'; statusElement.style.color = '#e74c3c'; } } window.addEventListener('load', checkBotStatus); setInterval(checkBotStatus, 5 * 60 * 1000);
一些注意事项
- 方案一要确保机器人服务器的端口已在防火墙/安全组中开放,如果需要HTTPS,可以用Nginx反向代理配置证书。
- 方案二的后端心跳记录如果用内存存储,重启后端会丢失数据,生产环境建议用SQLite、MongoDB等数据库持久化。
- 绝对不要把机器人的TOKEN暴露在前端代码里,所有涉及TOKEN的操作都要在机器人端或后端完成。
备注:内容来源于stack exchange,提问作者Tuggummi
相关产品推荐
相关产品推荐

