discord.py无法检测Rich Presence 游戏活动检测功能失效
问题根因排查
你的代码完全无法运行是多个基础错误叠加导致的,逐个列示:
- 事件注册无效:
@client.event仅支持绑定discord.py内置的网关事件,你自定义的get_all_members不属于框架认可的事件,永远不会被触发,所有逻辑从入口就不会执行。 - 对象认知错误:活动状态(Rich Presence)是*服务器成员(Member对象)的属性,不是频道(Channel对象)*的属性,你代码里尝试读取
channel.activity从根上就找错了对象,不可能拿到游戏状态。另外用户的活动是列表类型activities,支持同时存在多个活动,不存在单个activity属性。 - 语法调用错误:
client.get.channel是错误写法,正确的频道获取方法是client.get_channel(频道ID);你写的channel;client.get.channel(xxx)用分号分隔的语句没有做变量赋值,就算拿到目标频道对象也不会被后续发送逻辑使用。 - 权限配置缺失:读取用户活动状态属于Discord的特权权限,你需要先在开发者后台开启对应网关意图,同时在客户端初始化时声明启用,否则Discord根本不会把用户的活动数据推送给你的机器人。
可直接落地的修复方案
第一步:开启特权网关意图
- 打开Discord开发者后台,进入你的机器人应用的Bot设置页
- 找到Privileged Gateway Intents板块,开启
Presence Intent、Server Members Intent、Message Content Intent三个开关,保存配置 - 确认机器人在目标服务器拥有「发送消息」的基础权限
第二步:修正客户端初始化配置
初始化客户端时必须显式声明启用需要的意图,否则配置不生效:
import discord # 配置意图 intents = discord.Intents.default() intents.presences = True intents.members = True # 初始化客户端,替换成你自己的token即可 client = discord.Client(intents=intents) # 业务配置 TARGET_GAMES = {"osu!"} # 用集合做匹配效率更高,后续加游戏直接往里面放就行 NOTICE_CHANNEL_ID = 804884691328303115 # 缓存已发过提示的用户ID,避免每次状态更新都重复发消息骚扰 notified_user_set = set()
第三步:用正确的事件实现检测逻辑
使用discord.py内置的on_presence_update事件,该事件会在任意成员的在线状态、活动状态变更时自动触发,不需要轮询:
@client.event async def on_presence_update(before: discord.Member, after: discord.Member): # 跳过机器人自身的状态更新 if after.bot: return # 提取用户当前所有正在运行的游戏类活动名称 current_playing_games = set() for act in after.activities: # 仅匹配「正在玩」类型的活动,过滤听歌、自定义状态等非游戏活动 if act.type == discord.ActivityType.playing and act.name: current_playing_games.add(act.name.lower()) # 命中目标游戏且未发过提示 if current_playing_games & {g.lower() for g in TARGET_GAMES} and after.id not in notified_user_set: notice_channel = client.get_channel(NOTICE_CHANNEL_ID) if notice_channel: await notice_channel.send(f"{after.mention} 玩osu是不允许的") notified_user_set.add(after.id) # 可选逻辑:用户关闭目标游戏后从缓存移除,下次再打开游戏时重新触发提示 elif not (current_playing_games & {g.lower() for g in TARGET_GAMES}) and after.id in notified_user_set: notified_user_set.remove(after.id) # 补充原有机器人启动逻辑即可 # client.run("你的机器人Token")
补充说明
- 不要用定时遍历全服务器成员的方式做检测,效率极低且很容易触发Discord的速率限制,用网关事件推送是官方推荐的最优实现
- 如果需要匹配Rich Presence类的第三方游戏状态,只要活动类型是
playing就会被上述逻辑捕获,不需要额外做适配 - 如果频道获取失败返回None,优先检查机器人是否在该频道所在的服务器内、频道ID是否填写正确
内容的提问来源于stack exchange,提问作者Fran Li
相关产品推荐
相关产品推荐

