From 30b5f9329acd80c40d8aeb96a9d04fc88904e25c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B4=9B=E6=B0=B4=E5=B1=85=E5=AE=A4?= Date: Thu, 24 Nov 2022 09:47:29 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Improve=20exception=20handling?= =?UTF-8?q?=20and=20exception=20notification?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/decorators/error.py | 102 ++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 53 deletions(-) diff --git a/utils/decorators/error.py b/utils/decorators/error.py index bfee264..4333ef7 100644 --- a/utils/decorators/error.py +++ b/utils/decorators/error.py @@ -1,25 +1,26 @@ import json from functools import wraps -from typing import Callable, cast +from typing import Callable, cast, Optional from aiohttp import ClientConnectorError from genshin import InvalidCookies, GenshinException, TooManyRequests, DataNotPublic from httpx import ConnectTimeout -from telegram import Update, ReplyKeyboardRemove, InlineKeyboardButton, InlineKeyboardMarkup +from telegram import Update, ReplyKeyboardRemove, InlineKeyboardButton, InlineKeyboardMarkup, Message from telegram.error import BadRequest, TimedOut, Forbidden -from telegram.ext import CallbackContext, ConversationHandler +from telegram.ext import CallbackContext, ConversationHandler, filters +from core.baseplugin import add_delete_message_job from modules.apihelper.error import APIHelperException, ReturnCodeError, APIHelperTimedOut, ResponseException from utils.error import UrlResourcesNotFoundError from utils.log import logger -async def send_user_notification(update: Update, context: CallbackContext, text: str): +async def send_user_notification(update: Update, context: CallbackContext, text: str) -> Optional[Message]: if not isinstance(update, Update): logger.warning("错误的消息类型 %s", repr(update)) - return + return None if update.inline_query is not None: # 忽略 inline_query - return + return None if "重新绑定" in text: buttons = InlineKeyboardMarkup( [[InlineKeyboardButton("点我重新绑定", url=f"https://t.me/{context.bot.username}?start=set_cookie")]] @@ -36,10 +37,10 @@ async def send_user_notification(update: Update, context: CallbackContext, text: if message is None: update_str = update.to_dict() if isinstance(update, Update) else str(update) logger.warning("错误的消息类型\n %s", json.dumps(update_str, indent=2, ensure_ascii=False)) - return + return None logger.info("尝试通知用户 %s[%s] 在 %s[%s] 的错误信息[%s]", user.full_name, user.id, chat.full_name, chat.id, text) try: - await message.reply_text(text, reply_markup=buttons, allow_sending_without_reply=True) + return await message.reply_text(text, reply_markup=buttons, allow_sending_without_reply=True) except ConnectTimeout: logger.error("httpx 模块连接服务器 ConnectTimeout 发送 update_id[%s] 错误信息失败", update.update_id) except BadRequest as exc: @@ -49,6 +50,7 @@ async def send_user_notification(update: Update, context: CallbackContext, text: except Exception as exc: logger.error("发送 update_id[%s] 错误信息失败 错误信息为 [%s]", update.update_id, repr(exc)) logger.exception(exc) + return None def telegram_warning(update: Update, text: str): @@ -77,95 +79,89 @@ def error_callable(func: Callable) -> Callable: return await func(*args, **kwargs) update = cast(Update, update) context = cast(CallbackContext, context) + text: str = "" try: return await func(*args, **kwargs) except ClientConnectorError: logger.error("aiohttp 模块连接服务器 ClientConnectorError") - await send_user_notification(update, context, "出错了呜呜呜 ~ 服务器连接超时 服务器熟啦 ~ 请稍后再试") - return ConversationHandler.END + text = "出错了呜呜呜 ~ 服务器连接超时 服务器熟啦 ~ 请稍后再试" except ConnectTimeout: logger.error("httpx 模块连接服务器 ConnectTimeout") - await send_user_notification(update, context, "出错了呜呜呜 ~ 服务器连接超时 服务器熟啦 ~ 请稍后再试") - return ConversationHandler.END + text = "出错了呜呜呜 ~ 服务器连接超时 服务器熟啦 ~ 请稍后再试" except TimedOut: logger.error("python-telegram-bot 模块连接服务器 TimedOut") - await send_user_notification(update, context, "出错了呜呜呜 ~ 服务器连接超时 服务器熟啦 ~ 请稍后再试") - return ConversationHandler.END + text = "出错了呜呜呜 ~ 服务器连接超时 服务器熟啦 ~ 请稍后再试" except UrlResourcesNotFoundError as exc: logger.error("URL数据资源未找到") logger.exception(exc) - await send_user_notification(update, context, "出错了呜呜呜 ~ 资源未找到 ~ ") - return ConversationHandler.END + text = "出错了呜呜呜 ~ 资源未找到 ~ " except InvalidCookies as exc: if exc.retcode in (10001, -100): - await send_user_notification(update, context, "出错了呜呜呜 ~ Cookie 无效,请尝试重新绑定") + text = "出错了呜呜呜 ~ Cookie 无效,请尝试重新绑定" elif exc.retcode == 10103: - await send_user_notification(update, context, "出错了呜呜呜 ~ Cookie 有效,但没有绑定到游戏帐户,请尝试重新绑定") + text = "出错了呜呜呜 ~ Cookie 有效,但没有绑定到游戏帐户,请尝试重新绑定" else: logger.warning("Cookie错误") logger.exception(exc) - await send_user_notification(update, context, f"出错了呜呜呜 ~ Cookie 无效 错误信息为 {exc.original} 请尝试重新绑定") - return ConversationHandler.END + text = f"出错了呜呜呜 ~ Cookie 无效 错误信息为 {exc.original} 请尝试重新绑定" except TooManyRequests as exc: logger.warning("查询次数太多(操作频繁) %s", exc) - await send_user_notification(update, context, "出错了呜呜呜 ~ 当天查询次数已经超过30次,请次日再进行查询") - return ConversationHandler.END + text = "出错了呜呜呜 ~ 当天查询次数已经超过30次,请次日再进行查询" except DataNotPublic: - await send_user_notification(update, context, "出错了呜呜呜 ~ 查询的用户数据未公开") - return ConversationHandler.END + text = "出错了呜呜呜 ~ 查询的用户数据未公开" except GenshinException as exc: if exc.retcode == -130: - await send_user_notification(update, context, "出错了呜呜呜 ~ 未设置默认角色,请尝试重新绑定") + text = "出错了呜呜呜 ~ 未设置默认角色,请尝试重新绑定" elif exc.retcode == 1034: - await send_user_notification(update, context, "出错了呜呜呜 ~ 服务器检测到该账号可能存在异常,请求被拒绝,请尝试通过验证") + text = "出错了呜呜呜 ~ 服务器检测到该账号可能存在异常,请求被拒绝,请尝试通过验证" elif exc.retcode == -500001: - await send_user_notification(update, context, "出错了呜呜呜 ~ 网络出小差了,请稍后重试~") + text = "出错了呜呜呜 ~ 网络出小差了,请稍后重试~" elif exc.retcode == -1: - await send_user_notification(update, context, "出错了呜呜呜 ~ 系统发生错误,请稍后重试~") + text = "出错了呜呜呜 ~ 系统发生错误,请稍后重试~" elif exc.retcode == -10001: # 参数异常 应该抛出错误 raise exc else: logger.error("GenshinException") logger.exception(exc) - await send_user_notification( - update, - context, - f"出错了呜呜呜 ~ 获取账号信息发生错误 错误信息为 {exc.original if exc.original else exc.retcode} ~ 请稍后再试", - ) - return ConversationHandler.END + text = f"出错了呜呜呜 ~ 获取账号信息发生错误 错误信息为 {exc.original if exc.original else exc.retcode} ~ 请稍后再试" except ReturnCodeError as exc: - await send_user_notification(update, context, f"出错了呜呜呜 ~ API请求错误 错误信息为 {exc.message} ~ 请稍后再试") - return ConversationHandler.END + text = f"出错了呜呜呜 ~ API请求错误 错误信息为 {exc.message} ~ 请稍后再试" except APIHelperTimedOut: logger.warning("APIHelperException") - await send_user_notification(update, context, "出错了呜呜呜 ~ API请求超时 ~ 请稍后再试") + text = "出错了呜呜呜 ~ API请求超时 ~ 请稍后再试" except ResponseException as exc: logger.error("APIHelperException [%s]%s", exc.code, exc.message) - await send_user_notification( - update, context, f"出错了呜呜呜 ~ API请求错误 错误信息为 {exc.message if exc.message else exc.code} ~ 请稍后再试" - ) - return ConversationHandler.END + text = f"出错了呜呜呜 ~ API请求错误 错误信息为 {exc.message if exc.message else exc.code} ~ 请稍后再试" except APIHelperException as exc: logger.error("APIHelperException") logger.exception(exc) - await send_user_notification(update, context, "出错了呜呜呜 ~ API请求错误 ~ 请稍后再试") - return ConversationHandler.END + text = "出错了呜呜呜 ~ API请求错误 ~ 请稍后再试" except BadRequest as exc: if "Replied message not found" in exc.message: telegram_warning(update, exc.message) - await send_user_notification(update, context, "气死我了!怎么有人喜欢发一个命令就秒删了!") - return ConversationHandler.END - if "Message is not modified" in exc.message: + text = "气死我了!怎么有人喜欢发一个命令就秒删了!" + elif "Message is not modified" in exc.message: telegram_warning(update, exc.message) - return ConversationHandler.END - logger.error("python-telegram-bot 请求错误") - logger.exception(exc) - await send_user_notification(update, context, "出错了呜呜呜 ~ telegram-bot-api请求错误 ~ 请稍后再试") - return ConversationHandler.END + else: + logger.error("python-telegram-bot 请求错误") + logger.exception(exc) + text = "出错了呜呜呜 ~ telegram-bot-api请求错误 ~ 请稍后再试" except Forbidden as exc: logger.error("python-telegram-bot 返回 Forbidden") logger.exception(exc) - await send_user_notification(update, context, "出错了呜呜呜 ~ telegram-bot-api请求错误 ~ 请稍后再试") - return ConversationHandler.END + text = "出错了呜呜呜 ~ telegram-bot-api请求错误 ~ 请稍后再试" + if text: + notice_message = await send_user_notification(update, context, text) + message = update.effective_message + if message: + if filters.ChatType.GROUPS.filter(message): + if notice_message: + add_delete_message_job(context, notice_message.chat_id, notice_message.message_id, 60) + add_delete_message_job(context, message.chat_id, message.message_id, 60) + else: + user = update.effective_user + chat = update.effective_chat + logger.error("发送 %s[%s] 在 %s[%s] 的通知出现问题 通知文本不存在", user.full_name, user.id, chat.full_name, chat.id) + return ConversationHandler.END return decorator