summaryrefslogtreecommitdiff
path: root/ATRI/exceptions.py
diff options
context:
space:
mode:
Diffstat (limited to 'ATRI/exceptions.py')
-rw-r--r--ATRI/exceptions.py156
1 files changed, 149 insertions, 7 deletions
diff --git a/ATRI/exceptions.py b/ATRI/exceptions.py
index f3c4f5c..cdf2925 100644
--- a/ATRI/exceptions.py
+++ b/ATRI/exceptions.py
@@ -1,14 +1,156 @@
+import os
+import json
+import string
+import time
+from pydantic import BaseModel
+from typing import Optional
+import aiofiles
+from random import sample
+from pathlib import Path
+from traceback import format_exc
+
+from nonebot.matcher import Matcher
+from nonebot.adapters.cqhttp import Bot, MessageEvent
+from nonebot.message import run_postprocessor
+from nonebot.adapters.cqhttp.message import MessageSegment
+
+from .service.send import Send
+from .log import logger
+
+
+class Error:
+ ERROR_FILE = Path('.') / 'ATRI' / 'data' / 'error'
+ ERROR_FILE.parent.mkdir(exist_ok=True, parents=True)
+
+ class ExceptionInfo(BaseModel):
+ time: str
+ rais: str
+ stack: str
+
+ @classmethod
+ def _get_file(cls, error_id: str) -> Path:
+ file_name = error_id + '.json'
+ path = cls.ERROR_FILE / file_name
+ path.parent.mkdir(exist_ok=True, parents=True)
+ return path
+
+ @classmethod
+ async def capture_error(cls,
+ rais: Optional[str],
+ error_id: str) -> str:
+ data = cls.ExceptionInfo(
+ time=time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()),
+ rais=rais,
+ stack=format_exc()
+ )
+ async with aiofiles.open(cls.ERROR_FILE, 'w',
+ encoding='utf-8') as target:
+ await target.write(
+ json.dumps(data.dict(), indent=4))
+ logger.debug(
+ f'An error occurred!Writing file success!,track id:{error_id}')
+ return error_id
+
+ @classmethod
+ async def store_error(cls, rais: str, exc):
+ error_id = ''.join(sample(string.ascii_letters + string.digits, 16))
+ data = cls.ExceptionInfo(
+ time=time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()),
+ rais=rais,
+ stack=exc
+ )
+ async with aiofiles.open(cls._get_file(error_id), 'w',
+ encoding='utf-8') as target:
+ await target.write(
+ json.dumps(data.dict(), indent=4))
+ logger.debug(
+ f'An error occurred!Writing file success!,track id:{error_id}')
+ return error_id
+
+ @classmethod
+ async def read_error(cls, error_id: str):
+ path = cls._get_file(error_id)
+ async with aiofiles.open(path, 'r', encoding='utf-8') as target:
+ data = await target.read()
+ return cls.ExceptionInfo(**json.loads(data))
+
+
class ATRIError(BaseException):
- pass
+ msg: Optional[str] = None
+
+ async def __init__(self, msg: Optional[str]) -> None:
+ super().__init__(self)
+ self.msg = msg or self.__class__.msg or self.__class__.__name__
+ self.error = format_exc()
+ self.error_id = ''.join(
+ sample(string.ascii_letters + string.digits, 16))
+ await Error.capture_error(rais=self.msg, error_id=self.error_id)
+
+
+class BotSelfError(ATRIError):
+ msg = '程序自身错误'
+
+
+class InvalidConfig(ATRIError):
+ msg = '配置文件有问题'
+
+
+class InvalidRequest(ATRIError):
+ msg = '网络请求错误'
+
+
+class InvalidWriteText(ATRIError):
+ msg = '写入目标失败'
+
+
+class InvalidSetting(ATRIError):
+ msg = '改变变量失败'
-class InvalidConfigError(ATRIError):
- """配置文件有问题"""
+class InvalidLoad(ATRIError):
+ msg = '读取失败'
-class InvalidPluginError(ATRIError):
- """插件有问题"""
+@run_postprocessor # type: ignore
+async def _(matcher: Matcher, exception: Optional[Exception], bot: Bot,
+ event: MessageEvent, state: dict) -> None:
+ if not exception:
+ return
+ error_id = ''
+ try:
+ raise exception
+ except ATRIError as error:
+ error_msg = error.msg
+ error_id = error.error_id
+ # exc = error
+ except Exception as error:
+ error_msg = 'Unknown ERROR' + error.__class__.__name__
+ try:
+ error_id = await Error.store_error(rais=str(error), exc=format_exc())
+ except:
+ await matcher.finish(
+ MessageSegment.image(
+ file=f"file:///{Path('.').resolve() / 'ATRI' / 'data' / 'emoji' / 'error.jpg'}"))
+ repo_msg = (
+ "发生了意料之外的错误///\n"
+ "报错连自己都无法截取惹...\n"
+ "请翻阅log吧...顺便发个issues(\n"
+ f"Time: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}"
+ )
+ await Send.send_to_superuser(repo_msg)
-class InvalidRequestError(ATRIError):
- """网络请求有问题"""
+ logger.debug(
+ f'An error occurred!Writing file success!,track id:{error_id}')
+ await bot.send(
+ event,
+ message=MessageSegment.image(
+ file=f"file:///{Path('.').resolve() / 'ATRI' / 'data' / 'emoji' / 'error.jpg'}")
+ )
+ repo_msg = (
+ "WARNING, This is an ERROR!\n"
+ f"Track ID: {error_id}\n"
+ f"Reason: {error_msg}\n"
+ f"Please contact author!"
+ )
+ await Send.send_to_superuser(repo_msg)