import os from re import Match from aiogram import Router, F from aiogram.types import CallbackQuery, FSInputFile from aiogram.fsm.context import FSMContext from sqlalchemy.ext.asyncio import AsyncSession from config import PAGE_SIZE from misc.kb.client import ( render_product_interactions, render_products, ) from misc.texts import get_product_description from repositories.categories import CategoriesRepository from repositories.products import ProductRepository from services.orders import OrderService router = Router() @router.callback_query( F.data.regexp(r"products:(?P.*):(?P\d+)").as_( "pagination_match" ) ) async def products_pagination( cb: CallbackQuery, state: FSMContext, pagination_match: Match[str], session: AsyncSession, products_repo: ProductRepository, categories_repo: CategoriesRepository, ): await state.clear() pagination_data = pagination_match.groupdict() category_id = int(pagination_data.get("category_id")) category = await categories_repo.get_category_by_id(session, category_id) page_id = int(pagination_data.get("page_id", 0)) products = await products_repo.get_product_by_category( session, category_id, limit=PAGE_SIZE + 1, offset=page_id * PAGE_SIZE ) products_len = len(products) await cb.message.edit_reply_markup( reply_markup=render_products( products[:PAGE_SIZE], parent_id=category.parent_id, cat_id=category_id, page=page_id, show_prev=page_id > 0, show_next=products_len > PAGE_SIZE, ), ) @router.callback_query(F.data.startswith("product:")) async def product_card( cb: CallbackQuery, state: FSMContext, session: AsyncSession, products_repo: ProductRepository, order_service: OrderService, ): await state.clear() product_id = int(cb.data.split(":")[1]) product = await products_repo.get_product_by_id(session, product_id) order_item = await order_service.get_cart_product_amount( session, customer=cb.from_user.id, product_id=product_id ) if product.file_id: await cb.message.delete() msg = await cb.message.answer_photo( product.file_id, caption=get_product_description(product), reply_markup=render_product_interactions( product_id=product.id, category_id=product.category_id, show_cart=bool(order_item), cart_amount=order_item, ), ) return if not os.path.isfile(product.img_path): await cb.message.edit_text( get_product_description(product), reply_markup=render_product_interactions( product_id=product.id, category_id=product.category_id, show_cart=bool(order_item), cart_amount=order_item, ), ) return await cb.message.delete() msg = await cb.message.answer_photo( FSInputFile(product.img_path), caption=get_product_description(product), reply_markup=render_product_interactions( product_id=product.id, category_id=product.category_id, show_cart=bool(order_item), cart_amount=order_item, ), ) if not msg.photo: return # TODO: Add logging await products_repo.add_product_file_id( session, product_id, file_id=msg.photo[-1].file_id ) @router.callback_query(F.data.startswith("cart_action:")) async def add_to_cart( cb: CallbackQuery, state: FSMContext, session: AsyncSession, order_service: OrderService, products_repo: ProductRepository, ): await state.clear() action = cb.data.split(":")[1] product_id = int(cb.data.split(":")[2]) product = await products_repo.get_product_by_id(session, product_id) show_cart = True if action == "add": quantity = await order_service.add_to_cart( session, customer=cb.from_user.id, product_id=product_id ) elif action == "remove": quantity = await order_service.remove_from_cart( session, customer=cb.from_user.id, product_id=product_id ) show_cart = bool(quantity) else: show_cart = False quantity = 0 await order_service.clear_cart_item( session, customer=cb.from_user.id, product_id=product_id ) try: await cb.message.edit_reply_markup( reply_markup=render_product_interactions( product_id=product_id, category_id=product.category_id, show_cart=show_cart, cart_amount=quantity, ) ) except Exception as e: await cb.answer("🍃") raise e