diff --git a/VERSION b/VERSION
index b51d2a4..216edd8 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.0+65
+0.1.0+66
diff --git a/analytics.py b/analytics.py
index faa868c..46070d6 100644
--- a/analytics.py
+++ b/analytics.py
@@ -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"
{h} | " for h in headers)
+ body = "".join("" + "".join(f"| {v} | " for v in row) + "
" for row in rows)
+ return f""
+
+
+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"{label}: {value}"
- rows = ["📊 Статистика бота
", f"Период: {period}
", "Пользователи
", line("Пользователей", metrics["users"]), line("Активных", metrics["active_users"]), "Генерация
", 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 "нет"), "Обучение
", line("Сообщений", metrics["training_messages"]), line("Типы", ", ".join(f"{k}: {v}" for k, v in training_types.items()) or "нет")]
- return "" + "
".join(rows) + "
"
+ 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 (
+ "📊 Полная статистика бота
"
+ f"Период: {period}
"
+ "Пользователи
" + _html_table(["Показатель", "Количество"], user_rows)
+ + "Генерация
" + _html_table(["Показатель", "Количество"], activity_rows)
+ + "Типы сообщений в генерации
" + _html_table(["Тип", "Количество"], generation_type_rows)
+ + "Обучение
" + _html_table(["Показатель", "Количество"], training_rows)
+ + "Типы сообщений в обучении
" + _html_table(["Тип", "Количество"], training_type_rows)
+ )
diff --git a/bot.py b/bot.py
index 5f5f75c..72a494d 100644
--- a/bot.py
+++ b/bot.py
@@ -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