Discord.js V13 建议系统如何用createMessageComponentCollector统计24小时投票
核心问题梳理
- 重复创建了两个收集器,无需拆分赞成/反对的独立监听逻辑,单个收集器即可完成两类投票的统计
- 收集器绑定对象错误:你给当前交互的整个频道创建了收集器,而非你刚刚发出去的那条专属投票消息,会导致误统计其他投票的按钮点击
- 事件绑定逻辑错误:你将收集器的
collect、end事件监听放在了interaction.customId === "Yes/No"的判断分支中,只有触发这次交互的用户点击了Yes/No按钮才会启动监听,其他用户的投票完全无法被捕获 - 过滤器逻辑存在变量引用错误:你在filter中使用的
i未定义,无法正确匹配投票消息ID
修正后实现代码
// 发送投票消息,拿到消息实例 const voteChannel = client.channels.cache.get("909420357285474334") const voteMsg = await voteChannel.send({ embeds:[embed], components:[row] }) // 定义过滤器:只接收Yes/No按钮的交互 const filter = i => ["Yes", "No"].includes(i.customId) // 直接在投票消息上创建收集器,天然过滤其他消息的交互 const collector = voteMsg.createMessageComponentCollector({ filter, time: 86400000, // 24小时有效期 dispose: true }) // 存储已投票用户ID,防止重复投票 const votedUsers = new Set() // 统计票数 let yesCount = 0 let noCount = 0 // 监听投票交互 collector.on('collect', async i => { // 重复投票拦截 if (votedUsers.has(i.user.id)) { return i.reply({ content: "你已经为该建议投过票了", ephemeral: true }) } // 计入投票 votedUsers.add(i.user.id) if (i.customId === "Yes") yesCount++ else noCount++ // 实时回复投票用户 await i.reply({ content: "投票成功", ephemeral: true }) // 赞成票达标提前结束收集,无需等满24小时 if (yesCount >= 10) { collector.stop('pass') } }) // 监听收集结束事件 collector.on('end', (collected, reason) => { if (reason === 'pass' || yesCount >= 10) { client.logger(`建议通过,赞成票:${yesCount},反对票:${noCount}`) // 此处填写建议通过的后续逻辑 } else { client.logger(`建议未通过,赞成票:${yesCount},反对票:${noCount}`) // 此处填写建议未通过的后续逻辑 } // 投票结束后禁用按钮防止继续产生无效交互 voteMsg.edit({ components: [row.setComponents(row.components.map(c => c.setDisabled(true)))] }) })
注意事项
- 所有异步操作要注意加
await,发送投票消息的操作如果不加await会拿不到正确的消息实例 - 新增了重复投票拦截逻辑,避免同一个用户反复投票刷票
- 可根据业务需求删除提前结束收集的逻辑,强制等满24小时再统计结果
内容的提问来源于stack exchange,提问作者TestUser404
相关产品推荐
相关产品推荐

