#!/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()