You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 03:11:52