109 lines
3.4 KiB
Python
109 lines
3.4 KiB
Python
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
|
||
|