import asyncio import threading from aiogram import Bot, Dispatcher, types from aiogram.filters import CommandObject, Command from dotenv import load_dotenv import os from sqlalchemy import select from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession from database.database import User, get_database_url load_dotenv() BOT_API_KEY = os.getenv("BOT_API_KEY") if not BOT_API_KEY: raise RuntimeError("BOT_API_KEY not set") # Create separate database engine for bot to avoid event loop conflicts bot_engine = create_async_engine( get_database_url(), echo=False, pool_pre_ping=True, pool_size=5, max_overflow=10 ) BotSessionLocal = async_sessionmaker( bot_engine, class_=AsyncSession, expire_on_commit=False ) bot = Bot(token=BOT_API_KEY) dp = Dispatcher() @dp.message(Command("start")) async def cmd_start(message: types.Message, command: CommandObject): """Handle /start command with auth token""" token = command.args if not token: await message.answer("Пожалуйста, перейдите по ссылке с сайта для авторизации.") return # Use bot's dedicated database session async with BotSessionLocal() as session: try: # Find user by token result = await session.execute(select(User).where(User.token == token)) user = result.scalar_one_or_none() if user: # Update user with Telegram data user.status = "success" user.telegram_id = message.from_user.id user.username = message.from_user.username or f"user_{message.from_user.id}" await session.commit() await message.answer("Успешная авторизация! Вернитесь на сайт, вас должно автоматически авторизовать.") else: await message.answer("Ошибка: неверный или истекший токен.") except Exception as e: await session.rollback() print(f"Database error: {e}") import traceback traceback.print_exc() await message.answer("Произошла ошибка при авторизации. Попробуйте снова.") def start_web_server(): """Start the FastAPI web server in a separate thread""" import uvicorn from config import Config HOST = getattr(Config, "HOST", "127.0.0.1") PORT = getattr(Config, "PORT", 8000) print(f"Starting web server on http://{HOST}:{PORT}") uvicorn.run("app:app", host=HOST, port=PORT, reload=False) async def start_bot(): """Start the Telegram bot""" print("Starting Telegram bot...") print(f"Bot token loaded: {'Yes' if BOT_API_KEY else 'No'}") await dp.start_polling(bot) async def main(): """Run bot (web server runs in separate thread)""" await start_bot() if __name__ == "__main__": # Start web server in a separate thread server_thread = threading.Thread(target=start_web_server, daemon=True) server_thread.start() # Give the web server a moment to start import time time.sleep(1) # Run bot in main thread try: print("Initializing services...") asyncio.run(main()) except KeyboardInterrupt: print("\nShutting down...") except Exception as e: print(f"Error: {e}") raise