当Embed描述达4096字符限制时,如何实现警告日志分页?
解决Discord警告日志Embed字符超限的分页实现方案
我给警告斜杠命令加了日志功能,但遇到个问题:当Embed的描述内容达到4096字符上限时会直接报错,不符合预期。我希望内容超出限制时自动创建新Embed作为“第二页”,用已有的buttonPages分页函数实现页面导航,但不知道具体怎么入手。目标是做一个带分页按钮的功能性“警告日志”Embed,支持多页浏览。当前代码片段如下:
case "logs": { const buttonPages = require("../../functions/pagination"); const user = interaction.options.getUser("user"); const userWarnings = await warnSchema.find({ Guild: interaction.guild.id, User: user.id }); if (!userWarnings?.length) return interaction.reply({ content: `\`${user.tag}\` does not have any warnings.`, ephemeral: true }); const embedDescription = userWarnings.map((warn) => { const moderator = interaction.guild.members.cache.get(warn.Moderator); return [ `<:CL_Shield:937188831227183135> Warn ID: ${warn.id}`, `<:CL_ReplyContinued:909444370221137930> Moderator: ${moderator || "unknown"}`, `<:CL_ReplyContinued:909444370221137930> User: ${user}`, `<:CL_ReplyContinued:909444370221137930> Reason: \`${warn.Reason}\``, `<:CL_Reply:909436090413363252> Date: ${warn.Date}`, ].join("\n"); }).join("\n\n"); const embed = new EmbedBuilder() .setTitle(`${user.tag}'s warnings`) .setDescription(embedDescription) .setColor("#2f3136"); //const pages = [embed]; //buttonPages(interaction, pages); await interaction.reply({ embeds: [embed] }); }
实现方案
1. 拆分条目生成多页Embed
核心思路是逐个处理警告条目,动态构建Embed,当当前Embed的描述字符数接近4096限制时,新建Embed继续添加内容:
case "logs": { const buttonPages = require("../../functions/pagination"); const user = interaction.options.getUser("user"); const userWarnings = await warnSchema.find({ Guild: interaction.guild.id, User: user.id }); if (!userWarnings?.length) return interaction.reply({ content: `\`${user.tag}\` does not have any warnings.`, ephemeral: true }); // 初始化分页Embed数组 const pages = []; // 当前正在构建的Embed let currentEmbed = new EmbedBuilder() .setTitle(`${user.tag}'s warnings`) .setColor("#2f3136"); // 当前Embed的描述内容 let currentDescription = ""; for (const warn of userWarnings) { const moderator = interaction.guild.members.cache.get(warn.Moderator); // 单条警告的内容字符串 const warnEntry = [ `<:CL_Shield:937188831227183135> Warn ID: ${warn.id}`, `<:CL_ReplyContinued:909444370221137930> Moderator: ${moderator || "unknown"}`, `<:CL_ReplyContinued:909444370221137930> User: ${user}`, `<:CL_ReplyContinued:909444370221137930> Reason: \`${warn.Reason}\``, `<:CL_Reply:909436090413363252> Date: ${warn.Date}`, ].join("\n"); // 计算添加当前条目后的总字符数(加上分隔符\n\n) const newLength = currentDescription.length + warnEntry.length + (currentDescription ? 2 : 0); // 如果超过4096限制,就把当前Embed加入数组,新建一个Embed if (newLength > 4096) { currentEmbed.setDescription(currentDescription); pages.push(currentEmbed); // 初始化新的Embed currentEmbed = new EmbedBuilder() .setTitle(`${user.tag}'s warnings`) .setColor("#2f3136"); currentDescription = warnEntry; } else { // 否则继续累加内容,非第一个条目要加分隔符 currentDescription += currentDescription ? `\n\n${warnEntry}` : warnEntry; } } // 把最后一个未完成的Embed加入数组 currentEmbed.setDescription(currentDescription); // 可选:添加页码页脚 pages.forEach((embed, index) => { embed.setFooter({ text: `Page ${index + 1}/${pages.length + 1}` }); }); pages.push(currentEmbed); // 调用分页函数 buttonPages(interaction, pages); }
2. 关键细节说明
- 字符数判断:每次添加条目前计算总长度,预留了分隔符
\n\n的字符数,避免刚好超限。 - 样式统一:所有分页Embed使用相同的标题和颜色,保证用户体验一致。
- 页码标注:通过页脚显示当前页码和总页数,让用户清楚浏览进度。
- 收尾处理:循环结束后要把最后一个Embed加入数组,避免遗漏内容。
内容的提问来源于stack exchange,提问作者Roman Beard
相关产品推荐
相关产品推荐

