Spaces:
Sleeping
Sleeping
| import requests | |
| import datetime | |
| import uuid | |
| import json | |
| from typing import Optional, List, Dict, Any | |
| SUPABASE_URL = "https://qsyydjpuzjirxkqyjvqw.supabase.co" | |
| SUPABASE_KEY = "sb_publishable_dccy2bN7gpHHT41CHqaKQQ_LHDR6g2U" | |
| HEADERS = { | |
| "apikey": SUPABASE_KEY, | |
| "Authorization": f"Bearer {SUPABASE_KEY}", | |
| "Content-Type": "application/json", | |
| "Prefer": "return=representation" | |
| } | |
| class User: | |
| def __init__(self, id: str, google_id: str, email: str = None, name: str = None, picture: str = None, plan: str = "free", checks_used: int = 0, created_at: str = None): | |
| self.id = id | |
| self.google_id = google_id | |
| self.email = email | |
| self.name = name | |
| self.picture = picture | |
| self.plan = plan | |
| self.checks_used = checks_used | |
| self.created_at = created_at | |
| class Job: | |
| def __init__(self, id: str, user_id: str, job_id: str, file_name: str = None, status: str = "queued", verdict: str = None, max_score: float = None, runtime: float = None, result_json: Any = None, created_at: str = None, finished_at: str = None): | |
| self.id = id | |
| self.user_id = user_id | |
| self.job_id = job_id | |
| self.file_name = file_name | |
| self.status = status | |
| self.verdict = verdict | |
| self.max_score = max_score | |
| self.runtime = runtime | |
| self.result_json = result_json | |
| self.created_at = created_at | |
| self.finished_at = finished_at | |
| def get_user_by_id(user_id: str) -> Optional[User]: | |
| try: | |
| url = f"{SUPABASE_URL}/rest/v1/users?id=eq.{user_id}" | |
| res = requests.get(url, headers=HEADERS) | |
| if res.status_code == 200: | |
| data = res.json() | |
| if data: | |
| return User(**data[0]) | |
| except Exception as e: | |
| print(f"Error getting user by id: {e}") | |
| return None | |
| def get_user_by_google_id(google_id: str) -> Optional[User]: | |
| try: | |
| url = f"{SUPABASE_URL}/rest/v1/users?google_id=eq.{google_id}" | |
| res = requests.get(url, headers=HEADERS) | |
| if res.status_code == 200: | |
| data = res.json() | |
| if data: | |
| return User(**data[0]) | |
| except Exception as e: | |
| print(f"Error getting user by google_id: {e}") | |
| return None | |
| def create_user(google_id: str, email: str, name: str, picture: str) -> User: | |
| url = f"{SUPABASE_URL}/rest/v1/users" | |
| payload = { | |
| "google_id": google_id, | |
| "email": email, | |
| "name": name, | |
| "picture": picture | |
| } | |
| res = requests.post(url, headers=HEADERS, json=payload) | |
| res.raise_for_status() | |
| data = res.json() | |
| return User(**data[0]) | |
| def create_job(job_id: str, user_id: str, file_name: str) -> Job: | |
| url = f"{SUPABASE_URL}/rest/v1/jobs" | |
| payload = { | |
| "job_id": job_id, | |
| "user_id": user_id, | |
| "file_name": file_name, | |
| "status": "queued" | |
| } | |
| res = requests.post(url, headers=HEADERS, json=payload) | |
| res.raise_for_status() | |
| data = res.json() | |
| return Job(**data[0]) | |
| def get_job_by_job_id(job_id: str) -> Optional[Job]: | |
| try: | |
| url = f"{SUPABASE_URL}/rest/v1/jobs?job_id=eq.{job_id}" | |
| res = requests.get(url, headers=HEADERS) | |
| if res.status_code == 200: | |
| data = res.json() | |
| if data: | |
| return Job(**data[0]) | |
| except Exception as e: | |
| print(f"Error getting job by job_id: {e}") | |
| return None | |
| def get_jobs_by_user_id(user_id: str) -> List[Job]: | |
| try: | |
| url = f"{SUPABASE_URL}/rest/v1/jobs?user_id=eq.{user_id}&order=created_at.desc" | |
| res = requests.get(url, headers=HEADERS) | |
| if res.status_code == 200: | |
| data = res.json() | |
| return [Job(**item) for item in data] | |
| except Exception as e: | |
| print(f"Error getting jobs by user_id: {e}") | |
| return [] | |
| def complete_job(job_id: str, status: str, verdict: str = None, max_score: float = None, runtime: float = None, result_json: dict = None, report_items: list = None): | |
| try: | |
| job = get_job_by_job_id(job_id) | |
| if not job: | |
| print(f"Job {job_id} not found to complete.") | |
| return | |
| url = f"{SUPABASE_URL}/rest/v1/jobs?id=eq.{job.id}" | |
| payload = { | |
| "status": status, | |
| "verdict": verdict, | |
| "max_score": max_score, | |
| "runtime": runtime, | |
| "result_json": result_json, | |
| "finished_at": datetime.datetime.now(datetime.timezone.utc).isoformat() | |
| } | |
| res = requests.patch(url, headers=HEADERS, json=payload) | |
| res.raise_for_status() | |
| if report_items: | |
| items_url = f"{SUPABASE_URL}/rest/v1/report_items" | |
| payload_items = [] | |
| for item in report_items: | |
| payload_items.append({ | |
| "job_id": job.id, | |
| "sentence": item.get("sentence"), | |
| "url": item.get("url"), | |
| "title": item.get("title"), | |
| "final_score": item.get("final_score"), | |
| "lcs_score": item.get("lcs_score"), | |
| "ngram_score": item.get("ngram_score"), | |
| "semantic_score": item.get("semantic_score"), | |
| "contiguous_score": item.get("contiguous_score", 0.0), | |
| "matched_tokens": item.get("matched_tokens", []), | |
| "snippet": item.get("snippet") | |
| }) | |
| res_items = requests.post(items_url, headers=HEADERS, json=payload_items) | |
| # Fallback if inserting contiguous_score fails (e.g. column not yet added to Supabase) | |
| if res_items.status_code not in (200, 201): | |
| payload_fallback = [] | |
| for item in report_items: | |
| payload_fallback.append({ | |
| "job_id": job.id, | |
| "sentence": item.get("sentence"), | |
| "url": item.get("url"), | |
| "title": item.get("title"), | |
| "final_score": item.get("final_score"), | |
| "lcs_score": item.get("lcs_score"), | |
| "ngram_score": item.get("ngram_score"), | |
| "semantic_score": item.get("semantic_score"), | |
| "matched_tokens": item.get("matched_tokens", []), | |
| "snippet": item.get("snippet") | |
| }) | |
| res_fallback = requests.post(items_url, headers=HEADERS, json=payload_fallback) | |
| res_fallback.raise_for_status() | |
| except Exception as e: | |
| print(f"Error completing job {job_id}: {e}") | |
| def fail_job(job_id: str, error_msg: str): | |
| try: | |
| job = get_job_by_job_id(job_id) | |
| if not job: | |
| return | |
| url = f"{SUPABASE_URL}/rest/v1/jobs?id=eq.{job.id}" | |
| payload = { | |
| "status": "failed", | |
| "result_json": {"error": error_msg}, | |
| "finished_at": datetime.datetime.now(datetime.timezone.utc).isoformat() | |
| } | |
| res = requests.patch(url, headers=HEADERS, json=payload) | |
| res.raise_for_status() | |
| except Exception as e: | |
| print(f"Error failing job {job_id}: {e}") | |
| def get_report_items(job_uuid: str) -> List[dict]: | |
| try: | |
| url = f"{SUPABASE_URL}/rest/v1/report_items?job_id=eq.{job_uuid}" | |
| res = requests.get(url, headers=HEADERS) | |
| if res.status_code == 200: | |
| items = res.json() | |
| for item in items: | |
| if "contiguous_score" not in item or item["contiguous_score"] is None: | |
| item["contiguous_score"] = 0.0 | |
| return items | |
| except Exception as e: | |
| print(f"Error getting report items for job {job_uuid}: {e}") | |
| return [] | |