Discord bot定时更新embed倒计时功能无报错无响应问题排查求助
问题定位
- 1 错误使用filter方法遍历消息
你对channel.messages.cache调用filter方法执行逻辑是错误的:filter是集合筛选方法,回调需要返回布尔值来标记是否保留当前项,你没有返回值的情况下filter会返回空集合,所有更新逻辑不会实际执行。应该先筛选符合条件的消息,再用forEach遍历执行更新逻辑。 - 2 未主动拉取频道历史消息
Discord.js 默认不会缓存频道内的全部历史消息,只会保留客户端启动后新接收的、或主动拉取过的消息。你直接读取channel.messages.cache大概率找不到历史发布的活动embed消息,需要先主动fetch频道历史消息再处理。 - 3 变量未定义报错
新版本你已经去掉了数据库查询逻辑,不再有row对象,但活动开始的提示分支还在使用row.hostID,该变量未定义会触发运行时错误,你没有添加错误捕获逻辑,所以看不到报错、执行直接中断。 - 4 日期时间解析风险
你直接读取embed字段的value作为日期时间输入,这些值可能携带Discord markdown格式符(比如斜体、反引号、换行等),和原数据库的干净格式不一致,会导致new Date()解析失败生成无效日期,后续倒计时计算全部失效。
修正后代码
cron.schedule('* * * * *', async function () { // 遍历所有后缀为events的频道 const eventChannels = bot.channels.cache.filter(channel => channel.name.endsWith('events')); for (const channel of eventChannels.values()) { try { // 主动拉取频道最近100条消息,可根据实际情况调整拉取数量 const fetchedMessages = await channel.messages.fetch({ limit: 100 }); // 筛选符合条件的活动消息 const eventMessages = fetchedMessages.filter(message => { const embed = message.embeds[0]; return embed && embed.color === 65280; }); // 遍历处理每条活动消息 for (const message of eventMessages.values()) { const embed = message.embeds[0]; // 清理字段值里的markdown格式 const event_date = embed.fields[0].value.replace(/[*`\n]/g, '').trim(); const event_time = embed.fields[1].value.replace(/[*`\n]/g, '').trim(); // 这里根据你实际embed的字段结构调整索引,获取hostID const hostID = embed.fields[2].value.replace(/[^0-9]/g, '').trim(); const now = Date.now(); const targetDate = new Date(`${event_date} ${event_time}:00`); // 增加日期有效性校验,避免解析失败中断逻辑 if (isNaN(targetDate.getTime())) continue; const difference = (targetDate - now) / 1000; const days = Math.floor(difference / (3600 * 24)); const hours = Math.floor((difference - (days * 3600 * 24)) / 3600); const minutes = Math.floor((difference - (days * 3600 * 24) - (hours * 3600)) / 60); let timeTill; if (difference <= 0) { timeTill = `Event Started - get with <@!${hostID}> to join up in-game.`; } else if (days > 0) { timeTill = `${days} Days ${hours} Hours ${minutes} Min`; } else if (hours > 0) { timeTill = `${hours} Hours ${minutes} Min`; } else { timeTill = `${minutes} Min`; } embed.fields[9] = { name: 'Starts in:', value: timeTill, inline: false }; // 单条消息更新错误捕获,不影响其他消息处理 await message.edit(new Discord.MessageEmbed(embed)).catch(err => console.log('消息更新失败', err)); } } catch (err) { console.log('频道处理失败', channel.id, err); } } })
注意:代码中默认hostID存放在embed第3个字段(索引为2),你需要根据自己实际的embed字段结构调整hostID的取值索引;如果需要拉取更早的历史活动消息,可以调整
messages.fetch的limit参数或者实现分页拉取逻辑。
内容的提问来源于stack exchange,提问作者Kaspr
相关产品推荐
相关产品推荐

