Discord.py封禁命令报MemberNotFound及discord.User角色校验问题
问题原因
你使用discord.Member作为命令参数转换器时,Discord.py只会从当前服务器的成员列表中匹配目标用户,不在服务器的用户无法被解析为Member对象,因此会抛出MemberNotFound报错。
修复方案
1. 支持封禁不在服务器的用户
将参数类型替换为discord.User,该转换器可以匹配全局Discord用户,不受当前服务器成员列表限制,示例代码如下:
import discord from discord.ext import commands @commands.command() async def ban(ctx, user: discord.User = None, *, reason=None): if not user: await ctx.send("请指定需要封禁的用户") return # guild.ban 支持传入User对象或用户ID,不受用户是否在服务器限制 await ctx.guild.ban(user, reason=reason) await ctx.send(f"已成功封禁用户 {user.name}")
2. 判断目标用户是否持有指定角色
discord.User是全局用户对象,不包含任何服务器的角色信息,只有属于当前服务器的discord.Member对象才有角色属性,因此判断逻辑如下:
- 先尝试将User对象转换为当前服务器的Member对象
- 转换失败代表用户不在服务器,默认不持有当前服务器的任何角色
- 转换成功后遍历角色列表判断是否持有目标角色
示例逻辑代码:
# 替换为你需要校验的目标角色ID PROTECTED_ROLE_ID = 123456789012345678 # 在ban函数内加入角色校验逻辑 try: # 优先从缓存取成员,不在缓存则请求接口获取 member = ctx.guild.get_member(user.id) or await ctx.guild.fetch_member(user.id) except discord.NotFound: # 用户不在服务器,无当前服务器角色,跳过校验 has_protected_role = False else: # 检查是否持有目标角色 has_protected_role = any(role.id == PROTECTED_ROLE_ID for role in member.roles) if has_protected_role: await ctx.send("该用户持有受保护角色,无法封禁") return # 校验通过后执行封禁 await ctx.guild.ban(user, reason=reason) await ctx.send(f"已成功封禁用户 {user.name}")
可选优化:支持纯数字ID输入
如果需要支持用户直接输入纯数字ID作为参数,可以手动添加ID转换逻辑,避免转换器识别失败:
@commands.command() async def ban(ctx, user_input: str = None, *, reason=None): if not user_input: await ctx.send("请指定需要封禁的用户") return user = None # 先尝试用默认User转换器解析 try: user = await commands.UserConverter().convert(ctx, user_input) except commands.UserNotFound: # 解析失败则尝试转换为纯数字ID拉取用户 try: user_id = int(user_input) user = await ctx.bot.fetch_user(user_id) except (ValueError, discord.NotFound): await ctx.send("无效的用户ID或@提及") return # 后续角色校验、封禁逻辑和上面一致
内容的提问来源于stack exchange,提问作者Wayne
相关产品推荐
相关产品推荐

