feat: render full analytics as tables
This commit is contained in:
1 parent
112c3247e0
commit
e4b1b1e510
3 files changed
+25
-7
No files matched your search
+23
-5
@@ -127,12 +127,30 @@ def all_metrics(period: str = "all", db_path: str | None = None) -> dict[str, ob
|
||||
return result
|
||||
|
||||
|
||||
def render_report(period: str = "day", db_path: str | None = None) -> str:
|
||||
def _html_table(headers: list[str], rows: list[list[object]]) -> str:
|
||||
header = "".join(f"<th>{h}</th>" for h in headers)
|
||||
body = "".join("<tr>" + "".join(f"<td>{v}</td>" for v in row) + "</tr>" for row in rows)
|
||||
return f"<table><thead><tr>{header}</tr></thead><tbody>{body}</tbody></table>"
|
||||
|
||||
|
||||
def render_report(period: str = "all", db_path: str | None = None) -> str:
|
||||
metrics = all_metrics(period, db_path)
|
||||
types = metrics["message_types"]
|
||||
generation_types = {k[1]: v for k, v in types.items() if k[0] == "generation"}
|
||||
training_types = {k[1]: v for k, v in types.items() if k[0] == "training"}
|
||||
def line(label: str, value: object) -> str:
|
||||
return f"<b>{label}:</b> {value}"
|
||||
rows = ["<h2>📊 Статистика бота</h2>", f"<p>Период: {period}</p>", "<h3>Пользователи</h3>", line("Пользователей", metrics["users"]), line("Активных", metrics["active_users"]), "<h3>Генерация</h3>", line("Постов", metrics["post_generations"]), line("Идей", metrics["idea_generations"]), line("Правок", metrics["post_revisions"]), line("Сообщений", metrics["generation_messages"]), line("Типы", ", ".join(f"{k}: {v}" for k, v in generation_types.items()) or "нет"), "<h3>Обучение</h3>", line("Сообщений", metrics["training_messages"]), line("Типы", ", ".join(f"{k}: {v}" for k, v in training_types.items()) or "нет")]
|
||||
return "<p>" + "<br/>".join(rows) + "</p>"
|
||||
users = metrics["users"]
|
||||
active = metrics["active_users"]
|
||||
user_rows = [["Всего", users], ["Активные", active]]
|
||||
activity_rows = [["Генерации постов", metrics["post_generations"]], ["Идеи", metrics["idea_generations"]], ["Правки постов", metrics["post_revisions"]], ["Сообщения", metrics["generation_messages"]]]
|
||||
generation_type_rows = [[key, value] for key, value in sorted(generation_types.items())] or [["Нет данных", 0]]
|
||||
training_type_rows = [[key, value] for key, value in sorted(training_types.items())] or [["Нет данных", 0]]
|
||||
training_rows = [["Сообщения", metrics["training_messages"]]]
|
||||
return (
|
||||
"<h2>📊 Полная статистика бота</h2>"
|
||||
f"<p>Период: {period}</p>"
|
||||
"<h3>Пользователи</h3>" + _html_table(["Показатель", "Количество"], user_rows)
|
||||
+ "<h3>Генерация</h3>" + _html_table(["Показатель", "Количество"], activity_rows)
|
||||
+ "<h3>Типы сообщений в генерации</h3>" + _html_table(["Тип", "Количество"], generation_type_rows)
|
||||
+ "<h3>Обучение</h3>" + _html_table(["Показатель", "Количество"], training_rows)
|
||||
+ "<h3>Типы сообщений в обучении</h3>" + _html_table(["Тип", "Количество"], training_type_rows)
|
||||
)
|
||||
@@ -1529,7 +1529,7 @@ async def stats_command(message: Message, state: FSMContext) -> None:
|
||||
return
|
||||
if OWNER_USER_ID and (not message.from_user or message.from_user.id != OWNER_USER_ID):
|
||||
return
|
||||
period = ((message.text or "").split(maxsplit=1)[1] if len((message.text or "").split()) > 1 else "day")
|
||||
period = ((message.text or "").split(maxsplit=1)[1] if len((message.text or "").split()) > 1 else "all")
|
||||
report = await asyncio.to_thread(analytics.render_report, period)
|
||||
if message.bot is None:
|
||||
return
|
||||
|
||||
Reference in new issue
Block a user