From 490cac33c4a7a0c1380f0c281a663192ffe75367 Mon Sep 17 00:00:00 2001 From: Markov Andrey Date: Tue, 30 Jun 2026 08:51:39 +0000 Subject: [PATCH] Add new file --- core/bot.py | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 core/bot.py diff --git a/core/bot.py b/core/bot.py new file mode 100644 index 0000000..607249b --- /dev/null +++ b/core/bot.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Точка входа для запуска бота. +С расширенной диагностикой событий. +""" + +import argparse +import asyncio +import sys +import logging +import signal +from pathlib import Path + +from core.utils.config_loader import BotConfig +from core.utils.logger import setup_logging +from core.xmpp.client import Bot + +logger = logging.getLogger(__name__) + + +async def shutdown(sig, bot, stop_event): + logger.info(f"Получен сигнал {sig.name}, начинаю graceful shutdown...") + stop_event.set() + try: + if hasattr(bot, 'disconnect'): + await bot.disconnect() + except Exception as e: + logger.error(f"Ошибка отключения: {e}") + tasks = [t for t in asyncio.all_tasks() if t is not asyncio.current_task()] + for task in tasks: + task.cancel() + await asyncio.gather(*tasks, return_exceptions=True) + logger.info("Бот завершён") + + +async def main_async(profile_dir: str): + try: + config = BotConfig(profile_dir) + except Exception as e: + logger.error(f"Ошибка конфига: {e}") + sys.exit(1) + + setup_logging(config.name, config.log_file, log_level=logging.DEBUG) + logger.info(f"Запуск бота {config.name} с профилем {profile_dir}") + + bot = Bot(config) + + # Отключаем SRV и устанавливаем IP + bot.use_srv = False + bot.xmpp_server = "192.168.1.150" + bot.xmpp_port = 5222 + # Попробуем SSL, если не работает — отключим + # bot.xmpp_use_ssl = False # оставляем как есть + + # ---- ДОБАВЛЯЕМ ВСЕ ОБРАБОТЧИКИ ---- + def on_session_start(event): + logger.info("✅ СЕССИЯ УСПЕШНО УСТАНОВЛЕНА! Бот готов.") + bot.send_presence(pshow='chat', pstatus=config.status_message) + + def on_failed_auth(event): + logger.error("❌ ОШИБКА АВТОРИЗАЦИИ! Проверьте пароль и JID.") + # Принудительно завершаем бота, чтобы не висеть + asyncio.create_task(shutdown(None, bot, stop_event)) + + def on_disconnected(event): + logger.warning("⚠️ Соединение разорвано.") + + def on_connection_error(event): + logger.error(f"❌ ОШИБКА СОЕДИНЕНИЯ: {event}") + + def on_stream_error(event): + logger.error(f"❌ ОШИБКА ПОТОКА: {event}") + + def on_stream_start(event): + logger.info("🔄 ПОТОК ЗАПУЩЕН") + + def on_stream_end(event): + logger.info("🔄 ПОТОК ЗАВЕРШЁН") + + def on_roster_update(event): + logger.info("📇 Ростер обновлён") + + def on_presence(event): + logger.debug(f"Присутствие: {event}") + + bot.add_event_handler("session_start", on_session_start) + bot.add_event_handler("failed_auth", on_failed_auth) + bot.add_event_handler("disconnected", on_disconnected) + bot.add_event_handler("connection_error", on_connection_error) + bot.add_event_handler("stream_error", on_stream_error) + bot.add_event_handler("stream_start", on_stream_start) + bot.add_event_handler("stream_end", on_stream_end) + bot.add_event_handler("roster_update", on_roster_update) + bot.add_event_handler("presence", on_presence) + + stop_event = asyncio.Event() + + loop = asyncio.get_running_loop() + for sig in (signal.SIGINT, signal.SIGTERM): + loop.add_signal_handler( + sig, lambda s=sig: asyncio.create_task(shutdown(s, bot, stop_event)) + ) + + logger.info(f"Попытка подключения к {bot.xmpp_server}:{bot.xmpp_port}...") + bot.connect() + logger.info("connect() вызван, ожидаем событий...") + + await stop_event.wait() + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--profile-dir', required=True) + args = parser.parse_args() + profile_dir = Path(args.profile_dir).resolve() + if not profile_dir.exists(): + print(f"Ошибка: директория {profile_dir} не существует") + sys.exit(1) + + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + + try: + loop.run_until_complete(main_async(str(profile_dir))) + except KeyboardInterrupt: + logger.info("Бот остановлен пользователем") + except Exception as e: + logger.exception(f"Критическая ошибка: {e}") + sys.exit(1) + finally: + loop.close() + + +if __name__ == '__main__': + main() \ No newline at end of file