Discord.js提醒机器人开发:如何在指定作用域外发送频道消息
解决Discord.js机器人在外部函数发送消息的问题
核心问题分析
你当前的代码存在几个关键问题:
- 全局变量
userTime只能存储单个提醒,无法处理多个用户的请求 setInterval没有保存引用,导致clearInterval()无法停止定时器- 没有存储目标频道的信息,
checkTime函数不知道要往哪个频道发消息 - 用字符串对比时间容易出现格式不一致的问题,建议改用时间戳
解决方案
- 存储完整的提醒信息:用数组保存每个提醒的频道ID、提醒内容、目标时间戳
- 保存定时器引用:方便后续停止定时器
- 使用时间戳对比:避免字符串格式差异导致的判断错误
- 在
checkTime中通过频道ID获取频道对象:调用client.channels.fetch()获取频道后发送消息
修改后的完整代码
const { Client, GatewayIntentBits } = require(`discord.js`); const prefix = '!'; const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent ] }); // 存储所有提醒:每个元素是 { channelId, message, targetTimestamp } const reminders = []; let intervalId = null; client.on("ready", () => { console.log("Bot is online!"); // 机器人上线后启动定时器 intervalId = setInterval(checkTime, 1000); }); client.on("messageCreate", (message) => { if (message.author.bot) return; const content = message.content.split(" "); if (content[0] !== prefix + 'set-reminder') return; // 解析用户输入的参数 const [inputDate, inputTime, period, channelMention, ...reminderMsgParts] = content.slice(1); const reminderMessage = reminderMsgParts.join(' '); // 解析日期和时间 const [month, day, year] = inputDate.split('/').map(Number); const [hours, minutes] = inputTime.split(':').map(Number); // 转换为24小时制 let adjustedHours = hours; if (period.toLowerCase() === 'pm' && hours !== 12) { adjustedHours += 12; } else if (period.toLowerCase() === 'am' && hours === 12) { adjustedHours = 0; } // 创建目标时间对象(注意月份是0开始,所以要减1) const targetDate = new Date(year, month - 1, day, adjustedHours, minutes); const targetTimestamp = targetDate.getTime(); // 提取频道ID(从@频道的提及格式中) const channelId = channelMention.replace(/[<#>]/g, ''); // 添加到提醒数组 reminders.push({ channelId, message: reminderMessage, targetTimestamp }); // 发送确认消息 message.channel.send(`提醒已设置:将在 ${inputDate} ${inputTime} ${period} 发送消息到 ${channelMention} ✅`); }); const checkTime = () => { const now = Date.now(); // 遍历提醒,过滤已到时间的 const remainingReminders = []; for (const reminder of reminders) { if (now >= reminder.targetTimestamp) { // 获取频道并发送提醒 client.channels.fetch(reminder.channelId) .then(channel => { channel.send(`⏰ 提醒:${reminder.message}`); }) .catch(err => { console.error('发送提醒失败:', err); }); } else { // 未到时间的保留 remainingReminders.push(reminder); } } // 更新提醒数组,移除已触发的 reminders.length = 0; reminders.push(...remainingReminders); // 如果没有剩余提醒,可以停止定时器 if (reminders.length === 0 && intervalId) { clearInterval(intervalId); intervalId = null; } }; client.login("MY_LOGIN_KEY");
关键修改说明
reminders数组:存储每个提醒的完整信息,支持多个同时存在的提醒- 时间戳对比:用
Date.getTime()获取毫秒级时间戳,避免字符串格式问题 - 频道ID提取:从用户输入的
#频道提及中提取纯ID,方便后续获取频道对象 - 定时器管理:只有当有提醒时才运行定时器,无提醒时自动停止,节省资源
- 错误处理:获取频道失败时打印错误,避免程序崩溃
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

