diff --git a/requirements.txt b/requirements.txt
index 0c4aad2..502efcb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,6 +3,8 @@ pydantic-settings>=2.1.0
python-dotenv>=1.0.0
aiogram>=3.10.0
sqlalchemy>=2.0.0
+aiosqlite>=0.19.0
+httpx>=0.25.0
yookassa>=2.4.0
fastapi>=0.104.0
uvicorn>=0.24.0
diff --git a/tg_bot/domain/services/user_service.py b/tg_bot/domain/services/user_service.py
index 17d4e33..77c5dbc 100644
--- a/tg_bot/domain/services/user_service.py
+++ b/tg_bot/domain/services/user_service.py
@@ -1,29 +1,67 @@
-from sqlalchemy.orm import Session
+from sqlalchemy.ext.asyncio import AsyncSession
+from sqlalchemy import select
from datetime import datetime, timedelta
+from typing import Optional
from tg_bot.infrastructure.database.models import UserModel
class UserService:
- def __init__(self, session: Session):
+ def __init__(self, session: AsyncSession):
self.session = session
+ async def get_user_by_telegram_id(self, telegram_id: int) -> Optional[UserModel]:
+ result = await self.session.execute(
+ select(UserModel).filter_by(telegram_id=str(telegram_id))
+ )
+ return result.scalar_one_or_none()
+
+ async def get_or_create_user(
+ self,
+ telegram_id: int,
+ username: str = "",
+ first_name: str = "",
+ last_name: str = ""
+ ) -> UserModel:
+ user = await self.get_user_by_telegram_id(telegram_id)
+ if not user:
+ user = UserModel(
+ telegram_id=str(telegram_id),
+ username=username,
+ first_name=first_name,
+ last_name=last_name
+ )
+ self.session.add(user)
+ await self.session.commit()
+ else:
+ user.username = username
+ user.first_name = first_name
+ user.last_name = last_name
+ await self.session.commit()
+ return user
+
+ async def update_user_questions(self, telegram_id: int) -> bool:
+ user = await self.get_user_by_telegram_id(telegram_id)
+ if user:
+ user.questions_used += 1
+ await self.session.commit()
+ return True
+ return False
+
async def activate_premium(self, telegram_id: int) -> bool:
try:
- user = self.session.query(UserModel) \
- .filter(UserModel.telegram_id == str(telegram_id)) \
- .first()
+ user = await self.get_user_by_telegram_id(telegram_id)
if user:
user.is_premium = True
if user.premium_until and user.premium_until > datetime.now():
user.premium_until = user.premium_until + timedelta(days=30)
else:
user.premium_until = datetime.now() + timedelta(days=30)
- self.session.commit()
+ await self.session.commit()
return True
else:
return False
except Exception as e:
print(f"Error activating premium: {e}")
- self.session.rollback()
+ await self.session.rollback()
return False
diff --git a/tg_bot/infrastructure/database/database.py b/tg_bot/infrastructure/database/database.py
index 8044e09..f49a009 100644
--- a/tg_bot/infrastructure/database/database.py
+++ b/tg_bot/infrastructure/database/database.py
@@ -1,15 +1,19 @@
-from sqlalchemy import create_engine
-from sqlalchemy.orm import sessionmaker
+from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
from tg_bot.config.settings import settings
-engine = create_engine(
- settings.DATABASE_URL,
+database_url = settings.DATABASE_URL
+if database_url.startswith("sqlite:///"):
+ database_url = database_url.replace("sqlite:///", "sqlite+aiosqlite:///")
+
+engine = create_async_engine(
+ database_url,
echo=settings.DEBUG
)
-SessionLocal = sessionmaker(bind=engine)
+AsyncSessionLocal = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
-def create_tables():
+async def create_tables():
from .models import Base
- Base.metadata.create_all(bind=engine)
+ async with engine.begin() as conn:
+ await conn.run_sync(Base.metadata.create_all)
print(f"Таблицы созданы: {settings.DATABASE_URL}")
\ No newline at end of file
diff --git a/tg_bot/infrastructure/telegram/bot.py b/tg_bot/infrastructure/telegram/bot.py
index 606c203..3490201 100644
--- a/tg_bot/infrastructure/telegram/bot.py
+++ b/tg_bot/infrastructure/telegram/bot.py
@@ -32,6 +32,7 @@ async def create_bot() -> tuple[Bot, Dispatcher]:
async def start_bot():
+ bot = None
try:
bot, dp = await create_bot()
@@ -54,4 +55,5 @@ async def start_bot():
logger.error(f"Ошибка запуска: {e}")
raise
finally:
- await bot.session.close()
\ No newline at end of file
+ if bot:
+ await bot.session.close()
\ No newline at end of file
diff --git a/tg_bot/infrastructure/telegram/handlers/buy_handler.py b/tg_bot/infrastructure/telegram/handlers/buy_handler.py
index 444ffd9..0411d00 100644
--- a/tg_bot/infrastructure/telegram/handlers/buy_handler.py
+++ b/tg_bot/infrastructure/telegram/handlers/buy_handler.py
@@ -4,8 +4,10 @@ from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton
from decimal import Decimal
from tg_bot.config.settings import settings
from tg_bot.payment.yookassa.client import yookassa_client
-from tg_bot.infrastructure.database.database import SessionLocal
-from tg_bot.infrastructure.database.models import PaymentModel, UserModel
+from tg_bot.infrastructure.database.database import AsyncSessionLocal
+from tg_bot.infrastructure.database.models import PaymentModel
+from tg_bot.domain.services.user_service import UserService
+from sqlalchemy import select
import uuid
from datetime import datetime, timedelta
@@ -17,24 +19,23 @@ async def cmd_buy(message: Message):
user_id = message.from_user.id
username = message.from_user.username or f"user_{user_id}"
- session = SessionLocal()
- try:
- user = session.query(UserModel).filter_by(
- telegram_id=str(user_id)
- ).first()
+ async with AsyncSessionLocal() as session:
+ try:
+ user_service = UserService(session)
+ user = await user_service.get_user_by_telegram_id(user_id)
- if user and user.is_premium and user.premium_until and user.premium_until > datetime.now():
- days_left = (user.premium_until - datetime.now()).days
- await message.answer(
- f"У вас уже есть активная подписка!\n\n"
- f"• Статус: Premium активен\n"
- f"• Действует до: {user.premium_until.strftime('%d.%m.%Y')}\n"
- f"• Осталось дней: {days_left}\n\n"
- f"Новая подписка будет добавлена к текущей.",
- parse_mode="HTML"
- )
- finally:
- session.close()
+ if user and user.is_premium and user.premium_until and user.premium_until > datetime.now():
+ days_left = (user.premium_until - datetime.now()).days
+ await message.answer(
+ f"У вас уже есть активная подписка!\n\n"
+ f"• Статус: Premium активен\n"
+ f"• Действует до: {user.premium_until.strftime('%d.%m.%Y')}\n"
+ f"• Осталось дней: {days_left}\n\n"
+ f"Новая подписка будет добавлена к текущей.",
+ parse_mode="HTML"
+ )
+ except Exception:
+ pass
await message.answer(
"*Создаю ссылку для оплаты...*\n\n"
@@ -49,25 +50,23 @@ async def cmd_buy(message: Message):
user_id=user_id
)
- session = SessionLocal()
- try:
- payment = PaymentModel(
- payment_id=str(uuid.uuid4()),
- user_id=user_id,
- amount=str(settings.PAYMENT_AMOUNT),
- currency="RUB",
- status="pending",
- yookassa_payment_id=payment_data["id"],
- description="Оплата подписки VibeLawyerBot"
- )
- session.add(payment)
- session.commit()
- print(f"Платёж сохранён в БД: {payment.payment_id}")
- except Exception as e:
- print(f"Ошибка сохранения платежа в БД: {e}")
- session.rollback()
- finally:
- session.close()
+ async with AsyncSessionLocal() as session:
+ try:
+ payment = PaymentModel(
+ payment_id=str(uuid.uuid4()),
+ user_id=user_id,
+ amount=str(settings.PAYMENT_AMOUNT),
+ currency="RUB",
+ status="pending",
+ yookassa_payment_id=payment_data["id"],
+ description="Оплата подписки VibeLawyerBot"
+ )
+ session.add(payment)
+ await session.commit()
+ print(f"Платёж сохранён в БД: {payment.payment_id}")
+ except Exception as e:
+ print(f"Ошибка сохранения платежа в БД: {e}")
+ await session.rollback()
keyboard = InlineKeyboardMarkup(
inline_keyboard=[
@@ -140,49 +139,42 @@ async def check_payment_status(callback_query: types.CallbackQuery):
payment = YooPayment.find_one(yookassa_id)
if payment.status == "succeeded":
- session = SessionLocal()
- try:
- db_payment = session.query(PaymentModel).filter_by(
- yookassa_payment_id=yookassa_id
- ).first()
-
- if db_payment:
- db_payment.status = "succeeded"
- user = session.query(UserModel).filter_by(
- telegram_id=str(user_id)
- ).first()
-
- if user:
- user.is_premium = True
- if user.premium_until and user.premium_until > datetime.now():
- user.premium_until = user.premium_until + timedelta(days=30)
- else:
- user.premium_until = datetime.now() + timedelta(days=30)
-
- session.commit()
- user = session.query(UserModel).filter_by(
- telegram_id=str(user_id)
- ).first()
-
- await callback_query.message.answer(
- "Оплата подтверждена!\n\n"
- f"Ваш premium-доступ активирован до: "
- f"{user.premium_until.strftime('%d.%m.%Y')}\n\n"
- "Теперь вы можете:\n"
- "• Задавать неограниченное количество вопросов\n"
- "• Получать приоритетные ответы\n"
- "• Использовать все функции бота\n\n"
- "Спасибо за покупку!",
- parse_mode="HTML"
+ async with AsyncSessionLocal() as session:
+ try:
+ result = await session.execute(
+ select(PaymentModel).filter_by(yookassa_payment_id=yookassa_id)
)
- else:
- await callback_query.message.answer(
- "Платёж найден в ЮKассе, но не в нашей БД\n\n"
- "Пожалуйста, обратитесь к администратору.",
- parse_mode="HTML"
- )
- finally:
- session.close()
+ db_payment = result.scalar_one_or_none()
+
+ if db_payment:
+ db_payment.status = "succeeded"
+ user_service = UserService(session)
+ success = await user_service.activate_premium(user_id)
+ if success:
+ user = await user_service.get_user_by_telegram_id(user_id)
+ await session.commit()
+ if not user:
+ user = await user_service.get_user_by_telegram_id(user_id)
+
+ await callback_query.message.answer(
+ "Оплата подтверждена!\n\n"
+ f"Ваш premium-доступ активирован до: "
+ f"{user.premium_until.strftime('%d.%m.%Y')}\n\n"
+ "Теперь вы можете:\n"
+ "• Задавать неограниченное количество вопросов\n"
+ "• Получать приоритетные ответы\n"
+ "• Использовать все функции бота\n\n"
+ "Спасибо за покупку!",
+ parse_mode="HTML"
+ )
+ else:
+ await callback_query.message.answer(
+ "Платёж найден в ЮKассе, но не в нашей БД\n\n"
+ "Пожалуйста, обратитесь к администратору.",
+ parse_mode="HTML"
+ )
+ except Exception as e:
+ print(f"Ошибка обработки платежа: {e}")
elif payment.status == "pending":
await callback_query.message.answer(
@@ -212,45 +204,44 @@ async def check_payment_status(callback_query: types.CallbackQuery):
parse_mode="HTML"
)
-
@router.message(Command("mypayments"))
async def cmd_my_payments(message: Message):
user_id = message.from_user.id
- session = SessionLocal()
- try:
- payments = session.query(PaymentModel).filter_by(
- user_id=user_id
- ).order_by(PaymentModel.created_at.desc()).limit(10).all()
+ async with AsyncSessionLocal() as session:
+ try:
+ result = await session.execute(
+ select(PaymentModel).filter_by(user_id=user_id).order_by(PaymentModel.created_at.desc()).limit(10)
+ )
+ payments = result.scalars().all()
+
+ if not payments:
+ await message.answer(
+ "У вас пока нет платежей\n\n"
+ "Используйте команду /buy чтобы оформить подписку.",
+ parse_mode="HTML"
+ )
+ return
+
+ response = ["Ваши последние платежи:\n"]
+
+ for i, payment in enumerate(payments, 1):
+ status_text = "Успешно" if payment.status == "succeeded" else "Ожидание" if payment.status == "pending" else "Ошибка"
+ response.append(
+ f"\n{i}. {payment.amount} руб. ({status_text})\n"
+ f"Статус: {payment.status}\n"
+ f"Дата: {payment.created_at.strftime('%d.%m.%Y %H:%M')}\n"
+ f"ID: {payment.payment_id[:8]}..."
+ )
+
+ response.append("\n\nПолный доступ открывается после успешной оплаты")
- if not payments:
await message.answer(
- "У вас пока нет платежей\n\n"
- "Используйте команду /buy чтобы оформить подписку.",
+ "\n".join(response),
parse_mode="HTML"
)
- return
-
- response = ["Ваши последние платежи:\n"]
-
- for i, payment in enumerate(payments, 1):
- status_text = "Успешно" if payment.status == "succeeded" else "Ожидание" if payment.status == "pending" else "Ошибка"
- response.append(
- f"\n{i}. {payment.amount} руб. ({status_text})\n"
- f"Статус: {payment.status}\n"
- f"Дата: {payment.created_at.strftime('%d.%m.%Y %H:%M')}\n"
- f"ID: {payment.payment_id[:8]}..."
- )
-
- response.append("\n\nПолный доступ открывается после успешной оплаты")
-
- await message.answer(
- "\n".join(response),
- parse_mode="HTML"
- )
-
- finally:
- session.close()
+ except Exception as e:
+ print(f"Ошибка получения платежей: {e}")
@router.message(Command("testcards"))
diff --git a/tg_bot/infrastructure/telegram/handlers/question_handler.py b/tg_bot/infrastructure/telegram/handlers/question_handler.py
index b2b45f0..540aac7 100644
--- a/tg_bot/infrastructure/telegram/handlers/question_handler.py
+++ b/tg_bot/infrastructure/telegram/handlers/question_handler.py
@@ -3,8 +3,9 @@ from aiogram.types import Message
from datetime import datetime
import aiohttp
from tg_bot.config.settings import settings
-from tg_bot.infrastructure.database.database import SessionLocal
+from tg_bot.infrastructure.database.database import AsyncSessionLocal
from tg_bot.infrastructure.database.models import UserModel
+from tg_bot.domain.services.user_service import UserService
from tg_bot.application.services.rag_service import RAGService
router = Router()
@@ -18,41 +19,35 @@ async def handle_question(message: Message):
if question_text.startswith('/'):
return
- session = SessionLocal()
- try:
- user = session.query(UserModel).filter_by(
- telegram_id=str(user_id)
- ).first()
+ async with AsyncSessionLocal() as session:
+ try:
+ user_service = UserService(session)
+ user = await user_service.get_user_by_telegram_id(user_id)
- if not user:
- user = UserModel(
- telegram_id=str(user_id),
- username=message.from_user.username or "",
- first_name=message.from_user.first_name or "",
- last_name=message.from_user.last_name or ""
+ if not user:
+ user = await user_service.get_or_create_user(
+ user_id,
+ message.from_user.username or "",
+ message.from_user.first_name or "",
+ message.from_user.last_name or ""
+ )
+ await ensure_user_in_backend(str(user_id), message.from_user)
+
+ if user.is_premium:
+ await process_premium_question(message, user, question_text, user_service)
+
+ elif user.questions_used < settings.FREE_QUESTIONS_LIMIT:
+ await process_free_question(message, user, question_text, user_service)
+
+ else:
+ await handle_limit_exceeded(message, user)
+
+ except Exception as e:
+ print(f"Error processing question: {e}")
+ await message.answer(
+ "Произошла ошибка. Попробуйте позже.",
+ parse_mode="HTML"
)
- session.add(user)
- session.commit()
-
- await ensure_user_in_backend(str(user_id), message.from_user)
-
- if user.is_premium:
- await process_premium_question(message, user, question_text, session)
-
- elif user.questions_used < settings.FREE_QUESTIONS_LIMIT:
- await process_free_question(message, user, question_text, session)
-
- else:
- await handle_limit_exceeded(message, user)
-
- except Exception as e:
- print(f"Error processing question: {e}")
- await message.answer(
- "Произошла ошибка. Попробуйте позже.",
- parse_mode="HTML"
- )
- finally:
- session.close()
async def ensure_user_in_backend(telegram_id: str, telegram_user):
@@ -74,9 +69,8 @@ async def ensure_user_in_backend(telegram_id: str, telegram_user):
print(f"Error creating user in backend: {e}")
-async def process_premium_question(message: Message, user: UserModel, question_text: str, session):
- user.questions_used += 1
- session.commit()
+async def process_premium_question(message: Message, user: UserModel, question_text: str, user_service: UserService):
+ await user_service.update_user_questions(user.telegram_id)
await message.bot.send_chat_action(message.chat.id, "typing")
@@ -135,10 +129,10 @@ async def process_premium_question(message: Message, user: UserModel, question_t
await message.answer(response, parse_mode="HTML")
-async def process_free_question(message: Message, user: UserModel, question_text: str, session):
- user.questions_used += 1
+async def process_free_question(message: Message, user: UserModel, question_text: str, user_service: UserService):
+ await user_service.update_user_questions(user.telegram_id)
+ user = await user_service.get_user_by_telegram_id(user.telegram_id)
remaining = settings.FREE_QUESTIONS_LIMIT - user.questions_used
- session.commit()
await message.bot.send_chat_action(message.chat.id, "typing")
diff --git a/tg_bot/infrastructure/telegram/handlers/start_handler.py b/tg_bot/infrastructure/telegram/handlers/start_handler.py
index 71be4c8..8bc3a36 100644
--- a/tg_bot/infrastructure/telegram/handlers/start_handler.py
+++ b/tg_bot/infrastructure/telegram/handlers/start_handler.py
@@ -4,8 +4,8 @@ from aiogram.types import Message
from datetime import datetime
from tg_bot.config.settings import settings
-from tg_bot.infrastructure.database.database import SessionLocal
-from tg_bot.infrastructure.database.models import UserModel
+from tg_bot.infrastructure.database.database import AsyncSessionLocal
+from tg_bot.domain.services.user_service import UserService
router = Router()
@@ -16,33 +16,22 @@ async def cmd_start(message: Message):
username = message.from_user.username or ""
first_name = message.from_user.first_name or ""
last_name = message.from_user.last_name or ""
- session = SessionLocal()
- try:
- user = session.query(UserModel).filter_by(
- telegram_id=str(user_id)
- ).first()
-
- if not user:
- user = UserModel(
- telegram_id=str(user_id),
- username=username,
- first_name=first_name,
- last_name=last_name
+ async with AsyncSessionLocal() as session:
+ try:
+ user_service = UserService(session)
+ existing_user = await user_service.get_user_by_telegram_id(user_id)
+ user = await user_service.get_or_create_user(
+ user_id,
+ username,
+ first_name,
+ last_name
)
- session.add(user)
- session.commit()
- print(f"Новый пользователь: {user_id}")
- else:
- user.username = username
- user.first_name = first_name
- user.last_name = last_name
- session.commit()
-
- except Exception as e:
- print(f"Ошибка сохранения пользователя: {e}")
- session.rollback()
- finally:
- session.close()
+ if not existing_user:
+ print(f"Новый пользователь: {user_id}")
+
+ except Exception as e:
+ print(f"Ошибка сохранения пользователя: {e}")
+ await session.rollback()
welcome_text = (
f"Привет, {first_name}!\n\n"
f"Я VibeLawyerBot - ваш помощник в юридических вопросах.\n\n"
diff --git a/tg_bot/infrastructure/telegram/handlers/stats_handler.py b/tg_bot/infrastructure/telegram/handlers/stats_handler.py
index 3ce7534..58adfdc 100644
--- a/tg_bot/infrastructure/telegram/handlers/stats_handler.py
+++ b/tg_bot/infrastructure/telegram/handlers/stats_handler.py
@@ -4,8 +4,8 @@ from aiogram.filters import Command
from aiogram.types import Message
from tg_bot.config.settings import settings
-from tg_bot.infrastructure.database.database import SessionLocal
-from tg_bot.infrastructure.database.models import UserModel
+from tg_bot.infrastructure.database.database import AsyncSessionLocal
+from tg_bot.domain.services.user_service import UserService
router = Router()
@@ -14,52 +14,48 @@ router = Router()
async def cmd_stats(message: Message):
user_id = message.from_user.id
- session = SessionLocal()
- try:
- user = session.query(UserModel).filter_by(
- telegram_id=str(user_id)
- ).first()
+ async with AsyncSessionLocal() as session:
+ try:
+ user_service = UserService(session)
+ user = await user_service.get_user_by_telegram_id(user_id)
- if user:
- stats_text = (
- f"Ваша статистика\n\n"
- f"Основное:\n"
- f"• ID: {user_id}\n"
- f"• Premium: {'Да' if user.is_premium else 'Нет'}\n"
- f"• Вопросов использовано: {user.questions_used}/{settings.FREE_QUESTIONS_LIMIT}\n\n"
- )
-
- if user.is_premium:
- stats_text += (
- f"Premium статус:\n"
- f"• Активен до: {user.premium_until.strftime('%d.%m.%Y') if user.premium_until else 'Не указано'}\n"
- f"• Лимит вопросов: безлимитно\n\n"
+ if user:
+ stats_text = (
+ f"Ваша статистика\n\n"
+ f"Основное:\n"
+ f"• ID: {user_id}\n"
+ f"• Premium: {'Да' if user.is_premium else 'Нет'}\n"
+ f"• Вопросов использовано: {user.questions_used}/{settings.FREE_QUESTIONS_LIMIT}\n\n"
)
+
+ if user.is_premium:
+ stats_text += (
+ f"Premium статус:\n"
+ f"• Активен до: {user.premium_until.strftime('%d.%m.%Y') if user.premium_until else 'Не указано'}\n"
+ f"• Лимит вопросов: безлимитно\n\n"
+ )
+ else:
+ remaining = max(0, settings.FREE_QUESTIONS_LIMIT - user.questions_used)
+ stats_text += (
+ f"Бесплатный доступ:\n"
+ f"• Осталось вопросов: {remaining}\n"
+ f"• Для безлимита: /buy\n\n"
+ )
else:
- remaining = max(0, settings.FREE_QUESTIONS_LIMIT - user.questions_used)
- stats_text += (
- f"Бесплатный доступ:\n"
- f"• Осталось вопросов: {remaining}\n"
- f"• Для безлимита: /buy\n\n"
+ stats_text = (
+ f"Добро пожаловать!\n\n"
+ f"Вы новый пользователь.\n"
+ f"• Ваш ID: {user_id}\n"
+ f"• Бесплатных вопросов: {settings.FREE_QUESTIONS_LIMIT}\n"
+ f"• Для начала работы просто задайте вопрос!\n\n"
+ f"Используйте /buy для получения полного доступа"
)
- else:
- stats_text = (
- f"Добро пожаловать!\n\n"
- f"Вы новый пользователь.\n"
- f"• Ваш ID: {user_id}\n"
- f"• Бесплатных вопросов: {settings.FREE_QUESTIONS_LIMIT}\n"
- f"• Для начала работы просто задайте вопрос!\n\n"
- f"Используйте /buy для получения полного доступа"
+ await message.answer(stats_text, parse_mode="HTML")
+
+ except Exception as e:
+ await message.answer(
+ f"Ошибка получения статистики\n\n"
+ f"Попробуйте позже.",
+ parse_mode="HTML"
)
-
- await message.answer(stats_text, parse_mode="HTML")
-
- except Exception as e:
- await message.answer(
- f"Ошибка получения статистики\n\n"
- f"Попробуйте позже.",
- parse_mode="HTML"
- )
- finally:
- session.close()
diff --git a/tg_bot/payment/webhooks/handler.py b/tg_bot/payment/webhooks/handler.py
index 6bf0c99..c0cb1eb 100644
--- a/tg_bot/payment/webhooks/handler.py
+++ b/tg_bot/payment/webhooks/handler.py
@@ -19,47 +19,48 @@ async def handle_yookassa_webhook(request: Request):
try:
from tg_bot.config.settings import settings
from tg_bot.domain.services.user_service import UserService
- from tg_bot.infrastructure.database.database import SessionLocal
+ from tg_bot.infrastructure.database.database import AsyncSessionLocal
from tg_bot.infrastructure.database.models import UserModel
+ from sqlalchemy import select
from aiogram import Bot
- session = SessionLocal()
if event_type == "payment.succeeded":
payment = data.get("object", {})
user_id = payment.get("metadata", {}).get("user_id")
if user_id:
- user_service = UserService(session)
- success = await user_service.activate_premium(int(user_id))
- if success:
- print(f"Premium activated for user {user_id}")
-
- user = session.query(UserModel).filter_by(
- telegram_id=str(user_id)
- ).first()
-
- if user and settings.TELEGRAM_BOT_TOKEN:
- try:
- bot = Bot(token=settings.TELEGRAM_BOT_TOKEN)
- premium_until = user.premium_until or datetime.now() + timedelta(days=30)
-
- notification = (
- f"Оплата подтверждена!\n\n"
- f"Premium активирован до {premium_until.strftime('%d.%m.%Y')}"
- )
-
- await bot.send_message(
- chat_id=int(user_id),
- text=notification,
- parse_mode="HTML"
- )
- print(f"Notification sent to user {user_id}")
- await bot.session.close()
- except Exception as e:
- print(f"Error sending notification: {e}")
- else:
- print(f"User {user_id} not found")
- session.close()
+ async with AsyncSessionLocal() as session:
+ user_service = UserService(session)
+ success = await user_service.activate_premium(int(user_id))
+ if success:
+ print(f"Premium activated for user {user_id}")
+
+ result = await session.execute(
+ select(UserModel).filter_by(telegram_id=str(user_id))
+ )
+ user = result.scalar_one_or_none()
+
+ if user and settings.TELEGRAM_BOT_TOKEN:
+ try:
+ bot = Bot(token=settings.TELEGRAM_BOT_TOKEN)
+ premium_until = user.premium_until or datetime.now() + timedelta(days=30)
+
+ notification = (
+ f"Оплата подтверждена!\n\n"
+ f"Premium активирован до {premium_until.strftime('%d.%m.%Y')}"
+ )
+
+ await bot.send_message(
+ chat_id=int(user_id),
+ text=notification,
+ parse_mode="HTML"
+ )
+ print(f"Notification sent to user {user_id}")
+ await bot.session.close()
+ except Exception as e:
+ print(f"Error sending notification: {e}")
+ else:
+ print(f"User {user_id} not found")
except ImportError as e:
print(f"Import error: {e}")