Discord.js机器人开发:如何获取被提及用户的Presence/Activity活动信息
问题原因
- 你直接访问
activities[0]没有做空判断,当用户没有任何公开活动时,activities是空数组,activities[0]为undefined,调用.name自然会抛出未定义错误 - 机器人未开启Presence相关权限,即使是公开状态也无法读取到用户活动数据
- 未区分活动类型,自定义状态、听歌等非游戏活动也会被读取,不符合你的需求
修复步骤
1. 前置权限配置
- 打开Discord开发者平台你的Bot应用页面,进入「Bot」标签页,开启
PRESENCE INTENT和SERVER MEMBERS INTENT两个权限开关 - 初始化Client时确保包含所需Intent,v14版本示例:
const { Client, GatewayIntentBits } = require('discord.js'); const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildPresences ] });
如果你使用的是v13版本,将GatewayIntentBits.xxx替换为对应的intent字符串即可。
2. 命令代码修改
// v14版本用EmbedBuilder,v13版本替换为MessageEmbed const { EmbedBuilder } = require('discord.js'); module.exports = { name: 'game', aliases: ['gm', 'status'], category: 'Commands', utilisation: '{prefix}game', execute(client, message) { // 获取被提及用户,默认取指令发送者本人 const targetMember = message.mentions.members.first() || message.member; // 在线状态映射 const statusMap = { online: '在线', idle: '闲置', dnd: '请勿打扰', offline: '离线' }; const userStatus = statusMap[targetMember.presence?.status] || '未知状态'; // 过滤出类型为「正在游玩」的游戏活动 const playingActivity = targetMember.presence?.activities?.find(act => act.type === 'PLAYING'); // 无正在游玩的游戏时返回状态提示 if (!playingActivity) { return message.channel.send(`**${targetMember.user.tag}** 当前状态为:**${userStatus}**,没有正在游玩的游戏。`); } // 计算游戏时长 const startTime = playingActivity.timestamps?.start; let playTimeStr = '未知时长'; if (startTime) { const playTimeMs = Date.now() - startTime; const hours = Math.floor(playTimeMs / 3600000); const minutes = Math.floor((playTimeMs % 3600000) / 60000); playTimeStr = hours > 0 ? `${hours}小时${minutes}分钟` : `${minutes}分钟`; } const replyText = `**${targetMember.user.tag}** 已游玩 **${playingActivity.name}** 共 **${playTimeStr}**`; // 存在游戏封面资产时用Embed附带图片发送 if (playingActivity.assets?.largeImage) { const gameEmbed = new EmbedBuilder() .setDescription(replyText) .setImage(`https://cdn.discordapp.com/app-assets/${playingActivity.applicationId}/${playingActivity.assets.largeImage}.png`); return message.channel.send({ embeds: [gameEmbed] }); } // 无封面时直接发送文本 return message.channel.send(replyText); }, };
代码说明
- 全程加入空值安全判断,避免用户没有活动时抛出语法错误
- 只过滤类型为
PLAYING的活动,确保拿到的是游戏数据 - 自动计算游戏时长,格式化为小时+分钟的可读形式
- 存在游戏封面资产时,自动拼接Discord官方资源链接通过Embed发送封面图
- 无游戏时自动返回用户当前的在线状态,符合需求
内容的提问来源于stack exchange,提问作者Tachanks
相关产品推荐
相关产品推荐

