Discord.py的on_member_update事件无响应 无法实现用户最后上线记录功能
问题排查
- 缺少必要的Intents权限:监听用户在线状态变更需要开启
presence意图,你当前代码只开启了members意图,同时需要前往Discord开发者后台的Bot设置页,开启Presence Intent和Server Members Intent两个开关。 - 状态判断逻辑错误:discord.py中
Member.status返回的是枚举类型而非字符串,直接和"offline"字符串比对永远返回False,导致事件逻辑永远不执行。 - 逻辑设计缺陷:在事件回调中使用数小时的
asyncio.sleep会长期占用协程资源,且如果用户在sleep期间重新上线,后续执行列表删除操作时会抛出ValueError异常,多用户同时离线时还会导致严重的性能问题。
修复方案
1. 修正Intents配置
首先补全需要的意图:
import discord from discord.ext import commands from datetime import datetime # 开启需要的意图 intents = discord.Intents.default() intents.members = True intents.presence = True # 监听状态变化必须开启 bot = commands.Bot(command_prefix=["#","a#"], intents = intents)
2. 优化离线记录逻辑
不要用列表加sleep的方式实现,直接用字典存储用户ID和对应的离线时间戳,需要查询最后上线时间时直接计算即可,逻辑更稳定性能更高:
# 存储结构:key为用户ID,value为离线时间的datetime对象 offline_users = {} @bot.event async def on_member_update(before, after): # 仅当用户从非离线状态变为离线状态时记录 if before.status != discord.Status.offline and after.status == discord.Status.offline: offline_users[after.id] = datetime.now() # 如果用户从离线变为在线,删除对应的离线记录 if before.status == discord.Status.offline and after.status != discord.Status.offline: if after.id in offline_users: del offline_users[after.id] # 封装查询最后上线时间的方法 def get_last_online(user_id: int): if user_id not in offline_users: return "当前在线" offline_duration = datetime.now() - offline_users[user_id] # 可根据需要自定义时长输出格式 hours = offline_duration.total_seconds() // 3600 minutes = (offline_duration.total_seconds() % 3600) // 60 return f"最后上线时间:{int(hours)}小时{int(minutes)}分钟前"
3. 后台权限确认
登录Discord开发者平台,进入当前Bot的应用页,选择Bot选项卡,下滑到Privileged Gateway Intents区域,确认Presence Intent和Server Members Intent两个选项已开启,否则代码里声明了意图也不会生效。
内容的提问来源于stack exchange,提问作者Mushtaq Mahar
相关产品推荐
相关产品推荐

