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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 02:57:03