import asyncio import logging import warnings import os from sqlalchemy import select, update, and_, func, or_, case # Explicit case import from app.db.session import SessionLocal from app.models.vehicle_definitions import VehicleModelDefinition import httpx # 1. KRITIKUS JAVÍTÁS: A figyelmeztetések globális elnyomása az import előtt warnings.filterwarnings("ignore", category=RuntimeWarning, module='duckduckgo_search') from duckduckgo_search import DDGS # Logolás beállítása, hogy lássuk a haladást logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(name)s: %(message)s') logger = logging.getLogger("Robot-Researcher-v2.1") class ResearcherBot: def __init__(self): self.batch_size = 15 self.max_parallel_queries = 5 async def fetch_source(self, label, query): """Egyedi forrás lekérése a DuckDuckGo-tól.""" try: def search(): # Az újabb verziókban a DDGS() hívás így a legstabilabb with DDGS() as ddgs: results = ddgs.text(query, max_results=3) return [r['body'] for r in results] if results else [] results = await asyncio.to_thread(search) if not results: return f"=== SOURCE: {label} | NO DATA FOUND ===\n\n" content = f"=== SOURCE: {label} | QUERY: {query} ===\n" content += "\n---\n".join(results) content += "\n=== END SOURCE ===\n\n" return content except Exception as e: logger.error(f"❌ Keresési hiba ({label}): {e}") return f"=== SOURCE: {label} ERROR: {str(e)} ===\n\n" async def research_vehicle(self, vehicle_id): async with SessionLocal() as db: res = await db.execute(select(VehicleModelDefinition).where(VehicleModelDefinition.id == vehicle_id)) v = res.scalar_one_or_none() if not v: return make, model = v.make, v.marketing_name # Jelöljük be, hogy a kutatás folyamatban van await db.execute(update(VehicleModelDefinition).where(VehicleModelDefinition.id == vehicle_id).values(status='research_in_progress')) await db.commit() logger.info(f"🔎 Kutatás indul: {make} {model}") queries = [ ("TECH_SPECS", f"{make} {model} technical specifications engine power"), ("MAINTENANCE", f"{make} {model} service manual oil capacity spark plug"), ("TIRES_BRAKES", f"{make} {model} tire size brake pad type"), ("FLUIDS", f"{make} {model} coolant quantity transmission oil") ] tasks = [self.fetch_source(label, q) for label, q in queries] search_results = await asyncio.gather(*tasks) full_context = "".join(search_results) async with SessionLocal() as db: await db.execute( update(VehicleModelDefinition) .where(VehicleModelDefinition.id == vehicle_id) .values( raw_search_context=full_context, status='awaiting_ai_synthesis', # Itt adjuk át a Robot 2.2-nek (Alchemist) updated_at=func.now() ) ) await db.commit() logger.info(f"✅ Kutatás kész, adat a tartályban: {make} {model}") async def run(self): logger.info("🚀 Robot 2.1 (Researcher) ONLINE") while True: async with SessionLocal() as db: # 2. KRITIKUS JAVÍTÁS: func.case helyett az explicit case() használata # Ez javítja a "TypeError: got an unexpected keyword argument 'else_'" hibát priorities = case( (and_(VehicleModelDefinition.vehicle_type == 'car', VehicleModelDefinition.make.in_(['SUZUKI', 'TOYOTA', 'SKODA', 'VOLKSWAGEN', 'OPEL'])), 1), (VehicleModelDefinition.vehicle_type == 'car', 2), (and_(VehicleModelDefinition.vehicle_type == 'motorcycle', VehicleModelDefinition.make.in_(['HONDA', 'YAMAHA', 'SUZUKI', 'KAWASAKI'])), 3), else_=4 ) stmt = select(VehicleModelDefinition.id).where( or_(VehicleModelDefinition.status == 'unverified', VehicleModelDefinition.status == 'awaiting_research') ).order_by(priorities).limit(self.batch_size) res = await db.execute(stmt) ids = [r[0] for r in res.fetchall()] if not ids: logger.info("💤 Nincs több feldolgozandó feladat, pihenés...") await asyncio.sleep(60) continue # Batch feldolgozás indítása párhuzamosan await asyncio.gather(*[self.research_vehicle(rid) for rid in ids]) # Rövid szünet a keresőmotorok kímélése érdekében await asyncio.sleep(2) if __name__ == "__main__": asyncio.run(ResearcherBot().run())