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

discord.py如何获取带有jump_url和reactions属性的频道消息

Discord机器人功能实现修正方案

现有代码核心问题

  • channel.history().flatten()返回的是消息列表对象,不能直接访问单个消息的jump_url、reactions属性,这是你无法获取对应属性的核心原因
  • 反应计数检查逻辑放在on_message事件中不合理,该事件仅在消息发送时触发,后续用户给历史消息添加反应不会触发计数校验
  • 直接使用open()读写文件未做异常处理,也没有自动关闭文件的机制,容易出现IO错误
  • 未校验反应是否是你指定的<:MashaUpset:828589397074116709>表情,会把其他表情的计数也算进去

实现逻辑调整建议

你需要拆分两个事件实现功能:

  1. on_message事件:仅负责给符合条件的新消息自动加指定表情
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 23:39:03