218 lines
9.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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'<b>\1</b>', formatted_answer)
formatted_answer = re.sub(r'^(\d+)\.\s+', r'\1. ', formatted_answer, flags=re.MULTILINE)
formatted_answer = formatted_answer.replace("- ", "")
response = (
f"<b>Ваш вопрос:</b>\n"
f"<i>{question_text[:200]}</i>\n\n"
f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
f"💬 <b>Ответ:</b>\n\n"
f"{formatted_answer}\n\n"
)
if sources:
response += f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
response += f"📚 <b>Источники:</b>\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<i>💡 Используйте /mycollections для просмотра всех коллекций</i>\n\n"
response += (
f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
f"✨ <b>Статус:</b> Premium (вопросов безлимитно)\n"
f"📊 <b>Всего вопросов:</b> {user.questions_used}"
)
except Exception as e:
print(f"Error generating answer: {e}")
response = (
f"<b>Ваш вопрос:</b>\n"
f"<i>{question_text[:200]}</i>\n\n"
f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
f"❌ <b>Ошибка при генерации ответа.</b>\n"
f"Попробуйте позже.\n\n"
f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
f"✨ <b>Статус:</b> Premium\n"
f"📊 <b>Всего вопросов:</b> {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'<b>\1</b>', formatted_answer)
formatted_answer = re.sub(r'^(\d+)\.\s+', r'\1. ', formatted_answer, flags=re.MULTILINE)
formatted_answer = formatted_answer.replace("- ", "")
response = (
f"<b>Ваш вопрос:</b>\n"
f"<i>{question_text[:200]}</i>\n\n"
f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
f"💬 <b>Ответ:</b>\n\n"
f"{formatted_answer}\n\n"
)
if sources:
response += f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
response += f"📚 <b>Источники:</b>\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<i>💡 Используйте /mycollections для просмотра всех коллекций</i>\n\n"
response += (
f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
f"📊 <b>Статус:</b> Бесплатный доступ\n"
f"📈 <b>Использовано вопросов:</b> {user.questions_used}/{settings.FREE_QUESTIONS_LIMIT}\n"
f"🎯 <b>Осталось бесплатных:</b> {remaining}\n\n"
)
if remaining <= 3 and remaining > 0:
response += f"⚠️ <i>Осталось мало вопросов! Для продолжения используйте /buy</i>\n\n"
response += f"💎 <i>Для безлимитного доступа: /buy</i>"
except Exception as e:
print(f"Error generating answer: {e}")
response = (
f"<b>Ваш вопрос:</b>\n"
f"<i>{question_text[:200]}</i>\n\n"
f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
f"❌ <b>Ошибка при генерации ответа.</b>\n"
f"Попробуйте позже.\n\n"
f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n"
f"📊 <b>Статус:</b> Бесплатный доступ\n"
f"📈 <b>Использовано вопросов:</b> {user.questions_used}/{settings.FREE_QUESTIONS_LIMIT}\n"
f"🎯 <b>Осталось бесплатных:</b> {remaining}\n\n"
f"💎 <i>Для безлимитного доступа: /buy</i>"
)
await message.answer(response, parse_mode="HTML")
#Сново сохраняется в /rag/question
async def handle_limit_exceeded(message: Message, user: User):
response = (
f"<b>Лимит бесплатных вопросов исчерпан!</b>\n\n"
f"<b>Ваша статистика:</b>\n"
f"• Использовано вопросов: {user.questions_used}\n"
f"• Бесплатный лимит: {settings.FREE_QUESTIONS_LIMIT}\n\n"
f"<b>Что делать дальше?</b>\n"
f"1. Купите подписку командой /buy\n"
f"2. Получите неограниченный доступ к вопросам\n"
f"3. Продолжайте использовать бот без ограничений\n\n"
f"<b>Подписка включает:</b>\n"
f"• Неограниченное количество вопросов\n"
f"• Приоритетную обработку\n"
f"• Доступ ко всем функциям\n\n"
f"<b>Нажмите /buy чтобы продолжить</b>"
)
await message.answer(response, parse_mode="HTML")