136 lines
4.6 KiB
Python
136 lines
4.6 KiB
Python
#!/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() |