求助:基于Python disnake实现Discord自动语音频道机器人
基于disnake实现自动语音频道创建/销毁功能
需求说明
- 设置一个名为「Create voice chat」的触发语音频道,用户加入该频道时,机器人自动创建新的专属语音频道,并将用户移入新频道
- 当自动创建的语音频道内无成员时,自动销毁该频道
参考的JavaScript实现(来自autocode)
const lib = require('lib')({token: process.env.STDLIB_SECRET_TOKEN}); const event = context.params.event; const { guild_id, channel_id, user_id } = event // The 'central' voice channel users must join first const voiceChannelId = process.env.VOICE_CHANNEL_ID // The voice channel name to create for the user const voiceChannelName = `vc_${user_id}` // Create a new voice channel when the user joins the specifc voice channel const joinedChannel = channel_id === voiceChannelId if (joinedChannel) { const channel = await lib.discord.guilds['@0.1.0'].channels.create({ guild_id, name: voiceChannelName, type: 2, // vc }) await lib.discord.guilds['@0.1.0'].members.update({ guild_id, user_id, channel_id: channel.id, }); return } // Delete the user's voice channel when the user disconnects const leftChannel = !channel_id if (leftChannel) { const channels = await lib.discord.guilds['@0.1.0'].channels.list({ guild_id }); const channel = channels.find(c => c.name === voiceChannelName) if (channel) await lib.discord.channels['@0.2.0'].destroy({ channel_id: channel.id }); return }
自行编写的无法运行的Python代码
def _get_channel(self) -> disnake.abc.GuildChannel: return self.channel def __init__(self): self.auto_channel = 1030505142820282408 self.auto_channel = self.guild.get_channel(self.auto_channel) @bot.event async def on_voice_state_update(self, member = disnake.Member, before = disnake.VoiceState, after = disnake.VoiceState) -> None: if after.channel is not None and after.channel == auto_channel: ch = await self.auto_channel.category.create_voice_channel(name=member.display_name, overwrites={**self.auto_channel.category.overwrites, member: disnake.PermissionOverwrite(connect=True, move_members=True, manage_channels=True, manage_roles=True)}) try: await member.move_to(ch, reason='autochannel') except disnake.HTTPException: pass if before.channel is not None and before.channel.id != auto_channel and before.channel.category.id == auto_channel and len(before.channel.members) == 0: try: await before.channel.delete() except disnake.NotFound: pass
修正后的代码及说明
问题分析
原代码存在以下关键问题:
- 事件处理函数
on_voice_state_update定义错误:非Cog写法下不需要self参数;若用Cog则需用@commands.Cog.listener()装饰器而非@bot.event - 变量引用错误:
auto_channel未正确通过self引用,且初始化时self.guild未提前获取,导致无法拿到有效频道对象 - 判断条件错误:
before.channel.category.id == auto_channel应与auto_channel.category.id比较,而非直接和频道对象对比
修正后的代码(非Cog写法)
import disnake from disnake.ext import commands bot = commands.Bot(command_prefix="!", intents=disnake.Intents.all()) # 替换为你的触发频道ID TRIGGER_CHANNEL_ID = 1030505142820282408 @bot.event async def on_voice_state_update(member: disnake.Member, before: disnake.VoiceState, after: disnake.VoiceState): # 获取触发频道对象 trigger_channel = member.guild.get_channel(TRIGGER_CHANNEL_ID) if not trigger_channel: return # 情况1:用户加入触发频道,创建新语音频道并移动用户 if after.channel == trigger_channel: # 在触发频道的分类下创建新频道 new_channel = await trigger_channel.category.create_voice_channel( name=f"VC - {member.display_name}", # 继承分类权限,给用户额外管理权限 overwrites={ **trigger_channel.category.overwrites, member: disnake.PermissionOverwrite( connect=True, move_members=True, manage_channels=True ) } ) try: await member.move_to(new_channel, reason="自动创建专属语音频道") except disnake.HTTPException as e: print(f"移动用户失败: {e}") # 移动失败则清理已创建的频道 await new_channel.delete() # 情况2:用户离开频道,检查是否需要自动销毁 if before.channel and before.channel != trigger_channel: # 仅处理触发频道分类下的自动创建频道 if before.channel.category == trigger_channel.category: # 频道无成员时自动删除 if len(before.channel.members) == 0: try: await before.channel.delete(reason="频道无成员,自动销毁") except disnake.NotFound: pass bot.run("你的机器人Token")
代码逻辑说明
- 触发频道检测:用户加入指定的「Create voice chat」频道时,在同一分类下创建以用户昵称命名的新语音频道
- 用户移动:创建频道后立即将用户移入新频道,若移动失败则删除已创建的频道
- 自动销毁:用户离开频道时,检查该频道是否属于触发频道的分类且不是触发频道本身,若频道内无成员则自动删除
内容的提问来源于stack exchange,提问作者mxasd
相关产品推荐
相关产品推荐

