✅ Регистрация и верификация жильцов ✅ Рейтинг активности (уровни) ✅ Детект шпионов (Score 0-100) ✅ Анти-мат система (3 предупреждения → бан) ✅ Админ-панель с рассылкой ✅ Учёт квартир (несколько жильцов) ✅ Телефоны экстренных служб и мастеров ✅ Еженедельный экспорт JSON ✅ Прокси (socks5) для обхода РКН Бекап: backups/versions/v1.0_mvp_2026-02-26/ Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
168 lines
5.9 KiB
Python
168 lines
5.9 KiB
Python
"""
|
||
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'🔥 <b>Топ тем за {days} дн.</b>\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(
|
||
'❌ <b>Использование:</b>\n'
|
||
'<code>/topic_stats <тема></code>\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} <b>Статистика темы: {topic.capitalize()}</b>\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 = '📋 <b>Список тем для классификации</b>\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')
|