from typing import Optional from aiogram import Router, F from aiogram.types import CallbackQuery from aiogram.fsm.context import FSMContext from keyboards.client import devices_selector, duration_selector from misc.utils import calculate_price, convert_int_to_duration from schemas.subscriptions import SubscriptionPlan from states.buy import SubscriptionStorage from texts import ( CALLBACK_FALLBACK, CONTEXT_REINITIATED, NOTHING_PLACEHOLDER, SUBSCRIPTION_DEVICE_SELECTOR, SUBSCRIPTION_DURATION_SELECTOR, ) from config import settings router = Router() @router.callback_query(F.data == "buy") async def buy_init(cb: CallbackQuery, state: FSMContext): await state.clear() ctx = SubscriptionPlan() await cb.message.edit_text( SUBSCRIPTION_DEVICE_SELECTOR.format(price=calculate_price(ctx)), reply_markup=devices_selector(settings.min_devices), ) await state.set_state(SubscriptionStorage.devices) await state.set_data({"ctx": ctx}) @router.callback_query(F.data.startswith("devices:")) async def device_count_select(cb: CallbackQuery, state: FSMContext): data = await state.get_data() await state.clear() ctx: Optional[SubscriptionPlan] = data.get("ctx", SubscriptionPlan()) cb_data = cb.data.split(":") devices = int(cb_data[1]) if cb_data[1].isdigit() else settings.min_devices ctx.devices = devices ctx.whitelists = ctx.whitelists or devices >= settings.whitelist_device_threshold await cb.message.edit_text( SUBSCRIPTION_DEVICE_SELECTOR.format(price=calculate_price(ctx)), reply_markup=devices_selector(current=ctx.devices, whitelists=ctx.whitelists), ) await state.set_state(SubscriptionStorage.devices) await state.set_data({"ctx": ctx}) @router.callback_query(SubscriptionStorage.devices, F.data == "whitelist:toggle") async def toggle_whitelists(cb: CallbackQuery, state: FSMContext): data = await state.get_data() await state.clear() ctx: Optional[SubscriptionPlan] = data.get("ctx") if not ctx: await state.set_state(SubscriptionPlan()) await state.set_data({"ctx": ctx}) await cb.answer(CALLBACK_FALLBACK) return ctx.whitelists = ( not ctx.whitelists or ctx.devices >= settings.whitelist_device_threshold ) try: await cb.message.edit_reply_markup( SUBSCRIPTION_DEVICE_SELECTOR.format(price=calculate_price(ctx)), reply_markup=devices_selector( current=ctx.devices, whitelists=ctx.whitelists ), ) except Exception as exc: if "message is not modified:" in str(exc): await cb.answer(NOTHING_PLACEHOLDER) else: await cb.answer(CALLBACK_FALLBACK) await state.set_state(SubscriptionStorage.devices) await state.set_data({"ctx": ctx}) @router.callback_query(SubscriptionStorage.devices, F.data == "confirm") async def select_duration_init(cb: CallbackQuery, state: FSMContext): data = await state.get_data() await state.clear() ctx: Optional[SubscriptionPlan] = data.get("ctx") if not ctx: await state.set_state(SubscriptionPlan()) await state.set_data({"ctx": ctx}) await cb.answer(CALLBACK_FALLBACK) return try: await cb.message.edit_text( SUBSCRIPTION_DURATION_SELECTOR.format(price=calculate_price(ctx)), reply_markup=duration_selector( current=ctx.duration, back_cb=f"devices:{ctx.devices}" ), ) except Exception as exc: if "message is not modified:" in str(exc): await cb.answer(NOTHING_PLACEHOLDER) else: await cb.answer(CALLBACK_FALLBACK) raise await state.set_state(SubscriptionStorage.duration) await state.set_data({"ctx": ctx}) @router.callback_query(F.data.startswith("duration:")) async def select_duration(cb: CallbackQuery, state: FSMContext): data = await state.get_data() await state.clear() ctx: Optional[SubscriptionPlan] = data.get("ctx") if not ctx: await state.set_state() await state.set_data({"ctx": ctx}) await cb.answer(CONTEXT_REINITIATED) ctx = SubscriptionPlan() cb_data = cb.data.split(":") duration = int(cb_data[1]) if cb_data[1].isdigit() else 1 ctx.duration = convert_int_to_duration(duration) try: await cb.message.edit_text( SUBSCRIPTION_DURATION_SELECTOR.format(price=calculate_price(ctx)), reply_markup=duration_selector( current=ctx.duration, back_cb=f"devices:{ctx.devices}" ), ) except Exception as exc: if "message is not modified:" in str(exc): await cb.answer(NOTHING_PLACEHOLDER) else: await cb.answer(CALLBACK_FALLBACK) raise await state.set_state(SubscriptionStorage.duration) await state.set_data({"ctx": ctx}) @router.callback_query(SubscriptionStorage.duration, F.data == "confirm") async def proceed_to_checkout(cb: CallbackQuery, state: FSMContext): await cb.answer("yay!!!! fuck off.") ...