You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,这就是错误的直接来源。

修复步骤

  1. 在两个事件处理函数中,统一使用已经获取到的member变量,而非payload.member
  2. 确保获取角色时,使用已有的guild对象,避免依赖payload.member
  3. 增加空值判断,处理用户已离开服务器或公会不存在的情况

修正后的代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 12:47:27