Загрузка данных


import asyncio
import os
import aiohttp
from aiogram import Bot, Dispatcher, types, F
from aiogram.filters import Command
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from aiogram.types import FSInputFile
from docx import Document
from bs4 import BeautifulSoup  
from openai import AsyncOpenAI  

# --- НАСТРОЙКИ КЛЮЧЕЙ И ТОКЕНОВ ---
TELEGRAM_TOKEN = "8397324522:AAHkSqnHN5pMT9loQGUWot0ls-9kdZVBPX8"
VSEGPT_KEY = "sk-or-vv-8740fb10821695225615171b1c18b967f1123e97de074d6c2ac98928994713e8"

# Инициализируем бота Telegram
bot = Bot(token=TELEGRAM_TOKEN)
dp = Dispatcher()

# Инициализируем стабильный клиент ИИ по регламенту VseGPT
ai_client = AsyncOpenAI(
    api_key=VSEGPT_KEY,
    base_url="https://vsegpt.ru"  
)

# Шаги нашего опроса (FSM)
class CarEvaluation(StatesGroup):
    waiting_for_model = State()     
    waiting_for_year = State()      
    waiting_for_engine = State()    
    waiting_for_mileage = State()   

# Функция автоматического сбора цен с av.by
async def get_av_by_prices(car_model):
    # Превращаем пробелы в плюсы для поисковой строки
    search_query = car_model.replace(" ", "+")
    
    # ИСПРАВЛЕНО: Жёстко прописан правильный поисковый URL
    url = f"https://av.by{search_query}"
    
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
    }
    
    prices = []
    try:
        # Отключаем строгую проверку SSL в парсере для стабильности домашних ПК
        connector = aiohttp.TCPConnector(ssl=False)
        async with aiohttp.ClientSession(connector=connector) as session:
            async with session.get(url, headers=headers) as response:
                if response.status == 200:
                    html_text = await response.text()
                    soup = BeautifulSoup(html_text, "html.parser")
                    price_elements = soup.find_all(class_="listing-item__price-usd")
                    
                    for elem in price_elements[:15]:  
                        clean_price = elem.get_text().replace("$", "").replace(" ", "").strip()
                        if clean_price.isdigit():
                            prices.append(f"{clean_price} USD")
    except Exception as e:
        print(f"Ошибка при парсинге av.by: {e}")
        
    return prices, url

# Команда /start запускает опрос
@dp.message(Command("start"))
async def cmd_start(message: types.Message, state: FSMContext):
    await message.answer(
        "Привет! Я помогу оценить стоимость автомобиля на базе реальных объявлений av.by.\n"
        "Давай соберем данные. Напиши **марку и модель** автомобиля (например: BMW 5):"
    )
    await state.set_state(CarEvaluation.waiting_for_model)

@dp.message(CarEvaluation.waiting_for_model)
async def process_model(message: types.Message, state: FSMContext):
    await state.update_data(model=message.text)
    await message.answer("Отлично! Теперь введи **год выпуска** (например: 2015):")
    await state.set_state(CarEvaluation.waiting_for_year)

@dp.message(CarEvaluation.waiting_for_year)
async def process_year(message: types.Message, state: FSMContext):
    await state.update_data(year=message.text)
    await message.answer("Укажи **объем двигателя** в литрах (например: 2.0):")
    await state.set_state(CarEvaluation.waiting_for_engine)

@dp.message(CarEvaluation.waiting_for_engine)
async def process_engine(message: types.Message, state: FSMContext):
    await state.update_data(engine=message.text)
    await message.answer("И последнее: укажи **пробег** автомобиля в километрах (например: 175000):")
    await state.set_state(CarEvaluation.waiting_for_mileage)

# ФИНАЛЬНЫЙ ШАГ
@dp.message(CarEvaluation.waiting_for_mileage)
async def process_mileage(message: types.Message, state: FSMContext):
    await state.update_data(mileage=message.text)
    user_data = await state.get_data()
    
    await message.answer("Связываюсь с av.by и собираю актуальные цены на рынке РБ...")
    
    # Сбор цен
    found_prices, search_url = await get_av_by_prices(user_data['model'])
    
    await message.answer("Передаю массив данных в ИИ VseGPT...")
    
    if found_prices:
        prices_string = ", ".join(found_prices)
        prices_context = f"Вот реальные текущие цены на аналогичные машины с белорусского сайта av.by: {prices_string}."
    else:
        prices_string = "Цены на портале не найдены (попробуйте ввести марку точнее)"
        prices_context = "Прямые цены на av.by не найдены. Сделай приблизительную экспертную оценку на основе своих базовых знаний об автомобильном рынке Беларуси."
    
    prompt_text = f"""
    Ты — профессиональный автомобильный эксперт-оценщик на рынке Беларуси.
    Сделай подробный и структурированный анализ рыночной стоимости для автомобиля:
    • Марка и модель: {user_data['model']}
    • Год выпуска: {user_data['year']} год
    • Объем двигателя: {user_data['engine']} л.
    • Пробег: {user_data['mileage']} км
    
    Контекст рынка: {prices_context}
    
    В тексте отчета обязательно сделай:
    1. Расчет примерной стоимости авто (в USD) с учетом его года выпуска, мотора и пробега.
    2. Анализ ликвидности данной модели в Беларуси (насколько быстро её можно продать).
    3. Итоговую рекомендацию для продавца по цене сделки.
    
    Пиши строго в деловом, аналитическом стиле, без лишних приветствий.
    """
    
    ai_analysis = ""
    try:
        # ИСПРАВЛЕНО: Безопасный вызов через стабильную библиотеку OpenAI
        response = await ai_client.chat.completions.create(
            model="openai/gpt-4o-mini",
            messages=[{"role": "user", "content": prompt_text}],
            extra_headers={"X-Title": "Auto Eval Bot"}
        )
        ai_analysis = response.choices.message.content
    except Exception as e:
        print(f"Ошибка при запросе к ИИ: {e}")
        ai_analysis = f"К сожалению, не удалось получить анализ от ИИ. Ошибка: {e}"

# --- НАЧАЛО СОЗДАНИЯ WORD ---
    doc = Document()
    doc.add_heading("ЭКСПЕРТНЫЙ ОТЧЕТ ОБ ОЦЕНКЕ АВТОМОБИЛЯ", level=0)
    
    doc.add_heading("1. Технические характеристики объекта:", level=1)
    doc.add_paragraph(f"• Марка и модель: {user_data['model']}")
    doc.add_paragraph(f"• Год выпуска: {user_data['year']} г.")
    doc.add_paragraph(f"• Объем двигателя: {user_data['engine']} л.")
    doc.add_paragraph(f"• Пробег: {user_data['mileage']} км")
    
    doc.add_heading("2. Источник рыночных данных:", level=1)
    doc.add_paragraph(f"В ходе оценки проведен автоматический анализ активных объявлений на портале av.by.")
    doc.add_paragraph(f"Ссылка на результаты поиска: {search_url}")
    doc.add_paragraph(f"Обнаруженные срезы цен: {prices_string}")
    
    doc.add_heading("3. Экспертное заключение ИИ на основе рынка РБ:", level=1)
    doc.add_paragraph(ai_analysis)
    
    # Сохраняем и отправляем файл
    safe_model_name = user_data['model'].replace(' ', '_')
    file_name = f"Ocenka_{safe_model_name}.docx"
    doc.save(file_name)
    
    word_file = FSInputFile(file_name)
    await message.answer_document(word_file, caption=f"Ваш умный отчет для {user_data['model']} готов!")
    
    if os.path.exists(file_name):
        os.remove(file_name)
        
    await state.clear()

async def main():
    print("Бот успешно запущен на базе стабильной библиотеки openai. Жду тест...")
    await dp.start_polling(bot)

# Запуск программы
asyncio.run(main())