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

如何为自定义!!前缀Discord私有机器人实现反应角色功能?

Discord机器人特定消息反应检测实现方案

核心解决方法

用Discord.py的on_raw_reaction_add事件监听所有反应添加操作,这个事件能捕获缓存外的消息,完美适配你需要监听特定历史消息的场景。同时需要把命令配置的消息、表情、角色等信息存起来,方便事件触发时匹配执行逻辑。

具体代码实现

1. 存储监听配置

先定义一个全局字典用来保存反应角色的配置,重启后会丢失,要持久化的话可以存JSON或数据库:

# 格式: {消息ID: {表情字符串: {"role_id": 角色ID, "action": "Give"/"Remove", "duration": 秒数}}}
reaction_role_configs = {}

2. 监听反应添加事件

编写on_raw_reaction_add事件处理逻辑,自动移除用户反应并执行角色操作:

import asyncio

@bot.event
async def on_raw_reaction_add(payload):
    # 跳过机器人自身的反应
    if payload.user_id == bot.user.id:
        return

    message_id = payload.message_id
    # 把表情转成字符串,统一匹配格式(处理自定义表情和普通表情)
    emoji = str(payload.emoji)

    # 检查当前消息和表情是否在配置中
    if message_id not in reaction_role_configs or emoji not in reaction_role_configs[message_id]:
        return

    guild = bot.get_guild(payload.guild_id)
    if not guild:
        return

    # 获取用户和角色对象
    member = guild.get_member(payload.user_id)
    role_info = reaction_role_configs[message_id][emoji]
    target_role = guild.get_role(role_info["role_id"])
    if not member or not target_role:
        return

    # 自动移除用户的反应
    channel = guild.get_channel(payload.channel_id)
    target_message = await channel.fetch_message(message_id)
    await target_message.remove_reaction(payload.emoji, member)

    # 执行Give/Remove操作
    action = role_info["action"]
    duration = role_info["duration"]

    if action == "Give":
        await member.add_roles(target_role)
        # 处理定时移除逻辑
        if duration.isdigit():
            await asyncio.sleep(int(duration))
            # 再次检查用户是否还在服务器,避免报错
            if guild.get_member(payload.user_id):
                await member.remove_roles(target_role)
    elif action == "Remove":
        await member.remove_roles(target_role)

3. 整合命令解析逻辑

把你已有的命令逻辑和配置存储结合,假设命令是通过回复机器人消息触发,解析参数后存入配置:

@bot.command(prefix="!!")
async def reactionrole(ctx):
    # 这里替换成你解析参数的逻辑,从回复的消息中按/分割提取参数
    # 示例:假设回复内容是 "Give/3600/123456789/987654321/😊/"
    content = ctx.message.reference.resolved.content.strip().rstrip("/")
    params = content.split("/")
    if len(params) != 5:
        await ctx.send("参数错误!格式应为:Give/Remove/定时秒数/目标消息ID/角色ID/表情/")
        return

    action, duration, msg_id_str, role_id_str, emoji = params
    # 格式校验
    if action not in ["Give", "Remove"]:
        await ctx.send("第一个参数必须是Give或Remove")
        return
    try:
        msg_id = int(msg_id_str)
        role_id = int(role_id_str)
    except ValueError:
        await ctx.send("消息ID和角色ID必须是数字")
        return

    # 存入配置
    if msg_id not in reaction_role_configs:
        reaction_role_configs[msg_id] = {}
    reaction_role_configs[msg_id][emoji] = {
        "role_id": role_id,
        "action": action,
        "duration": duration
    }

    await ctx.send(f"配置完成:{emoji} 触发{action}角色 <@&{role_id}>,目标消息ID {msg_id}")

关键注意点

  • 机器人需要拥有Manage Roles(管理角色)和Manage Messages(管理消息)权限,否则无法执行角色操作和移除反应。
  • 若目标消息是旧消息,确保机器人能访问该消息所在的频道,否则fetch_message会抛出权限错误。
  • 定时角色逻辑在机器人重启后会失效,如需持久化,可将reaction_role_configs写入JSON文件,启动时读取加载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 01:27:01