Discord.js 12.2.0中voiceStateUpdate异常,私人语音频道无法创建
解决Discord.js v12中私人语音频道创建功能失效的问题
看起来你遇到的问题完全是因为Discord.js v12对语音状态事件和相关API做了不少破坏性更新,原代码还停留在v11的写法上,所以导致事件触发后没有任何响应。我帮你一步步梳理问题并修正代码:
1. voiceStateUpdate事件参数的核心变化
在Discord.js v12中,voiceStateUpdate事件的参数不再是oldMember和newMember(GuildMember对象),而是oldState和newState(VoiceState对象)。这意味着你不能再直接从参数里获取成员的频道ID,而是要从VoiceState对象的属性里取。
比如原代码里的oldMember.voice.channelID在v12里应该写成oldState.channelId,newMember.voice.channelID改成newState.channelId。
2. 先让测试代码正常触发
你的测试代码用了v11的属性名,所以控制台不会输出"1",修正后应该是:
bot.on('voiceStateUpdate', (oldState, newState) => { const MainChannel = '724268049137401911'; // 只在用户刚进入指定频道时触发,避免静音/取消静音等状态切换重复触发 if (newState.channelId === MainChannel && oldState.channelId !== MainChannel) { console.log('用户进入了创建私人频道的房间'); } });
3. 完整修正私人频道创建代码
下面是修正后的完整代码,我标注了所有关键改动:
bot.on('voiceStateUpdate', async (oldState, newState) => { // 参数改为oldState、newState(VoiceState对象) const server = bot.guilds.cache.get('724268046998437918'); // 直接从VoiceState取频道对象,不用再通过ID查找 const member_oldchannel = oldState.channel; const member_newchannel = newState.channel; // 用户只是在同一频道切换状态(比如静音),直接返回 if (oldState.channelId === newState.channelId) return; const member = newState.member; // 从newState直接获取成员,无需再查ID // 处理用户进入创建频道的逻辑 if (member_newchannel) { if (member_newchannel.name === '鱗・Создать приват') { const cat = server.channels.cache.get('724268048860577816'); if (!cat) { console.log('无法找到用于创建频道的分类。'); await member.send('`[AUTO] 您的房间未创建。错误:未找到分类。请将此消息发送给服务器技术管理员。`'); return; } // 防止用户快速切换频道导致逻辑异常 if (newState.channelId !== '724268049137401911') { console.log('用户退出了创建频道的房间,房间未创建'); await member.send('`[AUTO] 您退出了创建房间的频道。房间未创建。`'); return; } const rol = server.roles.cache.find(r => r.name === 'Jr. Discord Master'); // 增加角色不存在的容错处理 if (!rol) { console.log('无法找到Jr. Discord Master角色'); await member.send('`[AUTO] 您的房间未创建。错误:未找到指定角色。请联系管理员。`'); return; } const serverId = server.id; // 补全原代码未定义的serverid变量 // v12创建频道的方法是guild.channels.create,语音频道type为GUILD_VOICE const privateChannel = await server.channels.create(` | ${member.user.username}`, { type: 'GUILD_VOICE', permissionOverwrites: [ { id: member.id, allow: ['VIEW_CHANNEL', 'CONNECT', 'SPEAK', 'MUTE_MEMBERS', 'MOVE_MEMBERS', 'USE_VAD'], deny: ['CREATE_INSTANT_INVITE', 'MANAGE_ROLES', 'MANAGE_WEBHOOKS', 'DEAFEN_MEMBERS', 'MANAGE_CHANNELS'] }, { id: rol.id, allow: ['VIEW_CHANNEL', 'CONNECT', 'SPEAK', 'MUTE_MEMBERS', 'MOVE_MEMBERS', 'USE_VAD', 'MANAGE_CHANNELS'], deny: ['CREATE_INSTANT_INVITE', 'MANAGE_ROLES', 'MANAGE_WEBHOOKS', 'DEAFEN_MEMBERS'] }, { id: serverId, allow: ['VIEW_CHANNEL', 'CONNECT', 'SPEAK'], deny: ['MUTE_MEMBERS', 'MOVE_MEMBERS', 'USE_VAD', 'MANAGE_CHANNELS'] } ] }); // 设置频道分类,失败则清理频道并提示用户 await privateChannel.setParent(cat.id).catch(err => { console.log('设置频道分类失败:', err); privateChannel.delete(); member.send('`[AUTO] 房间创建失败,请重试。`'); }); // 设置用户上限 await privateChannel.setUserLimit(2); // 移动用户到新频道,失败则提示 await member.voice.setChannel(privateChannel).catch(err => { console.log('移动用户到新频道失败:', err); member.send('`[AUTO] 无法将您移动到新房间,请手动进入。`'); }); } } // 处理用户离开后自动删除空私人频道的逻辑 if (member_oldchannel) { if (member_oldchannel.name.startsWith(" |")) { // 检查频道是否为空,为空则删除 if (member_oldchannel.members.size === 0) { await member_oldchannel.delete().catch(err => console.log('删除频道失败:', err)); } } } });
关键改动点汇总
- 事件参数从
oldMember/newMember改为oldState/newState(VoiceState对象) - 属性名变更:
channelID→channelId,voice.channel→ 直接从VoiceState取channel - 创建频道的方法:
server.channel.create→server.channels.create - 语音频道类型:
'voice'→'GUILD_VOICE' - 权限常量更新:
MANAGE_ROLES_OR_PERMISSIONS→MANAGE_ROLES - 增加了角色不存在、频道设置失败等容错处理,避免代码崩溃
- 补全了原代码中未定义的
serverid变量
内容的提问来源于stack exchange,提问作者KaPToHblu_EHoT
相关产品推荐
相关产品推荐

