discord.py如何获取带有jump_url和reactions属性的频道消息
Discord机器人功能实现修正方案
现有代码核心问题
channel.history().flatten()返回的是消息列表对象,不能直接访问单个消息的jump_url、reactions属性,这是你无法获取对应属性的核心原因- 反应计数检查逻辑放在
on_message事件中不合理,该事件仅在消息发送时触发,后续用户给历史消息添加反应不会触发计数校验 - 直接使用
open()读写文件未做异常处理,也没有自动关闭文件的机制,容易出现IO错误 - 未校验反应是否是你指定的
<:MashaUpset:828589397074116709>表情,会把其他表情的计数也算进去
实现逻辑调整建议
你需要拆分两个事件实现功能:
on_message事件:仅负责给符合条件的新消息自动加指定表情on_raw_reaction_add事件:用户每次添加反应时触发,校验对应消息的表情计数,达标后发送通知、写日志
如果你要使用message.id手动拼接跳转链接,格式为:
https://discord.com/channels/{guild_id}/{channel_id}/{message_id}
其中guild_id是消息所在服务器的ID,channel_id是消息所在频道ID,message_id就是你获取的消息ID
修正后代码示例
import discord from discord.ext import commands # 常量提前定义,方便后续修改 TARGET_CHANNEL_ID = 828579458167996420 MOD_CHANNEL_ID = 892065611876823100 TARGET_REACTION = "<:MashaUpset:828589397074116709>" LOG_FILE = "message_log.txt" bot = commands.Bot(command_prefix="!", intents=discord.Intents.all()) # 自动给符合条件的消息加反应 @bot.event async def on_message(message): # 跳过机器人自己发的消息 if message.author.bot: return if message.channel.id == TARGET_CHANNEL_ID: # 判断是否带附件或包含http链接 if message.attachments or "http" in message.content: await message.add_reaction(TARGET_REACTION) # 保留命令处理逻辑,不需要指令功能可以删除 await bot.process_commands(message) # 监听反应添加事件,检查计数 @bot.event async def on_raw_reaction_add(payload): # 只处理目标频道的指定表情反应 if payload.channel_id != TARGET_CHANNEL_ID or str(payload.emoji) != TARGET_REACTION: return # 获取对应的消息对象 channel = bot.get_channel(payload.channel_id) message = await channel.fetch_message(payload.message_id) # 统计目标表情的计数 target_reaction_count = 0 for reaction in message.reactions: if str(reaction.emoji) == TARGET_REACTION: target_reaction_count = reaction.count break # 计数≥2才处理 if target_reaction_count < 2: return # 读取已记录的日志,避免重复发送 try: with open(LOG_FILE, "r", encoding="utf-8") as f: logged_links = f.read() except FileNotFoundError: logged_links = "" # 两种获取跳转链接的方式二选一即可 # 方式1:直接用自带的jump_url jump_url = message.jump_url # 方式2:用message.id手动拼接 # jump_url = f"https://discord.com/channels/{payload.guild_id}/{payload.channel_id}/{payload.message_id}" if jump_url not in logged_links: # 减去机器人自己加的1个反应,得到真实用户点赞数 user_like_count = target_reaction_count - 1 # 发送到moderation频道 mod_channel = bot.get_channel(MOD_CHANNEL_ID) await mod_channel.send(f"this post was liked {user_like_count} times! {jump_url}") # 写入日志 with open(LOG_FILE, "a", encoding="utf-8") as f: f.write(f"\n{jump_url}") bot.run("你的机器人Token")
注意事项
- 必须开启机器人的
Message Content Intent和Server Members Intent权限,在Discord开发者后台的Bot页面开启,否则无法读取消息内容和反应事件 - 日志文件路径如果报错可以写绝对路径,避免相对路径找不到文件的问题
- 代码里的
Intents.all()根据你的实际需求调整权限范围,不需要全部权限的话可以单独开需要的权限
内容的提问来源于stack exchange,提问作者CupQuakes
相关产品推荐
相关产品推荐

