Discord机器人按钮功能报错:discord.ui无ActionRow属性
问题解决:Discord机器人取消钉选消息时按钮组件报错
错误原因
- 参数使用错误:你在发送消息时用了
components参数,这是第三方库discord-components的语法,而原生discord.py 2.x发送组件应该使用view参数。 - 组件结构错误:虽然
discord.ui.ActionRow存在,但原生discord.py推荐用discord.ui.View来管理交互组件,直接实例化ActionRow的写法不符合当前版本的最佳实践,且容易引发属性识别问题。 - 回调逻辑不符合需求:你的按钮回调是重发消息内容,而需求是跳转至原消息,应该使用URL类型按钮,无需自定义回调。
修正后的代码
核心功能代码
@bot.event async def on_raw_reaction_remove(payload): if payload.emoji.name == "📌": channel = await bot.fetch_channel(payload.channel_id) message = await channel.fetch_message(payload.message_id) # 检查是否还有📌表情反应 has_pin_reaction = any(str(reaction.emoji) == "📌" for reaction in message.reactions) if not has_pin_reaction: await message.unpin() # 生成原消息的跳转链接 message_url = f"https://discord.com/channels/{payload.guild_id}/{payload.channel_id}/{payload.message_id}" # 创建链接类型按钮 button = discord.ui.Button( label="查看被取消钉选的消息", style=discord.ButtonStyle.link, url=message_url ) # 创建View容器并添加按钮 view = discord.ui.View() view.add_item(button) # 发送带按钮的提示消息 await channel.send("一条已钉选的消息被取消钉选。", view=view) print("Reaction removed.")
完整代码
import discord from discord.ext import commands intents = discord.Intents.all() bot = commands.Bot(command_prefix='!', intents=intents) THRESHOLD = 5 @bot.event async def on_ready(): channel = bot.get_channel(1069346031281651843) # 注释的公告代码保留原样 print('All systems go!'.format(bot)) # 钉选消息功能 @bot.event async def on_raw_reaction_add(payload): if payload.emoji.name == "📌": channel = await bot.fetch_channel(payload.channel_id) message = await channel.fetch_message(payload.message_id) await message.pin() print("Reaction added.") # 取消钉选消息功能(修正后) @bot.event async def on_raw_reaction_remove(payload): if payload.emoji.name == "📌": channel = await bot.fetch_channel(payload.channel_id) message = await channel.fetch_message(payload.message_id) has_pin_reaction = any(str(reaction.emoji) == "📌" for reaction in message.reactions) if not has_pin_reaction: await message.unpin() message_url = f"https://discord.com/channels/{payload.guild_id}/{payload.channel_id}/{payload.message_id}" button = discord.ui.Button( label="查看被取消钉选的消息", style=discord.ButtonStyle.link, url=message_url ) view = discord.ui.View() view.add_item(button) await channel.send("一条已钉选的消息被取消钉选。", view=view) print("Reaction removed.") bot.run('你的TOKEN')
关键修改说明
- 替换组件发送方式:用
view=view替代components=[...],符合discord.py原生组件系统的要求。 - 改用链接按钮:使用
discord.ButtonStyle.link类型按钮,直接生成原消息的跳转链接,无需编写回调函数,既满足需求又避免交互逻辑错误。 - 简化反应检查逻辑:用
any()替代列表推导式+长度判断,代码更简洁高效。 - 移除无效的ActionRow:使用
discord.ui.View管理按钮,这是discord.py 2.x推荐的组件管理方式。
内容的提问来源于stack exchange,提问作者stellarstye
相关产品推荐
相关产品推荐

