112 lines
3.4 KiB
Python
112 lines
3.4 KiB
Python
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("<b>🔍 Введите запрос:</b>", 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(
|
|
"<b>🗒 Результаты поиска:</b>",
|
|
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,
|
|
)
|
|
)
|