如何为discord.js音乐bot的队列embed功能实现分页效果
注意:如果你使用的是discord.js v13及以上版本,请确保client初始化时已开启
GUILD_MESSAGE_COMPONENTS意图,否则按钮交互无法正常触发。
实现步骤
1. 拆分队列生成分页Embed
我们将待播放队列按每页9条拆分,每一页顶部固定保留当前播放歌曲信息,避免翻页后看不到正在播放的内容。
2. 添加分页交互按钮
添加「上一页」「下一页」两个按钮,绑定自定义ID用于识别点击事件。
3. 配置交互收集器
仅允许触发队列命令的用户操作按钮,超时后自动禁用按钮防止无效操作。
完整可运行代码
const Discord = require('discord.js'); module.exports = { name: "queue", aliases: ['q'], description: "查看当前播放队列", run: async (client, message, args) => { const queue = client.distube.getQueue(message) // 队列为空的情况 if (!queue) return message.channel.send(new Discord.MessageEmbed() .setTitle(`**${message.guild.name}的播放队列**`) .setDescription(`__正在播放:__\n当前无播放内容`) .setColor('RANDOM') ); // 每页展示的待播放歌曲数量 const songsPerPage = 9; // 待播放队列(排除正在播放的第0首) const upNextSongs = queue.songs.slice(1); // 计算总页数 const totalPages = Math.ceil(upNextSongs.length / songsPerPage) || 1; // 当前页默认设为第1页 let currentPage = 1; // 生成分页Embed的方法 const generateQueueEmbed = (page) => { // 计算当前页展示的歌曲起始和结束索引 const start = (page - 1) * songsPerPage; const end = start + songsPerPage; const currentPageSongs = upNextSongs.slice(start, end); // 拼接内容,顶部固定展示正在播放的歌曲 let content = `__正在播放:__\n [${queue.songs[0].name}](${queue.songs[0].url})\n \`${queue.songs[0].formattedDuration} 点歌人: ${queue.songs[0].user.tag}\``; // 有待播放歌曲的情况拼接列表 if (currentPageSongs.length > 0) { content += `\n__即将播放:__\n ${currentPageSongs.map((song, index) => `\`${start + index + 1}.\` [${song.name}](${song.url})\n \`${song.formattedDuration} 点歌人: ${song.user.tag}\``).join("\n")}`; } else { content += `\n__即将播放:__\n暂无更多待播放歌曲`; } // 返回当前页Embed return new Discord.MessageEmbed() .setTitle(`**${message.guild.name}的播放队列**`) .setDescription(content) .setColor('RANDOM') .setFooter(`第 ${page} / ${totalPages} 页 | 共 ${queue.songs.length} 首歌 | 总时长 ${queue.formattedDuration}`) } // 生成按钮组件 const row = new Discord.MessageActionRow() .addComponents( new Discord.MessageButton() .setCustomId('prev_page') .setLabel('上一页') .setStyle('PRIMARY'), new Discord.MessageButton() .setCustomId('next_page') .setLabel('下一页') .setStyle('PRIMARY') ); // 发送初始队列Embed+按钮 const queueMessage = await message.channel.send({ embeds: [generateQueueEmbed(currentPage)], components: totalPages > 1 ? [row] : [] // 只有1页的话不展示按钮 }); // 只有1页不需要做后续交互处理 if (totalPages <= 1) return; // 创建按钮交互收集器,仅响应命令触发者,超时时间设为60秒 const collector = queueMessage.createMessageComponentCollector({ filter: i => i.user.id === message.author.id, time: 60000 }); // 监听按钮点击 collector.on('collect', async i => { // 根据按钮ID切换页面 if (i.customId === 'prev_page') { currentPage = currentPage === 1 ? totalPages : currentPage - 1; } else if (i.customId === 'next_page') { currentPage = currentPage === totalPages ? 1 : currentPage + 1; } // 更新Embed await i.update({ embeds: [generateQueueEmbed(currentPage)] }); }); // 收集器超时后禁用按钮 collector.on('end', () => { const disabledRow = new Discord.MessageActionRow() .addComponents( new Discord.MessageButton() .setCustomId('prev_page') .setLabel('上一页') .setStyle('PRIMARY') .setDisabled(true), new Discord.MessageButton() .setCustomId('next_page') .setLabel('下一页') .setStyle('PRIMARY') .setDisabled(true) ); queueMessage.edit({ components: [disabledRow] }).catch(() => {}); }); } }
可自定义配置项
- 修改
songsPerPage的数值可以调整每页展示的待播放歌曲数量 - 修改
time参数可以调整按钮的有效操作时长,单位为毫秒 - 可自行添加跳转到首页/尾页、跳转到指定页的按钮扩展功能
内容的提问来源于stack exchange,提问作者B1ackGX
相关产品推荐
相关产品推荐

