为何调用MessageManager.fetch()仅获取50条Discord频道消息?
Discord机器人/purge命令批量获取消息问题解决
问题描述
调试Discord机器人的/purge命令时,发现channel.messages.fetch()仅返回最近50条消息,无法获取频道全部消息。虽然知道limit参数但单次上限只有100,想确认这是API有意设计吗?该如何解决?
原代码:
async purgeDelete( channel: TextChannel, amount: number | undefined, target: GuildMember | undefined, keyword: string | undefined ): Promise<number> { // Most confused about this line: Am I doing the right thing? const messages = await channel.messages.fetch(); const twoWeeksAgo = new Date(); twoWeeksAgo.setDate(twoWeeksAgo.getDate() - 14); const purgelist = messages.filter(message => ( (!target || message.author.id === target.id) && (!keyword || message.content.includes(keyword)) && this.resultMessage?.id !== message.id && message.createdAt > twoWeeksAgo )); let purgeAmount: number; if (amount === undefined) { purgeAmount = purgelist.size; } else { console.log(purgelist.size, messages.size); purgeAmount = Math.min(amount, purgelist.size); } const slicedPurgelist = purgelist.first(purgeAmount); const partitionedPurgelist = []; for (let i = 0; i < slicedPurgelist.length; i += 100) { partitionedPurgelist.push(slicedPurgelist.slice(i, i + 100)); } await Promise.all(partitionedPurgelist.map(messages => channel.bulkDelete(messages))); return purgeAmount; }
问题原因
是的,这是Discord API的有意设计:channel.messages.fetch()不带参数时,默认只返回最近50条消息;即使指定limit参数,单次调用最多也只能获取100条消息,这是API的单次请求上限。
解决方案
要获取频道全部消息,必须通过分页循环的方式,每次请求传入before参数(用上一批消息中最早的那条ID),直到没有新消息返回为止。
修改后的完整代码:
async purgeDelete( channel: TextChannel, amount: number | undefined, target: GuildMember | undefined, keyword: string | undefined ): Promise<number> { let allMessages = new Collection<string, Message>(); let lastMessageId: string | undefined; // 循环分页拉取所有历史消息 while (true) { const fetchedMessages = await channel.messages.fetch({ limit: 100, // 每次拉满API允许的最大数量 ...(lastMessageId && { before: lastMessageId }) // 基于上一批的最后一条ID,拉更早的消息 }); if (fetchedMessages.size === 0) break; // 没有更多消息就终止循环 allMessages = allMessages.concat(fetchedMessages); lastMessageId = fetchedMessages.last()?.id; // 更新最后一条消息ID,用于下一次分页 } const twoWeeksAgo = new Date(); twoWeeksAgo.setDate(twoWeeksAgo.getDate() - 14); const purgelist = allMessages.filter(message => ( (!target || message.author.id === target.id) && (!keyword || message.content.includes(keyword)) && this.resultMessage?.id !== message.id && message.createdAt > twoWeeksAgo )); let purgeAmount: number; if (amount === undefined) { purgeAmount = purgelist.size; } else { console.log(purgelist.size, allMessages.size); purgeAmount = Math.min(amount, purgelist.size); } const slicedPurgelist = purgelist.first(purgeAmount); const partitionedPurgelist = []; for (let i = 0; i < slicedPurgelist.length; i += 100) { partitionedPurgelist.push(slicedPurgelist.slice(i, i + 100)); } await Promise.all(partitionedPurgelist.map(messages => channel.bulkDelete(messages))); return purgeAmount; }
补充说明
- Discord API不支持删除超过14天的消息,你的代码中已经通过
message.createdAt > twoWeeksAgo做了过滤,这部分逻辑没问题。 - 批量删除时,
bulkDelete单次最多处理100条消息,你原代码中的分片逻辑是正确的,无需修改。 - 分页拉取消息时,注意不要过于频繁请求,Discord有API速率限制,不过循环拉取100条/次的频率一般不会触发限制。
内容的提问来源于stack exchange,提问作者Ramen Dev
相关产品推荐
相关产品推荐

