如何基于谷歌日历事件,用Discord.js实现定时消息推送?
解决方案:动态定时推送Discord日历提醒
核心思路
放弃固定cron任务,改用setTimeout为每个日历事件单独设置定时推送——根据事件开始时间计算提醒触发点(比如提前30分钟),同时维护定时任务的引用,方便日历数据更新时取消旧任务、创建新任务,避免重复或错误提醒。
实现代码
let upcomingEvents = []; let scheduledReminders = new Map(); // 存储定时任务ID,键为事件ID,值为timeoutID const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages] }); // 初始化/刷新提醒任务的函数 function setupEventReminders(events, channelId) { const channel = client.channels.cache.get(channelId); if (!channel) { console.error('目标频道不存在'); return; } // 先取消所有旧的定时任务 scheduledReminders.forEach(timeoutId => clearTimeout(timeoutId)); scheduledReminders.clear(); // 为每个事件创建新的提醒 events.forEach(event => { // 计算提醒时间:比如提前30分钟发送,可自行调整 const reminderTime = new Date(event.startTime) - 30 * 60 * 1000; const now = Date.now(); // 如果提醒时间已经过去,跳过 if (reminderTime <= now) return; // 设置定时任务 const timeoutId = setTimeout(() => { channel.send(`⚠️ 即将开始:**${event.title}**,时间:${event.readabledate}`); scheduledReminders.delete(event.id); // 任务执行后移除引用 }, reminderTime - now); // 保存任务ID到Map scheduledReminders.set(event.id, timeoutId); console.log(`已为事件「${event.title}」设置提醒,将在${new Date(reminderTime)}发送`); }); } // 获取日历数据并更新提醒 async function fetchAndUpdateEvents() { try { const gcpClient = await authorize(); upcomingEvents = await listEvents(gcpClient); // 假设listEvents返回带id、startTime、title、readabledate的事件数组 // 调用提醒设置函数,传入目标频道ID setupEventReminders(upcomingEvents, '1049384497017266228'); } catch (err) { console.error('获取日历数据失败:', err); } } client.once(Events.ClientReady, c => { console.log('Ready! Logged in as ', c.user.tag); // 机器人就绪后立即获取日历并设置提醒 fetchAndUpdateEvents(); // 定期刷新日历数据(比如每小时一次,避免事件变动后提醒失效) setInterval(fetchAndUpdateEvents, 60 * 60 * 1000); }); client.login(TOKEN);
关键细节说明
- 定时任务管理:用
Map存储每个事件对应的timeoutID,刷新日历数据时先清空旧任务,避免重复提醒或已取消/修改的事件仍触发提醒。 - 提醒时间计算:示例中设置为事件开始前30分钟,可根据需求调整(比如提前1小时、1天),注意要判断提醒时间是否在当前时间之后,避免发送过期提醒。
- 日历数据刷新:用
setInterval定期重新拉取日历数据,确保事件变动(新增、修改、删除)后能及时更新提醒任务。 - 频道权限:确保机器人有目标频道的
SendMessages权限,同时在客户端intents中加入GuildMessages(如果使用v14+的Discord.js)。
关于GuildScheduledEvent的说明
GuildScheduledEvent是Discord自带的服务器日程事件功能,用于在Discord内创建可订阅的事件,而非用来触发机器人的定时消息。如果需要让用户直接在Discord中看到事件并订阅,可以结合使用:在创建定时提醒的同时,调用guild.scheduledEvents.create()创建Discord原生事件,但这和你需要的定时消息推送是两个独立的功能。
内容的提问来源于stack exchange,提问作者slyguy5646
相关产品推荐
相关产品推荐

