Python实现Discord移除用户反应时自动移除角色报错排查
解决Discord机器人移除反应时的角色删除问题
报错原因分析
你遇到的AttributeError: 'NoneType' object has no attribute 'guild',核心问题是**on_raw_reaction_remove事件中的payload.member可能为None**。Discord的原始反应事件里,当用户离线、不在机器人的服务器缓存中,或者已经退出服务器时,payload.member不会被填充,这时候直接访问它的guild属性自然就报错了。
另外你的代码还有两个小问题:
on_raw_reaction_remove函数多了个self参数,用@client.event装饰的事件不需要这个参数(除非是写在Cog类里)- 表情判断逻辑搞反了:你写的是
!=,但应该是当移除指定表情时才删除角色,所以要用==
修正后的代码
@client.event async def on_raw_reaction_add(payload): # channel和message IDs应为整数 if payload.channel_id == 700895165665247325 and payload.message_id == 756577133165543555: if str(payload.emoji) == "<:WarThunder:745425772944162907>": role = discord.utils.get(payload.member.guild.roles, name='War Thunder') await payload.member.add_roles(role) @client.event # 补上事件装饰器,否则不会触发该事件 async def on_raw_reaction_remove(payload): if payload.channel_id == 700895165665247325 and payload.message_id == 756577133165543555: if str(payload.emoji) == "<:WarThunder:745425772944162907>": # 通过guild_id获取服务器对象,再用user_id拉取成员数据(不受缓存限制) guild = client.get_guild(payload.guild_id) member = await guild.fetch_member(payload.user_id) if member: # 确保成员仍在服务器内,避免报错 role = discord.utils.get(guild.roles, name='War Thunder') await member.remove_roles(role)
关键修复点说明
- 移除多余的
self参数:on_raw_reaction_remove作为独立的事件函数,不需要self参数,加上会导致参数不匹配的问题。 - 用
payload.user_id获取成员:通过client.get_guild(payload.guild_id)拿到服务器对象,再用fetch_member方法获取用户——这个方法会从Discord API拉取用户数据,不受缓存限制,解决了payload.member为None的问题。 - 修正表情判断逻辑:把
!=改成==,确保只有移除指定的WarThunder表情时,才执行删除角色的操作。 - 增加成员存在判断:防止用户已经退出服务器时,
fetch_member返回None导致后续操作报错。 - 补上事件装饰器:你之前的
on_raw_reaction_remove函数没有加@client.event,这会导致机器人根本不会触发这个事件!
这样修改后,移除反应自动删角色的功能应该就能正常工作了。
内容的提问来源于stack exchange,提问作者MrMetacom
相关产品推荐
相关产品推荐

