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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 09:45:05