from datetime import datetime, timedelta, timezone from aiogram import Router from aiogram.filters import Command, CommandObject from aiogram.types import Message from loguru import logger from app.bot.texts import ( user_info, USER_NOT_FOUND, INVALID_ARGS, NO_DATA, expired_list, expiring_list, ) from app.database import async_session_factory from app.models.payment import PaymentStatus from app.repositories.payment import PaymentRepository from app.repositories.tariff import TariffRepository from app.repositories.user import UserRepository from app.services.billing import BillingService router = Router(name="subscription") @router.message(Command("renew")) async def cmd_renew(message: Message, command: CommandObject) -> None: if not command.args or not command.args.strip().isdigit(): await message.answer( INVALID_ARGS.format("/renew "), parse_mode="HTML", ) return telegram_id = int(command.args.strip()) async with async_session_factory() as session: user_repo = UserRepository(session) user = await user_repo.get_by_telegram_id(telegram_id) if user is None: await message.answer( USER_NOT_FOUND.format(telegram_id), parse_mode="HTML" ) return billing = BillingService( PaymentRepository(session), TariffRepository(session), user_repo, ) sub = await billing.get_active_subscription(user.id) await message.answer( user_info( user_id=user.id, telegram_id=user.telegram_id, username=user.username, full_name=user.full_name, is_active=user.is_active, created_at=user.created_at.strftime("%Y-%m-%d"), subscription_active=sub is not None and sub.is_active, tariff_name=sub.tariff.name if sub and sub.tariff else None, remaining_days=sub.remaining_days if sub else 0, ), parse_mode="HTML", ) @router.message(Command("expired")) async def cmd_expired(message: Message) -> None: async with async_session_factory() as session: payment_repo = PaymentRepository(session) tariff_repo = TariffRepository(session) user_repo = UserRepository(session) confirmed = await payment_repo.get_by_status(PaymentStatus.CONFIRMED) now = datetime.now(timezone.utc) items = [] for payment in confirmed: tariff = await tariff_repo.get(payment.tariff_id) if tariff is None: continue start = payment.paid_at or payment.created_at end = start + timedelta(days=tariff.duration_days) if now > end: user = await user_repo.get(payment.user_id) items.append( { "user_id": payment.user_id, "telegram_id": user.telegram_id if user else "?", "tariff_name": tariff.name, } ) await message.answer(expired_list(items), parse_mode="HTML") @router.message(Command("expiring")) async def cmd_expiring(message: Message, command: CommandObject) -> None: days = 3 if command.args and command.args.strip().isdigit(): days = int(command.args.strip()) async with async_session_factory() as session: payment_repo = PaymentRepository(session) tariff_repo = TariffRepository(session) user_repo = UserRepository(session) confirmed = await payment_repo.get_by_status(PaymentStatus.CONFIRMED) now = datetime.now(timezone.utc) items = [] for payment in confirmed: tariff = await tariff_repo.get(payment.tariff_id) if tariff is None: continue start = payment.paid_at or payment.created_at end = start + timedelta(days=tariff.duration_days) remaining = (end - now).days if 0 <= remaining <= days: user = await user_repo.get(payment.user_id) items.append( { "user_id": payment.user_id, "telegram_id": user.telegram_id if user else "?", "tariff_name": tariff.name, "remaining_days": remaining, } ) items.sort(key=lambda x: x["remaining_days"]) await message.answer(expiring_list(items, days), parse_mode="HTML")