Files
telegram-helper-bot/helper_bot/utils/auto_unban_scheduler.py

176 lines
8.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import asyncio
from datetime import datetime, timezone, timedelta
from typing import Optional
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger
from helper_bot.utils.base_dependency_factory import get_global_instance
from logs.custom_logger import logger
class AutoUnbanScheduler:
"""
Класс для автоматического разбана пользователей по истечении срока блокировки.
Запускается ежедневно в 5:00 по московскому времени.
"""
def __init__(self):
self.bdf = get_global_instance()
self.bot_db = self.bdf.get_db()
self.scheduler = AsyncIOScheduler()
self.bot = None # Будет установлен позже
def set_bot(self, bot):
"""Устанавливает экземпляр бота для отправки уведомлений"""
self.bot = bot
async def auto_unban_users(self):
"""
Основная функция автоматического разбана пользователей.
Получает список пользователей, у которых истекает срок блокировки сегодня,
и удаляет их из черного списка.
"""
try:
logger.info("Запуск автоматического разбана пользователей")
# Получаем сегодняшнюю дату в формате YYYY-MM-DD
moscow_tz = timezone(timedelta(hours=3)) # UTC+3 для Москвы
today = datetime.now(moscow_tz).strftime("%Y-%m-%d")
logger.info(f"Поиск пользователей для разблокировки на дату: {today}")
# Получаем список пользователей для разблокировки
users_to_unban = self.bot_db.get_users_for_unblock_today(today)
if not users_to_unban:
logger.info("Нет пользователей для разблокировки сегодня")
return
logger.info(f"Найдено {len(users_to_unban)} пользователей для разблокировки")
# Список для отслеживания результатов
success_count = 0
failed_count = 0
failed_users = []
# Разблокируем каждого пользователя
for user_id, username in users_to_unban.items():
try:
result = self.bot_db.delete_user_blacklist(user_id)
if result:
success_count += 1
logger.info(f"Пользователь {user_id} ({username}) успешно разблокирован")
else:
failed_count += 1
failed_users.append(f"{user_id} ({username})")
logger.error(f"Ошибка при разблокировке пользователя {user_id} ({username})")
except Exception as e:
failed_count += 1
failed_users.append(f"{user_id} ({username})")
logger.error(f"Исключение при разблокировке пользователя {user_id} ({username}): {e}")
# Формируем отчет
report = self._generate_report(success_count, failed_count, failed_users, users_to_unban)
# Отправляем отчет в лог-канал
await self._send_report(report)
logger.info(f"Автоматический разбан завершен. Успешно: {success_count}, Ошибок: {failed_count}")
except Exception as e:
error_msg = f"Критическая ошибка в автоматическом разбане: {e}"
logger.error(error_msg)
await self._send_error_report(error_msg)
def _generate_report(self, success_count: int, failed_count: int,
failed_users: list, all_users: dict) -> str:
"""Генерирует отчет о результатах автоматического разбана"""
report = f"🤖 <b>Отчет об автоматическом разбане</b>\n\n"
report += f"📅 Дата: {datetime.now().strftime('%d.%m.%Y %H:%M')}\n"
report += f"✅ Успешно разблокировано: {success_count}\n"
report += f"❌ Ошибок: {failed_count}\n\n"
if success_count > 0:
report += "✅ <b>Разблокированные пользователи:</b>\n"
for user_id, username in all_users.items():
if f"{user_id} ({username})" not in failed_users:
safe_username = username if username else "Неизвестный пользователь"
report += f"• ID: {user_id}, Имя: {safe_username}\n"
report += "\n"
if failed_users:
report += "❌ <b>Ошибки при разблокировке:</b>\n"
for user in failed_users:
report += f"{user}\n"
return report
async def _send_report(self, report: str):
"""Отправляет отчет в лог-канал"""
try:
if self.bot:
group_for_logs = self.bdf.settings['Telegram']['group_for_logs']
await self.bot.send_message(
chat_id=group_for_logs,
text=report,
parse_mode='HTML'
)
except Exception as e:
logger.error(f"Ошибка при отправке отчета: {e}")
async def _send_error_report(self, error_msg: str):
"""Отправляет отчет об ошибке в важный лог-канал"""
try:
if self.bot:
important_logs = self.bdf.settings['Telegram']['important_logs']
await self.bot.send_message(
chat_id=important_logs,
text=f"🚨 <b>Ошибка автоматического разбана</b>\n\n{error_msg}",
parse_mode='HTML'
)
except Exception as e:
logger.error(f"Ошибка при отправке отчета об ошибке: {e}")
def start_scheduler(self):
"""Запускает планировщик задач"""
try:
# Добавляем задачу на ежедневное выполнение в 5:00 по Москве
self.scheduler.add_job(
self.auto_unban_users,
CronTrigger(hour=5, minute=0, timezone='Europe/Moscow'),
id='auto_unban_users',
name='Автоматический разбан пользователей',
replace_existing=True
)
# Запускаем планировщик
self.scheduler.start()
logger.info("Планировщик автоматического разбана запущен. Задача запланирована на 5:00 по Москве")
except Exception as e:
logger.error(f"Ошибка при запуске планировщика: {e}")
def stop_scheduler(self):
"""Останавливает планировщик задач"""
try:
if self.scheduler.running:
self.scheduler.shutdown()
logger.info("Планировщик автоматического разбана остановлен")
except Exception as e:
logger.error(f"Ошибка при остановке планировщика: {e}")
async def run_manual_unban(self):
"""Запускает разбан вручную (для тестирования)"""
logger.info("Запуск ручного разбана пользователей")
await self.auto_unban_users()
# Глобальный экземпляр планировщика
auto_unban_scheduler = AutoUnbanScheduler()
def get_auto_unban_scheduler() -> AutoUnbanScheduler:
"""Возвращает глобальный экземпляр планировщика"""
return auto_unban_scheduler