You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord.js如何检测用户是否已在指定频道发送过消息

Discord特定频道重复发消息用户拦截实现

需求说明

需要实现拦截在指定频道重复发送消息的用户功能,当前已有代码完成了角色权限校验、触发私信、DM侧消息收集器逻辑,需要补全收集到用户ok开头消息时的「用户是否已在目标频道发过消息」判断分支,执行对应拦截处理。

现有基础代码

client.on("message", async message => {
    if ((message.content === config.RUN) && message.member.roles.cache.has(config.ROLE_ID)) {
        if (message.channel.type === 'DM') return;
        let filter = m => !m.author.bot;
        let destination = client.channels.cache.get(config.CHANNEL_ID);
        message.author.createDM().then(dmchannel => {
            dmchannel.send(textDM.FIRST_DM);
            const collector = new discord.MessageCollector(dmchannel, filter);
            collector.on('collect', (m, col) => {
                console.log(m.content);
                if (m.content.startsWith("ok")) { 
                    // 此处需要补全:用户已在目标频道发过消息的判断 + 拦截逻辑
                }
            })
        })
    }
})

实现方案

用内存集合存储已在目标频道发过消息的用户ID,启动时初始化历史数据,实时监听新消息更新集合,在收集器分支直接做判断即可,性能比每次拉取频道历史消息高很多。

  1. 先在事件监听外定义存储集合,加初始化和实时更新逻辑
const discord = require('discord.js');
const client = new discord.Client();
// 存储已在目标频道发过消息的非机器人用户ID
const submittedUserSet = new Set();

// bot启动完成后拉取目标频道近期消息初始化集合
client.on('ready', async () => {
  const targetChannel = client.channels.cache.get(config.CHANNEL_ID);
  if (!targetChannel) return;
  // 单接口最多拉100条历史消息,需要更久记录可分批循环拉取
  const historyMsgs = await targetChannel.messages.fetch({ limit: 100 });
  historyMsgs.forEach(msg => {
    if (!msg.author.bot) submittedUserSet.add(msg.author.id);
  });
});

// 实时监听目标频道新消息,同步更新已提交用户集合
client.on('message', msg => {
  if (msg.channel.id === config.CHANNEL_ID && !msg.author.bot) {
    submittedUserSet.add(msg.author.id);
  }
});
  1. 补全消息收集器内的判断分支
collector.on('collect', (m, col) => {
  console.log(m.content);
  if (m.content.startsWith("ok")) {
    // 判断用户是否已提交过
    if (submittedUserSet.has(m.author.id)) {
      // 拦截逻辑:提示重复提交、终止收集器
      m.reply("你已在对应频道发送过消息,请勿重复提交");
      collector.stop('duplicate_submit');
      return;
    }
    // 未提交则执行正常业务逻辑,比如转发内容到目标频道
    const submitContent = m.content.replace(/^ok\s*/i, '');
    destination.send(`${m.author.tag} 提交内容:${submitContent}`);
    // 提交成功后将用户加入已提交集合
    submittedUserSet.add(m.author.id);
    m.reply("提交成功");
    collector.stop('submit_success');
  }
})

注意事项

  • 如果bot重启频率高、需要永久留存提交记录,把内存Set替换成Redis、SQLite这类持久化存储即可,不需要每次启动拉取历史消息
  • 所有接口调用(发消息、拉取历史)建议加catch做异常捕获,避免接口报错导致bot进程崩溃
  • 如果需要限制特定周期内的重复提交(比如24小时内不能重复发),可以把Set结构改成Map,value存用户上次发消息的时间戳,判断时校验时间差即可

内容的提问来源于stack exchange,提问作者Crash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.17 16:16:01