Files
Click/main.py
T
Yuriy Yuriev fe9ada0558 add balance
2026-05-14 21:04:28 +07:00

157 lines
5.5 KiB
Python

"""
Главный файл бота с сохранением задач.
"""
import asyncio
import logging
from types import SimpleNamespace
from aiogram import Bot, Dispatcher
from aiogram.types import BotCommand
from aiogram.client.session.aiohttp import AiohttpSession
from config.settings import settings
from core.logger import setup_logger
from managers.proxy_manager import ProxyManager
from managers.background_tasks import BackgroundTaskManager
from services.browser_service import BrowserService
from handlers.commands import BotInterface
from managers.storage import TaskStorage, ChatStorage
logger = setup_logger(__name__)
async def set_bot_commands(bot: Bot, is_admin: bool = False):
"""Устанавливает команды бота в меню."""
if is_admin:
commands = [
BotCommand(command="start", description="🏠 Главное меню"),
BotCommand(command="logout", description="🔒 Выйти"),
BotCommand(command="streamers", description="📺 Стримеры"),
BotCommand(command="tasks", description="📊 Задачи"),
BotCommand(command="status", description="📈 Статус"),
]
else:
commands = [
BotCommand(command="start", description="🤖 Старт"),
]
await bot.set_my_commands(commands)
class BotApplication:
def __init__(self):
self.bot: Bot = None
self.dispatcher: Dispatcher = None
self.proxy_manager = ProxyManager()
self.background_tasks = BackgroundTaskManager()
self.browser_service = BrowserService(self.proxy_manager)
self.storage = TaskStorage()
self.chat_storage = ChatStorage()
self.interface = BotInterface(
background_tasks=self.background_tasks,
proxy_manager=self.proxy_manager,
browser_service=self.browser_service,
storage=self.storage,
chat_storage=self.chat_storage,
bot_ref=self,
)
async def _update_bot_commands(self):
is_admin = any(
self.interface.auth_manager.is_admin(uid)
for uid in self.interface.auth_manager._sessions
)
await set_bot_commands(self.bot, is_admin=is_admin)
async def initialize(self):
"""Инициализация бота."""
logger.info("Initializing bot...")
if not settings.BOT_TOKEN:
raise ValueError("BOT_TOKEN not set!")
session = AiohttpSession(proxy=settings.TELEGRAM_PROXY) if settings.TELEGRAM_PROXY else AiohttpSession()
self.bot = Bot(token=settings.BOT_TOKEN, session=session)
self.dispatcher = Dispatcher()
self.interface.register(self.dispatcher)
await self._update_bot_commands()
# Восстанавливаем задачи
await self._restore_tasks()
logger.info(f"Proxies: {self.proxy_manager.count}")
logger.info("Bot initialized!")
async def _restore_tasks(self):
"""Восстанавливает задачи после перезапуска."""
saved_tasks = await self.storage.load_tasks()
if not saved_tasks:
logger.info("No tasks to restore")
return
restored = 0
for task_id, params in saved_tasks.items():
if params.stopped:
continue
# Задачи с лимитом времени, завершившиеся нормально — не восстанавливаем
if params.completed and params.monitor_minutes > 0:
continue
# Сбрасываем некорректный completed (баг IRC) для бесконечных задач
if params.completed:
params.completed = False
params.paused = False
await self.interface.task_manager.add_task(task_id, params)
if params.task_type == "twitch_irc" and params.chat_id:
msg_mock = SimpleNamespace(
chat=SimpleNamespace(id=params.chat_id),
bot=self.bot,
)
await self.background_tasks.start_task(
task_id=task_id,
coro=self.interface._run_twitch(task_id, params, msg_mock),
task_type="twitch_irc",
metadata={'type': 'twitch_irc', 'channel': params.channel, 'chat_id': params.chat_id}
)
restored += 1
logger.info(f"🔄 Restored {restored} tasks")
async def start(self):
"""Запуск бота."""
await self.initialize()
logger.info("Starting polling...")
await self.dispatcher.start_polling(self.bot)
async def stop(self):
"""Остановка с сохранением."""
logger.info("Shutting down...")
# Сохраняем задачи
tasks = self.interface.task_manager._tasks
await self.storage.save_tasks(tasks)
await self.background_tasks.cancel_all()
await self.browser_service.cleanup()
if self.bot:
await self.bot.session.close()
logger.info("Bot stopped")
async def main():
app = BotApplication()
try:
await app.start()
except KeyboardInterrupt:
logger.info("Interrupted")
finally:
await app.stop()
if __name__ == "__main__":
asyncio.run(main())