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

discord.py斜杠命令中add_reaction等方法失效问题求助

问题描述

近期尝试制作一个通过表情反应切换页面的/help斜杠命令(暂未掌握按钮实现方法),该逻辑在普通前缀命令模式下运行正常,但改为斜杠命令后,add_reaction()、clear_reactions()和remove_reaction()完全无法工作,报错如下:

报错信息

2022-12-02 13:02:23 ERROR    discord.app_commands.tree Ignoring exception in command 'help'
Traceback (most recent call last):
  File "C:\Users\human\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\app_commands\commands.py", line 862, in _do_call
    return await self._callback(interaction, **params)  # type: ignore
  File "c:\Users\human\OneDrive\Documents\EverythingBot\main.py", line 155, in rob
    await message.add_reaction('⏮')
AttributeError: 'NoneType' object has no attribute 'add_reaction'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\human\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\app_commands\tree.py", line 1242, in _call        
    await command._invoke_with_namespace(interaction, namespace)
  File "C:\Users\human\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\app_commands\commands.py", line 887, in _invoke_with_namespace
    return await self._do_call(interaction, transformed_values)
  File "C:\Users\human\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\app_commands\commands.py", line 880, in _do_call  
    raise CommandInvokeError(self, e) from e
discord.app_commands.errors.CommandInvokeError: Command 'help' raised an exception: AttributeError: 'NoneType' object has no attribute 'add_reaction'
2022-12-02 13:04:44 ERROR    discord.ext.commands.bot Ignoring exception in command help
Traceback (most recent call last):
  File "C:\Users\human\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\ext\commands\core.py", line 229, in wrapped       
    ret = await coro(*args, **kwargs)
  File "c:\Users\human\OneDrive\Documents\EverythingBot\main.py", line 105, in help
    await message.clear_reactions()
  File "C:\Users\human\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\message.py", line 1154, in clear_reactions        
    await self._state.http.clear_reactions(self.channel.id, self.id)
  File "C:\Users\human\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\http.py", line 738, in request
    raise Forbidden(response, data)
discord.errors.Forbidden: 403 Forbidden (error code: 50003): Cannot execute action on a DM channel
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: Forbidden: 403 Forbidden (error code: 50003): Cannot execute action on a DM channel

当前代码

@client.tree.command(name = "help", description = "Display the bots commands")
async def rob(interaction: discord.Interaction):
        page1 = discord.Embed (
        title = 'Fun Commands:',
        description = '',
        colour = discord.Colour(0x00ffff)
        )
  
        page1.add_field(name = "Meme", value = "Sends a random meme.", inline=False)
        page1.add_field(name = "8ball [question]", value = "Ask the 8 ball a question!", inline=False)
        page1.add_field(name = "Hi", value = "Say hi to the bot!", inline=False)
        page1.add_field(name = "Die", value = "Sends randomly selected quotes of last words.", inline=False)
        page1.add_field(name = "Ping", value = "Returns your ping.", inline=False)
        page1.add_field(name = "ABC", value = "Displays the alphabet!", inline=False)
        page1.add_field(name = "Pi", value = "Displays the first 100 digits of pi.")
        
        page2 = discord.Embed (
            title = 'Economy Commands:',
            description = '',
            colour = discord.Colour(0x00ffff)
        )

        
    
        page3 = discord.Embed (
            title = 'Moderation Commands:',
            description = '',
            colour = discord.Colour(0x00ffff)
        )

        page3.add_field(name = "kick [user]", value = "Kicks a specified user.")
        page3.add_field(name = "ban [user]", value = "Bans a specified user.")
        page3.add_field(name = "unban [user]", value = "Unbans a specified user.")
        page3.add_field(name = "clear [number]", value = "Clears a specified number of messages.")
    
        page4 = discord.Embed (
            title = "Support Server:",
            description = "",
            colour = discord.Colour(0x00ffff)
        )
        
        pages = [page1, page2, page3, page4]

        message = await interaction.response.send_message(embed = page1)
        await message.add_reaction('⏮')
        await message.add_reaction('◀')
        await message.add_reaction('▶')
        await message.add_reaction('⏭')

        def check(reaction, user):
            return user == interaction.user

        i = 0
        reaction = None

        while True:
            if str(reaction) == '⏮':
                i = 0
                await message.edit(embed = pages[i])
            elif str(reaction) == '◀':
                if i > 0:
                    i -= 1
                    await message.edit(embed = pages[i])
            elif str(reaction) == '▶':
                if i < 3:
                    i += 1
                    await message.edit(embed = pages[i])
            elif str(reaction) == '⏭':
                i = 3
                await message.edit(embed = pages[i])
            
            try:
                reaction, user = await client.wait_for('reaction_add', timeout = 120.0, check = check)
                await message.remove_reaction(reaction, user)
            except:
                break
        await message.clear_reactions()

问题原因及修复方案

1. AttributeError: 'NoneType' object has no attribute 'add_reaction'

斜杠命令的interaction.response.send_message()默认不返回消息对象,需要添加wait=True参数,让方法等待消息发送完成后返回对应的Message实例,否则message变量会是None,自然无法调用add_reaction。

2. Forbidden: 403 Forbidden (error code: 50003): Cannot execute action on a DM channel

Discord不允许在DM频道中对斜杠命令的消息进行表情反应操作,因此需要先判断当前频道是否为服务器频道,若为DM则提示用户无法使用该功能。

3. 额外优化

  • 斜杠命令的消息若设置为ephemeral=True(仅自己可见),同样无法添加表情反应,需确保发送公开消息(默认ephemeral=False)。
  • 可以添加权限判断,确保bot有添加表情反应的权限。

修复后的完整代码

@client.tree.command(name="help", description="Display the bots commands")
async def rob(interaction: discord.Interaction):
    # 检查是否在服务器频道中
    if not isinstance(interaction.channel, discord.GuildChannel):
        await interaction.response.send_message("此命令仅能在服务器频道中使用!", ephemeral=True)
        return

    page1 = discord.Embed(
        title='Fun Commands:',
        description='',
        colour=discord.Colour(0x00ffff)
    )
  
    page1.add_field(name="Meme", value="Sends a random meme.", inline=False)
    page1.add_field(name="8ball [question]", value="Ask the 8 ball a question!", inline=False)
    page1.add_field(name="Hi", value="Say hi to the bot!", inline=False)
    page1.add_field(name="Die", value="Sends randomly selected quotes of last words.", inline=False)
    page1.add_field(name="Ping", value="Returns your ping.", inline=False)
    page1.add_field(name="ABC", value="Displays the alphabet!", inline=False)
    page1.add_field(name="Pi", value="Displays the first 100 digits of pi.")
    
    page2 = discord.Embed(
        title='Economy Commands:',
        description='',
        colour=discord.Colour(0x00ffff)
    )

    page3 = discord.Embed(
        title='Moderation Commands:',
        description='',
        colour=discord.Colour(0x00ffff)
    )

    page3.add_field(name="kick [user]", value="Kicks a specified user.")
    page3.add_field(name="ban [user]", value="Bans a specified user.")
    page3.add_field(name="unban [user]", value="Unbans a specified user.")
    page3.add_field(name="clear [number]", value="Clears a specified number of messages.")

    page4 = discord.Embed(
        title="Support Server:",
        description="",
        colour=discord.Colour(0x00ffff)
    )
    
    pages = [page1, page2, page3, page4]

    # 添加wait=True获取消息对象
    message = await interaction.response.send_message(embed=page1, wait=True)
    await message.add_reaction('⏮')
    await message.add_reaction('◀')
    await message.add_reaction('▶')
    await message.add_reaction('⏭')

    def check(reaction, user):
        return user == interaction.user and str(reaction.emoji) in ['⏮', '◀', '▶', '⏭']

    i = 0
    reaction = None

    while True:
        if str(reaction) == '⏮':
            i = 0
            await message.edit(embed=pages[i])
        elif str(reaction) == '◀':
            if i > 0:
                i -= 1
                await message.edit(embed=pages[i])
        elif str(reaction) == '▶':
            if i < len(pages)-1:  # 改为动态获取页数,避免硬编码3
                i += 1
                await message.edit(embed=pages[i])
        elif str(reaction) == '⏭':
            i = len(pages)-1
            await message.edit(embed=pages[i])
        
        try:
            reaction, user = await client.wait_for('reaction_add', timeout=120.0, check=check)
            await message.remove_reaction(reaction, user)
        except:
            break
    await message.clear_reactions()

关键修改点说明

  • 增加了服务器频道判断,避免在DM中执行操作。
  • send_message添加wait=True参数,正确获取消息对象。
  • 优化了页数判断逻辑,从硬编码3改为len(pages)-1,方便后续增减页面。
  • 完善了check函数,只处理指定的表情,避免无关反应触发逻辑。

内容的提问来源于stack exchange,提问作者Human101929

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 15:45:33