✨ message 统计
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
from liteyuki.internal.base.data import Database, LiteModel
|
||||
from liteyuki.utils.base.data import Database, LiteModel
|
||||
|
||||
|
||||
class MessageEventModel(LiteModel):
|
||||
|
@ -1,12 +1,22 @@
|
||||
import time
|
||||
from typing import Any
|
||||
|
||||
from liteyuki.utils.message.html_tool import template2image
|
||||
from .common import MessageEventModel, msg_db
|
||||
from liteyuki.utils.base.language import Language
|
||||
from liteyuki.utils.base.resource import get_path
|
||||
from liteyuki.utils.message.npl import convert_seconds_to_time
|
||||
from contextvars import ContextVar
|
||||
|
||||
|
||||
def get_stat_msg_data(duration, period) -> tuple[list[int,], list[int,]]:
|
||||
async def get_stat_msg_image(duration: int, period: int, group_id: str = None, bot_id: str = None, ulang: Language = Language()) -> bytes:
|
||||
"""
|
||||
获取统计消息
|
||||
Args:
|
||||
ctx:
|
||||
ulang:
|
||||
bot_id:
|
||||
group_id:
|
||||
duration: 统计时间,单位秒
|
||||
period: 统计周期,单位秒
|
||||
|
||||
@ -14,20 +24,56 @@ def get_stat_msg_data(duration, period) -> tuple[list[int,], list[int,]]:
|
||||
tuple: [int,], [int,] 两个列表,分别为周期中心时间戳和消息数量
|
||||
"""
|
||||
now = int(time.time())
|
||||
start_time = (now - duration)
|
||||
|
||||
condition = "time > ?"
|
||||
condition_args = [start_time]
|
||||
|
||||
if group_id:
|
||||
condition += " AND group_id = ?"
|
||||
condition_args.append(group_id)
|
||||
if bot_id:
|
||||
condition += " AND bot_id = ?"
|
||||
condition_args.append(bot_id)
|
||||
|
||||
msg_rows = msg_db.where_all(
|
||||
MessageEventModel(),
|
||||
"time > ?",
|
||||
now - duration
|
||||
condition,
|
||||
*condition_args
|
||||
)
|
||||
timestamps = []
|
||||
msg_count = []
|
||||
msg_rows.sort(key=lambda x: x.time)
|
||||
for msg_row in msg_rows:
|
||||
period_center_time = msg_row.time - msg_row.time % period + period // 2
|
||||
|
||||
# if not timestamps or period_start_time != timestamps[-1]:
|
||||
# timestamps.append(period_start_time)
|
||||
# msg_count.append(1)
|
||||
# else:
|
||||
# msg_count[-1] += 1
|
||||
#
|
||||
start_time = max(msg_rows[0].time, start_time)
|
||||
|
||||
for i in range(start_time, now, period):
|
||||
timestamps.append(i + period // 2)
|
||||
msg_count.append(0)
|
||||
|
||||
for msg in msg_rows:
|
||||
period_start_time = start_time + (msg.time - start_time) // period * period
|
||||
period_center_time = period_start_time + period // 2
|
||||
index = timestamps.index(period_center_time)
|
||||
msg_count[index] += 1
|
||||
|
||||
templates = {
|
||||
"data": [
|
||||
{
|
||||
"name" : ulang.get("stat.message")
|
||||
+ f" Period {convert_seconds_to_time(period)}" + f" Duration {convert_seconds_to_time(duration)}"
|
||||
+ (f" Group {group_id}" if group_id else "") + (f" Bot {bot_id}" if bot_id else ""),
|
||||
"times" : timestamps,
|
||||
"counts": msg_count
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return await template2image(get_path("templates/stat_msg.html"), templates, debug=True)
|
||||
|
||||
# if not timestamps or period_start_time != timestamps[-1]:
|
||||
# timestamps.append(period_start_time)
|
||||
# msg_count.append(1)
|
||||
# else:
|
||||
# msg_count[-1] += 1
|
||||
#
|
||||
|
@ -1,31 +1,39 @@
|
||||
from nonebot import require
|
||||
from liteyuki.internal.message.npl import convert_duration
|
||||
from nonebot import Bot, require
|
||||
from liteyuki.utils.message.npl import convert_duration, convert_time_to_seconds
|
||||
from .stat_api import *
|
||||
from ...utils.base.language import Language
|
||||
from ...utils.base.ly_typing import T_MessageEvent
|
||||
|
||||
require("nonebot_plugin_alconna")
|
||||
|
||||
from nonebot_plugin_alconna import on_alconna, Alconna, Args, Subcommand, Arparma, Option
|
||||
from nonebot_plugin_alconna import UniMessage, on_alconna, Alconna, Args, Subcommand, Arparma, Option
|
||||
|
||||
stat_msg = on_alconna(
|
||||
Alconna(
|
||||
"stat",
|
||||
Subcommand(
|
||||
"message",
|
||||
Args["duration", str, "1d"], # 默认为1天
|
||||
# Args["duration", str, "2d"]["period", str, "60s"], # 默认为1天
|
||||
Option(
|
||||
"-d|--duration",
|
||||
Args["duration", str, "2d"],
|
||||
help_text="统计时间",
|
||||
),
|
||||
Option(
|
||||
"-p|--period",
|
||||
Args["period", str, "60s"],
|
||||
help_text="统计周期",
|
||||
),
|
||||
Option(
|
||||
"-b|--bot", # 生成图表
|
||||
Args["bot_id", str, ""],
|
||||
Args["bot_id", str, "current"],
|
||||
help_text="是否指定机器人",
|
||||
),
|
||||
Option(
|
||||
"-g|--group",
|
||||
Args["group_id", str, ""],
|
||||
Args["group_id", str, "current"],
|
||||
help_text="指定群组"
|
||||
),
|
||||
Option(
|
||||
"-c|--chart", # 生成图表
|
||||
help_text="是否生成图表",
|
||||
),
|
||||
alias={"msg", "m"},
|
||||
help_text="查看统计次数内的消息"
|
||||
)
|
||||
@ -34,13 +42,27 @@ stat_msg = on_alconna(
|
||||
|
||||
|
||||
@stat_msg.assign("message")
|
||||
async def _(result: Arparma):
|
||||
args = result.subcommands.get("message").args
|
||||
options = result.subcommands.get("message").options
|
||||
duration = convert_duration(args.get("duration"), 86400) # 秒数
|
||||
enable_chart = options.get("chart")
|
||||
async def _(result: Arparma, event: T_MessageEvent, bot: Bot):
|
||||
ulang = Language(event.user_id)
|
||||
|
||||
if options.get("group"):
|
||||
group_id = options["group"].args.get("group_id")
|
||||
else:
|
||||
msg_rows = get_stat_msg_data(duration)
|
||||
try:
|
||||
duration = convert_time_to_seconds(result.other_args.get("duration", "2d")) # 秒数
|
||||
period = convert_time_to_seconds(result.other_args.get("period", "1m"))
|
||||
except BaseException as e:
|
||||
await stat_msg.send(ulang.get("liteyuki.invalid_command", TEXT=str(e.__str__())))
|
||||
return
|
||||
|
||||
group_id = result.other_args.get("group_id")
|
||||
bot_id = result.other_args.get("bot_id")
|
||||
|
||||
if group_id in ["current", "c"]:
|
||||
group_id = str(event.group_id)
|
||||
|
||||
if group_id in ["all", "a"]:
|
||||
group_id = "all"
|
||||
|
||||
if bot_id == ["current", "c"]:
|
||||
bot_id = str(bot.self_id)
|
||||
|
||||
img = await get_stat_msg_image(duration, period, group_id, bot_id)
|
||||
await stat_msg.send(UniMessage.image(raw=img))
|
||||
|
@ -3,8 +3,8 @@ import time
|
||||
from nonebot import require
|
||||
from nonebot.message import event_postprocessor
|
||||
|
||||
from liteyuki.internal.base.data import Database, LiteModel
|
||||
from liteyuki.internal.base.ly_typing import v11
|
||||
from liteyuki.utils.base.data import Database, LiteModel
|
||||
from liteyuki.utils.base.ly_typing import v11
|
||||
|
||||
from .common import MessageEventModel, msg_db
|
||||
|
||||
|
Reference in New Issue
Block a user