import hashlib from aiogram import F, Router from aiogram.fsm.context import FSMContext from aiogram.types import CallbackQuery, Message from sqlalchemy.ext.asyncio import AsyncSession from config import PAGE_SIZE, VERIFIED_ACCOUNTS from misc.kb.client import render_products from misc.kb.common import return_menu from misc.redis import RedisClient from misc.states import SearchStorage from repositories.products import ProductRepository router = Router() @router.callback_query(F.data == "find") async def search_trigger(cb: CallbackQuery, state: FSMContext): await state.clear() await cb.message.edit_text("🔍 Введите запрос:", reply_markup=return_menu) await state.set_state(SearchStorage.query) await state.set_data({"msg": cb.message}) @router.message(SearchStorage.query) async def searching( msg: Message, state: FSMContext, session: AsyncSession, products_repo: ProductRepository, redis_client: RedisClient, ): data = await state.get_data() await state.clear() await msg.delete() orig_msg: Message | None = data.get("msg") or await msg.answer("⏳") await orig_msg.edit_text("⏳ Поиск...") is_admin = msg.from_user.id in VERIFIED_ACCOUNTS results = await products_repo.search( session, msg.text, include_hidden=is_admin, ) next_cb = None if len(results) > PAGE_SIZE: query_hash = hashlib.sha256(msg.text.encode()).hexdigest()[:16] await redis_client.set_search_query(query_hash, msg.text) next_cb = f"search:{query_hash}:1" total = await products_repo.count_search(session, msg.text, include_hidden=is_admin) total_pages = (total + PAGE_SIZE - 1) // PAGE_SIZE if total else None await orig_msg.edit_text( "🗒 Результаты поиска:", reply_markup=render_products( results[:PAGE_SIZE], product_cb_factory=lambda p: f"product:{p.id}", back_cb="menu:main", next_cb=next_cb, is_admin=is_admin, page=0, total_pages=total_pages, ), ) @router.callback_query(F.data.startswith("search:")) async def search_pagination( cb: CallbackQuery, state: FSMContext, session: AsyncSession, products_repo: ProductRepository, redis_client: RedisClient, ): await state.clear() data = cb.data.split(":") q_hash = data[1] page = int(data[2]) query = await redis_client.get_search_query(q_hash) if not query: await cb.message.edit_text("🍃 Попробуйте ещё раз...") is_admin = cb.from_user.id in VERIFIED_ACCOUNTS results = await products_repo.search( session, query, offset=PAGE_SIZE * page, include_hidden=is_admin, ) total = await products_repo.count_search(session, query, include_hidden=is_admin) total_pages = (total + PAGE_SIZE - 1) // PAGE_SIZE if total else None await cb.message.edit_reply_markup( reply_markup=render_products( results[:PAGE_SIZE], product_cb_factory=lambda p: f"product:{p.id}", back_cb="menu:main", next_cb=f"search:{q_hash}:{page + 1}" if len(results) > PAGE_SIZE else None, prev_cb=f"search:{q_hash}:{page - 1}" if page > 0 else None, is_admin=is_admin, page=page, total_pages=total_pages, ) )