from aiogram import Router, types from aiogram.types import Message from tg_bot.config.settings import settings from tg_bot.domain.user_service import UserService, User from tg_bot.application.services.rag_service import RAGService import re router = Router() rag_service = RAGService() user_service = UserService() @router.message() async def handle_question(message: Message): user_id = message.from_user.id question_text = message.text.strip() if question_text.startswith('/'): return try: user = await user_service.get_user_by_telegram_id(user_id) if not user: user = await user_service.get_or_create_user( user_id, message.from_user.username or "", message.from_user.first_name or "", message.from_user.last_name or "" ) if user.is_premium: await process_premium_question(message, user, question_text) elif user.questions_used < settings.FREE_QUESTIONS_LIMIT: await process_free_question(message, user, question_text) else: await handle_limit_exceeded(message, user) except Exception as e: print(f"Error processing question: {e}") await message.answer( "Произошла ошибка. Попробуйте позже.", parse_mode="HTML" ) async def process_premium_question(message: Message, user: User, question_text: str): await user_service.update_user_questions(int(user.telegram_id)) user = await user_service.get_user_by_telegram_id(int(user.telegram_id)) await message.bot.send_chat_action(message.chat.id, "typing") try: rag_result = await rag_service.generate_answer_with_rag( question_text, str(message.from_user.id) ) answer = rag_result.get("answer", "Извините, не удалось сгенерировать ответ.") sources = rag_result.get("sources", []) # Беседа уже сохранена в бэкенде через API /rag/question import re formatted_answer = answer formatted_answer = re.sub(r'\*\*(.+?)\*\*', r'\1', formatted_answer) formatted_answer = re.sub(r'^(\d+)\.\s+', r'\1. ', formatted_answer, flags=re.MULTILINE) formatted_answer = formatted_answer.replace("- ", "• ") response = ( f"Ваш вопрос:\n" f"{question_text[:200]}\n\n" f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n" f"💬 Ответ:\n\n" f"{formatted_answer}\n\n" ) if sources: response += f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n" response += f"📚 Источники:\n" for idx, source in enumerate(sources[:5], 1): title = source.get('title', 'Без названия') try: from urllib.parse import unquote decoded = unquote(title) # Если декодирование изменило строку или исходная содержит %XX if decoded != title or '%' in title: title = decoded except: pass response += f" {idx}. {title}\n" response += "\n💡 Используйте /mycollections для просмотра всех коллекций\n\n" response += ( f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n" f"✨ Статус: Premium (вопросов безлимитно)\n" f"📊 Всего вопросов: {user.questions_used}" ) except Exception as e: print(f"Error generating answer: {e}") response = ( f"Ваш вопрос:\n" f"{question_text[:200]}\n\n" f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n" f"❌ Ошибка при генерации ответа.\n" f"Попробуйте позже.\n\n" f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n" f"✨ Статус: Premium\n" f"📊 Всего вопросов: {user.questions_used}" ) await message.answer(response, parse_mode="HTML") async def process_free_question(message: Message, user: User, question_text: str): await user_service.update_user_questions(int(user.telegram_id)) user = await user_service.get_user_by_telegram_id(int(user.telegram_id)) remaining = settings.FREE_QUESTIONS_LIMIT - user.questions_used await message.bot.send_chat_action(message.chat.id, "typing") try: rag_result = await rag_service.generate_answer_with_rag( question_text, str(message.from_user.id) ) answer = rag_result.get("answer", "Извините, не удалось сгенерировать ответ.") sources = rag_result.get("sources", []) # Уже все сохранили через /rag/question formatted_answer = answer formatted_answer = re.sub(r'\*\*(.+?)\*\*', r'\1', formatted_answer) formatted_answer = re.sub(r'^(\d+)\.\s+', r'\1. ', formatted_answer, flags=re.MULTILINE) formatted_answer = formatted_answer.replace("- ", "• ") response = ( f"Ваш вопрос:\n" f"{question_text[:200]}\n\n" f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n" f"💬 Ответ:\n\n" f"{formatted_answer}\n\n" ) if sources: response += f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n" response += f"📚 Источники:\n" for idx, source in enumerate(sources[:5], 1): title = source.get('title', 'Без названия') try: from urllib.parse import unquote decoded = unquote(title) # Если декодирование изменило строку или исходная содержит %XX if decoded != title or '%' in title: title = decoded except: pass response += f" {idx}. {title}\n" response += "\n💡 Используйте /mycollections для просмотра всех коллекций\n\n" response += ( f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n" f"📊 Статус: Бесплатный доступ\n" f"📈 Использовано вопросов: {user.questions_used}/{settings.FREE_QUESTIONS_LIMIT}\n" f"🎯 Осталось бесплатных: {remaining}\n\n" ) if remaining <= 3 and remaining > 0: response += f"⚠️ Осталось мало вопросов! Для продолжения используйте /buy\n\n" response += f"💎 Для безлимитного доступа: /buy" except Exception as e: print(f"Error generating answer: {e}") response = ( f"Ваш вопрос:\n" f"{question_text[:200]}\n\n" f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n" f"❌ Ошибка при генерации ответа.\n" f"Попробуйте позже.\n\n" f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n" f"📊 Статус: Бесплатный доступ\n" f"📈 Использовано вопросов: {user.questions_used}/{settings.FREE_QUESTIONS_LIMIT}\n" f"🎯 Осталось бесплатных: {remaining}\n\n" f"💎 Для безлимитного доступа: /buy" ) await message.answer(response, parse_mode="HTML") #Сново сохраняется в /rag/question async def handle_limit_exceeded(message: Message, user: User): response = ( f"Лимит бесплатных вопросов исчерпан!\n\n" f"Ваша статистика:\n" f"• Использовано вопросов: {user.questions_used}\n" f"• Бесплатный лимит: {settings.FREE_QUESTIONS_LIMIT}\n\n" f"Что делать дальше?\n" f"1. Купите подписку командой /buy\n" f"2. Получите неограниченный доступ к вопросам\n" f"3. Продолжайте использовать бот без ограничений\n\n" f"Подписка включает:\n" f"• Неограниченное количество вопросов\n" f"• Приоритетную обработку\n" f"• Доступ ко всем функциям\n\n" f"Нажмите /buy чтобы продолжить" ) await message.answer(response, parse_mode="HTML")