如何统计Discord服务器指定时间段消息数以实现自动触发slowmode?
Discord机器人10秒内消息数检测实现方案
你原本采用每10秒重置计数器的逻辑会存在统计边界误差,比如跨重置节点的高频消息无法被正确识别,建议改用滑动时间窗口的方案实现,具体步骤如下:
- 为每个频道维护一个消息时间戳存储队列,频道每次触发新消息事件时,将当前消息的毫秒级Unix时间戳插入队列
- 每次插入新时间戳后,过滤队列中所有早于「当前时间戳 - 10000」的元素,剩余元素的数量就是最近10秒内的消息总数量
- 得到总数后即可计算平均消息频率,达到阈值后调用对应Discord库的频道slowmode设置接口即可
以下为discord.js v14版本的简化实现示例:
// 全局存储结构:key为频道ID,value为该频道的消息时间戳数组 const channelMsgTimestamps = new Map(); client.on('messageCreate', async (message) => { // 过滤机器人消息、非服务器频道消息 if (message.author.bot || !message.inGuild()) return; const channelId = message.channel.id; const currentTime = Date.now(); const TIME_WINDOW = 10 * 1000; // 10秒时间窗口 // 初始化对应频道的时间戳数组 if (!channelMsgTimestamps.has(channelId)) { channelMsgTimestamps.set(channelId, []); } const timestampArr = channelMsgTimestamps.get(channelId); timestampArr.push(currentTime); // 过滤掉10秒外的无效时间戳,剩余长度即为最近10秒消息总数 const validTimestamps = timestampArr.filter(ts => currentTime - ts <= TIME_WINDOW); channelMsgTimestamps.set(channelId, validTimestamps); const msgCount10s = validTimestamps.length; // 示例阈值:10秒内超过25条消息则开启15秒慢模式 if (msgCount10s > 25) { await message.channel.setRateLimitPerUser(15); await message.channel.send('检测到频道消息频率过高,已自动开启慢模式'); } });
优化建议
- 消息量大的场景下,因为时间戳是按递增顺序插入数组的,可以用
findIndex找到第一个符合时间要求的元素下标,直接用splice截断数组,不用遍历全量数组过滤,性能更高 - 可以加定时任务定期清理超过30分钟没有新消息的频道的时间戳数组,避免无用内存占用
内容的提问来源于stack exchange,提问作者DisplayNameNotFound
相关产品推荐
相关产品推荐

