基于Discord.py实现反应角色功能及嵌入消息持久化需求
实现Discord.py表情角色分配机器人(重启无需重发嵌入消息)
核心思路
要实现重启后不用重发消息,关键是保存嵌入消息的频道ID和消息ID,机器人启动时直接拉取这条已存在的消息,重新绑定表情监听逻辑。这里用本地JSON文件存储消息信息,简单易上手。
完整代码实现
import discord from discord.ext import commands import json import os # 初始化机器人,开启必要意图 intents = discord.Intents.default() intents.message_content = True intents.members = True bot = commands.Bot(command_prefix="!", intents=intents) # 自定义配置:表情对应角色,替换成你服务器的实际内容 EMOJI_ROLE_MAP = { "😎": "酷玩达人", "🤓": "技术宅", "🥳": "派对动物" } # 存储消息ID的本地文件 MESSAGE_DATA_PATH = "role_reaction_msg.json" def save_msg_info(channel_id, msg_id): """把消息的频道ID和消息ID存到本地文件""" data = {"channel_id": channel_id, "message_id": msg_id} with open(MESSAGE_DATA_PATH, "w") as f: json.dump(data, f) def load_msg_info(): """从本地文件读取已保存的消息信息""" if os.path.exists(MESSAGE_DATA_PATH): with open(MESSAGE_DATA_PATH, "r") as f: return json.load(f) return None @bot.command() @commands.has_permissions(administrator=True) async def setup_role(ctx): """管理员专属命令:创建角色分配嵌入消息并保存信息""" # 构建嵌入消息 embed = discord.Embed(title="自助领角色", description="点击下方表情获取对应身份:", color=discord.Color.green()) for emoji, role_name in EMOJI_ROLE_MAP.items(): embed.add_field(name=emoji, value=f"领取「{role_name}」", inline=False) # 发送消息并批量添加表情 target_msg = await ctx.send(embed=embed) for emoji in EMOJI_ROLE_MAP.keys(): await target_msg.add_reaction(emoji) # 保存消息信息到本地 save_msg_info(ctx.channel.id, target_msg.id) await ctx.send("角色分配消息已创建完成!") @bot.event async def on_ready(): print(f"机器人已登录:{bot.user.name}") # 重启后自动绑定已有的消息 msg_data = load_msg_info() if msg_data: try: channel = bot.get_channel(msg_data["channel_id"]) target_msg = await channel.fetch_message(msg_data["message_id"]) # 检查消息上的表情是否完整,缺失的话补加 for emoji in EMOJI_ROLE_MAP.keys(): if not any(reaction.emoji == emoji for reaction in target_msg.reactions): await target_msg.add_reaction(emoji) print("已成功绑定现有角色分配消息") except Exception as e: print(f"加载旧消息失败:{str(e)}") @bot.event async def on_raw_reaction_add(payload): """处理表情添加事件,给用户分配角色""" # 忽略机器人自己的操作 if payload.user_id == bot.user.id: return # 确认是我们监听的消息 msg_data = load_msg_info() if not msg_data or payload.message_id != msg_data["message_id"]: return # 匹配对应的角色 emoji = str(payload.emoji) if emoji not in EMOJI_ROLE_MAP: return guild = bot.get_guild(payload.guild_id) role = discord.utils.get(guild.roles, name=EMOJI_ROLE_MAP[emoji]) if not role: print(f"找不到对应角色:{EMOJI_ROLE_MAP[emoji]}") return member = guild.get_member(payload.user_id) if member: await member.add_roles(role) print(f"已给{member.name}添加角色{role.name}") @bot.event async def on_raw_reaction_remove(payload): """处理表情移除事件,移除用户对应角色""" if payload.user_id == bot.user.id: return msg_data = load_msg_info() if not msg_data or payload.message_id != msg_data["message_id"]: return emoji = str(payload.emoji) if emoji not in EMOJI_ROLE_MAP: return guild = bot.get_guild(payload.guild_id) role = discord.utils.get(guild.roles, name=EMOJI_ROLE_MAP[emoji]) if not role: print(f"找不到对应角色:{EMOJI_ROLE_MAP[emoji]}") return member = guild.get_member(payload.user_id) if member: await member.remove_roles(role) print(f"已给{member.name}移除角色{role.name}") # 替换成你的机器人Token bot.run("YOUR_BOT_TOKEN")
使用步骤
- 配置修改:
- 调整
EMOJI_ROLE_MAP里的表情和角色名称,对应你服务器的实际角色 - 把
YOUR_BOT_TOKEN替换成你的Discord机器人Token
- 调整
- 首次部署:
- 机器人上线后,用管理员账号在服务器发送
!setup_role,机器人会自动创建嵌入消息并保存消息ID
- 机器人上线后,用管理员账号在服务器发送
- 重启机器人:
- 重启后机器人会自动读取本地保存的消息信息,找到旧的嵌入消息并重新监听表情事件,不需要重新发送消息
注意事项
- 确保机器人拥有管理角色的权限,否则无法给用户添加/移除角色
- 不要删除
role_reaction_msg.json文件,否则机器人重启后会找不到旧消息 - 如果需要修改嵌入消息内容,先删除旧消息和JSON文件,再重新执行
!setup_role命令
内容的提问来源于stack exchange,提问作者GiveOff
相关产品推荐
相关产品推荐

