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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 14:38:11