Discord.js v12中/op-stock命令消息过长,如何拆分发送?
解决Discord.js v12中/op-stock命令内容过长的消息拆分问题
原代码将所有服务库存信息合并到单个Embed字段中,当内容超出Discord的消息长度限制时会发送失败。以下是修改后的实现,通过拆分内容为多条消息解决该问题:
修改后的完整代码
const { SlashCommandBuilder } = require('@discordjs/builders'); const { MessageEmbed } = require('discord.js'); const fs = require('fs').promises; const config = require('../config.json'); module.exports = { data: new SlashCommandBuilder() .setName('op-stock') .setDescription('View op Gen stock'), async execute(interaction) { const opStock = await getStock(`${__dirname}/../op/`); if (opStock.length === 0) { // 无库存时直接回复 const emptyEmbed = new MessageEmbed() .setColor(config.color.default) .setTitle(`${interaction.guild.name} Service Stock`) .setDescription(`👋 Hello and welcome to **${interaction.guild.name}**!`) .addField('op Services', '暂无可用服务', true) .setFooter(config.footer) .setImage(config.banner); return interaction.reply({ embeds: [emptyEmbed] }); } // 获取服务信息数组(不直接拼接) const opStockInfoArray = await getServiceInfoArray(`${__dirname}/../op/`, opStock); // 拆分为多个符合长度限制的块 const chunks = splitIntoMessageChunks(opStockInfoArray); // 发送第一条消息 const firstEmbed = new MessageEmbed() .setColor(config.color.default) .setTitle(`${interaction.guild.name} Service Stock`) .setDescription(`👋 Hello and welcome to **${interaction.guild.name}**!`) .addField('op Services', chunks[0].join('\n'), true) .setFooter(`${config.footer} | 第1/${chunks.length}页`) .setImage(config.banner); await interaction.reply({ embeds: [firstEmbed] }); // 发送后续消息 for (let i = 1; i < chunks.length; i++) { const followEmbed = new MessageEmbed() .setColor(config.color.default) .setTitle(`${interaction.guild.name} Service Stock`) .addField('op Services', chunks[i].join('\n'), true) .setFooter(`${config.footer} | 第${i+1}/${chunks.length}页`) .setImage(config.banner); await interaction.followUp({ embeds: [followEmbed] }); } }, }; async function getStock(directory) { try { const files = await fs.readdir(directory); const stock = files.filter(file => file.endsWith('.txt')); return stock; } catch (err) { console.error('Unable to scan directory: ' + err); return []; } } // 修改为返回数组,而非拼接后的字符串 async function getServiceInfoArray(directory, stock) { const info = []; for (const service of stock) { const serviceContent = await fs.readFile(`${directory}/${service}`, 'utf-8'); const lines = serviceContent.split(/\r?\n/); info.push(`**${service.replace('.txt', '')}:** \`${lines.length}\``); } return info; } // 辅助函数:将数组拆分为多个子数组,每个子数组拼接后不超过Discord字段长度限制(1024字符) function splitIntoMessageChunks(arr) { const chunks = []; let currentChunk = []; let currentLength = 0; const maxLength = 1000; // 预留24字符余量,避免触发限制 for (const item of arr) { const itemLength = item.length + 1; // +1是换行符的长度 if (currentLength + itemLength > maxLength) { chunks.push(currentChunk); currentChunk = [item]; currentLength = itemLength; } else { currentChunk.push(item); currentLength += itemLength; } } if (currentChunk.length > 0) { chunks.push(currentChunk); } return chunks; }
关键修改说明
- 调整服务信息返回格式:将原
getServiceInfo改为getServiceInfoArray,返回单个服务信息的数组,而非直接拼接成大字符串,方便后续拆分。 - 新增内容拆分函数:
splitIntoMessageChunks会将数组拆分为多个子数组,确保每个子数组拼接后的内容长度不超过Discord Embed字段的限制(预留了余量避免触发限制)。 - 分批次发送消息:首条消息使用
interaction.reply发送,后续消息通过interaction.followUp发送,同时在页脚标注页码,方便用户查看进度。 - 空库存处理:新增无库存时的友好提示,避免发送空字段的Embed。
内容的提问来源于stack exchange,提问作者FlixerDev
相关产品推荐
相关产品推荐

