Discord.js TypeError及定时消息、服务器连接故障求助
解决你的Discord机器人两大问题:连接失败与发送消息错误
咱们一步一步来拆解和修复你遇到的问题:
问题一:ready事件未触发,机器人无法连接
你代码里最关键的错误是事件监听的顺序搞反了!你把client.once('ready')的代码写在了const client = new Discord.Client()之前——这时候client变量还没被定义,相当于给一个不存在的对象绑定事件监听,机器人启动后自然不会触发ready事件,也就看不到Event activate日志,连基础的连接都没法完成。
修复方法:
把client.once('ready')的代码块移到创建客户端实例的代码之后,也就是:
const Discord = require('discord.js'); const client = new Discord.Client(); // 现在client已经存在,绑定ready事件才有效 client.once('ready', () => { client.user.setActivity("WestWorld.", { type: 'PLAYING'}) console.log('Event activate'); });
问题二:TypeError: user.send is not a function + 定时消息失效
这个问题有两个核心原因:异步操作处理错误,以及同步阻塞导致的事件循环卡死。
1. 异步fetch未正确处理
client.users.fetch()是异步函数,它返回的是一个Promise对象,而不是直接的User实例。你直接把它赋值给user,此时user是Promise,自然没有send方法。
2. 同步wait函数阻塞事件循环
你写的wait函数用while循环死等,这在Node.js里是致命的——Node.js是单线程运行,一旦阻塞,整个机器人会彻底卡死,无法处理任何事件(包括ready事件、异步fetch的回调,甚至登录后的心跳包),所以你的定时逻辑根本跑不起来。
完整修复方案:
替换你的定时逻辑,用非阻塞的setInterval实现定时检查,同时正确处理异步fetch:
const Discord = require('discord.js'); // 注意:Discord.js v12+必须指定intents,否则无法获取用户或发送消息 const client = new Discord.Client({ intents: [Discord.Intents.FLAGS.GUILDS, Discord.Intents.FLAGS.DIRECT_MESSAGES] }); client.once('ready', () => { client.user.setActivity("WestWorld.", { type: 'PLAYING'}) console.log('Event activate'); // 机器人准备就绪后才启动定时任务 startDailyTimer(); }); // 全局变量控制一分钟内不重复发送(避免30秒检查一次时重复触发) let canSendMessage = true; async function sendTimedMessage() { const now = new Date(); const currentHour = now.getHours(); const currentMinute = now.getMinutes(); console.log(`当前时间:${currentHour}:${currentMinute}`); if (currentHour === 14 && currentMinute === 24 && canSendMessage) { console.log("到点了,准备发送消息!"); try { // 用await获取实际的User实例,替换成你的目标用户ID(数字ID,不是IP) const user = await client.users.fetch('YOUR_TARGET_USER_ID'); if (user) { await user.send("Hey, it's now time"); console.log("消息发送成功!"); // 标记60秒内不再发送 canSendMessage = false; setTimeout(() => { canSendMessage = true; }, 60000); } } catch (error) { console.error("发送消息失败:", error); // 出错后也要恢复发送权限,避免永久卡住 canSendMessage = true; } } } function startDailyTimer() { // 每隔30秒检查一次时间 setInterval(async () => { await sendTimedMessage(); }, 30000); } client.login("YOUR_BOT_TOKEN");
额外注意事项:
- 替换代码中的
YOUR_TARGET_USER_ID为实际的用户数字ID(可以在Discord设置里开启开发者模式后右键用户复制ID),YOUR_BOT_TOKEN为你的机器人token。 - 如果你使用的是Discord.js v13及以上版本,必须指定intents(代码里已经加了必要的意图:服务器权限和私信权限),否则机器人无法获取用户或发送私信。
- 加入了错误捕获,避免因为网络问题或用户不存在导致定时任务崩溃。
内容的提问来源于stack exchange,提问作者Mat Darwin
相关产品推荐
相关产品推荐

