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

开发Discord表情反应授角色机器人遇异常:反应后未添加角色

Discord表情反应分配角色故障排查

我正在开发一款Discord机器人,需求是当用户对指定消息使用特定表情反应时,为用户分配对应角色。但测试发现,用户完成表情反应后,机器人并未成功添加角色。

此示例需要'members'特权意图

代码实现

import discord


class MyClient(discord.Client):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.role_message_id = 1060179348356866119  # 可通过反应添加/移除角色的消息ID
        self.emoji_to_role = {
            discord.PartialEmoji(name=':white_check_mark:'): 1060127733151170590,  # 对应Unicode表情'✅'的角色ID
            discord.PartialEmoji(name=':green_circle:'): 1060127733151170590,  # 对应Unicode表情':green_circle:'的角色ID
            discord.PartialEmoji(name='green', id=0): 1060127733151170590,  # 对应自定义表情ID的角色ID
        }

    async def on_raw_reaction_add(self, payload: discord.RawReactionActionEvent):
        print("CAZZI NU CGAUSHDUQEWGRIQGH")
        """根据反应表情分配角色"""
        # 确认用户反应的是目标消息
        if payload.message_id != self.role_message_id:
            return
        print("消息正确")

        guild = self.get_guild(payload.guild_id)
        if guild is None:
            # 检查是否仍在服务器且已缓存
            return
        print("服务器存在")

        try:
            role_id = self.emoji_to_role[payload.emoji]
        except KeyError:
            # 如果表情不在目标列表则退出
            return
        print("获取角色ID成功")

        role = guild.get_role(role_id)
        if role is None:
            # 确保角色仍存在且有效
            return
        print("角色存在")
    
        try:
            # 最终添加角色
            await payload.member.add_roles(role)
        except discord.HTTPException:
            # 错误处理可在此添加逻辑
            pass
        print("角色添加完成")

    async def on_raw_reaction_remove(self, payload: discord.RawReactionActionEvent):
        """根据反应表情移除角色"""
        # 确认用户反应的是目标消息
        if payload.message_id != self.role_message_id:
            return
        print("消息ID匹配")

        guild = self.get_guild(payload.guild_id)
        if guild is None:
            # 检查是否仍在服务器且已缓存
            return
        print("服务器验证通过")

        try:
            role_id = self.emoji_to_role[payload.emoji]
        except KeyError:
            # 如果表情不在目标列表则退出
            return
        print("角色ID无错误")

        role = guild.get_role(role_id)
        if role is None:
            # 确保角色仍存在且有效
            return
        print("角色存在验证通过")

        # `on_raw_reaction_remove`的payload不提供`.member`,需通过`.user_id`获取成员
        member = guild.get_member(payload.user_id)
        if member is None:
            # 确保成员仍存在且有效
            return
        print("成员有效")

        try:
            # 最终移除角色
            await member.remove_roles(role)
        except discord.HTTPException:
            # 错误处理可在此添加逻辑
            pass
        print("执行移除操作")


intents = discord.Intents.default()
intents.members = True

client = MyClient(intents=intents)
client.run('....token.....')

控制台输出(使用✅表情反应时)

message id
guild ok
CAZZI NU CGAUSHDUQEWGRIQGH
messaggio giusto
guild

问题原因

  1. 表情匹配失败:emoji_to_role中对Unicode表情的定义错误。原生Unicode表情不需要加冒号,比如✅直接写name='✅'即可,而不是:white_check_mark:,这会导致payload.emoji无法匹配字典中的键,触发KeyError后直接退出,无法执行添加角色的逻辑。
  2. 自定义表情配置无效:第三个PartialEmoji的id设为0,这是无效值,自定义表情必须使用Discord分配的真实ID。

修复方案

  • 修正表情映射字典:
    self.emoji_to_role = {
        discord.PartialEmoji(name='✅'): 1060127733151170590,  # 对应✅表情的角色ID
        discord.PartialEmoji(name='🟢'): 1060127733151170590,  # 对应🟢表情的角色ID
        # 自定义表情示例(替换为实际name和id):
        # discord.PartialEmoji(name='green', id=123456789012345678): 1060127733151170590,
    }
    
  • 确保Discord开发者门户中已开启服务器成员意图(Server Members Intent),并且机器人角色拥有管理角色权限。
  • 测试时观察控制台是否打印出获取角色ID成功,如果没有,说明表情匹配仍有问题,需要进一步核对表情格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 21:50:34