discord.py on_message事件角色校验失效 实现管理角色删链豁免
核心问题定位
你遇到的权限判断失效、高权限用户发的邀请链接照样被删,本质是两个代码层面的硬伤:
- 权限判断的逻辑运算符完全写反:原代码用
or串接了四个“角色不在用户列表”的判断,等价于「只要用户缺四个豁免角色里的任意一个,就触发删除」,哪怕用户已经拥有Admin这类最高权限角色,只要没凑齐所有四个豁免角色,判断就会成立,消息照样被删。 - 初始的链接匹配逻辑永远不生效:原代码写
if serverLink in message_content,其中serverLink是存了多个域名的列表对象,直接和字符串做in判断永远返回假,根本进不到后续的权限校验分支。
修正后可用的实现代码
直接替换原有Cog里的逻辑即可,优化了集合判断的效率,避免反复调用discord.utils.get拉取角色对象:
import discord from discord.ext import commands # 需拦截的邀请域名列表 server_link = ["discord.gg", "disboard.com"] # 享有豁免权限、不被拦截链接的角色名称白名单 EXEMPT_ROLES = ["Admin", "Moderator", "Realm OP", "Bots"] class InviteMonitorCog(commands.Cog): def __init__(self, bot): self.bot = bot @commands.Cog.listener() async def on_message(self, message): # 跳过机器人消息、跳过私聊场景的无意义校验 if message.author.bot or not message.guild: return # 判断消息是否包含需拦截的域名 hit_link = any(link in message.content for link in server_link) if not hit_link: return # 校验用户是否拥有任意一个白名单角色 user_role_names = {role.name for role in message.author.roles} has_exempt_role = not user_role_names.isdisjoint(EXEMPT_ROLES) # 有豁免权限直接跳过删除逻辑 if has_exempt_role: return # 无豁免权限、命中链接的消息直接删除 await message.delete()
关键优化点说明
- 权限判断改用集合交集逻辑:只要用户角色和白名单角色有任意重叠,就直接放行,不需要逐个判断每个角色是否存在,代码可读性和执行效率都更高。
- 补全了基础兜底:提前跳过机器人自身消息、私聊场景,避免不必要的API请求和权限报错。
- 去掉了冗余的
discord.utils.get角色拉取逻辑:直接从用户已经加载的角色列表里取名称做比对,减少无效的服务器请求。 - 修正了原代码的运算符错误:如果要按原来的逐角色判断写法,正确的触发删除的条件应该写为
if not (RealmOP in message.author.roles or Bots in message.author.roles or Moderator in message.author.roles or Admin in message.author.roles),也就是“用户一个豁免角色都没有的时候才执行删除”,和原代码的逻辑差了一层“非”的关系。
内容的提问来源于stack exchange,提问作者Saphire
相关产品推荐
相关产品推荐

