Discord.js TypeError求助:无法读取undefined的'id'属性
问题分析与修复
错误根源
控制台抛出的TypeError: Cannot read properties of undefined (reading 'id'),是因为部分消息(比如系统通知、Webhook消息)没有author属性,直接访问msg.author.id会触发报错。另外你的代码当前遍历了服务器所有文本频道,但需求是只删除命令执行频道内的目标用户消息,逻辑不符合预期。
修复后的完整代码
const { SlashCommandBuilder } = require('@discordjs/builders'); const { EmbedBuilder, PermissionsBitField, ButtonBuilder, ActionRowBuilder, ButtonStyle, ChannelType, } = require('discord.js'); module.exports = { data: new SlashCommandBuilder() .setName('clearuser') .setDescription('删除指定用户在当前频道内的所有消息') .addUserOption((option) => option .setName('user') .setDescription('要删除消息的目标用户') .setRequired(true) ), async execute(interaction) { // 检查用户权限 if (!interaction.member.permissions.has(PermissionsBitField.Flags.ManageMessages)) { return await interaction.reply({ content: '你没有执行此命令的权限(需要管理消息权限)', ephemeral: true, }); } const targetUser = interaction.options.getUser('user'); if (!targetUser) { return await interaction.reply({ content: '请指定一个有效的用户', ephemeral: true, }); } // 限制仅在文本频道执行 if (interaction.channel.type !== ChannelType.GuildText) { return await interaction.reply({ content: '此命令仅能在文本频道使用', ephemeral: true, }); } let targetUserMessages = []; let lastMessageId; // 循环分页获取所有消息(单次fetch最多100条) do { const messages = await interaction.channel.messages.fetch({ limit: 100, ...(lastMessageId && { before: lastMessageId }) }); if (messages.size === 0) break; // 过滤目标用户消息,同时排除无author的消息 const filtered = messages.filter(msg => msg.author && msg.author.id === targetUser.id); targetUserMessages.push(...filtered.values()); lastMessageId = messages.last().id; } while (true); // 分批次删除:批量删14天内消息,单条删旧消息 const recentMessages = targetUserMessages.filter(msg => Date.now() - msg.createdTimestamp < 1209600000); // 14天毫秒数 const oldMessages = targetUserMessages.filter(msg => Date.now() - msg.createdTimestamp >= 1209600000); if (recentMessages.length > 0) { try { await interaction.channel.bulkDelete(recentMessages); } catch (error) { console.error('批量删除消息失败:', error.message); } } if (oldMessages.length > 0) { await Promise.all( oldMessages.map(async msg => { try { await msg.delete(); } catch (error) { console.error(`删除单条消息失败: ${error.message}`); } }) ); } // 回复操作结果 const embed = new EmbedBuilder() .setColor('DarkRed') .setDescription(`:white_check_mark: 已删除 ${targetUserMessages.length} 条来自 ${targetUser} 的消息`); const button = new ActionRowBuilder().addComponents( new ButtonBuilder() .setCustomId('clearuser_delete_reply') .setEmoji('🗑️') .setStyle(ButtonStyle.Danger) ); const replyMessage = await interaction.reply({ embeds: [embed], components: [button], fetchReply: true }); // 按钮交互处理 const collector = replyMessage.createMessageComponentCollector({ time: 60000 }); collector.on('collect', async (i) => { if (i.customId === 'clearuser_delete_reply') { if (!i.member.permissions.has(PermissionsBitField.Flags.ManageMessages)) { return await i.reply({ content: '你没有权限执行此操作', ephemeral: true }); } await interaction.deleteReply(); await i.deferUpdate(); } }); collector.on('end', () => { button.components[0].setDisabled(true); replyMessage.edit({ components: [button] }); }); }, };
核心修改说明
- 解决报错:过滤消息时增加
msg.author判断,避免访问不存在的id属性。 - 匹配需求:改为仅在命令执行的当前频道操作,而非遍历全服务器频道。
- 优化消息获取:通过循环分页获取所有消息,突破单次
fetch最多100条的限制。 - 高效删除:用
bulkDelete批量处理14天内的消息,单条删除超过14天的旧消息,提升效率。 - 完善交互:按钮收集器增加超时时间,权限检查时回复交互避免超时,超时后禁用按钮防止无效操作。
内容的提问来源于stack exchange,提问作者Hamza Farayi
相关产品推荐
相关产品推荐

