mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2026-10-19 11:10:10 +08:00
✨ 插件商店
This commit is contained in:
@@ -1,41 +0,0 @@
|
||||
from pathlib import Path
|
||||
|
||||
from nonebot.plugin import PluginMetadata
|
||||
from nonebot.rule import to_me
|
||||
from nonebot_plugin_alconna import Alconna, Arparma, on_alconna
|
||||
from nonebot_plugin_session import EventSession
|
||||
|
||||
from zhenxun.configs.utils import PluginExtraData
|
||||
from zhenxun.services.log import logger
|
||||
from zhenxun.utils.message import MessageUtils
|
||||
|
||||
__plugin_meta__ = PluginMetadata(
|
||||
name="关于",
|
||||
description="想要更加了解真寻吗",
|
||||
usage="""
|
||||
指令:
|
||||
关于
|
||||
""".strip(),
|
||||
extra=PluginExtraData(author="HibiKier", version="0.1", menu_type="其他").dict(),
|
||||
)
|
||||
|
||||
|
||||
_matcher = on_alconna(Alconna("关于"), priority=5, block=True, rule=to_me())
|
||||
|
||||
|
||||
@_matcher.handle()
|
||||
async def _(session: EventSession, arparma: Arparma):
|
||||
ver_file = Path() / "__version__"
|
||||
version = None
|
||||
if ver_file.exists():
|
||||
with open(ver_file, "r", encoding="utf8") as f:
|
||||
version = f.read().split(":")[-1].strip()
|
||||
info = f"""
|
||||
『绪山真寻Bot』
|
||||
版本:{version}
|
||||
简介:基于Nonebot2开发,支持多平台,是一个非常可爱的Bot呀,希望与大家要好好相处
|
||||
项目地址:https://github.com/HibiKier/zhenxun_bot
|
||||
文档地址:https://hibikier.github.io/zhenxun_bot/
|
||||
""".strip()
|
||||
await MessageUtils.build_message(info).send()
|
||||
logger.info("查看关于", arparma.header_result, session=session)
|
||||
@@ -1,87 +0,0 @@
|
||||
import nonebot
|
||||
from nonebot.adapters import Bot
|
||||
from nonebot.permission import SUPERUSER
|
||||
from nonebot.plugin import PluginMetadata
|
||||
from nonebot_plugin_alconna import Alconna, Args, Match, on_alconna
|
||||
from nonebot_plugin_session import EventSession
|
||||
|
||||
from zhenxun.configs.utils import PluginExtraData, RegisterConfig
|
||||
from zhenxun.services.log import logger
|
||||
from zhenxun.utils.enum import PluginType
|
||||
from zhenxun.utils.message import MessageUtils
|
||||
|
||||
from ._data_source import UpdateManage
|
||||
|
||||
__plugin_meta__ = PluginMetadata(
|
||||
name="自动更新",
|
||||
description="就算是真寻也会成长的",
|
||||
usage="""
|
||||
usage:
|
||||
检查更新真寻最新版本,包括了自动更新
|
||||
指令:
|
||||
检查更新真寻
|
||||
""".strip(),
|
||||
extra=PluginExtraData(
|
||||
author="HibiKier",
|
||||
version="0.1",
|
||||
plugin_type=PluginType.SUPERUSER,
|
||||
configs=[
|
||||
RegisterConfig(
|
||||
key="UPDATE_REMIND",
|
||||
value=True,
|
||||
help="是否检测更新版本",
|
||||
default_value=True,
|
||||
),
|
||||
RegisterConfig(
|
||||
key="UPDATE_REMIND",
|
||||
value=True,
|
||||
help="是否检测更新版本",
|
||||
default_value=True,
|
||||
),
|
||||
],
|
||||
).dict(),
|
||||
)
|
||||
|
||||
_matcher = on_alconna(
|
||||
Alconna("检查更新", Args["ver_type?", ["main", "dev", "release"]]),
|
||||
priority=1,
|
||||
block=True,
|
||||
permission=SUPERUSER,
|
||||
)
|
||||
|
||||
|
||||
@_matcher.handle()
|
||||
async def _(bot: Bot, session: EventSession, ver_type: Match[str]):
|
||||
if not session.id1:
|
||||
await MessageUtils.build_message("用户id为空...").finish()
|
||||
if not ver_type.available:
|
||||
result = await UpdateManage.check_version()
|
||||
logger.info("查看当前版本...", "检查更新", session=session)
|
||||
await MessageUtils.build_message(result).finish()
|
||||
try:
|
||||
result = await UpdateManage.update(bot, session.id1, ver_type.result)
|
||||
except Exception as e:
|
||||
logger.error("版本更新失败...", "检查更新", session=session, e=e)
|
||||
await MessageUtils.build_message(f"更新版本失败...e: {e}").finish()
|
||||
if result:
|
||||
await MessageUtils.build_message(result).finish()
|
||||
await MessageUtils.build_message("更新版本失败...").finish()
|
||||
|
||||
|
||||
# driver = nonebot.get_driver()
|
||||
|
||||
|
||||
# @driver.on_startup
|
||||
# async def _():
|
||||
# result = await UpdateManage.check_version()
|
||||
# print("-----------------------")
|
||||
# print("-----------------------")
|
||||
# print(result)
|
||||
# print("-----------------------")
|
||||
# print("-----------------------")
|
||||
# result = await UpdateManage.update(None, "", "dev")
|
||||
# print("-----------------------")
|
||||
# print("-----------------------")
|
||||
# print(result)
|
||||
# print("-----------------------")
|
||||
# print("-----------------------")
|
||||
@@ -1,202 +0,0 @@
|
||||
import os
|
||||
import shutil
|
||||
import tarfile
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
from nonebot.adapters import Bot
|
||||
from nonebot.utils import run_sync
|
||||
|
||||
from zhenxun.services.log import logger
|
||||
from zhenxun.utils.http_utils import AsyncHttpx
|
||||
from zhenxun.utils.platform import PlatformUtils
|
||||
|
||||
from .config import (
|
||||
BACKUP_PATH,
|
||||
BASE_PATH,
|
||||
DEV_URL,
|
||||
DOWNLOAD_GZ_FILE,
|
||||
DOWNLOAD_ZIP_FILE,
|
||||
MAIN_URL,
|
||||
PYPROJECT_FILE,
|
||||
PYPROJECT_LOCK_FILE,
|
||||
RELEASE_URL,
|
||||
REPLACE_FOLDERS,
|
||||
TMP_PATH,
|
||||
VERSION_FILE,
|
||||
)
|
||||
|
||||
|
||||
@run_sync
|
||||
def _file_handle(latest_version: str | None):
|
||||
"""文件移动操作
|
||||
|
||||
参数:
|
||||
latest_version: 版本号
|
||||
"""
|
||||
BACKUP_PATH.mkdir(exist_ok=True, parents=True)
|
||||
logger.debug("开始解压文件压缩包...", "检查更新")
|
||||
download_file = DOWNLOAD_GZ_FILE
|
||||
if DOWNLOAD_GZ_FILE.exists():
|
||||
tf = tarfile.open(DOWNLOAD_GZ_FILE)
|
||||
else:
|
||||
download_file = DOWNLOAD_ZIP_FILE
|
||||
tf = zipfile.ZipFile(DOWNLOAD_ZIP_FILE)
|
||||
tf.extractall(TMP_PATH)
|
||||
logger.debug("解压文件压缩包完成...", "检查更新")
|
||||
download_file_path = (
|
||||
TMP_PATH / [x for x in os.listdir(TMP_PATH) if (TMP_PATH / x).is_dir()][0]
|
||||
)
|
||||
_pyproject = download_file_path / "pyproject.toml"
|
||||
_lock_file = download_file_path / "poetry.lock"
|
||||
extract_path = download_file_path / "zhenxun"
|
||||
target_path = BASE_PATH
|
||||
if PYPROJECT_FILE.exists():
|
||||
logger.debug(f"移除备份文件: {PYPROJECT_FILE}", "检查更新")
|
||||
shutil.move(PYPROJECT_FILE, BACKUP_PATH / "pyproject.toml")
|
||||
if PYPROJECT_LOCK_FILE.exists():
|
||||
logger.debug(f"移除备份文件: {PYPROJECT_FILE}", "检查更新")
|
||||
shutil.move(PYPROJECT_LOCK_FILE, BACKUP_PATH / "poetry.lock")
|
||||
if _pyproject.exists():
|
||||
logger.debug("移动文件: pyproject.toml", "检查更新")
|
||||
shutil.move(_pyproject, Path() / "pyproject.toml")
|
||||
if _lock_file.exists():
|
||||
logger.debug("移动文件: pyproject.toml", "检查更新")
|
||||
shutil.move(_lock_file, Path() / "poetry.lock")
|
||||
for folder in REPLACE_FOLDERS:
|
||||
"""移动指定文件夹"""
|
||||
_dir = BASE_PATH / folder
|
||||
_backup_dir = BACKUP_PATH / folder
|
||||
if _backup_dir.exists():
|
||||
logger.debug(f"删除备份文件夹 {_backup_dir}", "检查更新")
|
||||
shutil.rmtree(_backup_dir)
|
||||
if _dir.exists():
|
||||
logger.debug(f"移动旧文件夹 {_dir}", "检查更新")
|
||||
shutil.move(_dir, _backup_dir)
|
||||
else:
|
||||
logger.warning(f"文件夹 {_dir} 不存在,跳过删除", "检查更新")
|
||||
for folder in REPLACE_FOLDERS:
|
||||
src_folder_path = extract_path / folder
|
||||
dest_folder_path = target_path / folder
|
||||
if src_folder_path.exists():
|
||||
logger.debug(
|
||||
f"移动文件夹: {src_folder_path} -> {dest_folder_path}", "检查更新"
|
||||
)
|
||||
shutil.move(src_folder_path, dest_folder_path)
|
||||
else:
|
||||
logger.debug(f"源文件夹不存在: {src_folder_path}", "检查更新")
|
||||
if download_file.exists():
|
||||
logger.debug(f"删除下载文件: {download_file}", "检查更新")
|
||||
download_file.unlink()
|
||||
if extract_path.exists():
|
||||
logger.debug(f"删除解压文件夹: {extract_path}", "检查更新")
|
||||
shutil.rmtree(extract_path)
|
||||
if tf:
|
||||
tf.close()
|
||||
if TMP_PATH.exists():
|
||||
shutil.rmtree(TMP_PATH)
|
||||
if latest_version:
|
||||
with open(VERSION_FILE, "w", encoding="utf8") as f:
|
||||
f.write(f"__version__: {latest_version}")
|
||||
os.system(f"poetry install --directory={Path().absolute()}")
|
||||
|
||||
|
||||
class UpdateManage:
|
||||
|
||||
@classmethod
|
||||
async def check_version(cls) -> str:
|
||||
"""检查更新版本
|
||||
|
||||
返回:
|
||||
str: 更新信息
|
||||
"""
|
||||
cur_version = cls.__get_version()
|
||||
data = await cls.__get_latest_data()
|
||||
if not data:
|
||||
return "检查更新获取版本失败..."
|
||||
return f"检测到当前版本更新\n当前版本:{cur_version}\n最新版本:{data.get('name')}\n创建日期:{data.get('created_at')}\n更新内容:\n{data.get('body')}"
|
||||
|
||||
@classmethod
|
||||
async def update(cls, bot: Bot, user_id: str, version_type: str) -> str | None:
|
||||
"""更新操作
|
||||
|
||||
参数:
|
||||
bot: Bot
|
||||
user_id: 用户id
|
||||
version_type: 更新版本类型
|
||||
|
||||
返回:
|
||||
str | None: 返回消息
|
||||
"""
|
||||
logger.info(f"开始下载真寻最新版文件....", "检查更新")
|
||||
cur_version = cls.__get_version()
|
||||
new_version = "main"
|
||||
url = MAIN_URL
|
||||
if version_type == "dev":
|
||||
url = DEV_URL
|
||||
new_version = "dev"
|
||||
if version_type == "release":
|
||||
data = await cls.__get_latest_data()
|
||||
if not data:
|
||||
return "获取更新版本失败..."
|
||||
url = data.get("tarball_url")
|
||||
new_version = data.get("name")
|
||||
url = (await AsyncHttpx.get(url)).headers.get("Location") # type: ignore
|
||||
if not url:
|
||||
return "获取版本下载链接失败..."
|
||||
if TMP_PATH.exists():
|
||||
logger.debug(f"删除临时文件夹 {TMP_PATH}", "检查更新")
|
||||
shutil.rmtree(TMP_PATH)
|
||||
logger.debug(
|
||||
f"开始更新版本:{cur_version} -> {new_version} | 下载链接:{url}",
|
||||
"检查更新",
|
||||
)
|
||||
await PlatformUtils.send_superuser(
|
||||
bot,
|
||||
f"检测真寻已更新,版本更新:{cur_version} -> {new_version}\n开始更新...",
|
||||
user_id,
|
||||
)
|
||||
download_file = (
|
||||
DOWNLOAD_GZ_FILE if version_type == "release" else DOWNLOAD_ZIP_FILE
|
||||
)
|
||||
if await AsyncHttpx.download_file(url, download_file):
|
||||
logger.debug("下载真寻最新版文件完成...", "检查更新")
|
||||
if version_type != "release":
|
||||
new_version = None
|
||||
await _file_handle(new_version)
|
||||
return f"版本更新完成\n版本: {cur_version} -> {new_version}\n请重新启动真寻以完成更新!"
|
||||
else:
|
||||
logger.debug("下载真寻最新版文件失败...", "检查更新")
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def __get_version(cls) -> str:
|
||||
"""获取当前版本
|
||||
|
||||
返回:
|
||||
str: 当前版本号
|
||||
"""
|
||||
_version = "v0.0.0"
|
||||
if VERSION_FILE.exists():
|
||||
text = VERSION_FILE.open(encoding="utf8").readline()
|
||||
if text:
|
||||
_version = text.split(":")[-1].strip()
|
||||
return _version
|
||||
|
||||
@classmethod
|
||||
async def __get_latest_data(cls) -> dict:
|
||||
"""获取最新版本信息
|
||||
|
||||
返回:
|
||||
dict: 最新版本数据
|
||||
"""
|
||||
for _ in range(3):
|
||||
try:
|
||||
res = await AsyncHttpx.get(RELEASE_URL)
|
||||
if res.status_code == 200:
|
||||
return res.json()
|
||||
except TimeoutError:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.error(f"检查更新真寻获取版本失败", e=e)
|
||||
return {}
|
||||
@@ -1,24 +0,0 @@
|
||||
from pathlib import Path
|
||||
|
||||
from zhenxun.configs.path_config import TEMP_PATH
|
||||
|
||||
DEV_URL = "https://ghproxy.cc/https://github.com/HibiKier/zhenxun_bot/archive/refs/heads/dev.zip"
|
||||
MAIN_URL = "https://ghproxy.cc/https://github.com/HibiKier/zhenxun_bot/archive/refs/heads/main.zip"
|
||||
RELEASE_URL = "https://api.github.com/repos/HibiKier/zhenxun_bot/releases/latest"
|
||||
|
||||
|
||||
VERSION_FILE = Path() / "__version__"
|
||||
|
||||
PYPROJECT_FILE = Path() / "pyproject.toml"
|
||||
PYPROJECT_LOCK_FILE = Path() / "poetry.lock"
|
||||
|
||||
BASE_PATH = Path() / "zhenxun"
|
||||
|
||||
TMP_PATH = TEMP_PATH / "auto_update"
|
||||
|
||||
BACKUP_PATH = Path() / "backup"
|
||||
|
||||
DOWNLOAD_GZ_FILE = TMP_PATH / "download_latest_file.tar.gz"
|
||||
DOWNLOAD_ZIP_FILE = TMP_PATH / "download_latest_file.zip"
|
||||
|
||||
REPLACE_FOLDERS = ["builtin_plugins", "plugins", "services", "utils", "models"]
|
||||
@@ -1,132 +0,0 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import nonebot
|
||||
import ujson as json
|
||||
|
||||
from zhenxun.configs.path_config import DATA_PATH
|
||||
|
||||
nonebot.load_plugins(str(Path(__file__).parent.resolve()))
|
||||
|
||||
old_file1 = DATA_PATH / "_prefix_count.json"
|
||||
old_file2 = DATA_PATH / "_prefix_user_count.json"
|
||||
new_path = DATA_PATH / "statistics"
|
||||
new_path.mkdir(parents=True, exist_ok=True)
|
||||
if old_file1.exists():
|
||||
os.rename(old_file1, new_path / "_prefix_count.json")
|
||||
if old_file2.exists():
|
||||
os.rename(old_file2, new_path / "_prefix_user_count.json")
|
||||
|
||||
|
||||
# 修改旧数据
|
||||
|
||||
statistics_group_file = DATA_PATH / "statistics" / "_prefix_count.json"
|
||||
statistics_user_file = DATA_PATH / "statistics" / "_prefix_user_count.json"
|
||||
|
||||
for file in [statistics_group_file, statistics_user_file]:
|
||||
if file.exists():
|
||||
with open(file, "r", encoding="utf8") as f:
|
||||
data = json.load(f)
|
||||
if not (statistics_group_file.parent / f"{file}.bak").exists():
|
||||
with open(f"{file}.bak", "w", encoding="utf8") as wf:
|
||||
json.dump(data, wf, ensure_ascii=False, indent=4)
|
||||
for x in ["total_statistics", "day_statistics"]:
|
||||
for key in data[x].keys():
|
||||
num = 0
|
||||
if data[x][key].get("ai") is not None:
|
||||
if data[x][key].get("Ai") is not None:
|
||||
data[x][key]["Ai"] += data[x][key]["ai"]
|
||||
else:
|
||||
data[x][key]["Ai"] = data[x][key]["ai"]
|
||||
del data[x][key]["ai"]
|
||||
if data[x][key].get("抽卡") is not None:
|
||||
if data[x][key].get("游戏抽卡") is not None:
|
||||
data[x][key]["游戏抽卡"] += data[x][key]["抽卡"]
|
||||
else:
|
||||
data[x][key]["游戏抽卡"] = data[x][key]["抽卡"]
|
||||
del data[x][key]["抽卡"]
|
||||
if data[x][key].get("我的道具") is not None:
|
||||
num += data[x][key]["我的道具"]
|
||||
del data[x][key]["我的道具"]
|
||||
if data[x][key].get("使用道具") is not None:
|
||||
num += data[x][key]["使用道具"]
|
||||
del data[x][key]["使用道具"]
|
||||
if data[x][key].get("我的金币") is not None:
|
||||
num += data[x][key]["我的金币"]
|
||||
del data[x][key]["我的金币"]
|
||||
if data[x][key].get("购买") is not None:
|
||||
num += data[x][key]["购买"]
|
||||
del data[x][key]["购买"]
|
||||
if data[x][key].get("商店") is not None:
|
||||
data[x][key]["商店"] += num
|
||||
else:
|
||||
data[x][key]["商店"] = num
|
||||
for x in ["week_statistics", "month_statistics"]:
|
||||
for key in data[x].keys():
|
||||
num = 0
|
||||
if key == "total":
|
||||
if data[x][key].get("ai") is not None:
|
||||
if data[x][key].get("Ai") is not None:
|
||||
data[x][key]["Ai"] += data[x][key]["ai"]
|
||||
else:
|
||||
data[x][key]["Ai"] = data[x][key]["ai"]
|
||||
del data[x][key]["ai"]
|
||||
if data[x][key].get("抽卡") is not None:
|
||||
if data[x][key].get("游戏抽卡") is not None:
|
||||
data[x][key]["游戏抽卡"] += data[x][key]["抽卡"]
|
||||
else:
|
||||
data[x][key]["游戏抽卡"] = data[x][key]["抽卡"]
|
||||
del data[x][key]["抽卡"]
|
||||
if data[x][key].get("我的道具") is not None:
|
||||
num += data[x][key]["我的道具"]
|
||||
del data[x][key]["我的道具"]
|
||||
if data[x][key].get("使用道具") is not None:
|
||||
num += data[x][key]["使用道具"]
|
||||
del data[x][key]["使用道具"]
|
||||
if data[x][key].get("我的金币") is not None:
|
||||
num += data[x][key]["我的金币"]
|
||||
del data[x][key]["我的金币"]
|
||||
if data[x][key].get("购买") is not None:
|
||||
num += data[x][key]["购买"]
|
||||
del data[x][key]["购买"]
|
||||
if data[x][key].get("商店") is not None:
|
||||
data[x][key]["商店"] += num
|
||||
else:
|
||||
data[x][key]["商店"] = num
|
||||
else:
|
||||
for day in data[x][key].keys():
|
||||
num = 0
|
||||
if data[x][key][day].get("ai") is not None:
|
||||
if data[x][key][day].get("Ai") is not None:
|
||||
data[x][key][day]["Ai"] += data[x][key][day]["ai"]
|
||||
else:
|
||||
data[x][key][day]["Ai"] = data[x][key][day]["ai"]
|
||||
del data[x][key][day]["ai"]
|
||||
if data[x][key][day].get("抽卡") is not None:
|
||||
if data[x][key][day].get("游戏抽卡") is not None:
|
||||
data[x][key][day]["游戏抽卡"] += data[x][key][day][
|
||||
"抽卡"
|
||||
]
|
||||
else:
|
||||
data[x][key][day]["游戏抽卡"] = data[x][key][day][
|
||||
"抽卡"
|
||||
]
|
||||
del data[x][key][day]["抽卡"]
|
||||
if data[x][key][day].get("我的道具") is not None:
|
||||
num += data[x][key][day]["我的道具"]
|
||||
del data[x][key][day]["我的道具"]
|
||||
if data[x][key][day].get("使用道具") is not None:
|
||||
num += data[x][key][day]["使用道具"]
|
||||
del data[x][key][day]["使用道具"]
|
||||
if data[x][key][day].get("我的金币") is not None:
|
||||
num += data[x][key][day]["我的金币"]
|
||||
del data[x][key][day]["我的金币"]
|
||||
if data[x][key][day].get("购买") is not None:
|
||||
num += data[x][key][day]["购买"]
|
||||
del data[x][key][day]["购买"]
|
||||
if data[x][key][day].get("商店") is not None:
|
||||
data[x][key][day]["商店"] += num
|
||||
else:
|
||||
data[x][key][day]["商店"] = num
|
||||
with open(file, "w", encoding="utf8") as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||
@@ -1,130 +0,0 @@
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from tortoise.functions import Count
|
||||
|
||||
from zhenxun.models.group_console import GroupConsole
|
||||
from zhenxun.models.group_member_info import GroupInfoUser
|
||||
from zhenxun.models.plugin_info import PluginInfo
|
||||
from zhenxun.models.statistics import Statistics
|
||||
from zhenxun.utils.enum import PluginType
|
||||
from zhenxun.utils.image_utils import BuildImage, BuildMat, MatType
|
||||
|
||||
|
||||
class StatisticsManage:
|
||||
|
||||
@classmethod
|
||||
async def get_statistics(
|
||||
cls,
|
||||
plugin_name: str | None,
|
||||
is_global: bool,
|
||||
search_type: str | None,
|
||||
user_id: str | None = None,
|
||||
group_id: str | None = None,
|
||||
):
|
||||
day = None
|
||||
day_type = ""
|
||||
if search_type == "day":
|
||||
day = 1
|
||||
day_type = "日"
|
||||
if search_type == "week":
|
||||
day = 7
|
||||
day_type = "周"
|
||||
if search_type == "month":
|
||||
day = 30
|
||||
day_type = "月"
|
||||
if day_type:
|
||||
day_type += f"({day}天)"
|
||||
title = ""
|
||||
if user_id:
|
||||
"""查用户"""
|
||||
query = GroupInfoUser.filter(user_id=user_id)
|
||||
if group_id:
|
||||
query = query.filter(group_id=group_id)
|
||||
user = await query.first()
|
||||
title = f"{user.user_name if user else user_id} {day_type}功能调用统计"
|
||||
elif group_id:
|
||||
"""查群组"""
|
||||
group = await GroupConsole.get_or_none(
|
||||
group_id=group_id, channel_id__isnull=True
|
||||
)
|
||||
title = f"{group.group_name if group else group_id} {day_type}功能调用统计"
|
||||
else:
|
||||
title = "功能调用统计"
|
||||
if is_global and not user_id:
|
||||
title = "全局 " + title
|
||||
return await cls.get_global_statistics(plugin_name, day, title)
|
||||
if user_id:
|
||||
return await cls.get_my_statistics(user_id, group_id, day, title)
|
||||
if group_id:
|
||||
return await cls.get_group_statistics(group_id, day, title)
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
async def get_global_statistics(
|
||||
cls, plugin_name: str | None, day: int | None, title: str
|
||||
) -> BuildImage | str:
|
||||
query = Statistics
|
||||
if plugin_name:
|
||||
query = query.filter(plugin_name=plugin_name)
|
||||
if day:
|
||||
time = datetime.now() - timedelta(days=day)
|
||||
query = query.filter(create_time__gte=time)
|
||||
data_list = (
|
||||
await query.annotate(count=Count("id"))
|
||||
.group_by("plugin_name")
|
||||
.values_list("plugin_name", "count")
|
||||
)
|
||||
if not data_list:
|
||||
return "统计数据为空..."
|
||||
return await cls.__build_image(data_list, title)
|
||||
|
||||
@classmethod
|
||||
async def get_my_statistics(
|
||||
cls, user_id: str, group_id: str | None, day: int | None, title: str
|
||||
):
|
||||
query = Statistics.filter(user_id=user_id)
|
||||
if group_id:
|
||||
query = query.filter(group_id=group_id)
|
||||
if day:
|
||||
time = datetime.now() - timedelta(days=day)
|
||||
query = query.filter(create_time__gte=time)
|
||||
data_list = (
|
||||
await query.annotate(count=Count("id"))
|
||||
.group_by("plugin_name")
|
||||
.values_list("plugin_name", "count")
|
||||
)
|
||||
if not data_list:
|
||||
return "统计数据为空..."
|
||||
return await cls.__build_image(data_list, title)
|
||||
|
||||
@classmethod
|
||||
async def get_group_statistics(cls, group_id: str, day: int | None, title: str):
|
||||
query = Statistics.filter(group_id=group_id)
|
||||
if day:
|
||||
time = datetime.now() - timedelta(days=day)
|
||||
query = query.filter(create_time__gte=time)
|
||||
data_list = (
|
||||
await query.annotate(count=Count("id"))
|
||||
.group_by("plugin_name")
|
||||
.values_list("plugin_name", "count")
|
||||
)
|
||||
if not data_list:
|
||||
return "统计数据为空..."
|
||||
return await cls.__build_image(data_list, title)
|
||||
|
||||
@classmethod
|
||||
async def __build_image(cls, data_list: list[tuple[str, int]], title: str):
|
||||
mat = BuildMat(MatType.BARH)
|
||||
module2count = {x[0]: x[1] for x in data_list}
|
||||
plugin_info = await PluginInfo.filter(
|
||||
module__in=module2count.keys(), plugin_type=PluginType.NORMAL
|
||||
).all()
|
||||
x_index = []
|
||||
data = []
|
||||
for plugin in plugin_info:
|
||||
x_index.append(plugin.name)
|
||||
data.append(module2count.get(plugin.module, 0))
|
||||
mat.x_index = x_index
|
||||
mat.data = data
|
||||
mat.title = title
|
||||
return await mat.build()
|
||||
@@ -1,162 +0,0 @@
|
||||
from nonebot.plugin import PluginMetadata
|
||||
from nonebot_plugin_alconna import (
|
||||
Alconna,
|
||||
Args,
|
||||
Arparma,
|
||||
Match,
|
||||
Option,
|
||||
on_alconna,
|
||||
store_true,
|
||||
)
|
||||
from nonebot_plugin_session import EventSession
|
||||
|
||||
from zhenxun.configs.utils import PluginExtraData
|
||||
from zhenxun.utils.enum import PluginType
|
||||
from zhenxun.utils.message import MessageUtils
|
||||
|
||||
from ._data_source import StatisticsManage
|
||||
|
||||
__plugin_meta__ = PluginMetadata(
|
||||
name="功能调用统计",
|
||||
description="功能调用统计可视化",
|
||||
usage="""
|
||||
usage:
|
||||
功能调用统计可视化
|
||||
指令:
|
||||
功能调用统计
|
||||
日功能调用统计
|
||||
周功能调用统计
|
||||
月功能调用统计
|
||||
我的功能调用统计 : 当前群我的统计
|
||||
我的功能调用统计 -g: 我的全局统计
|
||||
我的日功能调用统计
|
||||
我的周功能调用统计
|
||||
我的月功能调用统计
|
||||
""".strip(),
|
||||
extra=PluginExtraData(
|
||||
author="HibiKier",
|
||||
version="0.1",
|
||||
plugin_type=PluginType.NORMAL,
|
||||
menu_type="数据统计",
|
||||
aliases={"功能调用统计"},
|
||||
superuser_help="""
|
||||
"全局功能调用统计",
|
||||
"全局日功能调用统计",
|
||||
"全局周功能调用统计",
|
||||
"全局月功能调用统计",
|
||||
""".strip(),
|
||||
).dict(),
|
||||
)
|
||||
|
||||
|
||||
_matcher = on_alconna(
|
||||
Alconna(
|
||||
"功能调用统计",
|
||||
Args["name?", str],
|
||||
Option("-g|--global", action=store_true, help_text="全局统计"),
|
||||
Option("-my", action=store_true, help_text="我的"),
|
||||
Option("-t|--type", Args["search_type", ["day", "week", "month"]]),
|
||||
),
|
||||
priority=5,
|
||||
block=True,
|
||||
)
|
||||
|
||||
_matcher.shortcut(
|
||||
"日功能调用统计(?P<name>.*)",
|
||||
command="功能调用统计",
|
||||
arguments=["{name}", "-t", "day"],
|
||||
prefix=True,
|
||||
)
|
||||
|
||||
_matcher.shortcut(
|
||||
"周功能调用统计(?P<name>.*)",
|
||||
command="功能调用统计",
|
||||
arguments=["{name}", "-t", "week"],
|
||||
prefix=True,
|
||||
)
|
||||
|
||||
_matcher.shortcut(
|
||||
"月功能调用统计(?P<name>.*)",
|
||||
command="功能调用统计",
|
||||
arguments=["{name}", "-t", "month"],
|
||||
prefix=True,
|
||||
)
|
||||
|
||||
_matcher.shortcut(
|
||||
"全局功能调用统计(?P<name>.*)",
|
||||
command="功能调用统计",
|
||||
arguments=["{name}", "-g"],
|
||||
prefix=True,
|
||||
)
|
||||
|
||||
_matcher.shortcut(
|
||||
"全局日功能调用统计(?P<name>.*)",
|
||||
command="功能调用统计",
|
||||
arguments=["{name}", "-t", "day", "-g"],
|
||||
prefix=True,
|
||||
)
|
||||
|
||||
_matcher.shortcut(
|
||||
"全局周功能调用统计(?P<name>.*)",
|
||||
command="功能调用统计",
|
||||
arguments=["{name}", "-t", "week", "-g"],
|
||||
prefix=True,
|
||||
)
|
||||
|
||||
_matcher.shortcut(
|
||||
"全局月功能调用统计(?P<name>.*)",
|
||||
command="功能调用统计",
|
||||
arguments=["{name}", "-t", "month", "-g"],
|
||||
prefix=True,
|
||||
)
|
||||
|
||||
_matcher.shortcut(
|
||||
"我的功能调用统计(?P<name>.*)",
|
||||
command="功能调用统计",
|
||||
arguments=["{name}", "-my"],
|
||||
prefix=True,
|
||||
)
|
||||
|
||||
_matcher.shortcut(
|
||||
"我的日功能调用统计(?P<name>.*)",
|
||||
command="功能调用统计",
|
||||
arguments=["{name}", "-t", "day", "-my"],
|
||||
prefix=True,
|
||||
)
|
||||
|
||||
_matcher.shortcut(
|
||||
"我的周功能调用统计(?P<name>.*)",
|
||||
command="功能调用统计",
|
||||
arguments=["{name}", "-t", "week", "-my"],
|
||||
prefix=True,
|
||||
)
|
||||
|
||||
_matcher.shortcut(
|
||||
"我的月功能调用统计(?P<name>.*)",
|
||||
command="功能调用统计",
|
||||
arguments=["{name}", "-t", "month", "-my"],
|
||||
prefix=True,
|
||||
)
|
||||
|
||||
|
||||
@_matcher.handle()
|
||||
async def _(
|
||||
session: EventSession, arparma: Arparma, name: Match[str], search_type: Match[str]
|
||||
):
|
||||
plugin_name = name.result if name.available else None
|
||||
st = search_type.result if search_type.available else None
|
||||
gid = session.id3 or session.id2
|
||||
uid = session.id1 if (arparma.find("my") or not gid) else None
|
||||
is_global = arparma.find("global")
|
||||
if uid and is_global:
|
||||
"""个人全局"""
|
||||
gid = None
|
||||
if result := await StatisticsManage.get_statistics(
|
||||
plugin_name, arparma.find("global"), st, uid, gid
|
||||
):
|
||||
if isinstance(result, str):
|
||||
await MessageUtils.build_message(result).finish(reply_to=True)
|
||||
else:
|
||||
await MessageUtils.build_message(result).send()
|
||||
else:
|
||||
await MessageUtils.build_message("获取数据失败...").send()
|
||||
@@ -1,48 +0,0 @@
|
||||
from datetime import datetime
|
||||
|
||||
from nonebot.adapters import Bot, Event
|
||||
from nonebot.adapters.onebot.v11 import PokeNotifyEvent
|
||||
from nonebot.matcher import Matcher
|
||||
from nonebot.message import run_postprocessor
|
||||
from nonebot.plugin import PluginMetadata
|
||||
from nonebot_plugin_session import EventSession
|
||||
|
||||
from zhenxun.configs.utils import PluginExtraData
|
||||
from zhenxun.models.plugin_info import PluginInfo
|
||||
from zhenxun.models.statistics import Statistics
|
||||
from zhenxun.utils.enum import PluginType
|
||||
|
||||
__plugin_meta__ = PluginMetadata(
|
||||
name="功能调用统计",
|
||||
description="功能调用统计",
|
||||
usage="""""".strip(),
|
||||
extra=PluginExtraData(
|
||||
author="HibiKier", version="0.1", plugin_type=PluginType.HIDDEN
|
||||
).dict(),
|
||||
)
|
||||
|
||||
|
||||
@run_postprocessor
|
||||
async def _(
|
||||
matcher: Matcher,
|
||||
exception: Exception | None,
|
||||
bot: Bot,
|
||||
session: EventSession,
|
||||
event: Event,
|
||||
):
|
||||
if matcher.type == "notice" and not isinstance(event, PokeNotifyEvent):
|
||||
"""过滤除poke外的notice"""
|
||||
return
|
||||
if session.id1:
|
||||
plugin = await PluginInfo.get_or_none(module=matcher.module_name)
|
||||
plugin_type = plugin.plugin_type if plugin else None
|
||||
if plugin_type == PluginType.NORMAL and matcher.plugin_name not in [
|
||||
"update_info",
|
||||
"statistics_handle",
|
||||
]:
|
||||
await Statistics.create(
|
||||
user_id=session.id1,
|
||||
group_id=session.id3 or session.id2,
|
||||
plugin_name=matcher.plugin_name,
|
||||
create_time=datetime.now(),
|
||||
)
|
||||
Reference in New Issue
Block a user