Discord.py反应角色机器人报'NoneType'无'roles'属性错误如何解决
错误原因定位
报错AttributeError("'NoneType' object has no attribute 'roles'")指向member.roles调用,说明你通过utils.get(message.guild.members, id=payload.user_id)拿到的member对象是None。
这个问题是Discord.py版本迭代导致的,一年前你使用的大概率是v1.x版本,v2.x版本之后做了两个核心调整导致原有代码失效:
- 默认关闭服务器成员缓存,
message.guild.members只能拿到当前已缓存的少量成员,大部分用户查询都会返回None - 强制要求明确声明网关意图,成员相关的接口需要手动开启权限才能调用
修复步骤
- 开启开发者后台权限
进入Discord开发者平台对应Bot的管理页,找到「Privileged Gateway Intents」板块,开启Server Members Intent权限。 - 代码中添加意图声明
初始化Client的时候明确指定需要的意图,开启成员访问权限。 - 替换成员获取方式
不要用缓存查询的utils.get获取成员,改用直接请求API的fetch_member方法,避免缓存缺失导致返回None。 - 增加非空校验逻辑
拿到成员对象后先判断是否为None,避免后续调用属性报错。
修改后的完整代码
import discord from discord import utils import config # 声明需要的网关意图 intents = discord.Intents.default() intents.members = True # 开启成员访问意图 intents.guilds = True intents.message_content = True # 可根据实际需求调整 class MyClient(discord.Client): async def on_ready(self): print('Logged on as {0}!'.format(self.user)) async def on_raw_reaction_add(self, payload): # 过滤机器人自身的反应 if payload.user_id == self.user.id: return if payload.message_id == config.POST_ID: channel = self.get_channel(payload.channel_id) message = await channel.fetch_message(payload.message_id) # 替换为API请求获取成员,替代缓存查询 try: member = await message.guild.fetch_member(payload.user_id) except discord.NotFound: # 成员不存在直接返回 return # 非空判断 if not member: return try: emoji = str(payload.emoji) role = utils.get(message.guild.roles, id=config.ROLES[emoji]) if not role: return if(len([i for i in member.roles if i.id not in config.EXCROLES]) <= config.MAX_ROLES_PER_USER): await member.add_roles(role) print('[SUCCESS] User {0.display_name} has been granted with role {1.name}'.format(member, role)) else: await message.remove_reaction(payload.emoji, member) print('[ERROR] Too many roles for user {0.display_name}'.format(member)) except KeyError as e: print('[ERROR] KeyError, no role found for ' + emoji) except Exception as e: print(repr(e)) async def on_raw_reaction_remove(self, payload): # 过滤机器人自身的反应 if payload.user_id == self.user.id: return channel = self.get_channel(payload.channel_id) message = await channel.fetch_message(payload.message_id) # 替换为API请求获取成员 try: member = await message.guild.fetch_member(payload.user_id) except discord.NotFound: return if not member: return try: emoji = str(payload.emoji) role = utils.get(message.guild.roles, id=config.ROLES[emoji]) if not role: return await member.remove_roles(role) print('[SUCCESS] Role {1.name} has been remove for user {0.display_name}'.format(member, role)) except KeyError as e: print('[ERROR] KeyError, no role found for ' + emoji) except Exception as e: print(repr(e)) # 初始化时传入意图参数 client = MyClient(intents=intents) client.run(config.TOKEN)
内容的提问来源于stack exchange,提问作者Adrian Makridenko
相关产品推荐
相关产品推荐

