Files
fckbot/bots/bot.py
2026-06-30 09:45:29 +00:00

136 lines
4.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.
#!/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()