discord.js 如何获取并随机选取消息中的被提及用户?
提及用户获取与随机选取的正确实现
现有代码的核心问题
message.mentions.users.get(1)这类取值方式完全无效。该属性返回Discord.js的Collection集合结构,所有用户的存储键是字符串格式的用户ID,而非代表提及顺序的数字索引,按数字取值永远只会返回undefined。- 硬编码取第1、第2、第3个提及用户的写法没有容错能力,如果用户发消息时的提及数量少于你硬编码的取值数,直接就会出现逻辑报错。
正确实现步骤
- 收集全量提及用户:Collection是可迭代结构,直接通过扩展运算符把内部值转为数组,就能拿到按消息里提及顺序排列的用户对象列表,无需手动按索引取值:
const mentionedUsers = [...message.mentions.users.values()] - 构建随机候选池:把消息发送者加入列表,同时做去重处理,避免发送者本身被提及导致重复出现在候选范围:
// 用Set做ID去重,避免重复候选 const candidateIdSet = new Set([ message.author.id, ...mentionedUsers.map(user => user.id) ]) // 从客户端缓存里拿到对应的用户对象,过滤掉缓存失效的无效条目 const candidateUsers = [...candidateIdSet] .map(id => message.client.users.cache.get(id)) .filter(Boolean) - 实现随机选取:对候选数组生成随机下标取值即可,不需要复杂逻辑:
const randomTarget = candidateUsers[Math.floor(Math.random() * candidateUsers.length)]
完整可运行参考代码
// 基础信息获取 const sender = message.author const mentionedUsers = [...message.mentions.users.values()] // 去重构建候选池 const candidatePool = [...new Set([ sender.id, ...mentionedUsers.map(u => u.id) ])].map(id => message.client.users.cache.get(id)).filter(Boolean) // 随机选取目标 const randomTarget = candidatePool[Math.floor(Math.random() * candidatePool.length)] // 测试输出 message.channel.send( `发送者:${sender.username}\n` + `检测到提及用户数:${mentionedUsers.length}\n` + `随机选中的私信接收者:${randomTarget?.username || "暂无有效候选用户"}` ) // 发送私信(需加异常捕获,应对用户关闭私信权限的场景) randomTarget?.send("你收到了系统随机推送的私信").catch(() => { message.channel.send(`向${randomTarget.username}发送私信失败,对方可能关闭了来自服务器成员的私信`) })
注意事项
- 所有涉及用户私信的操作必须加异常捕获,否则用户关闭私信权限时会直接导致bot报错崩溃。
- 不要硬编码按提及位置取固定用户,用户发消息时的提及数量是完全随机的,硬编码写法没有实际可用性。
内容的提问来源于stack exchange,提问作者Miskakao
相关产品推荐
相关产品推荐

