qa-and-rag-ai-assistant/bot.py
2026-01-13 15:38:27 +03:00

109 lines
3.4 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.

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