discord.js开发获取用户状态时presence.status未定义报错如何解决
错误根因
该报错是user.presence为undefined导致的,在discord.js v13及以上版本中非常常见,触发原因主要有三类:
- 未开启必要的网关Intent权限,presence属于特权网关意图,需要手动在代码和开发者后台双端开启
- 用户查询逻辑存在写法错误,无法正确命中目标用户导致拿到的用户对象不完整
- 目标用户不在机器人缓存内、未加入当前服务器、或者处于隐身状态,都会导致presence字段为空
修复步骤
1. 开启特权Intent
首先进入Discord开发者平台,找到你对应的机器人应用,进入「Bot」页面,在Privileged Gateway Intents板块下,开启以下两个权限:
- Server Members Intent
- Presence Intent
然后修改你初始化Client的代码,加入对应的意图,以discord.js v14为例:
const { Client, GatewayIntentBits } = require('discord.js'); const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildPresences // 必须开启才能获取用户状态 ] });
2. 修正用户查询逻辑
原代码中client.users.cache.get((u) => u.id === args[0])写法错误,get方法仅接收ID字符串作为参数,条件匹配需要用find方法,或者直接传入ID查询即可:
// 修改前 const user = message.mentions.users.first() || message.author || client.users.cache.get((u) => u.id === args[0]); // 修改后 const user = message.mentions.users.first() || client.users.cache.get(args[0]) || message.author;
3. 加空值判断避免报错
对presence字段做可选链访问,同时设置默认值。另外clientStatus是对象,不能直接转为字符串,需要做格式处理:
// 优先从 guild member 对象拿状态,比全局user对象更准确 const status = member.presence?.status || user.presence?.status || '离线/不可见'; // 提取在线设备拼接为字符串 const clientStatus = user.presence?.clientStatus ? Object.keys(user.presence.clientStatus).join('、') : '无数据';
4. 其他字段兼容优化
原代码中member.nickname如果为空会显示undefined,调整默认值逻辑:
{ name: "nickname", value: member.nickname ?? "none" },
完整修正后代码
const { MessageEmbed } = require("discord.js"); const user = message.mentions.users.first() || client.users.cache.get(args[0]) || message.author; const avatar = user.displayAvatarURL(); const member = message.guild.members.cache.get(user.id); const status = member.presence?.status || user.presence?.status || '离线/不可见'; const clientStatus = user.presence?.clientStatus ? Object.keys(user.presence.clientStatus).join('、') : '无数据'; const embed = new MessageEmbed() .setTitle(`This is ${user.username}`) .setColor("RANDOM") .setDescription("Users info:") .setFooter(`${user.id}`, avatar) .setThumbnail(avatar) .setTimestamp(Date.now()) .addFields( { name: "User tag", value: `${user.tag}` }, { name: "nickname", value: member.nickname ?? "none" }, { name: "joined Discord", value: `${user.createdAt}` }, { name: "joined Server", value: `${member.joinedAt}` }, { name: "Roles", value: `${member.roles.cache.size - 1}` }, { name: "status", value: `${status}` }, { name: "Device", value: `${clientStatus}` } ); message.channel.send({ embeds: [embed] });
内容的提问来源于stack exchange,提问作者Soak
相关产品推荐
相关产品推荐

