from aiogram import F, Router from aiogram.filters import Command, CommandObject, CommandStart from aiogram.fsm.context import FSMContext from aiogram.types import CallbackQuery, Message from sqlalchemy.ext.asyncio import AsyncSession from bot.keyboards.client import close_kb, main_menu, subscription_controls from bot.keyboards.common import return_to_menu from bot.texts import ( CALLBACK_FALLBACK, FAQ_TEXT, GENERAL_PROCESSING, GENERAL_SUCCESS, NO_SUBSCRIPTION, NOTHING_PLACEHOLDER, ) from db.models.users import User from misc import utils from misc.utils import build_main_menu_text, format_subscription_link from schemas.di import DependenciesDTO from schemas.subscriptions import InternalSquads, SubscriptionPlan from services.rw import get_user_by_telegram_id router = Router() @router.message(CommandStart(deep_link=True, deep_link_encoded=True)) async def fetch_referal( msg: Message, command: CommandObject, state: FSMContext, session: AsyncSession, deps: DependenciesDTO, ): await state.clear() data = command.args.split("_") if not data: await standard_start(msg, command, state) return referal = int(data[1]) user = await deps.user_service.add_user( session, user_id=msg.from_user.id, referal=referal, rw_sdk=deps.rw_sdk ) await msg.answer( build_main_menu_text( format_subscription_link(user.subscription_link), balance=user.balance ), reply_markup=main_menu, ) @router.message(Command(commands=["start", "cancel"])) async def standard_start( msg: Message, state: FSMContext, session: AsyncSession, deps: DependenciesDTO, ): await state.clear() user = await deps.user_service.add_user(session, user_id=msg.from_user.id, rw_sdk=deps.rw_sdk) await msg.answer( build_main_menu_text( format_subscription_link(user.subscription_link), balance=user.balance ), reply_markup=main_menu, ) @router.callback_query(F.data == "menu:main") async def main_menu_cb( cb: CallbackQuery, state: FSMContext, session: AsyncSession, deps: DependenciesDTO ): await state.clear() user = await deps.user_repository.get_user_by_id(session, cb.from_user.id) await cb.message.edit_text( build_main_menu_text( format_subscription_link(user.subscription_link), balance=user.balance ), reply_markup=main_menu, ) @router.callback_query(F.data == "update_link") async def update_link( cb: CallbackQuery, state: FSMContext, session: AsyncSession, deps: DependenciesDTO ): await state.clear() await cb.message.edit_text(GENERAL_PROCESSING) user = await deps.user_service.update_user_link(session, cb.from_user.id, deps.rw_sdk) await cb.answer("✅") await cb.message.edit_text( build_main_menu_text( format_subscription_link(user.subscription_link), balance=user.balance ), reply_markup=main_menu, ) @router.callback_query(F.data == "faq") async def faq(cb: CallbackQuery, state: FSMContext): await state.clear() await cb.message.edit_text(FAQ_TEXT, reply_markup=return_to_menu) @router.callback_query(F.data == "sub_info") async def sub_info( cb: CallbackQuery, state: FSMContext, deps: DependenciesDTO, session: AsyncSession ): await state.clear() await cb.message.edit_text(GENERAL_PROCESSING, reply_markup=close_kb) rw_user = await get_user_by_telegram_id(deps.rw_sdk, cb.from_user.id) user: User | None = await deps.user_service.update_user_link( session, cb.from_user.id, deps.rw_sdk ) sub = await deps.subscriptions_repository.get_subscription_by_user_id(session, cb.from_user.id) if not rw_user: await cb.message.edit_text(NO_SUBSCRIPTION, reply_markup=return_to_menu) return if not user: await cb.answer("1" + CALLBACK_FALLBACK) return if rw_user and not sub: try: dto = SubscriptionPlan( devices=rw_user.hwid_device_limit, whitelists=bool(rw_user.active_squads.count(InternalSquads.WHITELISTS)), discount=0, ) sub = await deps.subscriptions_repository.create_subscription( session, user_id=user.id, end_date=rw_user.expire_at, devices=rw_user.hwid_device_limit, duration_days=30, whitelists=dto.whitelists, plan_price_paid=utils.calculate_price(dto), ) except Exception: await cb.answer("2" + CALLBACK_FALLBACK) return await cb.message.edit_text( deps.user_service.format_subscription_message( rw_user, link=user.subscription_link, autorenew=sub.autorenew ), reply_markup=subscription_controls( show_autorenew=bool(rw_user), current_autorenewal_status=sub.autorenew ), ) @router.callback_query(F.data == "toggle:autorenewal") async def toggle_autorenewal( cb: CallbackQuery, state: FSMContext, session: AsyncSession, deps: DependenciesDTO ): await state.clear() await cb.message.edit_text(GENERAL_PROCESSING) sub = await deps.subscriptions_repository.get_subscription_by_user_id(session, cb.from_user.id) if not sub: await cb.answer(CALLBACK_FALLBACK) return new_autorenew = not sub.autorenew sub = await deps.subscriptions_repository.update_subscription_autorenew( session, sub.user_id, new_autorenew ) rw_user = await get_user_by_telegram_id(deps.rw_sdk, cb.from_user.id) user: User | None = await deps.user_service.update_user_link( session, cb.from_user.id, deps.rw_sdk ) status_text = "включено" if new_autorenew else "отключено" await cb.answer(f"Автопродление {status_text}") await cb.message.edit_text( deps.user_service.format_subscription_message( rw_user, link=user.subscription_link, autorenew=sub.autorenew ), reply_markup=subscription_controls( show_autorenew=bool(rw_user), current_autorenewal_status=sub.autorenew ), ) rw_user = await get_user_by_telegram_id(deps.rw_sdk, cb.from_user.id) user: User | None = await deps.user_service.update_user_link( session, cb.from_user.id, deps.rw_sdk ) status_text = "включено" if new_autorenew else "отключено" await cb.answer(f"Автопродление {status_text}") await cb.message.edit_text( deps.user_service.format_subscription_message( rw_user, link=user.subscription_link, autorenew=sub.autorenew ), reply_markup=subscription_controls( show_autorenew=bool(rw_user), current_autorenewal_status=sub.autorenew ), )