Discord.js仅删除指定频道图片附件及endsWith报错解决方案
功能实现需求
- 自动删除指定频道内发送的图片类附件
- 仅删除携带图片附件的消息,不得删除仅携带非图片类型附件的消息
- 运行环境:Node.js 16.13.2、npm 8.1.2
原有代码问题
- 初始判断逻辑仅用
message.attachments.size > 0判定附件存在,会无差别删除所有带附件的消息,不符合仅删图片附件的要求 - 参考社区帖子写的后缀判断逻辑运行报错,提示无法识别
.endsWith方法
原有错误代码片段:
async execute(message, client) { if (!message.guild || message.author.bot) return; if (message.channel.id === 'CHANNEL-ID' && message.attachments.size > 0) { message.delete() } }
报错原因
参考的筛选代码适配discord.js v12及更早版本,v13+版本中MessageAttachment对象存储文件名的属性从filename调整为name,调用attachment.filename时返回值为undefined,对非字符串类型的undefined调用字符串原型方法.endsWith()会直接抛出类型错误。
仅靠文件后缀判断图片类型可靠性极低,用户可通过修改文件后缀绕过检测,优先使用Discord返回的MIME类型做判断准确率更高。
修正后可运行代码
// 定义需要检测的目标频道ID const TARGET_CHANNEL_ID = '替换成你的实际频道ID'; // 图片类MIME类型前缀,所有image开头的类型均为图片 const IMAGE_MIME_PREFIX = 'image/'; async execute(message, client) { if (!message.guild || message.author.bot) return; // 非目标频道直接跳过 if (message.channel.id !== TARGET_CHANNEL_ID) return; // 无附件直接跳过 if (message.attachments.size === 0) return; // 检测是否存在图片类附件 const hasImageAttachment = message.attachments.some(attachment => { // 优先用MIME类型判断,兼容所有图片格式 if (attachment.contentType) { return attachment.contentType.startsWith(IMAGE_MIME_PREFIX); } // 兜底用文件名后缀判断,覆盖无contentType返回的场景 const fileName = attachment.name || ''; return ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp'] .some(ext => fileName.toLowerCase().endsWith(ext)); }); // 存在图片附件则删除消息,捕获权限不足等异常避免进程崩溃 if (hasImageAttachment) { message.delete() .catch(err => console.log(`删除图片消息失败: ${err.message}`)); } }
逻辑说明
- 受Discord平台接口限制,无法单独删除消息内的单个附件,只要消息中包含图片类附件就会删除整条消息,非图片附件和图片在同一条消息时会被连带删除
- 用
Collection.some()做存在性判断,只要匹配到一个图片附件就终止遍历,性能优于find()方法 - 优先通过
contentType判断文件类型,覆盖所有Discord可识别的图片格式,可识别改后缀的违规图片 - 增加文件名后缀判断做兜底,兼容极端场景下接口未返回contentType的情况
- 增加异常捕获,避免bot因权限不足、消息已被提前删除等场景抛出未捕获错误导致离线
内容的提问来源于stack exchange,提问作者Maxence
相关产品推荐
相关产品推荐

