Discord机器人on_raw_reaction_remove事件报错AttributeError求助
Discord机器人移除角色失败:AttributeError: 'NoneType' object has no attribute 'guild'
我正在开发一个Discord机器人(感谢社区用户之前的帮助让它正常运行),现在遇到添加角色后无法移除角色的问题。终端抛出如下错误:
2023-02-28 12:06:37 ERROR discord.client Ignoring exception in on_raw_reaction_remove Traceback (most recent call last): File "C:\Python311\Lib\site-packages\discord\client.py", line 409, in _run_event await coro(*args, **kwargs) File "e:\Turlington - Test\bot.py", line 155, in on_raw_reaction_remove role = get(payload.member.guild.roles, id=1080163217877254174) ^^^^^^^^^^^^^^^^^^^^ AttributeError: 'NoneType' object has no attribute 'guild'
错误原因是on_raw_reaction_remove事件处理函数中,payload.member为None,无法访问guild属性。以下是我的代码:
import os import datetime import asyncio from typing import Self import requests as rq import discord import discord.ext from discord.utils import get from discord.ext import commands from dotenv import load_dotenv load_dotenv() TOKEN = os.getenv('DISCORD_TOKEN') intents = discord.Intents.all()bot = discord.Client(intents=discord.Intents.default()) bot = commands.Bot(command_prefix="?", intents=intents) self = bot class Embed(commands.Cog): def __init__(self, bot): self.bot = bot @bot.event async def on_raw_reaction_add(payload): guild = bot.get_guild(payload.guild_id) # Get guild member = get(guild.members, id=payload.user_id) # Get the member out of the guild # The channel ID should be an integer: if payload.channel_id == 1080162990181064714: # Only channel where it will work if str(payload.emoji) == "❌": # Your emoji role = get(payload.member.guild.roles, id=1080163217877254174) # Role ID else: role = get(guild.roles, name=payload.emoji) if role is not None: # If role exists await payload.member.add_roles(role) print(f"Added {role}") @bot.event async def on_raw_reaction_remove(payload): guild = bot.get_guild(payload.guild_id) member = guild.get_member(payload.user_id) if payload.channel_id == 1080162990181064714: if str(payload.emoji) == "❌": role = get(payload.member.guild.roles, id=1080163217877254174) else: role = get(guild.roles, name=payload.emoji) if role is not None: await payload.member.remove_roles(role) print(f"Removed {role}") bot.run(TOKEN)
问题根源
在on_raw_reaction_remove事件中,payload.member字段不存在或为None——Discord的RawReactionActionEvent payload里,member属性仅在on_raw_reaction_add事件中保证存在(当用户是服务器成员时),而在移除反应时,该字段不会被提供,因此不能依赖它来获取成员或公会信息。
你已经在函数开头获取了guild和member变量,但后续代码仍在使用payload.member,这就是错误的直接来源。
修复步骤
- 在两个事件处理函数中,统一使用已经获取到的
member变量,而非payload.member - 确保获取角色时,使用已有的
guild对象,避免依赖payload.member - 增加空值判断,处理用户已离开服务器或公会不存在的情况
修正后的代码
import os import datetime import asyncio from typing import Self import requests as rq import discord import discord.ext from discord.utils import get from discord.ext import commands from dotenv import load_dotenv load_dotenv() TOKEN = os.getenv('DISCORD_TOKEN') intents = discord.Intents.all() # 移除多余的discord.Client初始化,避免实例冲突 bot = commands.Bot(command_prefix="?", intents=intents) class Embed(commands.Cog): def __init__(self, bot): self.bot = bot @bot.event async def on_raw_reaction_add(payload): guild = bot.get_guild(payload.guild_id) if not guild: return member = guild.get_member(payload.user_id) if not member: return if payload.channel_id == 1080162990181064714: if str(payload.emoji) == "❌": role = get(guild.roles, id=1080163217877254174) else: role = get(guild.roles, name=str(payload.emoji)) if role is not None: await member.add_roles(role) print(f"Added {role} to {member}") @bot.event async def on_raw_reaction_remove(payload): guild = bot.get_guild(payload.guild_id) if not guild: return member = guild.get_member(payload.user_id) if not member: print(f"Member {payload.user_id} not found in guild, skipping role removal") return if payload.channel_id == 1080162990181064714: if str(payload.emoji) == "❌": role = get(guild.roles, id=1080163217877254174) else: role = get(guild.roles, name=str(payload.emoji)) if role is not None: await member.remove_roles(role) print(f"Removed {role} from {member}") bot.run(TOKEN)
额外优化说明
- 移除了多余的
discord.Client初始化代码,避免实例冲突 - 增加了
guild和member的空值判断,防止后续代码报错 - 统一使用
str(payload.emoji)获取表情字符串,避免类型匹配问题 - 在移除角色时,处理了用户已离开服务器的情况(
member为None时直接返回)
内容的提问来源于stack exchange,提问作者iandrice
相关产品推荐
相关产品推荐

