Add new file

This commit is contained in:
Markov Andrey
2026-06-30 09:07:59 +00:00
parent f3363e2830
commit 33f4f18f00

166
core/commands/stats.py Normal file
View File

@@ -0,0 +1,166 @@
# -*- coding: utf-8 -*-
"""
Административные команды: !stats, !status, !clean.
- !stats статистика работы бота (сообщения, файлы, AI-запросы, ошибки, uptime).
- !status проверка состояния сервисов (GigaChat, PostgreSQL, Qdrant, диск).
- !clean очистка временной директории.
Изменения для PostgreSQL:
- Замена `conn.ping()` на `conn.execute("SELECT 1")` в команде !status.
- Обновлены тексты сообщений (MariaDB → PostgreSQL).
"""
import os
import shutil
import logging
from datetime import datetime
from core.commands.base import Command
logger = logging.getLogger(__name__)
class StatsCommand(Command):
"""Показывает статистику работы бота (только для администраторов)."""
name = "!stats"
aliases = ["/stats", "!статистика", "/статистика", "!стат", "/стат"]
permission = "admin"
async def execute(self, msg, args: str, user_jid: str, room_jid: str = None):
"""
Выводит:
- uptime бота
- количество обработанных сообщений
- количество AI-запросов
- количество обработанных файлов
- количество ошибок
- количество документов в базе знаний (с учётом контекста)
"""
if not self.check_permission(user_jid):
reply = msg.reply("⛔ Нет прав.")
if reply:
reply.send() # исправлено
else:
logger.error("Не удалось отправить сообщение о недостатке прав (stats)")
return
# Время работы бота
uptime = datetime.now() - self.bot.start_time
# Получение метрик из MetricsHandler
stats = self.bot.metrics_handler.get()
# Количество доступных документов в БЗ (личные/комнатные + глобальные)
sources = await self.bot.kb.get_available_sources(user_jid, room_jid)
response = (
f"📊 **Статистика бота {self.bot.config.name}**\n"
f"⏱ Uptime: {str(uptime).split('.')[0]}\n"
f"💬 Сообщений: {stats.get('messages_total', 0)}\n"
f"🤖 AI запросов: {stats.get('ai_requests', 0)}\n"
f"📁 Файлов обработано: {stats.get('files_processed', 0)}\n"
f"❌ Ошибок: {stats.get('errors_total', 0)}\n"
f"📚 Документов в БЗ: {len(sources)}"
)
reply = msg.reply(response)
if reply:
reply.send() # исправлено
else:
logger.error("Не удалось отправить статистику")
def get_help(self) -> str:
return "Показывает статистику работы бота (админ)."
class StatusCommand(Command):
"""Проверяет состояние всех внешних сервисов (административная команда)."""
name = "!status"
aliases = ["/status", "!статус", "/статус"]
permission = "admin"
async def execute(self, msg, args: str, user_jid: str, room_jid: str = None):
if not self.check_permission(user_jid):
reply = msg.reply("⛔ Нет прав.")
if reply:
reply.send() # исправлено
else:
logger.error("Не удалось отправить сообщение о недостатке прав (stats)")
return
# --- GigaChat ---
try:
# Простой запрос для проверки доступности API
await self.bot.giga.chat([], "ping", system_prompt=None, file_id=None, temperature=0.1)
ai_status = "✅ GigaChat Online"
except Exception as e:
ai_status = f"❌ GigaChat Offline: {e}"
# --- PostgreSQL (asyncpg) ---
try:
async with self.bot.db.pool.acquire() as conn:
# В asyncpg нет метода ping(), используем SELECT 1
await conn.execute("SELECT 1")
db_status = "✅ PostgreSQL Online"
except Exception as e:
db_status = f"❌ PostgreSQL Error: {e}"
# --- Qdrant ---
try:
self.bot.qdrant.client.get_collection(self.bot.qdrant.collection_name)
qd_status = "✅ Qdrant Online"
except Exception as e:
qd_status = f"❌ Qdrant Error: {e}"
# --- Дисковое пространство (временная директория) ---
total, used, free = shutil.disk_usage(self.bot.config.temp_dir)
disk_info = f"💾 Диск: {used // (2**20)}MB / {total // (2**20)}MB"
full_status = f"🛰 **СТАТУС БОТА**\n{ai_status}\n{db_status}\n{qd_status}\n{disk_info}"
reply = msg.reply(full_status)
if reply:
reply.send() # исправлено
else:
logger.error("Не удалось отправить статус")
def get_help(self) -> str:
return "Проверяет состояние сервисов (GigaChat, PostgreSQL, Qdrant, диск) админ."
class CleanCommand(Command):
"""Очищает временную директорию бота (temp_dir)."""
name = "!clean"
aliases = ["/clean", "!очистка", "/очистка"]
permission = "admin"
async def execute(self, msg, args: str, user_jid: str, room_jid: str = None):
if not self.check_permission(user_jid):
reply = msg.reply("⛔ Нет прав.")
if reply:
reply.send() # исправлено
else:
logger.error("Не удалось отправить сообщение о недостатке прав (stats)")
return
count = 0
temp_dir = self.bot.config.temp_dir
for f in os.listdir(temp_dir):
try:
p = os.path.join(temp_dir, f)
if os.path.isfile(p):
os.unlink(p)
elif os.path.isdir(p):
shutil.rmtree(p)
count += 1
except Exception:
pass
reply = msg.reply(f"🧹 Удалено объектов из temp_dir: {count}")
if reply:
reply.send() # исправлено
else:
logger.error("Не удалось отправить отчёт об очистке")
def get_help(self) -> str:
return "Очищает временную директорию бота (админ)."