Telegram Bot无法检测用户退出事件的技术求助
Telegram Bot退群事件检测异常问题
基本信息
使用Python 3.11.0和python-telegram-bot==21.5,通过Redis存储数据。
Bot核心功能:为每个新加入群组的用户设置10分钟计时器,到期自动踢出用户;若用户在计时器到期前主动退群,计时器暂停,再次入群时从上次剩余时间继续计时(比如初始10分钟,退群时剩4分钟,再次入群就设4分钟计时器)。
问题现象
用自己的小号测试(加入、退群、再次加入)时功能正常,但在大群或其他用户操作时失效:Bot无法检测到用户退群事件,退群分支的日志从未输出。用户再次入群时,Redis中没有存储该用户的left时间,导致left_time为None,执行datetime.fromisoformat(left_time)时触发错误。
日志示例
INFO:apscheduler.scheduler:Removed job 9065c10968444e8dba41593926032c99 INFO:__main__: Join Time: 2025-01-04T08:25:38.461033+00:00 +++++++ Left Time: None ERROR:__main__:There has been an error: fromisoformat: argument must be str INFO:apscheduler.scheduler:Added job "<JOB_NAME>" to job store "default"
相关代码
def memberJoin(chatMemberUpdate: ChatMemberUpdated): status = chatMemberUpdate.difference().get("status") old, new = status or (None, status) if old in (None, ChatMember.BANNED, ChatMember.LEFT) and new == ChatMember.MEMBER: return True return False def memberLeft(chatMemberUpdate: ChatMemberUpdated): status = chatMemberUpdate.difference().get("status") old, new = status or (None, status) if old == ChatMember.MEMBER and new == ChatMember.LEFT: return True return False async def check_status(update: Update, context: ContextTypes.DEFAULT_TYPE): left = memberLeft(update.chat_member) join = memberJoin(update.chat_member) user_id = update.chat_member.from_user.id chat_id = update.chat_member.chat.id if join: # 首次入群 if not memory.hexists(user_id, "join"): memory.hset(user_id, "join", datetime.now().isoformat()) # 计时器相关逻辑... else: # 计时器到期前再次入群 memory.persist(user_id) join_time = memory.hget(user_id, "join") left_time = memory.hget(user_id, "left") logger.info(f"Join Time: {join_time} +++++++ Left Time: {left_time}") elapsed_time = (datetime.fromisoformat(left_time) - datetime.fromisoformat(join_time)).total_seconds() remaining_time = 10 * 60 - elapsed_time # 剩余计时时间 if remaining_time > 0: # 重新设置计时器相关逻辑... elif left: logger.info(f"User {user_id} left at {datetime.now().isoformat()}.") memory.hset(user_id, "left", datetime.now().isoformat()) memory.expire(user_id, timedelta(hours = 1)) # 停止之前的计时器相关逻辑... if __name__ == "__main__": app = ApplicationBuilder().token(API_KEY).build() app.add_handler(ChatMemberHandler(check_status, ChatMemberHandler.CHAT_MEMBER)) app.run_polling(drop_pending_updates = True, allowed_updates = Update.ALL_TYPES)
更新
调试发现群组内还有另一个Bot在踢人,这干扰了测试结果,但不是核心问题。另外,重启Docker容器时JobQueue被取消,但Redis中残留了旧的用户ID,可能引发部分异常。目前功能看似恢复正常,已能看到退群日志:
INFO:__main__: User <USER_ID> left at 2025-01-04T18:05:55.069938+00:00.
内容的提问来源于stack exchange,提问作者Leah
相关产品推荐
相关产品推荐

