Files
telegram-helper-bot/run_helper.py
Andrey fc0517c011 Enhance bot functionality with new features and improvements
- Added a new `/status` endpoint in `server_prometheus.py` to provide process status information, including uptime and resource usage metrics.
- Implemented a PID manager in `run_helper.py` to track the bot's process, improving monitoring capabilities.
- Introduced a method to delete audio moderation records in `audio_repository.py`, enhancing database management.
- Updated voice message handling in callback handlers to ensure proper deletion of audio moderation records.
- Improved error handling and logging in various services, ensuring better tracking of media processing and file downloads.
- Refactored media handling functions to streamline operations and improve code readability.
- Enhanced metrics tracking for file downloads and media processing, providing better insights into bot performance.
2025-09-04 00:46:45 +03:00

168 lines
7.4 KiB
Python
Raw Permalink 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
import os
import sys
import signal
# Ensure project root is on sys.path for module resolution
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
if CURRENT_DIR not in sys.path:
sys.path.insert(0, CURRENT_DIR)
from helper_bot.main import start_bot
from helper_bot.utils.base_dependency_factory import get_global_instance
from helper_bot.utils.auto_unban_scheduler import get_auto_unban_scheduler
from logs.custom_logger import logger
# Импортируем PID менеджер из инфраструктуры (если доступен)
import sys
import os
def get_pid_manager():
"""Получение PID менеджера из инфраструктуры проекта"""
try:
# Пытаемся импортировать из инфраструктуры проекта
infra_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'infra', 'monitoring')
if infra_path not in sys.path:
sys.path.insert(0, infra_path)
from pid_manager import get_bot_pid_manager
return get_bot_pid_manager
except ImportError:
# В изолированном запуске PID менеджер не нужен
logger.info("PID менеджер недоступен (изолированный запуск), PID файл не создается")
return None
# Получаем функцию создания PID менеджера
get_bot_pid_manager = get_pid_manager()
async def main():
"""Основная функция запуска"""
# Создаем PID менеджер для отслеживания процесса (если доступен)
pid_manager = None
if get_bot_pid_manager:
pid_manager = get_bot_pid_manager("helper_bot")
if not pid_manager.create_pid_file():
logger.error("Не удалось создать PID файл, завершаем работу")
return
else:
logger.info("PID менеджер недоступен, запуск без PID файла")
bdf = get_global_instance()
# Создаем бота для автоматического разбана
from aiogram import Bot
from aiogram.client.default import DefaultBotProperties
auto_unban_bot = Bot(
token=bdf.settings['Telegram']['bot_token'],
default=DefaultBotProperties(parse_mode='HTML'),
timeout=30.0
)
# Инициализируем планировщик автоматического разбана
auto_unban_scheduler = get_auto_unban_scheduler()
auto_unban_scheduler.set_bot(auto_unban_bot)
auto_unban_scheduler.start_scheduler()
# Метрики запускаются в main.py через server_prometheus.py
# Здесь не нужно дублировать функциональность
# Флаг для корректного завершения
shutdown_event = asyncio.Event()
def signal_handler(signum, frame):
"""Обработчик сигналов для корректного завершения"""
logger.info(f"Получен сигнал {signum}, завершаем работу...")
shutdown_event.set()
# Регистрируем обработчики сигналов
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
# Запускаем бота (метрики запускаются внутри start_bot)
bot_task = asyncio.create_task(start_bot(bdf))
main_bot = None
try:
# Ждем сигнала завершения
await shutdown_event.wait()
logger.info("Начинаем корректное завершение...")
except KeyboardInterrupt:
logger.info("Получен сигнал завершения...")
finally:
logger.info("Останавливаем планировщик автоматического разбана...")
auto_unban_scheduler.stop_scheduler()
# Останавливаем планировщик метрик
try:
from helper_bot.utils.metrics_scheduler import stop_metrics_scheduler
stop_metrics_scheduler()
logger.info("Планировщик метрик остановлен")
except Exception as e:
logger.error(f"Ошибка при остановке планировщика метрик: {e}")
# Метрики останавливаются в main.py
logger.info("Останавливаем задачи...")
# Отменяем задачу бота
bot_task.cancel()
# Очищаем PID файл (если PID менеджер доступен)
if pid_manager:
pid_manager.cleanup_pid_file()
# Ждем завершения задачи бота и получаем результат main bot
try:
results = await asyncio.gather(bot_task, return_exceptions=True)
# Результат - это main bot
if results[0] and not isinstance(results[0], Exception):
main_bot = results[0]
except Exception as e:
logger.error(f"Ошибка при остановке задач: {e}")
# Закрываем сессию основного бота (если она еще не закрыта)
if main_bot and hasattr(main_bot, 'session') and not main_bot.session.closed:
try:
await main_bot.session.close()
logger.info("Сессия основного бота корректно закрыта")
except Exception as e:
logger.error(f"Ошибка при закрытии сессии основного бота: {e}")
# Закрываем сессию бота для автоматического разбана
if not auto_unban_bot.session.closed:
try:
await auto_unban_bot.session.close()
logger.info("Сессия бота автоматического разбана корректно закрыта")
except Exception as e:
logger.error(f"Ошибка при закрытии сессии бота автоматического разбана: {e}")
# Даем время на завершение всех aiohttp соединений
await asyncio.sleep(0.2)
logger.info("Бот корректно остановлен")
if __name__ == '__main__':
try:
asyncio.run(main())
except AttributeError:
# Fallback for Python 3.6-3.7
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main())
finally:
# Закрываем все pending tasks
pending = asyncio.all_tasks(loop)
for task in pending:
task.cancel()
# Ждем завершения всех задач
if pending:
loop.run_until_complete(asyncio.gather(*pending, return_exceptions=True))
loop.close()