Discord.py 如何为临时语音频道实现创建者专属的锁定解锁功能
实现方案
首先我们用内存字典存储临时频道和创建者的映射关系,查询效率为O(1),完全可以支撑大量临时频道的并发操作,不需要额外接入数据库。
1. 新增存储结构并修改频道创建/删除逻辑
首先在代码全局位置定义存储字典:
# key为临时语音频道ID,value为创建者用户ID temp_channel_owners = {}
修改on_voice_state_update函数的对应逻辑:
async def on_voice_state_update(member, before, after): person_freq=['1', '2', '3'] person = member.name if member.bot: return if str(after.channel) == "+ NEW": if str(after) != str(before): guild = member.guild act_voice_channels = (c.name for c in guild.voice_channels) for freq in person_freq: if freq not in act_voice_channels: await after.channel.clone(name=freq) channel = discord.utils.get(guild.voice_channels, name=freq) # 给创建者授予频道本地管理权限 await channel.set_permissions(member, manage_channels=True, connect=True, speak=True) # 记录频道与创建者的对应关系 temp_channel_owners[channel.id] = member.id await member.move_to(channel) return # 临时频道无人时删除逻辑 if before.channel and len(before.channel.members) == 0 and before.channel.id in temp_channel_owners: # 先清除存储的映射关系 del temp_channel_owners[before.channel.id] await before.channel.delete()
2. 重写lock/unlock命令
去掉原有命令的全局管理员校验装饰器,改为自定义校验:只有临时频道的创建者、服务器全局管理员可以执行操作,默认操作用户当前加入的临时语音频道。
# lock命令 @client.command(pass_context=True) async def lock(ctx): # 校验用户是否加入语音频道 if not ctx.author.voice: await ctx.send("请先加入你创建的临时语音频道") return channel = ctx.author.voice.channel # 校验是否为临时频道 if channel.id not in temp_channel_owners: await ctx.send("当前频道不是可操作的临时语音频道") return # 校验权限:要么是创建者,要么是服务器全局管理员 is_owner = temp_channel_owners[channel.id] == ctx.author.id is_admin = ctx.author.guild_permissions.administrator if not is_owner and not is_admin: await ctx.send("你没有权限操作该频道") return # 执行lock:禁止所有人加入,管理员和创建者因有单独权限不受影响 await channel.set_permissions(ctx.guild.default_role, connect=False) await ctx.send("频道已锁定") # unlock命令 @client.command(pass_context=True) async def unlock(ctx): if not ctx.author.voice: await ctx.send("请先加入你创建的临时语音频道") return channel = ctx.author.voice.channel if channel.id not in temp_channel_owners: await ctx.send("当前频道不是可操作的临时语音频道") return is_owner = temp_channel_owners[channel.id] == ctx.author.id is_admin = ctx.author.guild_permissions.administrator if not is_owner and not is_admin: await ctx.send("你没有权限操作该频道") return # 执行unlock:恢复所有人的加入权限 await channel.set_permissions(ctx.guild.default_role, connect=True) await ctx.send("频道已解锁")
可选优化
如果担心机器人重启后内存字典丢失导致已存在的临时频道无法操作,可以把temp_channel_owners字典持久化存储到本地json文件,启动时加载、更新时同步写入文件即可。
内容的提问来源于stack exchange,提问作者Les_Grosman
相关产品推荐
相关产品推荐

