基于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
相关产品推荐
相关产品推荐

