feat✨: 功能调用统计

This commit is contained in:
HibiKier
2024-05-27 16:09:24 +08:00
parent 2e17f56f1e
commit 2021a2cc1c
9 changed files with 657 additions and 67 deletions
-9
View File
@@ -50,15 +50,6 @@ async def get_image_info(mod: str, url: str) -> str | list[Image | Text] | None:
return await get_saucenao_image(url)
# def parse_image(key: str):
# async def _key_parser(state: T_State, img: Message = Arg(key)):
# if not get_message_img(img):
# await search_image.reject_arg(key, "请发送要识别的图片!")
# state[key] = img
# return _key_parser
@_matcher.handle()
async def _(mode: Match[str], img: Match[alcImg]):
if mode.available:
@@ -189,7 +189,7 @@ async def _(
if result := SetuManage.get_luo(float(user.impression)):
await result.finish()
is_r18 = arparma.find("r")
_num = num.result
_num = num.result if num.available else 1
if is_r18 and gid:
"""群聊中禁止查看r18"""
if not base_config.get("ALLOW_GROUP_R18"):
+131
View File
@@ -0,0 +1,131 @@
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():
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)
+131
View File
@@ -0,0 +1,131 @@
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.models.user_console import UserConsole
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()
@@ -0,0 +1,170 @@
import asyncio
import os
import ujson as json
from nonebot.plugin import PluginMetadata
from nonebot_plugin_alconna import (
Alconna,
Args,
Arparma,
Match,
Option,
on_alconna,
store_true,
)
from nonebot_plugin_saa import Image, Text
from nonebot_plugin_session import EventSession
from zhenxun.configs.path_config import DATA_PATH, IMAGE_PATH
from zhenxun.configs.utils import PluginExtraData
from zhenxun.models.group_info import GroupInfo
from zhenxun.utils.depends import OneCommand
from zhenxun.utils.enum import PluginType
from zhenxun.utils.image_utils import BuildMat
from ._data_source import StatisticsManage
__plugin_meta__ = PluginMetadata(
name="功能调用统计可视化",
description="功能调用统计可视化",
usage="""
usage:
功能调用统计可视化
指令:
功能调用统计
日功能调用统计
周功能调用统计
月功能调用统计
我的功能调用统计 : 当前群我的统计
我的功能调用统计 -g: 我的全局统计
我的日功能调用统计
我的周功能调用统计
我的月功能调用统计
""".strip(),
extra=PluginExtraData(
author="HibiKier",
version="0.1",
plugin_type=PluginType.ADMIN,
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
uid = session.id1 if arparma.find("my") else None
gid = session.id3 or session.id2
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 Text(result).finish(reply=True)
else:
await Image(result.pic2bytes()).send()
else:
await Text("获取数据失败...").send()
@@ -0,0 +1,40 @@
from datetime import datetime
from nonebot.adapters import Bot
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
):
plugin = await PluginInfo.get_or_none(module=matcher.plugin_name)
plugin_type = plugin.plugin_type if plugin else None
if (
plugin_type == PluginType.NORMAL
and matcher.priority not in [1, 999]
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(),
)