import logging import asyncio from typing import Optional, List, Dict try: # Try local import first (when running as app.main) from .grok.grok import Grok except ImportError: try: # Try absolute import (if running differently) from app.grok.grok import Grok except ImportError: Grok = None logger = logging.getLogger(__name__) class GrokChatClient: def __init__(self): self.client = None if Grok: try: self.client = Grok() logger.info("Grok API client initialized safely") except Exception as e: logger.error(f"Failed to initialize Grok client: {e}") else: logger.warning("grok-api library not found. Please install git+https://github.com/realasfngl/Grok-Api.git") async def chat(self, message: str, history: List[Dict[str, str]] = None, cookies: Dict[str, str] = None, user_agent: str = None) -> str: """ Send a chat message to Grok. """ if not self.client: return "Error: Grok API not installed or initialized." try: # Apply user-provided cookies and UA if cookies: try: self.client.session.cookies.update(cookies) except Exception as e: logger.warning(f"Failed to update cookies: {e}") if user_agent: # Override the User-Agent header in the session self.client.session.headers["User-Agent"] = user_agent # Also set in the client's internal headers object if present if hasattr(self.client, 'headers'): if hasattr(self.client.headers, 'LOAD'): self.client.headers.LOAD["User-Agent"] = user_agent if hasattr(self.client.headers, 'C_REQUEST'): self.client.headers.C_REQUEST["User-Agent"] = user_agent # Use start_convo (sync method) try: result = await asyncio.to_thread(self.client.start_convo, message) except Exception as e: # If we catch inside the thread, it returns dict with error raise e if isinstance(result, dict): if "error" in result: error_msg = result["error"] # If we have cookies, we've already tried them. # We can fallback to browser auth ONLY if no cookies were provided # OR if the user wants us to try anyway. if not cookies: logger.warning(f"Grok request failed: {error_msg}. Attempting browser auth bypass...") # Try to get cookies via browser from .grok_auth import get_grok_cookies browser_cookies = await get_grok_cookies() if browser_cookies: logger.info("Got cookies from browser, applying to Grok client...") self.client.session.cookies.update(browser_cookies) # Retry the request result = await asyncio.to_thread(self.client.start_convo, message) if isinstance(result, dict) and "error" in result: raise Exception(f"Retry failed: {result['error']}") else: raise Exception(f"Browser auth failed, original error: {error_msg}") else: # If cookies were provided but failed, trust the error logger.warning(f"User-provided cookies failed: {error_msg}") raise Exception(f"Grok Error: {error_msg} (Check your cookies)") return result.get("response", "No response from Grok.") return str(result) except Exception as e: import traceback error_trace = traceback.format_exc() logger.error(f"Grok Chat Error: {e}\n{error_trace}") with open("error.log", "a") as f: f.write(f"\nFAILED GROK REQUEST: {e}\n{error_trace}") return f"Error communicating with Grok: {str(e)}"