Discord.js插件开发问题:如何移除多上传中的不合规附件?
问题分析与解决方案
核心问题
Discord.js 中,已发送消息的附件集合是只读的——你无法通过 message.attachments.delete() 移除单个不合规附件。消息一旦发送,附件就与消息绑定,无法拆分修改,这是你当前代码无效的根本原因。
另外原代码还有两个逻辑问题:
- 使用
forEach(async ...)会导致异步逻辑混乱,循环内的await不会按顺序执行,后续代码可能在异步操作完成前就触发 - 重复执行删除消息的逻辑,且前面的删除附件操作本身就不生效
可行解决方案
针对你的需求,有两种可选方案:
方案1:存在不合规附件则删除整条消息
适合要求严格的场景,只要有不合规文件就直接移除整条消息:
- 遍历所有附件,标记不合规项
- 若存在不合规附件,删除原消息并发送警告
方案2:保留合规附件,重新发送后删除原消息
如果需要保留合规内容,可提取合规附件重新发送,再删除原消息:
- 分离合规与不合规附件
- 发送警告告知用户
- 若有合规附件,重新发送到频道
- 删除原消息
修正后的代码(方案2示例)
/* @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ * | [ Image / Link Checker ] | * @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ */ const allowedExtensions = ['png', 'jpg', 'jpeg', 'gif', 'mp4']; const util = require('util'); // 将数据库查询转换为Promise形式(避免回调嵌套) const dbQuery = util.promisify(db.query.bind(db)); try { // 数据库查询 const [res] = await dbQuery( 'SELECT imageChannel, warnChannel FROM config WHERE server = ?', [message.guild.id] ); const warnChannel = res[0]['warnChannel']; const imageChannel = [res[0]['imageChannel']]; if (imageChannel.includes(message.channel.id)) { const attachments = message.attachments; if (attachments.size > 0) { const validAttachments = []; const invalidAttachments = []; // 用for...of遍历,避免异步forEach的顺序问题 for (const attachment of attachments.values()) { // 提取文件扩展名(兼容无扩展名的情况) const fileParts = attachment.name.toLowerCase().split('.'); const fileExtension = fileParts.length > 1 ? fileParts.pop() : ''; if (allowedExtensions.includes(fileExtension)) { validAttachments.push(attachment); } else { invalidAttachments.push(attachment); } } if (invalidAttachments.length > 0) { // 发送警告消息 const warnChannelObj = message.guild.channels.cache.get(warnChannel); if (warnChannelObj) { warnChannelObj.send(`${message.author}, 你上传了不符合要求的文件,仅支持图片(png/jpg/jpeg/gif)和视频(mp4)格式。`); } // 重新发送合规附件 if (validAttachments.length > 0) { await message.channel.send({ content: `${message.author} 上传的合规文件:`, files: validAttachments.map(att => ({ attachment: att.url, name: att.name })) }); } // 删除原消息 await message.delete(); console.log(`删除包含不合规附件的消息,原作者:${message.author.tag}`); } } } } catch (err) { console.error('数据库查询错误:', err); }
关键优化点
- 用
for...of替代forEach(async ...),确保异步操作按顺序执行 - 简化文件扩展名提取逻辑,兼容无扩展名的异常情况
- 将数据库查询改为Promise形式,避免回调地狱
- 通过「重新发送合规附件 + 删除原消息」的方式实现需求,绕开Discord无法修改已发送消息附件的限制
内容的提问来源于stack exchange,提问作者oscak41
相关产品推荐
相关产品推荐

