Discord.js V14按钮15分钟后停止更新,如何绕过超时限制?
解决Discord.js V14按钮超时后无法更新时间的问题
核心逻辑
Discord的SlashCommand交互令牌15分钟后就会过期,没法再用它编辑最初的回复。要实现永久更新,得换个不受这个限制的方式——用webhook或者直接用bot身份发送的普通消息来管理内容,这俩都没有15分钟的编辑限制。
具体实现方法
方法一:用Webhook管理消息(推荐)
Webhook不受15分钟编辑限制,只要bot有频道的Manage Webhooks权限,就能一直更新消息。
步骤如下:
- 触发命令时,先在目标频道创建一个临时webhook(也可以提前手动建好在频道里,直接用它的ID和token)。
- 通过这个webhook发送带时区按钮的消息,同时把webhook的ID、token和消息ID存起来(PM2重启会丢内存数据,最好存在数据库里,比如SQLite或者MongoDB)。
- 用
setInterval定时通过webhook编辑消息,更新按钮标签。
示例代码:
const { ButtonBuilder, ActionRowBuilder, WebhookClient, SlashCommandBuilder } = require('discord.js'); const { DateTime } = require('luxon'); module.exports = { data: new SlashCommandBuilder() .setName('timezones') .setDescription('显示各时区实时时间'), async execute(interaction) { // 创建临时webhook const webhook = await interaction.channel.createWebhook({ name: '时区更新bot', avatar: interaction.user.displayAvatarURL(), }); // 封装生成按钮的函数 const getTimeButtons = () => { return new ActionRowBuilder() .addComponents( new ButtonBuilder() .setCustomId('utc') .setLabel(`UTC: ${DateTime.utc().toFormat('HH:mm:ss')}`) .setStyle('Primary'), new ButtonBuilder() .setCustomId('beijing') .setLabel(`北京: ${DateTime.now().setZone('Asia/Shanghai').toFormat('HH:mm:ss')}`) .setStyle('Success'), new ButtonBuilder() .setCustomId('newyork') .setLabel(`纽约: ${DateTime.now().setZone('America/New_York').toFormat('HH:mm:ss')}`) .setStyle('Danger') ); }; // 通过webhook发送消息 const sentMsg = await webhook.send({ content: '实时时区时间:', components: [getTimeButtons()], }); // 存webhook和消息信息到数据库(示例用全局变量,生产环境换数据库) global.timezoneTasks = global.timezoneTasks || []; global.timezoneTasks.push({ webhookId: webhook.id, webhookToken: webhook.token, msgId: sentMsg.id, }); // 给用户发个悄悄通知 await interaction.reply({ content: '实时时区面板已创建!', ephemeral: true }); // 启动30秒更新定时器 setInterval(async () => { const webhookClient = new WebhookClient({ id: webhook.id, token: webhook.token }); try { await webhookClient.editMessage(sentMsg.id, { components: [getTimeButtons()], }); } catch (err) { console.error('更新按钮失败:', err); // 可以在这里加个逻辑:如果webhook失效,就清理这个定时器 } }, 30000); }, };
方法二:直接发送普通频道消息
如果不想搞webhook,也可以直接用bot的身份在频道发普通消息(不是通过交互回复),然后用bot的token去编辑这条消息——bot自己发的消息,只要有Manage Messages权限,就能永久编辑。
示例代码片段:
// 在命令执行里发送普通消息 const sentMsg = await interaction.channel.send({ content: '实时时区时间:', components: [getTimeButtons()], }); // 定时更新消息里的按钮 setInterval(async () => { await sentMsg.edit({ components: [getTimeButtons()], }); }, 30000); // 给用户反馈 await interaction.reply({ content: '实时时区面板已创建!', ephemeral: true });
这个方法更简单,但要注意:如果bot被踢出服务器,或者消息被删除,更新就会停止。
内容的提问来源于stack exchange,提问作者Jon LeForge
相关产品推荐
相关产品推荐

