summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ATRI/configs/config.py2
-rw-r--r--ATRI/exceptions.py40
-rw-r--r--ATRI/plugins/bilibili_dynamic/__init__.py4
-rw-r--r--ATRI/plugins/bilibili_dynamic/data_source.py4
-rw-r--r--ATRI/plugins/code_runner/__init__.py6
-rw-r--r--ATRI/plugins/essential/__init__.py2
-rw-r--r--ATRI/plugins/essential/models.py1
-rw-r--r--ATRI/plugins/funny/__init__.py11
-rw-r--r--ATRI/plugins/funny/data_source.py53
-rw-r--r--ATRI/plugins/rss/rss_mikanan/__init__.py5
-rw-r--r--ATRI/plugins/rss/rss_rsshub/__init__.py4
-rw-r--r--ATRI/plugins/setu/__init__.py37
-rw-r--r--ATRI/plugins/setu/data_source.py115
-rw-r--r--ATRI/plugins/setu/models.py6
-rw-r--r--ATRI/plugins/setu/nsfw_checker.py4
-rw-r--r--ATRI/plugins/status.py135
-rw-r--r--ATRI/plugins/status/__init__.py45
-rw-r--r--ATRI/plugins/status/data_source.py88
-rw-r--r--ATRI/plugins/thesaurus/data_source.py9
-rw-r--r--ATRI/plugins/twitter/__init__.py6
-rw-r--r--ATRI/utils/__init__.py97
-rw-r--r--poetry.lock129
-rw-r--r--pyproject.toml2
23 files changed, 397 insertions, 408 deletions
diff --git a/ATRI/configs/config.py b/ATRI/configs/config.py
index 3ea0bf7..23cd1bb 100644
--- a/ATRI/configs/config.py
+++ b/ATRI/configs/config.py
@@ -61,7 +61,7 @@ class Config:
command_sep=bot_conf.command_sep,
session_expire_timeout=bot_conf.session_expire_timeout,
gocq_accounts=gocq_conf.accounts,
- gocq_download_domain=gocq_conf.download_version,
+ gocq_download_domain=gocq_conf.download_domain,
gocq_version=gocq_conf.download_version,
gocq_webui_username=gocq_conf.gocq_webui_username,
gocq_webui_password=gocq_conf.gocq_webui_password,
diff --git a/ATRI/exceptions.py b/ATRI/exceptions.py
index 22f643f..457acc8 100644
--- a/ATRI/exceptions.py
+++ b/ATRI/exceptions.py
@@ -7,13 +7,12 @@ from pydantic.main import BaseModel
from nonebot.matcher import Matcher
from nonebot.adapters.onebot.v11 import ActionFailed
-from nonebot.adapters.onebot.v11 import Bot, PrivateMessageEvent, GroupMessageEvent
+from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent
from nonebot.message import run_postprocessor
-from ATRI import conf
-
from .log import log
-from .utils import gen_random_str
+from .message import MessageBuilder
+from .utils import Limiter, gen_random_str
ERROR_DIR = Path(".") / "data" / "errors"
@@ -103,6 +102,9 @@ class RssError(BaseBotException):
prompt = "RSS订阅错误"
+limiter = Limiter(3, 600)
+
+
@run_postprocessor
async def _(bot: Bot, event, matcher: Matcher, exception: Optional[Exception]):
if not exception:
@@ -117,21 +119,23 @@ async def _(bot: Bot, event, matcher: Matcher, exception: Optional[Exception]):
prompt = "请参考协议端输出"
track_id = _save_error(prompt, format_exc())
except Exception as err:
- prompt = "Unknown ERROR->" + err.__class__.__name__
+ prompt = "UnkErr " + err.__class__.__name__
track_id = _save_error(prompt, format_exc())
- if isinstance(event, PrivateMessageEvent):
- _id = "用户" + event.get_user_id()
- elif isinstance(event, GroupMessageEvent):
- _id = "群" + str(event.group_id)
- else:
- _id = "unknown"
-
log.error(f"Error Track ID: {track_id}")
- msg = f"呜——出错了...追踪: {track_id}\n来自: {_id}"
- for superusers in conf.BotConfig.superusers:
- try:
- await bot.send_private_msg(user_id=superusers, message=msg)
- except BaseBotException:
- return
+ msg = (
+ MessageBuilder("呜——出错了...请反馈维护者")
+ .text(f"信息: {prompt}")
+ .text(f"追踪ID: {track_id}")
+ )
+ if isinstance(event, GroupMessageEvent):
+ group_id = str(event.group_id)
+ if not limiter.check(group_id):
+ msg = MessageBuilder("该群报错提示已达限制, 将冷却10min").text("如需反馈请: 来杯红茶")
+ limiter.increase(group_id)
+
+ try:
+ await matcher.finish(msg)
+ except Exception:
+ return
diff --git a/ATRI/plugins/bilibili_dynamic/__init__.py b/ATRI/plugins/bilibili_dynamic/__init__.py
index 7459a15..c47feed 100644
--- a/ATRI/plugins/bilibili_dynamic/__init__.py
+++ b/ATRI/plugins/bilibili_dynamic/__init__.py
@@ -16,8 +16,8 @@ from nonebot.adapters.onebot.v11 import Message, MessageSegment, GroupMessageEve
from ATRI.log import log
from ATRI.service import Service
+from ATRI.utils import TimeDealer
from ATRI.permission import MASTER, ADMIN
-from ATRI.utils import timestamp2datetime
from ATRI.utils.apscheduler import scheduler
from ATRI.database import BilibiliSubscription
@@ -192,7 +192,7 @@ async def _():
m.uid,
m.group_id,
{
- "last_update": timestamp2datetime(i["timestamp"]),
+ "last_update": TimeDealer(float(i["timestamp"])).to_datetime(),
},
)
if _pic:
diff --git a/ATRI/plugins/bilibili_dynamic/data_source.py b/ATRI/plugins/bilibili_dynamic/data_source.py
index 26ebf50..2bdfee9 100644
--- a/ATRI/plugins/bilibili_dynamic/data_source.py
+++ b/ATRI/plugins/bilibili_dynamic/data_source.py
@@ -3,7 +3,7 @@ from datetime import datetime
from operator import itemgetter
from ATRI.message import MessageBuilder
-from ATRI.utils import timestamp2datetime
+from ATRI.utils import TimeDealer
from ATRI.exceptions import BilibiliDynamicError
from .db import DB
@@ -95,7 +95,7 @@ class BilibiliDynamicSubscriptor:
pattern["like"] = desc["like"]
pattern["dynamic_id"] = desc["dynamic_id"]
pattern["timestamp"] = desc["timestamp"]
- pattern["time"] = timestamp2datetime(desc["timestamp"])
+ pattern["time"] = TimeDealer(float(desc["timestamp"])).to_datetime()
pattern["type_zh"] = str()
# alternative 部分
diff --git a/ATRI/plugins/code_runner/__init__.py b/ATRI/plugins/code_runner/__init__.py
index 26fcce5..95d3b0c 100644
--- a/ATRI/plugins/code_runner/__init__.py
+++ b/ATRI/plugins/code_runner/__init__.py
@@ -6,6 +6,7 @@ from nonebot.adapters.onebot.v11 import MessageEvent, Message, MessageSegment, u
from nonebot.adapters.onebot.v11.helpers import Cooldown
from ATRI.service import Service
+from ATRI.utils import MessageChecker
from .data_source import CodeRunner
@@ -26,7 +27,7 @@ async def _code_runner(matcher: Matcher, args: Message = CommandArg()):
matcher.set_arg("opt", args)
else:
content = "请键入 /code.help 以获取帮助~!"
- await code_runner.finish(Message(content))
+ await code_runner.finish(content)
@code_runner.got("opt", prompt="需要运行的语言及代码?\n获取帮助:/code.help")
@@ -38,6 +39,9 @@ async def _(event: MessageEvent, opt: str = ArgPlainText("opt")):
await code_runner.finish(CodeRunner().help())
content = MessageSegment.at(user_id) + str(await CodeRunner().runner(unescape(opt)))
+ is_save = MessageChecker(str(content)).check_cq_code
+ if not is_save:
+ await code_runner.finish("有潜在的风险, 不予发送")
await code_runner.finish(Message(content))
diff --git a/ATRI/plugins/essential/__init__.py b/ATRI/plugins/essential/__init__.py
index f8e3cb1..da59ef8 100644
--- a/ATRI/plugins/essential/__init__.py
+++ b/ATRI/plugins/essential/__init__.py
@@ -96,7 +96,7 @@ async def _(event: GroupRequestEvent):
user_id=user_id,
comment=apply_comment,
time=now_time,
- )
+ ).dict()
await file.write(json.dumps(data))
result = (
diff --git a/ATRI/plugins/essential/models.py b/ATRI/plugins/essential/models.py
index 4aa5693..dd2a801 100644
--- a/ATRI/plugins/essential/models.py
+++ b/ATRI/plugins/essential/models.py
@@ -1,4 +1,3 @@
-from typing import List, Optional
from pydantic import BaseModel
diff --git a/ATRI/plugins/funny/__init__.py b/ATRI/plugins/funny/__init__.py
index 094e569..8b060cc 100644
--- a/ATRI/plugins/funny/__init__.py
+++ b/ATRI/plugins/funny/__init__.py
@@ -63,14 +63,3 @@ async def _deal_fake(
await bot.send_group_forward_msg(group_id=group_id, messages=node)
except Exception:
await fake_msg.finish("构造失败惹...可能是被制裁了(")
-
-
-eat_what = plugin.on_regex(r"大?[今明后]天(.*?)吃[什啥]么?", "我来决定你吃什么!")
-
-
-@eat_what.handle([Cooldown(15, prompt="慢慢吃,不要贪心哦!")])
-async def _eat_what(event: MessageEvent):
- msg = str(event.get_message())
- user_name = event.sender.nickname or "裙友"
- eat = await Funny().eat_what(user_name, msg)
- await eat_what.finish(Message(eat))
diff --git a/ATRI/plugins/funny/data_source.py b/ATRI/plugins/funny/data_source.py
index d3f88cc..9437034 100644
--- a/ATRI/plugins/funny/data_source.py
+++ b/ATRI/plugins/funny/data_source.py
@@ -58,56 +58,3 @@ class Funny:
dic = {"type": "node", "data": {"name": name, "uin": qq, "content": repo}}
node.append(dic)
return node
-
- @staticmethod
- async def eat_what(name: str, msg: str) -> str:
- EAT_URL = "https://wtf.hiigara.net/api/run/"
- params = {"event": "ManualRun"}
- pattern_0 = r"大?[今明后]天(.*?)吃[什啥]么?"
- pattern_1 = r"[今|明|后|大后]天"
- arg = re.findall(pattern_0, msg)[0]
- day = re.findall(pattern_1, msg)[0]
-
- if arg == "中午":
- a = f"LdS4K6/{randint(0, 1145141919810)}"
- url = EAT_URL + a
- try:
- data = await request.post(url, params=params)
- data = data.json()
- except Exception:
- raise RequestError("Request failed!")
-
- text = Translate(data["text"]).to_simple().replace("今天", day)
- get_a = re.search(r"非常(.*?)的", text).group(0) # type: ignore
- result = text.replace(get_a, "")
-
- elif arg == "晚上":
- a = f"KaTMS/{randint(0, 1145141919810)}"
- url = EAT_URL + a
- try:
- data = await request.post(url, params=params)
- data = data.json()
- except Exception:
- raise RequestError("Request failed!")
-
- result = Translate(data["text"]).to_simple().replace("今天", day)
-
- else:
- rd = randint(1, 10)
- if rd == 5:
- result = ["吃我吧 ❤", "(脸红)请...请享用咱吧......", "都可以哦~不能挑食呢~"]
- return choice(result)
- else:
- a = f"JJr1hJ/{randint(0, 1145141919810)}"
- url = EAT_URL + a
- try:
- data = await request.post(url, params=params)
- data = data.json()
- except Exception:
- raise RequestError("Request failed!")
-
- text = Translate(data["text"]).to_simple().replace("今天", day)
- get_a = re.match(r"(.*?)的智商", text).group(0) # type: ignore
- result = text.replace(get_a, f"{name}的智商")
-
- return result
diff --git a/ATRI/plugins/rss/rss_mikanan/__init__.py b/ATRI/plugins/rss/rss_mikanan/__init__.py
index ec8dd60..fb4b23c 100644
--- a/ATRI/plugins/rss/rss_mikanan/__init__.py
+++ b/ATRI/plugins/rss/rss_mikanan/__init__.py
@@ -17,8 +17,7 @@ from ATRI.log import log
from ATRI.service import Service
from ATRI.permission import ADMIN
from ATRI.message import MessageBuilder
-from ATRI.plugins.rss.rss_rsshub.data_source import RssHubSubscriptor
-from ATRI.utils import timestamp2datetime
+from ATRI.utils import TimeDealer
from ATRI.utils.apscheduler import scheduler
from ATRI.database import RssMikananiSubcription
@@ -168,5 +167,5 @@ async def _():
bot = get_bot()
await bot.send_group_msg(group_id=data.group_id, message=repo)
await sub.update_sub(
- data._id, data.group_id, {"update_time": timestamp2datetime(m_t)}
+ data._id, data.group_id, {"update_time": TimeDealer(m_t).to_datetime()}
)
diff --git a/ATRI/plugins/rss/rss_rsshub/__init__.py b/ATRI/plugins/rss/rss_rsshub/__init__.py
index 969fe0a..137ec88 100644
--- a/ATRI/plugins/rss/rss_rsshub/__init__.py
+++ b/ATRI/plugins/rss/rss_rsshub/__init__.py
@@ -16,7 +16,7 @@ from nonebot.adapters.onebot.v11 import Message, GroupMessageEvent
from ATRI.log import log
from ATRI.service import Service
from ATRI.permission import ADMIN
-from ATRI.utils import timestamp2datetime
+from ATRI.utils import TimeDealer
from ATRI.utils.apscheduler import scheduler
from ATRI.database import RssRsshubSubcription
@@ -164,5 +164,5 @@ async def _():
bot = get_bot()
await bot.send_group_msg(group_id=m.group_id, message=repo)
await sub.update_sub(
- m._id, m.group_id, {"update_time": timestamp2datetime(ts_t)}
+ m._id, m.group_id, {"update_time": TimeDealer(ts_t).to_datetime()}
)
diff --git a/ATRI/plugins/setu/__init__.py b/ATRI/plugins/setu/__init__.py
index 1dea9b4..edb6532 100644
--- a/ATRI/plugins/setu/__init__.py
+++ b/ATRI/plugins/setu/__init__.py
@@ -29,17 +29,17 @@ async def _():
async def _random_setu(bot: Bot, event: MessageEvent):
loop = asyncio.get_running_loop()
- repo, se = await Setu.random_setu()
- await bot.send(event, repo)
+ setu, setu_data = await Setu.new()
+ setu_info = f"Title: {setu_data.title}\nPid: {setu_data.pid}"
+ await bot.send(event, setu_info)
try:
- msg_1 = await bot.send(event, Message(se))
+ msg_1 = await bot.send(event, setu)
except Exception:
- await random_setu.finish("hso(发不出")
+ await random_setu.finish("hso (发不出")
- event_id = msg_1["message_id"]
- loop.create_task(Setu.async_recall(bot, event_id))
- loop.close()
+ msg_id = msg_1["message_id"]
+ loop.call_later(60, lambda: loop.create_task(bot.delete_msg(message_id=msg_id)))
@random_setu.got("r_rush_after_think", prompt="看完不来点感想么-w-")
@@ -54,27 +54,24 @@ async def _(think: str = ArgPlainText("r_rush_after_think")):
tag_setu = plugin.on_regex(r"来[张点丶份](.*?)的[涩色🐍]图", "根据提供的tag查找涩图,冷却2分钟")
-@tag_setu.handle([Cooldown(120, prompt="慢...慢一..点❤")])
+@tag_setu.handle([Cooldown(120, prompt="")])
async def _tag_setu(bot: Bot, event: MessageEvent):
loop = asyncio.get_running_loop()
msg = str(event.get_message()).strip()
pattern = r"来[张点丶份](.*?)的[涩色🐍]图"
tag = re.findall(pattern, msg)[0]
- repo, se = await Setu.tag_setu(tag)
- if not plugin:
- await tag_setu.finish(repo)
-
- await bot.send(event, repo)
+ setu, setu_data = await Setu.new(tag)
+ setu_info = f"Title: {setu_data.title}\nPid: {setu_data.pid}"
+ await bot.send(event, setu_info)
try:
- msg_1 = await bot.send(event, Message(se))
+ msg_1 = await bot.send(event, setu)
except Exception:
- await random_setu.finish("hso(发不出")
+ await random_setu.finish("hso (发不出")
- event_id = msg_1["message_id"]
- loop.create_task(Setu.async_recall(bot, event_id))
- loop.close()
+ msg_id = msg_1["message_id"]
+ loop.call_later(60, lambda: loop.create_task(bot.delete_msg(message_id=msg_id)))
@tag_setu.got("t_rush_after_think", prompt="看完不来点感想么-w-")
@@ -101,7 +98,7 @@ async def _setu_catcher(bot: Bot, event: MessageEvent):
hso = list()
for i in args:
try:
- data = await Setu.detecter(i, _catcher_max_file_size)
+ data = await Setu(i).detecter(_catcher_max_file_size)
except Exception:
return
if data > 0.7:
@@ -140,7 +137,7 @@ async def _deal_check(bot: Bot, event: MessageEvent):
if not args:
await nsfw_checker.reject("请发送图片而不是其他东西!!")
- hso = await Setu.detecter(args[0], _catcher_max_file_size)
+ hso = await Setu(args[0]).detecter(_catcher_max_file_size)
if not hso:
await nsfw_checker.finish("图太小了!不测!")
diff --git a/ATRI/plugins/setu/data_source.py b/ATRI/plugins/setu/data_source.py
index 79a36e0..59f511a 100644
--- a/ATRI/plugins/setu/data_source.py
+++ b/ATRI/plugins/setu/data_source.py
@@ -1,81 +1,72 @@
-import asyncio
-from nonebot.adapters.onebot.v11 import Bot, MessageSegment
+from typing import Tuple
+from nonebot.adapters.onebot.v11 import MessageSegment
from ATRI import conf
from ATRI.utils import request
+from ATRI.exceptions import RequestError
+
+from .models import SetuInfo
from .nsfw_checker import detect_image, init_model
-LOLICON_URL = "https://api.lolicon.app/setu/v2"
-DEFAULT_SETU = (
- "https://i.pixiv.cat/img-original/img/2021/02/28/22/44/49/88124144_p0.jpg"
-)
+_LOLICON_URL = "https://api.lolicon.app/setu/v2"
class Setu:
- @staticmethod
- def _use_proxy(url: str) -> str:
- if conf.Setu.reverse_proxy:
- return url.replace("i.pixiv.cat", conf.Setu.reverse_proxy_domain)
- else:
- return url
+ def __init__(self, url: str):
+ self.url = url
@classmethod
- async def random_setu(cls) -> tuple:
- """
- 随机涩图.
- """
- res = await request.get(LOLICON_URL)
- data: dict = res.json()
- temp_data: dict = data.get("data", list())
- if not temp_data:
- return "涩批爬", None
+ async def new(cls, tag: str = str()) -> Tuple[MessageSegment, SetuInfo]:
+ """new 一个涩图
- data: dict = temp_data[0]
- title = data.get("title", "木陰のねこ")
- p_id = data.get("pid", 88124144)
- url: str = data["urls"].get("original", "ignore")
+ Args:
+ tag (str, optional): 附加 tag, 默认无
- setu = MessageSegment.image(cls._use_proxy(url), timeout=114514)
- repo = f"Title: {title}\nPid: {p_id}"
- return repo, setu
+ Raises:
+ RequestError: 涩图请求失败
- @classmethod
- async def tag_setu(cls, tag: str) -> tuple:
- """
- 指定tag涩图.
- """
- url = LOLICON_URL + f"?tag={tag}"
- res = await request.get(url)
- data: dict = res.json()
-
- temp_data: dict = data.get("data", list())
- if not temp_data:
- return f"没有 {tag} 的涩图呢...", None
-
- data = temp_data[0]
- title = data.get("title", "木陰のねこ")
- p_id = data.get("pid", 88124144)
- url = data["urls"].get(
- "original",
- cls._use_proxy(DEFAULT_SETU),
- )
- setu = MessageSegment.image(url, timeout=114514)
- repo = f"Title: {title}\nPid: {p_id}"
- return repo, setu
-
- @staticmethod
- async def detecter(url: str, file_size: int) -> float:
- """
- 涩值检测.
+ Returns:
+ Tuple[MessageSegment, dict]: 涩图本体, 涩图信息
"""
- data = await detect_image(url, file_size)
- return data
+ url = _LOLICON_URL
+ if tag:
+ url = _LOLICON_URL + f"?tag={tag}"
+ try:
+ req = await request.get(url)
+ except Exception:
+ raise RequestError("setu: 请求失败")
+
+ data = req.json()
+ cache_data = data.get("data")
+ if not cache_data:
+ raise RequestError("今天不可以涩")
+
+ data = cache_data[0]
+ title = data["title"]
+ pid = data["pid"]
+ setu = data["urls"].get("original", "ignore")
- @staticmethod
- async def async_recall(bot: Bot, event_id):
- await asyncio.sleep(30)
- await bot.delete_msg(message_id=event_id)
+ if conf.Setu.reverse_proxy:
+ setu = MessageSegment.image(
+ file=setu.replace("i.pixiv.cat", conf.Setu.reverse_proxy_domain),
+ timeout=114514,
+ )
+
+ setu_data = SetuInfo(title=title, pid=pid)
+
+ return setu, setu_data
+
+ async def detecter(self, max_size: int) -> float:
+ """图片涩值检测
+
+ Args:
+ max_size (int): 检测文件大小限制
+
+ Returns:
+ float: 百分比涩值
+ """
+ return await detect_image(self.url, max_size)
from ATRI import driver
diff --git a/ATRI/plugins/setu/models.py b/ATRI/plugins/setu/models.py
new file mode 100644
index 0000000..7144f27
--- /dev/null
+++ b/ATRI/plugins/setu/models.py
@@ -0,0 +1,6 @@
+from pydantic import BaseModel
+
+
+class SetuInfo(BaseModel):
+ title: str
+ pid: str
diff --git a/ATRI/plugins/setu/nsfw_checker.py b/ATRI/plugins/setu/nsfw_checker.py
index c0bd2ba..53546f6 100644
--- a/ATRI/plugins/setu/nsfw_checker.py
+++ b/ATRI/plugins/setu/nsfw_checker.py
@@ -40,14 +40,14 @@ def prepare_image(img):
return image
-async def detect_image(url: str, file_size: int) -> float:
+async def detect_image(url: str, max_size: int) -> float:
try:
req = await request.get(url)
except Exception:
raise RequestError("Get info from download image failed!")
img_byte = getsizeof(req.read()) // 1024
- if img_byte < file_size:
+ if img_byte < max_size:
return 0
try:
diff --git a/ATRI/plugins/status.py b/ATRI/plugins/status.py
new file mode 100644
index 0000000..d6a5682
--- /dev/null
+++ b/ATRI/plugins/status.py
@@ -0,0 +1,135 @@
+import os
+import time
+import psutil
+from typing import Tuple
+from datetime import datetime
+
+from nonebot import get_bot
+from nonebot.adapters.onebot.v11 import unescape
+
+from ATRI.log import log
+from ATRI.service import Service
+from ATRI.message import MessageBuilder
+from ATRI.exceptions import GetStatusError
+from ATRI.utils import Limiter
+from ATRI.utils.apscheduler import scheduler
+
+
+plugin = Service("状态").document("检查自身状态")
+
+
+ping = plugin.on_command("/ping", "检测bot是否存活")
+
+
+async def _():
+ await ping.finish("I'm fine.")
+
+
+status = plugin.on_command("/status", "检查bot运行资源占用")
+
+
+async def _():
+ msg, _ = get_status()
+ print(msg)
+ await status.finish(msg)
+
+
+limiter = Limiter(5, 21600)
+
+
[email protected]_job("interval", name="状态检查", minutes=30, misfire_grace_time=15)
+async def _():
+ log.info("检查资源消耗中...")
+ msg, stat = get_status()
+ if not stat:
+ log.warning("资源消耗异常")
+
+ try:
+ bot = get_bot()
+ except Exception:
+ bot = None
+ if not limiter.check("114514"):
+ try:
+ if bot: await plugin.send_to_master(msg)
+ limiter.increase("114514")
+ except Exception:
+ return
+ else:
+ log.info("资源消耗正常")
+
+
+_STATUS_MSG = (
+ MessageBuilder("[Status Overview]")
+ .text("[CPU: {b_cpu}% of {p_cpu}%]")
+ .text("[Memory: {b_mem} of {p_mem}%]")
+ .text("[Disk usage: {p_disk}%]")
+ .text("")
+ .text("[Net sent: {inteSENT}MB]")
+ .text("[Net recv: {inteRECV}MB]")
+ .text("")
+ .text("[Run Duration]")
+ .text("[Bot: {bot_time}]")
+ .text("[Platform: {boot_time}]")
+ .text("{msg}")
+ .done()
+)
+
+
+def get_status() -> Tuple[str, bool]:
+ try:
+ cpu = psutil.cpu_percent(interval=1)
+ mem = psutil.virtual_memory().percent
+ disk = psutil.disk_usage("/").percent
+ inte_send = psutil.net_io_counters().bytes_sent / 1000000
+ inte_recv = psutil.net_io_counters().bytes_recv / 1000000
+
+ process = psutil.Process(os.getpid())
+ b_cpu = process.cpu_percent(interval=1)
+ b_mem = process.memory_percent(memtype="rss")
+
+ now = time.time()
+ boot = psutil.boot_time()
+ b = process.create_time()
+ boot_time = str(
+ datetime.utcfromtimestamp(now).replace(microsecond=0)
+ - datetime.utcfromtimestamp(boot).replace(microsecond=0)
+ )
+ bot_time = str(
+ datetime.utcfromtimestamp(now).replace(microsecond=0)
+ - datetime.utcfromtimestamp(b).replace(microsecond=0)
+ )
+ except Exception:
+ raise GetStatusError("Failed to get status.")
+
+ msg = "アトリは、高性能ですから!"
+ if cpu > 90:
+ msg = "咱感觉有些头晕..."
+ is_ok = False
+ if mem > 90:
+ msg = "咱感觉有点头晕并且有点累..."
+ is_ok = False
+ elif mem > 90:
+ msg = "咱感觉有点累..."
+ is_ok = False
+ elif disk > 90:
+ msg = "咱感觉身体要被塞满了..."
+ is_ok = False
+ else:
+ is_ok = True
+
+ msg0 = _STATUS_MSG.format(
+ p_cpu=cpu,
+ p_mem=mem,
+ p_disk=disk,
+ b_cpu=b_cpu,
+ b_mem="%.1f%%" % b_mem,
+ inteSENT=inte_send,
+ inteRECV=inte_recv,
+ bot_time=bot_time,
+ boot_time=boot_time,
+ msg=msg,
+ )
+
+ return unescape(msg0), is_ok \ No newline at end of file
diff --git a/ATRI/plugins/status/__init__.py b/ATRI/plugins/status/__init__.py
deleted file mode 100644
index 08e099c..0000000
--- a/ATRI/plugins/status/__init__.py
+++ /dev/null
@@ -1,45 +0,0 @@
-from nonebot import get_bot
-
-from ATRI import conf
-from ATRI.log import log
-from ATRI.service import Service
-from ATRI.utils.apscheduler import scheduler
-
-from .data_source import Status
-
-
-plugin = Service("状态").document("检查自身状态")
-
-
-ping = plugin.on_command("/ping", "检测bot简单信息处理速度")
-
-
-async def _():
- await ping.finish(Status.ping())
-
-
-status = plugin.on_command("/status", "查看运行资源占用")
-
-
-async def _():
- msg, _ = Status.get_status()
- await status.finish(msg)
-
-
-info_msg = "アトリは高性能ですから!"
-
-
[email protected]_job("interval", name="状态检查", minutes=10, misfire_grace_time=15) # type: ignore
-async def _():
- log.info("开始检查资源消耗...")
- msg, stat = Status.get_status()
- if not stat:
- log.warning(msg)
-
- bot = get_bot()
- for super in conf.BotConfig.superusers:
- await bot.send_private_msg(user_id=super, message=msg)
-
- log.info("资源消耗正常")
diff --git a/ATRI/plugins/status/data_source.py b/ATRI/plugins/status/data_source.py
deleted file mode 100644
index 5daea59..0000000
--- a/ATRI/plugins/status/data_source.py
+++ /dev/null
@@ -1,88 +0,0 @@
-import os
-import time
-import psutil
-from datetime import datetime
-
-from ATRI.service import Service
-from ATRI.message import MessageBuilder
-from ATRI.exceptions import GetStatusError
-
-
-_STATUS_MSG = (
- MessageBuilder("> Status Overview")
- .text("[CPU: {b_cpu}% of {p_cpu}%]")
- .text("[Memory: {b_mem} of {p_mem}%]")
- .text("[Disk usage: {p_disk}%]")
- .text("")
- .text("[Net sent: {inteSENT}MB]")
- .text("[Net recv: {inteRECV}MB]")
- .text("")
- .text("[Bot runtime: {bot_time}]")
- .text("[Platform runtime: {boot_time}]")
- .text("{msg}")
- .done()
-)
-
-
-class Status:
- @staticmethod
- def ping() -> str:
- return "I'm fine."
-
- @staticmethod
- def get_status() -> tuple:
- try:
- cpu = psutil.cpu_percent(interval=1)
- mem = psutil.virtual_memory().percent
- disk = psutil.disk_usage("/").percent
- inte_send = psutil.net_io_counters().bytes_sent / 1000000 # type: ignore
- inte_recv = psutil.net_io_counters().bytes_recv / 1000000 # type: ignore
-
- process = psutil.Process(os.getpid())
- b_cpu = process.cpu_percent(interval=1)
- b_mem = process.memory_percent(memtype="rss")
-
- now = time.time()
- boot = psutil.boot_time()
- b = process.create_time()
- boot_time = str(
- datetime.utcfromtimestamp(now).replace(microsecond=0)
- - datetime.utcfromtimestamp(boot).replace(microsecond=0)
- )
- bot_time = str(
- datetime.utcfromtimestamp(now).replace(microsecond=0)
- - datetime.utcfromtimestamp(b).replace(microsecond=0)
- )
- except Exception:
- raise GetStatusError("Failed to get status.")
-
- msg = "アトリは、高性能ですから!"
- if cpu > 90: # type: ignore
- msg = "咱感觉有些头晕..."
- is_ok = False
- if mem > 90:
- msg = "咱感觉有点头晕并且有点累..."
- is_ok = False
- elif mem > 90:
- msg = "咱感觉有点累..."
- is_ok = False
- elif disk > 90:
- msg = "咱感觉身体要被塞满了..."
- is_ok = False
- else:
- is_ok = True
-
- msg0 = _STATUS_MSG.format(
- p_cpu=cpu,
- p_mem=mem,
- p_disk=disk,
- b_cpu=b_cpu,
- b_mem="%.1f%%" % b_mem,
- inteSENT=inte_send,
- inteRECV=inte_recv,
- bot_time=bot_time,
- boot_time=boot_time,
- msg=msg,
- )
-
- return msg0, is_ok
diff --git a/ATRI/plugins/thesaurus/data_source.py b/ATRI/plugins/thesaurus/data_source.py
index 8098179..8c12b16 100644
--- a/ATRI/plugins/thesaurus/data_source.py
+++ b/ATRI/plugins/thesaurus/data_source.py
@@ -1,6 +1,7 @@
import pytz
from datetime import datetime
+from ATRI.message import MessageBuilder
from ATRI.exceptions import ThesaurusError
from .db import DBForTS, DBForTAL
@@ -98,8 +99,14 @@ class ThesaurusManager:
{"matcher": q, "group_id": group_id}, is_main
)
if query_result:
+ await self.del_item(_id, group_id, is_main)
item_info = query_result[0]
- return f"""{"(需审核/投票)" if not is_main else str()}该词条已存在!! ID: {item_info._id}"""
+ return (
+ MessageBuilder(f"{str() if is_main else '(需审核/投票)'}该词条已存在!!")
+ .text(f"ID: {item_info._id}")
+ .text("因此, 此新增词条将被删除")
+ .done()
+ )
if t == "全匹配":
m_type = 0
diff --git a/ATRI/plugins/twitter/__init__.py b/ATRI/plugins/twitter/__init__.py
index a64e712..6e69cc1 100644
--- a/ATRI/plugins/twitter/__init__.py
+++ b/ATRI/plugins/twitter/__init__.py
@@ -17,7 +17,7 @@ from nonebot.adapters.onebot.v11 import Message, MessageSegment, GroupMessageEve
from ATRI.log import log
from ATRI.service import Service
from ATRI.permission import ADMIN
-from ATRI.utils import timestamp2datetime
+from ATRI.utils import TimeDealer
from ATRI.utils.apscheduler import scheduler
from ATRI.permission import MASTER
from ATRI.database import TwitterSubscription
@@ -177,7 +177,7 @@ async def _check_td():
group_list = await _bot.get_group_list()
gl = [f"{i['group_id']}" for i in group_list]
- if m.group_id not in gl:
+ if str(m.group_id) not in gl:
await sub.del_sub(m.tid, m.group_id)
log.warning(f"群 {m.group_id} 不存在, 已删除订阅 {m.name}@{m.screen_name}")
@@ -215,7 +215,7 @@ async def _check_td():
log.warning("推信息发送失败")
await sub.update_sub(
- m.tid, m.group_id, {"last_update": timestamp2datetime(ts_t)}
+ m.tid, m.group_id, {"last_update": TimeDealer(ts_t).to_datetime()}
)
if _pic:
pic = Message(MessageSegment.image(_pic))
diff --git a/ATRI/utils/__init__.py b/ATRI/utils/__init__.py
index aeeb9db..9ce3735 100644
--- a/ATRI/utils/__init__.py
+++ b/ATRI/utils/__init__.py
@@ -2,53 +2,64 @@ import os
import re
import json
import pytz
-import yaml
-import time
import string
+import asyncio
import aiofiles
from pathlib import Path
from random import sample
from datetime import datetime
from PIL import Image, ImageFile
+from collections import defaultdict
from aiofiles.threadpool.text import AsyncTextIOWrapper
-def timestamp2datetimestr(timestamp: int) -> str:
- format = "%Y-%m-%d %H:%M:%S"
- tt = time.localtime(timestamp)
- dt = time.strftime(format, tt)
- return dt
+def gen_random_str(k: int) -> str:
+ return str().join(sample(string.ascii_letters + string.digits, k))
-def timestamp2datetime(value: float) -> datetime:
- tz = pytz.timezone("Asia/Shanghai")
- return datetime.fromtimestamp(value, tz=tz)
+class TimeDealer:
+ def __init__(self, timestamp: float):
+ """对时间进行处理
+ Args:
+ timestamp (int): _description_
+ """
+ self.timestamp = timestamp
-def now_time() -> float:
- """获取当前时间的整数."""
- now_ = datetime.now()
- hour = now_.hour
- minute = now_.minute
- now = hour + minute / 60
- return now
+ def to_str(
+ self, tz=pytz.timezone("Asia/Shanghai"), format: str = "%Y-%m-%d %H:%M:%S"
+ ) -> str:
+ """将时间戳转换为格式化形式
+ Args:
+ tz: 时区. 默认: `pytz.timezone("Asia/Shanghai")`.
+ format: 时间格式. 默认: `"%Y-%m-%d %H:%M:%S"`.
-def load_yml(file: Path, encoding="utf-8") -> dict:
- """打开 yaml 格式的文件."""
- with open(file, "r", encoding=encoding) as f:
- data = yaml.safe_load(f)
- return data
+ Returns:
+ str: 格式化后的时间戳
+ """
+ return datetime.fromtimestamp(self.timestamp, tz).strftime(format)
+ def to_datetime(self, tz=pytz.timezone("Asia/Shanghai")) -> datetime:
+ """将时间戳转化成 datetime 类型
-def safe_string(value):
- if isinstance(value, bytes):
- return value.decode()
- return str(value)
+ Args:
+ tz: 时区. 默认: `pytz.timezone("Asia/Shanghai")`.
+ Returns:
+ datetime: 转换后的 datetime 类型
+ """
+ return datetime.fromtimestamp(self.timestamp, tz)
-def gen_random_str(k: int) -> str:
- return str().join(sample(string.ascii_letters + string.digits, k))
+ def int_now(self) -> float:
+ """将时间戳转换为一天中整数的时间.
+ e.g. 9:30 > 9.50
+
+ Returns:
+ float: 转换后的整数时间
+ """
+ time = datetime.fromtimestamp(self.timestamp)
+ return time.hour + time.minute / 60
class ListDealer:
@@ -220,3 +231,33 @@ class Translate:
output_str_list.append(self.text[i])
return "".join(output_str_list)
+
+
+class Limiter:
+ def __init__(self, max_count: int, down_time: float):
+ """冷却设置
+
+ Args:
+ max_count (int): 最大次数
+ down_time (float): 到达次数后的冷却时间
+ """
+ self.max_count = max_count
+ self.down_time = down_time
+ self.count = defaultdict(int)
+
+ def check(self, key: str) -> bool:
+ if self.count[key] >= self.max_count:
+ loop = asyncio.get_running_loop()
+ loop.call_later(self.down_time, self.reset)
+ return False
+
+ return True
+
+ def increase(self, key: str, times: int = 1) -> None:
+ self.count[key] += times
+
+ def reset(self, key: str) -> None:
+ self.count[key] = 0
+
+ def get_times(self, key: str) -> int:
+ return self.count[key]
diff --git a/poetry.lock b/poetry.lock
index 43ecf2e..c703ca4 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -193,7 +193,7 @@ python-versions = ">=3.5"
dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"]
docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"]
tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"]
-tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
+tests-no-zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"]
[package.source]
type = "legacy"
@@ -265,7 +265,7 @@ optional = false
python-versions = ">=3.6.0"
[package.extras]
-unicode_backport = ["unicodedata2"]
+unicode-backport = ["unicodedata2"]
[package.source]
type = "legacy"
@@ -880,7 +880,7 @@ reference = "tsinghua-mirror"
[[package]]
name = "pillow"
-version = "9.2.0"
+version = "9.3.0"
description = "Python Imaging Library (Fork)"
category = "main"
optional = false
@@ -1196,7 +1196,7 @@ urllib3 = ">=1.21.1,<1.27"
[package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
-use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"]
+use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[package.source]
type = "legacy"
@@ -1668,7 +1668,7 @@ reference = "tsinghua-mirror"
[metadata]
lock-version = "1.1"
python-versions = "^3.8.5"
-content-hash = "c14a3e98d5ab08f9bf58e1fbea6e21cd8c985b1111a34d95fc53f9f611a339df"
+content-hash = "35d36ce70a7e3286ec2d478ae0368e82e419ee3e9818d4f85844300a2f41eb62"
[metadata.files]
aiofiles = [
@@ -2272,64 +2272,67 @@ pathspec = [
{file = "pathspec-0.10.1.tar.gz", hash = "sha256:7ace6161b621d31e7902eb6b5ae148d12cfd23f4a249b9ffb6b9fee12084323d"},
]
pillow = [
- {file = "Pillow-9.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:a9c9bc489f8ab30906d7a85afac4b4944a572a7432e00698a7239f44a44e6efb"},
- {file = "Pillow-9.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:510cef4a3f401c246cfd8227b300828715dd055463cdca6176c2e4036df8bd4f"},
- {file = "Pillow-9.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7888310f6214f19ab2b6df90f3f06afa3df7ef7355fc025e78a3044737fab1f5"},
- {file = "Pillow-9.2.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:831e648102c82f152e14c1a0938689dbb22480c548c8d4b8b248b3e50967b88c"},
- {file = "Pillow-9.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1cc1d2451e8a3b4bfdb9caf745b58e6c7a77d2e469159b0d527a4554d73694d1"},
- {file = "Pillow-9.2.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:136659638f61a251e8ed3b331fc6ccd124590eeff539de57c5f80ef3a9594e58"},
- {file = "Pillow-9.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:6e8c66f70fb539301e064f6478d7453e820d8a2c631da948a23384865cd95544"},
- {file = "Pillow-9.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:37ff6b522a26d0538b753f0b4e8e164fdada12db6c6f00f62145d732d8a3152e"},
- {file = "Pillow-9.2.0-cp310-cp310-win32.whl", hash = "sha256:c79698d4cd9318d9481d89a77e2d3fcaeff5486be641e60a4b49f3d2ecca4e28"},
- {file = "Pillow-9.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:254164c57bab4b459f14c64e93df11eff5ded575192c294a0c49270f22c5d93d"},
- {file = "Pillow-9.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:adabc0bce035467fb537ef3e5e74f2847c8af217ee0be0455d4fec8adc0462fc"},
- {file = "Pillow-9.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:336b9036127eab855beec9662ac3ea13a4544a523ae273cbf108b228ecac8437"},
- {file = "Pillow-9.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50dff9cc21826d2977ef2d2a205504034e3a4563ca6f5db739b0d1026658e004"},
- {file = "Pillow-9.2.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb6259196a589123d755380b65127ddc60f4c64b21fc3bb46ce3a6ea663659b0"},
- {file = "Pillow-9.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b0554af24df2bf96618dac71ddada02420f946be943b181108cac55a7a2dcd4"},
- {file = "Pillow-9.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:15928f824870535c85dbf949c09d6ae7d3d6ac2d6efec80f3227f73eefba741c"},
- {file = "Pillow-9.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:bdd0de2d64688ecae88dd8935012c4a72681e5df632af903a1dca8c5e7aa871a"},
- {file = "Pillow-9.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5b87da55a08acb586bad5c3aa3b86505f559b84f39035b233d5bf844b0834b1"},
- {file = "Pillow-9.2.0-cp311-cp311-win32.whl", hash = "sha256:b6d5e92df2b77665e07ddb2e4dbd6d644b78e4c0d2e9272a852627cdba0d75cf"},
- {file = "Pillow-9.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6bf088c1ce160f50ea40764f825ec9b72ed9da25346216b91361eef8ad1b8f8c"},
- {file = "Pillow-9.2.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:2c58b24e3a63efd22554c676d81b0e57f80e0a7d3a5874a7e14ce90ec40d3069"},
- {file = "Pillow-9.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eef7592281f7c174d3d6cbfbb7ee5984a671fcd77e3fc78e973d492e9bf0eb3f"},
- {file = "Pillow-9.2.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dcd7b9c7139dc8258d164b55696ecd16c04607f1cc33ba7af86613881ffe4ac8"},
- {file = "Pillow-9.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a138441e95562b3c078746a22f8fca8ff1c22c014f856278bdbdd89ca36cff1b"},
- {file = "Pillow-9.2.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:93689632949aff41199090eff5474f3990b6823404e45d66a5d44304e9cdc467"},
- {file = "Pillow-9.2.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:f3fac744f9b540148fa7715a435d2283b71f68bfb6d4aae24482a890aed18b59"},
- {file = "Pillow-9.2.0-cp37-cp37m-win32.whl", hash = "sha256:fa768eff5f9f958270b081bb33581b4b569faabf8774726b283edb06617101dc"},
- {file = "Pillow-9.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:69bd1a15d7ba3694631e00df8de65a8cb031911ca11f44929c97fe05eb9b6c1d"},
- {file = "Pillow-9.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:030e3460861488e249731c3e7ab59b07c7853838ff3b8e16aac9561bb345da14"},
- {file = "Pillow-9.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:74a04183e6e64930b667d321524e3c5361094bb4af9083db5c301db64cd341f3"},
- {file = "Pillow-9.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d33a11f601213dcd5718109c09a52c2a1c893e7461f0be2d6febc2879ec2402"},
- {file = "Pillow-9.2.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fd6f5e3c0e4697fa7eb45b6e93996299f3feee73a3175fa451f49a74d092b9f"},
- {file = "Pillow-9.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a647c0d4478b995c5e54615a2e5360ccedd2f85e70ab57fbe817ca613d5e63b8"},
- {file = "Pillow-9.2.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:4134d3f1ba5f15027ff5c04296f13328fecd46921424084516bdb1b2548e66ff"},
- {file = "Pillow-9.2.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:bc431b065722a5ad1dfb4df354fb9333b7a582a5ee39a90e6ffff688d72f27a1"},
- {file = "Pillow-9.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1536ad017a9f789430fb6b8be8bf99d2f214c76502becc196c6f2d9a75b01b76"},
- {file = "Pillow-9.2.0-cp38-cp38-win32.whl", hash = "sha256:2ad0d4df0f5ef2247e27fc790d5c9b5a0af8ade9ba340db4a73bb1a4a3e5fb4f"},
- {file = "Pillow-9.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:ec52c351b35ca269cb1f8069d610fc45c5bd38c3e91f9ab4cbbf0aebc136d9c8"},
- {file = "Pillow-9.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0ed2c4ef2451de908c90436d6e8092e13a43992f1860275b4d8082667fbb2ffc"},
- {file = "Pillow-9.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ad2f835e0ad81d1689f1b7e3fbac7b01bb8777d5a985c8962bedee0cc6d43da"},
- {file = "Pillow-9.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea98f633d45f7e815db648fd7ff0f19e328302ac36427343e4432c84432e7ff4"},
- {file = "Pillow-9.2.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7761afe0126d046974a01e030ae7529ed0ca6a196de3ec6937c11df0df1bc91c"},
- {file = "Pillow-9.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a54614049a18a2d6fe156e68e188da02a046a4a93cf24f373bffd977e943421"},
- {file = "Pillow-9.2.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:5aed7dde98403cd91d86a1115c78d8145c83078e864c1de1064f52e6feb61b20"},
- {file = "Pillow-9.2.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:13b725463f32df1bfeacbf3dd197fb358ae8ebcd8c5548faa75126ea425ccb60"},
- {file = "Pillow-9.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:808add66ea764ed97d44dda1ac4f2cfec4c1867d9efb16a33d158be79f32b8a4"},
- {file = "Pillow-9.2.0-cp39-cp39-win32.whl", hash = "sha256:337a74fd2f291c607d220c793a8135273c4c2ab001b03e601c36766005f36885"},
- {file = "Pillow-9.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:fac2d65901fb0fdf20363fbd345c01958a742f2dc62a8dd4495af66e3ff502a4"},
- {file = "Pillow-9.2.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ad2277b185ebce47a63f4dc6302e30f05762b688f8dc3de55dbae4651872cdf3"},
- {file = "Pillow-9.2.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c7b502bc34f6e32ba022b4a209638f9e097d7a9098104ae420eb8186217ebbb"},
- {file = "Pillow-9.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d1f14f5f691f55e1b47f824ca4fdcb4b19b4323fe43cc7bb105988cad7496be"},
- {file = "Pillow-9.2.0-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:dfe4c1fedfde4e2fbc009d5ad420647f7730d719786388b7de0999bf32c0d9fd"},
- {file = "Pillow-9.2.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:f07f1f00e22b231dd3d9b9208692042e29792d6bd4f6639415d2f23158a80013"},
- {file = "Pillow-9.2.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1802f34298f5ba11d55e5bb09c31997dc0c6aed919658dfdf0198a2fe75d5490"},
- {file = "Pillow-9.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17d4cafe22f050b46d983b71c707162d63d796a1235cdf8b9d7a112e97b15bac"},
- {file = "Pillow-9.2.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:96b5e6874431df16aee0c1ba237574cb6dff1dcb173798faa6a9d8b399a05d0e"},
- {file = "Pillow-9.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:0030fdbd926fb85844b8b92e2f9449ba89607231d3dd597a21ae72dc7fe26927"},
- {file = "Pillow-9.2.0.tar.gz", hash = "sha256:75e636fd3e0fb872693f23ccb8a5ff2cd578801251f3a4f6854c6a5d437d3c04"},
+ {file = "Pillow-9.3.0-1-cp37-cp37m-win32.whl", hash = "sha256:e6ea6b856a74d560d9326c0f5895ef8050126acfdc7ca08ad703eb0081e82b74"},
+ {file = "Pillow-9.3.0-1-cp37-cp37m-win_amd64.whl", hash = "sha256:32a44128c4bdca7f31de5be641187367fe2a450ad83b833ef78910397db491aa"},
+ {file = "Pillow-9.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:0b7257127d646ff8676ec8a15520013a698d1fdc48bc2a79ba4e53df792526f2"},
+ {file = "Pillow-9.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b90f7616ea170e92820775ed47e136208e04c967271c9ef615b6fbd08d9af0e3"},
+ {file = "Pillow-9.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68943d632f1f9e3dce98908e873b3a090f6cba1cbb1b892a9e8d97c938871fbe"},
+ {file = "Pillow-9.3.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be55f8457cd1eac957af0c3f5ece7bc3f033f89b114ef30f710882717670b2a8"},
+ {file = "Pillow-9.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d77adcd56a42d00cc1be30843d3426aa4e660cab4a61021dc84467123f7a00c"},
+ {file = "Pillow-9.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:829f97c8e258593b9daa80638aee3789b7df9da5cf1336035016d76f03b8860c"},
+ {file = "Pillow-9.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:801ec82e4188e935c7f5e22e006d01611d6b41661bba9fe45b60e7ac1a8f84de"},
+ {file = "Pillow-9.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:871b72c3643e516db4ecf20efe735deb27fe30ca17800e661d769faab45a18d7"},
+ {file = "Pillow-9.3.0-cp310-cp310-win32.whl", hash = "sha256:655a83b0058ba47c7c52e4e2df5ecf484c1b0b0349805896dd350cbc416bdd91"},
+ {file = "Pillow-9.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:9f47eabcd2ded7698106b05c2c338672d16a6f2a485e74481f524e2a23c2794b"},
+ {file = "Pillow-9.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:57751894f6618fd4308ed8e0c36c333e2f5469744c34729a27532b3db106ee20"},
+ {file = "Pillow-9.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7db8b751ad307d7cf238f02101e8e36a128a6cb199326e867d1398067381bff4"},
+ {file = "Pillow-9.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3033fbe1feb1b59394615a1cafaee85e49d01b51d54de0cbf6aa8e64182518a1"},
+ {file = "Pillow-9.3.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22b012ea2d065fd163ca096f4e37e47cd8b59cf4b0fd47bfca6abb93df70b34c"},
+ {file = "Pillow-9.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a65733d103311331875c1dca05cb4606997fd33d6acfed695b1232ba1df193"},
+ {file = "Pillow-9.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:502526a2cbfa431d9fc2a079bdd9061a2397b842bb6bc4239bb176da00993812"},
+ {file = "Pillow-9.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:90fb88843d3902fe7c9586d439d1e8c05258f41da473952aa8b328d8b907498c"},
+ {file = "Pillow-9.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:89dca0ce00a2b49024df6325925555d406b14aa3efc2f752dbb5940c52c56b11"},
+ {file = "Pillow-9.3.0-cp311-cp311-win32.whl", hash = "sha256:3168434d303babf495d4ba58fc22d6604f6e2afb97adc6a423e917dab828939c"},
+ {file = "Pillow-9.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:18498994b29e1cf86d505edcb7edbe814d133d2232d256db8c7a8ceb34d18cef"},
+ {file = "Pillow-9.3.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:772a91fc0e03eaf922c63badeca75e91baa80fe2f5f87bdaed4280662aad25c9"},
+ {file = "Pillow-9.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa4107d1b306cdf8953edde0534562607fe8811b6c4d9a486298ad31de733b2"},
+ {file = "Pillow-9.3.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b4012d06c846dc2b80651b120e2cdd787b013deb39c09f407727ba90015c684f"},
+ {file = "Pillow-9.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77ec3e7be99629898c9a6d24a09de089fa5356ee408cdffffe62d67bb75fdd72"},
+ {file = "Pillow-9.3.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:6c738585d7a9961d8c2821a1eb3dcb978d14e238be3d70f0a706f7fa9316946b"},
+ {file = "Pillow-9.3.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:828989c45c245518065a110434246c44a56a8b2b2f6347d1409c787e6e4651ee"},
+ {file = "Pillow-9.3.0-cp37-cp37m-win32.whl", hash = "sha256:82409ffe29d70fd733ff3c1025a602abb3e67405d41b9403b00b01debc4c9a29"},
+ {file = "Pillow-9.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:41e0051336807468be450d52b8edd12ac60bebaa97fe10c8b660f116e50b30e4"},
+ {file = "Pillow-9.3.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:b03ae6f1a1878233ac620c98f3459f79fd77c7e3c2b20d460284e1fb370557d4"},
+ {file = "Pillow-9.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4390e9ce199fc1951fcfa65795f239a8a4944117b5935a9317fb320e7767b40f"},
+ {file = "Pillow-9.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40e1ce476a7804b0fb74bcfa80b0a2206ea6a882938eaba917f7a0f004b42502"},
+ {file = "Pillow-9.3.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0a06a052c5f37b4ed81c613a455a81f9a3a69429b4fd7bb913c3fa98abefc20"},
+ {file = "Pillow-9.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03150abd92771742d4a8cd6f2fa6246d847dcd2e332a18d0c15cc75bf6703040"},
+ {file = "Pillow-9.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:15c42fb9dea42465dfd902fb0ecf584b8848ceb28b41ee2b58f866411be33f07"},
+ {file = "Pillow-9.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:51e0e543a33ed92db9f5ef69a0356e0b1a7a6b6a71b80df99f1d181ae5875636"},
+ {file = "Pillow-9.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3dd6caf940756101205dffc5367babf288a30043d35f80936f9bfb37f8355b32"},
+ {file = "Pillow-9.3.0-cp38-cp38-win32.whl", hash = "sha256:f1ff2ee69f10f13a9596480335f406dd1f70c3650349e2be67ca3139280cade0"},
+ {file = "Pillow-9.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:276a5ca930c913f714e372b2591a22c4bd3b81a418c0f6635ba832daec1cbcfc"},
+ {file = "Pillow-9.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:73bd195e43f3fadecfc50c682f5055ec32ee2c933243cafbfdec69ab1aa87cad"},
+ {file = "Pillow-9.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c7c8ae3864846fc95f4611c78129301e203aaa2af813b703c55d10cc1628535"},
+ {file = "Pillow-9.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e0918e03aa0c72ea56edbb00d4d664294815aa11291a11504a377ea018330d3"},
+ {file = "Pillow-9.3.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0915e734b33a474d76c28e07292f196cdf2a590a0d25bcc06e64e545f2d146c"},
+ {file = "Pillow-9.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af0372acb5d3598f36ec0914deed2a63f6bcdb7b606da04dc19a88d31bf0c05b"},
+ {file = "Pillow-9.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:ad58d27a5b0262c0c19b47d54c5802db9b34d38bbf886665b626aff83c74bacd"},
+ {file = "Pillow-9.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:97aabc5c50312afa5e0a2b07c17d4ac5e865b250986f8afe2b02d772567a380c"},
+ {file = "Pillow-9.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9aaa107275d8527e9d6e7670b64aabaaa36e5b6bd71a1015ddd21da0d4e06448"},
+ {file = "Pillow-9.3.0-cp39-cp39-win32.whl", hash = "sha256:bac18ab8d2d1e6b4ce25e3424f709aceef668347db8637c2296bcf41acb7cf48"},
+ {file = "Pillow-9.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:b472b5ea442148d1c3e2209f20f1e0bb0eb556538690fa70b5e1f79fa0ba8dc2"},
+ {file = "Pillow-9.3.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:ab388aaa3f6ce52ac1cb8e122c4bd46657c15905904b3120a6248b5b8b0bc228"},
+ {file = "Pillow-9.3.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbb8e7f2abee51cef77673be97760abff1674ed32847ce04b4af90f610144c7b"},
+ {file = "Pillow-9.3.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bca31dd6014cb8b0b2db1e46081b0ca7d936f856da3b39744aef499db5d84d02"},
+ {file = "Pillow-9.3.0-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c7025dce65566eb6e89f56c9509d4f628fddcedb131d9465cacd3d8bac337e7e"},
+ {file = "Pillow-9.3.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ebf2029c1f464c59b8bdbe5143c79fa2045a581ac53679733d3a91d400ff9efb"},
+ {file = "Pillow-9.3.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b59430236b8e58840a0dfb4099a0e8717ffb779c952426a69ae435ca1f57210c"},
+ {file = "Pillow-9.3.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12ce4932caf2ddf3e41d17fc9c02d67126935a44b86df6a206cf0d7161548627"},
+ {file = "Pillow-9.3.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae5331c23ce118c53b172fa64a4c037eb83c9165aba3a7ba9ddd3ec9fa64a699"},
+ {file = "Pillow-9.3.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:0b07fffc13f474264c336298d1b4ce01d9c5a011415b79d4ee5527bb69ae6f65"},
+ {file = "Pillow-9.3.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:073adb2ae23431d3b9bcbcff3fe698b62ed47211d0716b067385538a1b0f28b8"},
+ {file = "Pillow-9.3.0.tar.gz", hash = "sha256:c935a22a557a560108d780f9a0fc426dd7459940dc54faa49d83249c8d3e760f"},
]
platformdirs = [
{file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"},
diff --git a/pyproject.toml b/pyproject.toml
index ef120ea..83a8435 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -18,7 +18,7 @@ default = true
python = "^3.8.5"
aiofiles = "^0.8.0"
APScheduler = "^3.9.1"
-Pillow = "^9.1.1"
+Pillow = "^9.3.0"
nonebot2 = "2.0.0-rc.1"
nonebot-adapter-onebot = "2.0.0-beta.1"
nonebot-plugin-gocqhttp = "^0.5.5"