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

Discord.js v13 如何检测用户是否已点击特定消息的指定按钮

问题原因与解决方案

现有代码的核心错误点

  • Array.indexOf()用法错误:该方法第二个参数为搜索起始位置,并非你要匹配的消息ID,传参后逻辑完全不符合预期
  • 存储结构错误:将用户ID和消息ID作为独立元素存入数组,无法建立「某用户点击某消息按钮」的关联关系
  • 判断逻辑错误:indexOf未匹配到元素时返回-1,JS中-1属于真值,所以即使用户首次点击也会触发「已投票」的判断
  • 清理逻辑错误:直接删除数组前两位的操作在多投票场景下会误删其他投票的记录

可行实现方案

方案1:修改现有Collector逻辑(推荐,匹配你原有实现思路)

改用Map结构存储点击记录,用消息ID:用户ID格式的字符串作为唯一键,关联用户和消息的点击关系,修改后代码如下:

// 用Map存储点击记录,键为`${messageId}:${userId}`格式的唯一标识
const alreadyPressed = new Map()
// 如果你需要限制只有发起该交互的用户才能点击按钮,可以保留原filter中m.user.id === interaction.user.id的判断,多用户投票场景可删除该条件
const filter = m => m.customId === "No" && m.messageId === interaction.messageId;
const collector = embedMsg.createMessageComponentCollector({filter: filter, time: 10000});

collector.on('collect', async i => {
    client.logger("collector1 collected")
    // 生成唯一标识
    const voteKey = `${i.message.id}:${i.user.id}`
    // 判断是否已经点击过
    if (alreadyPressed.has(voteKey)) {
        return i.reply({ content: `You've already voted ${i.user.username}!`, ephemeral: true })
    }
    // 未点击过的逻辑
    i.reply({ content: `Thank you for your vote ${i.user.username}!`, ephemeral: true });
    alreadyPressed.set(voteKey, true)
});   
collector.on('end', collected => {
    client.logger(collected.size)
    // 直接清空当前collector对应的所有记录,不会影响其他投票
    alreadyPressed.clear()
});

方案2:通过interactionCreate全局监听实现

适合多投票同时存在的场景:

// 全局存储所有投票的点击记录
const globalVoteRecord = new Map()

client.on('interactionCreate', async interaction => {
    // 只处理指定customId的按钮交互
    if (!interaction.isButton() || interaction.customId !== 'No') return
    const voteKey = `${interaction.message.id}:${interaction.user.id}`
    if (globalVoteRecord.has(voteKey)) {
        return interaction.reply({ content: `你已经投过票了${interaction.user.username}!`, ephemeral: true })
    }
    await interaction.reply({ content: `感谢你的投票${interaction.user.username}!`, ephemeral: true });
    globalVoteRecord.set(voteKey, true)
    // 配合定时器在投票结束后删除对应记录,避免内存占用过高
    setTimeout(() => {
        globalVoteRecord.delete(voteKey)
    }, 10000)
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 12:15:00