
在使用 discord.js 构建机器人时,开发者经常会遇到一个挑战:机器人能够响应用户发起的命令并发送消息,但在执行定时任务(例如每隔一段时间自动发布新闻更新)时,却无法成功发送消息。这种问题通常表现为机器人似乎没有在指定频道中执行发送操作,尽管其在响应用户命令时功能正常。
具体来说,一个设计用于定时从外部网站抓取突发新闻并通过 node-cron 或 setInterval 机制发送到特定 Discord 频道的机器人,可能会在自动发送环节失效。开发者会发现,当用户手动输入“news”命令时,机器人能正确抓取并回复新闻;但当定时任务触发 sendPromptNews 函数时,频道中却没有任何消息出现。
经过排查,发现目标频道 ID 和机器人权限均无问题。代码的其他部分,如数据抓取和命令响应,也运行良好。这暗示问题可能出在定时任务上下文下,机器人获取目标服务器(Guild)或频道(Channel)对象的方式上。
Discord.js 为了提高性能,会缓存它所接触过的服务器、频道、用户等数据。当一个 messageCreate 事件发生时,相关的服务器和频道信息通常会被加载到缓存中。因此,在处理用户命令时,bot.guilds.cache.get() 或 guild.channels.cache.find() 能够轻易地找到所需的对象。
然而,对于由 node-cron 或 setInterval 触发的定时任务,情况有所不同。这些任务是在独立于任何特定 Discord 事件的上下文中执行的。如果机器人长时间未与某个服务器或频道进行交互,或者在启动时未完全加载所有数据,那么该服务器或频道的信息可能不会存在于缓存中。此时,cache.get() 或 cache.find() 将返回 undefined,导致后续的发送消息操作无法执行。
问题代码片段中的 bot.guilds.cache.get(targetGuildId) 和 guild.channels.cache.find(...) 正是依赖于缓存。当缓存中没有所需数据时,这些调用会静默失败,而缺乏适当的错误日志使得问题难以定位。
解决此问题的关键在于:当依赖的数据可能不在缓存中时,主动从 Discord API 获取(fetch)最新数据,而不是仅仅依赖缓存。 同时,加入详细的错误日志,以便在获取失败时能够及时发现并调试。
以下是 sendPromptNews 函数的优化方案:
// Function to send prompt news as automated replies
const sendPromptNews = async () => {
if (targetGuildId) {
let guild;
try {
// 尝试从 Discord API 获取服务器,而不是仅仅依赖缓存
guild = await bot.guilds.fetch(targetGuildId);
} catch (error) {
console.error(`Error fetching guild ${targetGuildId}:`, error);
// 如果获取服务器失败,则无需继续
return;
}
if (guild) {
let channel;
try {
// 获取服务器的所有频道,或者直接获取特定频道
// 推荐使用 await guild.channels.fetch('channel_id') 直接获取已知 ID 的频道
const channels = await guild.channels.fetch(); // 获取所有频道
channel = channels.find((ch) => ch.type === 0 && ch.id === '1111638079103574159'); // 0代表文本频道
// 更直接的方式:
// channel = await guild.channels.fetch('1111638079103574159');
} catch (error) {
console.error(`Error fetching channels for guild ${targetGuildId} or finding channel 1111638079103574159:`, error);
// 如果获取频道失败,则无需继续
return;
}
if (channel) {
try {
const response = await axios.get('http://localhost:5000/prompt-news');
const newsData = response.data.map((promptNewsItem) => `${promptNewsItem.title}\n${url}${promptNewsItem.link}`);
newsData.forEach((data) => {
// 对于定时发送的非回复消息,使用 channel.send() 是正确的
channel.send(`Breaking Automatic News:\n\n${data}`);
});
} catch (error) {
console.error('An error occurred while fetching or sending the news highlights:', error);
// 在 Discord 频道中发送错误消息
if (channel) { // 再次检查 channel 是否存在,以防万一
channel.send('An error occurred while fetching the news highlights.');
}
}
} else {
console.error(`Could not find the channel with ID '1111638079103574159' in guild ${targetGuildId}.`);
}
} else {
console.error(`Could not find the guild with ID '${targetGuildId}'.`);
}
} else {
console.log("TargetGuildID is not set. Automatic news updates are not active.");
}
};代码改进点说明:
通过上述优化,您的 Discord 机器人将能够稳定可靠地执行定时任务,自动发布新闻或其他更新,为用户提供无缝的体验。
以上就是Discord.js 机器人定时发送消息:解决缓存与异步获取问题的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号