Spaces:
Sleeping
Sleeping
| import json | |
| import os | |
| import time | |
| from pathlib import Path | |
| from urllib.parse import urlsplit | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| BASE_DIR = Path(__file__).resolve().parent | |
| PROJECT_ROOT = BASE_DIR.parent | |
| WORKSPACE_ROOT = PROJECT_ROOT.parent | |
| RAW_DATABASE_URL = os.getenv("DATABASE_URL", f"sqlite:///{BASE_DIR / 'docverify.db'}") | |
| DATABASE_URL = RAW_DATABASE_URL | |
| TEMP_UPLOADS = Path(os.getenv("TEMP_UPLOADS", BASE_DIR / "temp_uploads")) | |
| MASKED_OUTPUT = Path(os.getenv("MASKED_OUTPUT", BASE_DIR / "masked_output")) | |
| ORIGINAL_UPLOADS = Path(os.getenv("ORIGINAL_UPLOADS", BASE_DIR / "original_uploads")) | |
| def _debug_log(hypothesis_id: str, location: str, message: str, data: dict) -> None: | |
| try: | |
| payload = { | |
| "sessionId": "8197a1", | |
| "runId": "startup-db-url", | |
| "hypothesisId": hypothesis_id, | |
| "location": location, | |
| "message": message, | |
| "data": data, | |
| "timestamp": int(time.time() * 1000), | |
| } | |
| with (WORKSPACE_ROOT / "debug-8197a1.log").open("a", encoding="utf-8") as f: | |
| f.write(json.dumps(payload, separators=(",", ":")) + "\n") | |
| except Exception: | |
| pass | |
| # #region agent log | |
| try: | |
| _split = urlsplit(DATABASE_URL) | |
| _userinfo = _split.netloc.rsplit("@", 1)[0] if "@" in _split.netloc else "" | |
| _debug_log( | |
| "H1-H4", | |
| "config.py:18", | |
| "database_url_loaded", | |
| { | |
| "scheme": _split.scheme, | |
| "hostname": _split.hostname, | |
| "port": _split.port, | |
| "username": _split.username, | |
| "netloc_at_count": _split.netloc.count("@"), | |
| "userinfo_has_brackets": "[" in _userinfo or "]" in _userinfo, | |
| "userinfo_has_raw_at": "@" in _userinfo, | |
| "is_sqlite": DATABASE_URL.startswith("sqlite"), | |
| }, | |
| ) | |
| except Exception as exc: | |
| _debug_log( | |
| "H1-H4", | |
| "config.py:18", | |
| "database_url_parse_failed", | |
| {"error_type": type(exc).__name__}, | |
| ) | |
| # #endregion | |
| # --- EasyOCR Configuration --- | |
| EASYOCR_LANGUAGES = ["en"] | |
| EASYOCR_GPU = os.getenv("EASYOCR_GPU", "false").strip().lower() in ("1", "true", "yes") | |
| EASYOCR_MODEL_DIR = Path(os.getenv("EASYOCR_MODEL_DIR", BASE_DIR / "ocr_models")) | |
| # OCR tuning | |
| OCR_TEXT_THRESHOLD = float(os.getenv("OCR_TEXT_THRESHOLD", "0.6")) | |
| OCR_LINK_THRESHOLD = float(os.getenv("OCR_LINK_THRESHOLD", "0.3")) | |
| OCR_LOW_TEXT = float(os.getenv("OCR_LOW_TEXT", "0.3")) | |
| OCR_CANVAS_SIZE = int(os.getenv("OCR_CANVAS_SIZE", "2560")) | |
| OCR_MAG_RATIO = float(os.getenv("OCR_MAG_RATIO", "2.0")) | |
| OCR_LOW_CONFIDENCE_THRESHOLD = float(os.getenv("OCR_LOW_CONFIDENCE_THRESHOLD", "0.4")) | |
| CORS_ORIGINS = [ | |
| o.strip() | |
| for o in os.getenv("CORS_ORIGINS", "http://localhost:5173,http://127.0.0.1:5173").split(",") | |
| if o.strip() | |
| ] | |
| ACCEPTED_IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".pdf"} | |
| ACCEPTED_EXTENSIONS: dict[str, set[str]] = { | |
| doc_type: set(ACCEPTED_IMAGE_EXTENSIONS) | |
| for doc_type in ("aadhaar", "pan", "caste", "experience", "education", "resume", "general") | |
| } | |
| SMTP_HOST = os.getenv("SMTP_HOST", "") | |
| SMTP_PORT = int(os.getenv("SMTP_PORT", "587")) | |
| SMTP_USER = os.getenv("SMTP_USER", "") | |
| SMTP_PASS = os.getenv("SMTP_PASS", "") | |
| IMAP_HOST = os.getenv("IMAP_HOST", "") | |
| IMAP_USER = os.getenv("IMAP_USER", "") | |
| IMAP_PASS = os.getenv("IMAP_PASS", "") | |
| MOCK_REPLY = os.getenv("MOCK_REPLY", "") | |
| def _flag(name: str, default: str = "false") -> bool: | |
| return os.getenv(name, default).strip().lower() in ("1", "true", "yes", "on") | |
| # Send-only is the production default: send the verification email and stop. | |
| # IMAP reply polling and the Selenium scraper are heavy / extra attack surface | |
| # and stay off unless explicitly enabled. | |
| ENABLE_REPLY_POLLING = _flag("ENABLE_REPLY_POLLING") | |
| ENABLE_SCRAPER = _flag("ENABLE_SCRAPER") | |
| # Upload + security knobs. | |
| MAX_UPLOAD_BYTES = int(os.getenv("MAX_UPLOAD_BYTES", str(10 * 1024 * 1024))) | |
| PDF_MAX_PAGES = int(os.getenv("PDF_MAX_PAGES", "3")) | |
| GEMINI_PDF_PAGES = int(os.getenv("GEMINI_PDF_PAGES", "1")) | |
| MAX_IMAGE_DIMENSION = int(os.getenv("MAX_IMAGE_DIMENSION", "2048")) | |
| GEMINI_MAX_IMAGE_DIMENSION = int(os.getenv("GEMINI_MAX_IMAGE_DIMENSION", "768")) | |
| API_KEY = os.getenv("API_KEY", "") | |
| FREE_EMAIL_DOMAINS = {"gmail.com", "yahoo.com", "hotmail.com", "outlook.com", "rediffmail.com"} | |
| # ββ Gemini Vision AI βββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| GEMINI_API_KEY = os.getenv("GEMINI_API_KEY", "") | |
| # Comma-separated failover key pool (primary key always prepended) | |
| GEMINI_API_KEYS = [k.strip() for k in os.getenv("GEMINI_API_KEYS", "").split(",") if k.strip()] | |
| # gemini-3-flash: 1000 RPD free, 1M context, agentic vision on images | |
| GEMINI_MODEL = os.getenv("GEMINI_MODEL", "gemini-3-flash") | |
| GEMINI_ENABLED = bool(GEMINI_API_KEY or GEMINI_API_KEYS) | |
| # Image sent to Gemini: max dimension (higher = better accuracy, more tokens) | |
| GEMINI_MAX_IMAGE_DIMENSION = int(os.getenv("GEMINI_MAX_IMAGE_DIMENSION", "1024")) | |
| # PDF rendering DPI for Gemini image conversion | |
| GEMINI_PDF_DPI = int(os.getenv("GEMINI_PDF_DPI", "150")) | |