"""
Topics Analyzer — анализ тем чата, облако тегов
Только для администраторов
"""
import logging
from aiogram import Router, F
from aiogram.types import Message
from aiogram.filters import Command
from sqlalchemy.ext.asyncio import AsyncSession
from database.db import AsyncSessionLocal
from services.topics_analyzer import TopicsAnalyzer
from utils.decorators import admin_only
logger = logging.getLogger(__name__)
router = Router()
# =============================================================================
# ОБЛАКО ТЕГОВ
# =============================================================================
@router.message(Command('topics'))
@router.message(Command('темы'))
@admin_only
async def cmd_topics(message: Message):
"""
Показать облако тегов тем чата
Использование: /topics [дни]
"""
args = message.text.split()
days = int(args[1]) if len(args) > 1 and args[1].isdigit() else 7
async with AsyncSessionLocal() as session:
analyzer = TopicsAnalyzer(session)
cloud = await analyzer.get_topics_cloud(days)
await message.answer(cloud, parse_mode='HTML')
# =============================================================================
# ТОП ТЕМ
# =============================================================================
@router.message(Command('top_topics'))
@router.message(Command('топ_тем'))
@admin_only
async def cmd_top_topics(message: Message):
"""
Показать топ тем за период
Использование: /top_topics [дни] [лимит]
"""
args = message.text.split()
days = int(args[1]) if len(args) > 1 and args[1].isdigit() else 7
limit = int(args[2]) if len(args) > 2 and args[2].isdigit() else 5
async with AsyncSessionLocal() as session:
analyzer = TopicsAnalyzer(session)
top = await analyzer.get_top_topics(days, limit)
if not top:
await message.answer('ℹ️ Нет данных за указанный период')
return
text = f'🔥 Топ тем за {days} дн.\n\n'
for i, (topic_name, data) in enumerate(top, 1):
text += f'{i}. {data["emoji"]} {topic_name.capitalize()}: {data["percent"]}% ({data["count"]} сообщ.)\n'
await message.answer(text, parse_mode='HTML')
# =============================================================================
# СТАТИСТИКА ПО ТЕМЕ
# =============================================================================
@router.message(Command('topic_stats'))
@router.message(Command('статистика_темы'))
@admin_only
async def cmd_topic_stats(message: Message):
"""
Показать статистику по конкретной теме
Использование: /topic_stats <тема>
"""
args = message.text.split()
if len(args) < 2:
await message.answer(
'❌ Использование:\n'
'/topic_stats <тема>\n\n'
'Пример: /topic_stats лифты',
parse_mode='HTML'
)
return
topic = args[1].lower()
async with AsyncSessionLocal() as session:
analyzer = TopicsAnalyzer(session)
# Получаем общую статистику
stats = await analyzer.get_topics_stats(7)
if topic not in stats['topics']:
await message.answer(f'ℹ️ Тема "{topic}" не найдена')
return
topic_data = stats['topics'][topic]
emoji = topic_data['emoji']
# Получаем тренд
trend = await analyzer.get_topic_trend(topic, 14)
text = (
f'{emoji} Статистика темы: {topic.capitalize()}\n\n'
f'📊 За 7 дней:\n'
f'├─ Сообщений: {topic_data["count"]}\n'
f'└─ Доля: {topic_data["percent"]}%\n\n'
f'📈 За 14 дней:\n'
f'└─ Сообщений: {trend["total"]}\n'
)
# Тренд по дням
if trend['daily_counts']:
text += '\n📅 По дням:\n'
for date, count in list(trend['daily_counts'].items())[-7:]:
text += f' {date}: {count} сообщ.\n'
await message.answer(text, parse_mode='HTML')
# =============================================================================
# ЕЖЕНЕДЕЛЬНЫЙ ОТЧЁТ
# =============================================================================
@router.message(Command('weekly_report'))
@router.message(Command('недельный_отчёт'))
@admin_only
async def cmd_weekly_report(message: Message):
"""Сформировать еженедельный отчёт по темам"""
async with AsyncSessionLocal() as session:
analyzer = TopicsAnalyzer(session)
report = await analyzer.get_weekly_report()
await message.answer(report, parse_mode='HTML')
# =============================================================================
# СПИСОК ТЕМ
# =============================================================================
@router.message(Command('topics_list'))
@router.message(Command('список_тем'))
@admin_only
async def cmd_topics_list(message: Message):
"""Показать список всех доступных тем"""
async with AsyncSessionLocal() as session:
analyzer = TopicsAnalyzer(session)
topics = analyzer.topics
text = '📋 Список тем для классификации\n\n'
for topic_name, data in sorted(topics.items()):
text += f'{data["emoji"]} {topic_name.capitalize()}\n'
text += f' └─ Ключевые слова: {", ".join(data["keywords"][:5])}...\n'
text += f'\n💡 Всего тем: {len(topics)}'
await message.answer(text, parse_mode='HTML')