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

基于Node/Discord.js开发自动移除Threads成员的机器人报错求助

Discord线程成员自动移除机器人报错解决建议

我用Node.js开发了一款Discord机器人,功能是自动移除那些失去对应父频道或分类VIEW_CHANNEL权限的Discord Threads成员。机器人能成功连接并上线,但运行时抛出错误,相关代码和错误信息如下:

import { Client, GatewayIntentBits, Partials } from 'discord.js';
const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildMembers,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.MessageContent,
    GatewayIntentBits.GuildScheduledEvents
  ],
  partials: [Partials.Message, Partials.Channel, Partials.Reaction],
});

const TOKEN = '**HIDDEN**';

client.once('ready', async () => {
  console.log(`Logged in as ${client.user.tag}!`);
  // Check access for all existing threads
  try {
    await checkAllThreads();
  } catch (error) {
    console.error('Error checking all threads:', error);
  }
});

async function checkMemberAccess(thread) {
  try {
    const members = await thread.members.fetch();
    const channel = thread.parent;

    members.forEach(async member => {
      const guildMember = await thread.guild.members.fetch(member.id);
      const hasAccessRole = guildMember.roles.cache.some(role => {
        return channel.permissionsFor(role).has('VIEW_CHANNEL');
      });

      if (!hasAccessRole) {
        await thread.members.remove(member.id);
        console.log(`Removed ${member.user.tag} from thread ${thread.name}`);
      }
    });
  } catch (error) {
    console.error('Error checking thread members:', error);
  }
}

async function checkAllThreads() {
  client.guilds.cache.forEach(async guild => {
    try {
      const threads = await guild.threads.fetch();
      threads.forEach(async thread => {
        await checkMemberAccess(thread);
      });
    } catch (error) {
      console.error(`Error checking threads for guild ${guild.name}:`, error);
    }
  });
}

client.on('threadCreate', thread => {
  // Check access when a new thread is created
  checkMemberAccess(thread);
});

client.login(TOKEN);

运行时抛出的错误:

Logged in as thread#8061!
Error checking threads for guild T1MAT0's server: TypeError: Cannot read properties of undefined (reading 'fetch')
    at file:///home/runner/threadbot/index.js:49:43
    at _Collection.forEach (<anonymous>)
    at checkAllThreads (file:///home/runner/threadbot/index.js:47:23)
    at Client.<anonymous> (file:///home/runner/threadbot/index.js:19:11)
    at Object.onceWrapper (node:events:633:26)
    at Client.emit (node:events:518:28)
    at WebSocketManager.triggerClientReady (/home/runner/threadbot/node_modules/discord.js/src/client/websocket/WebSocketManager.js:388:17)
    at WebSocketManager.checkShardsReady (/home/runner/threadbot/node_modules/discord.js/src/client/websocket/WebSocketManager.js:371:10)
    at WebSocketShard.<anonymous> (/home/runner/threadbot/node_modules/discord.js/src/client/websocket/WebSocketManager.js:201:16)
    at WebSocketShard.emit (node:events:518:28)

解决建议

1. 修复线程获取逻辑

报错核心是guild.threads为undefined,这是因为discord.js v14中没有这个直接属性,需要使用官方提供的方法获取线程:

修改checkAllThreads函数,分别获取活跃线程和归档线程(如果需要处理归档线程的话):

async function checkAllThreads() {
  for (const guild of client.guilds.cache.values()) {
    try {
      // 获取活跃线程
      const activeThreads = await guild.fetchActiveThreads();
      for (const thread of activeThreads.threads.values()) {
        await checkMemberAccess(thread);
      }

      // 获取公开归档线程,如需私有归档可调用fetchArchivedThreads({ type: 'private' })
      const publicArchivedThreads = await guild.fetchArchivedThreads();
      for (const thread of publicArchivedThreads.threads.values()) {
        await checkMemberAccess(thread);
      }
    } catch (error) {
      console.error(`Error checking threads for guild ${guild.name}:`, error);
    }
  }
}

2. 修复checkMemberAccess函数的潜在问题

  • 增加thread.parent的判断,避免无父频道的线程导致后续报错
  • 使用for...of替代forEach处理异步操作,确保每个成员的移除操作按顺序完成
  • 直接检查成员的综合权限(角色+个人权限),比单独检查角色更准确

修改后的checkMemberAccess函数:

async function checkMemberAccess(thread) {
  try {
    const members = await thread.members.fetch();
    const channel = thread.parent;

    // 无父频道则跳过(比如论坛帖子线程)
    if (!channel) return;

    for (const member of members.values()) {
      const guildMember = await thread.guild.members.fetch(member.id);
      // 检查成员是否有父频道的VIEW_CHANNEL权限
      const hasAccess = channel.permissionsFor(guildMember).has('VIEW_CHANNEL');

      if (!hasAccess) {
        await thread.members.remove(member.id);
        console.log(`Removed ${member.user.tag} from thread ${thread.name}`);
      }
    }
  } catch (error) {
    console.error('Error checking thread members:', error);
  }
}

3. 确认机器人权限

确保机器人在服务器中拥有以下权限:

  • ManageThreads:用于移除线程成员
  • ViewChannel:用于查看父频道的权限设置
  • GuildMembers相关权限:用于获取服务器成员的角色和权限信息

内容的提问来源于stack exchange,提问作者TimM

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 18:22:03