import json import datetime import httpx from config import SUPABASE_URL, SUPABASE_KEY, user_tokens GOOGLE_SERVICES = ["google", "gmail", "calendar", "drive", "sheets", "docs", "slides", "youtube"] async def save_token_to_supabase(user_id: str, service: str, token_data: dict): target_services = GOOGLE_SERVICES if service in GOOGLE_SERVICES else [service] now_iso = datetime.datetime.now(datetime.timezone.utc).isoformat() for s in target_services: user_tokens[(user_id, s)] = token_data try: url = f"{SUPABASE_URL}/rest/v1/user_connectors" headers = { "apikey": SUPABASE_KEY, "Authorization": f"Bearer {SUPABASE_KEY}", "Content-Type": "application/json", "Prefer": "resolution=merge-duplicates" } payload = { "user_id": user_id, "service": s, "token_data": token_data, "updated_at": now_iso } async with httpx.AsyncClient(timeout=15.0) as c: await c.post(url, headers=headers, json=payload) except Exception: pass async def get_token_from_supabase(user_id: str, service: str): check_services = [service] + [x for x in GOOGLE_SERVICES if x != service] if service in GOOGLE_SERVICES else [service] for s in check_services: if (user_id, s) in user_tokens: return user_tokens[(user_id, s)] try: url = f"{SUPABASE_URL}/rest/v1/user_connectors?user_id=eq.{user_id}&service=eq.{s}&select=token_data" headers = { "apikey": SUPABASE_KEY, "Authorization": f"Bearer {SUPABASE_KEY}" } async with httpx.AsyncClient(timeout=15.0) as c: res = await c.get(url, headers=headers) if res.status_code == 200: data = res.json() if data and len(data) > 0: raw_t = data[0].get("token_data") if isinstance(raw_t, dict): t_data = raw_t elif isinstance(raw_t, str): t_data = json.loads(raw_t) else: t_data = {} if t_data: user_tokens[(user_id, s)] = t_data return t_data except Exception: pass return None async def delete_token_from_supabase(user_id: str, service: str): target_services = GOOGLE_SERVICES if service in GOOGLE_SERVICES else [service] for s in target_services: user_tokens.pop((user_id, s), None) try: url = f"{SUPABASE_URL}/rest/v1/user_connectors?user_id=eq.{user_id}&service=eq.{s}" headers = { "apikey": SUPABASE_KEY, "Authorization": f"Bearer {SUPABASE_KEY}" } async with httpx.AsyncClient(timeout=15.0) as c: await c.delete(url, headers=headers) except Exception: pass async def fetch_session_messages(session_id: str): try: url = f"{SUPABASE_URL}/rest/v1/chat_messages?session_id=eq.{session_id}&order=created_at.asc" headers = { "apikey": SUPABASE_KEY, "Authorization": f"Bearer {SUPABASE_KEY}" } async with httpx.AsyncClient(timeout=20.0) as c: res = await c.get(url, headers=headers) if res.status_code == 200: return res.json() except Exception: pass return [] async def save_assistant_message_to_db(session_id: str, user_id: str, content: str, thought_reasoning: str = "", sources = None, tool_calls = None): try: url = f"{SUPABASE_URL}/rest/v1/chat_messages" headers = { "apikey": SUPABASE_KEY, "Authorization": f"Bearer {SUPABASE_KEY}", "Content-Type": "application/json", "Prefer": "return=minimal" } payload = { "session_id": session_id, "user_id": user_id, "sender": "assistant", "content": content, "thought_reasoning": thought_reasoning } if sources is not None: payload["sources"] = sources if tool_calls is not None: payload["tool_calls"] = tool_calls async with httpx.AsyncClient(timeout=20.0) as c: await c.post(url, headers=headers, json=payload) except Exception: pass async def update_user_message_file_content(session_id: str, file_name: str, file_content: str): try: url = f"{SUPABASE_URL}/rest/v1/chat_messages?session_id=eq.{session_id}&sender=eq.user&file_name=eq.{file_name}&order=created_at.desc&limit=1" headers = { "apikey": SUPABASE_KEY, "Authorization": f"Bearer {SUPABASE_KEY}", "Content-Type": "application/json" } payload = { "file_content": file_content } async with httpx.AsyncClient(timeout=20.0) as c: await c.patch(url, headers=headers, json=payload) except Exception: pass