import html from aiogram import Router, F from aiogram.filters import Command from aiogram.types import Message, CallbackQuery from database import Database from kwork import get_kwork_projects from ai import filter_vacancies_with_ai from aiogram import F from aiogram.types import CallbackQuery import logging from keyboards import get_pagination_kb router = Router() db = Database("users.db") @router.message(Command("search")) async def search_projects(message: Message): args = message.text.split() start_p, end_p = 1, 1 if len(args) == 3: if args[1].isdigit() and args[2].isdigit(): start_p, end_p = int(args[1]), int(args[2]) elif len(args) == 2: if args[1].isdigit(): start_p, end_p = int(args[1]), int(args[1]) user_data = await db.get_user(message.from_user.id) if not user_data or user_data[0] is None: await message.answer("⚠️ Твой профиль еще не настроен.") return sphere, lang, prefs = user_data user_preferences = f"- Сфера: {sphere}\n- Стек: {lang}\n- Доп: {prefs}" msg = await message.answer(f"⏳ Собираю свежие проекты и анализирую их нейросетью...\nЭто может занять около минуты.") try: raw_vacancies = await get_kwork_projects(start_page=start_p, end_page=end_p) if not raw_vacancies: await msg.edit_text("❌ Проектов не найдено.") return filtered_vacancies = await filter_vacancies_with_ai(raw_vacancies, user_preferences) if not filtered_vacancies: await msg.edit_text("😔 Подходящих проектов сейчас нет.") return await msg.delete() await message.answer(f"🎯 Найдено {len(filtered_vacancies)} подходящих проектов:") for vac in filtered_vacancies: title = html.escape(vac.get('title', 'Без названия')) price = html.escape(vac.get('price', 'По договоренности')) desc = html.escape(vac.get('description', '')) url = vac.get('url', '#') text = ( f"💼 {title}\n\n" f"💰 Бюджет: {price}\n" f"📝 Описание: {desc}...\n\n" f"🔗 Смотреть на Kwork" ) # Отправляем, отключая превью ссылок, чтобы не захламлять чат await message.answer(text, disable_web_page_preview=True) except Exception as e: print(f"Ошибка в поиске: {e}") await msg.edit_text("❌ Произошла ошибка при анализе проектов. Попробуй еще раз чуть позже.") async def build_pages_text(page_num: int): raw_vacancies = await get_kwork_projects(start_page=page_num, end_page=page_num) if not raw_vacancies: return "❌ На этой странице проектов не найдено." text = f"📂 Все проекты (Страница {page_num}):\n\n" for i, vac in enumerate(raw_vacancies, 1): title = html.escape(vac.get('title', 'Без названия')) price = html.escape(vac.get('price', 'По договоренности')) url = vac.get('url', '#') desc = html.escape(vac.get('description', ''))[:100] + "..." text += f"{i}. {title}\n💰 {price}\n📝 {desc}\n\n" return text @router.message(Command("all")) async def command_all_vancancies(message: Message): wait_msg = await message.answer("⏳ Загружаю список проектов...") try: page = 1 content = await build_pages_text(page) await wait_msg.edit_text( content, reply_markup=get_pagination_kb(page), disable_web_page_preview=True ) except Exception as e: logging.error(f"Error in /all: {e}") await wait_msg.edit_text("⚠️ Ошибка при загрузке данных.") # Обработка нажатий на кнопки пагинации @router.callback_query(F.data.startswith("browse_")) async def process_pagination(callback: CallbackQuery): page = int(callback.data.split("_")[1]) await callback.message.edit_text("🔄 Обновляю список...") try: content = await build_pages_text(page) await callback.message.edit_text( content, reply_markup=get_pagination_kb(page), disable_web_page_preview=True ) await callback.answer() except Exception as e: logging.error(f"Error in pagination: {e}") await callback.answer("Ошибка при смене страницы", show_alert=True)