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

Discord.js提醒机器人开发:如何在指定作用域外发送频道消息

解决Discord.js机器人在外部函数发送消息的问题

核心问题分析

你当前的代码存在几个关键问题:

  • 全局变量userTime只能存储单个提醒,无法处理多个用户的请求
  • setInterval没有保存引用,导致clearInterval()无法停止定时器
  • 没有存储目标频道的信息,checkTime函数不知道要往哪个频道发消息
  • 用字符串对比时间容易出现格式不一致的问题,建议改用时间戳

解决方案

  1. 存储完整的提醒信息:用数组保存每个提醒的频道ID、提醒内容、目标时间戳
  2. 保存定时器引用:方便后续停止定时器
  3. 使用时间戳对比:避免字符串格式差异导致的判断错误
  4. 在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 15:41:46