Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| """ | |
| Hugging Face Space launcher for gemini-web2api. | |
| Builds a runtime config.json from the committed config.example.json, applying | |
| overrides from Space Secrets / environment variables, then starts the server. | |
| Supported environment variables (all optional): | |
| PORT port to listen on (default 7860) | |
| HOST bind address (default 0.0.0.0) | |
| COOKIE raw Gemini cookie string (plain "k=v; k=v" or JSON) | |
| -> written to cookie.txt and wired into config | |
| API_KEY single API key for Bearer auth (default sk-gemini) | |
| API_KEYS comma-separated list of API keys (overrides API_KEY) | |
| DEFAULT_MODEL default model name | |
| GEMINI_BL Gemini backend version string | |
| PROXY HTTP/HTTPS proxy for outbound calls | |
| """ | |
| import json | |
| import os | |
| import sys | |
| APP_DIR = os.path.dirname(os.path.abspath(__file__)) | |
| def main(): | |
| # 1. base config from the committed example | |
| base_path = os.path.join(APP_DIR, "config.example.json") | |
| with open(base_path) as f: | |
| cfg = json.load(f) | |
| # 2. apply env overrides | |
| cfg["port"] = int(os.environ.get("PORT", cfg.get("port", 7860))) | |
| cfg["host"] = os.environ.get("HOST", cfg.get("host", "0.0.0.0")) | |
| if os.environ.get("DEFAULT_MODEL"): | |
| cfg["default_model"] = os.environ["DEFAULT_MODEL"] | |
| if os.environ.get("GEMINI_BL"): | |
| cfg["gemini_bl"] = os.environ["GEMINI_BL"] | |
| if os.environ.get("PROXY"): | |
| cfg["proxy"] = os.environ["PROXY"] | |
| # 3. API keys (Bearer auth). Empty list => no auth required. | |
| if os.environ.get("API_KEYS", "").strip(): | |
| cfg["api_keys"] = [k.strip() for k in os.environ["API_KEYS"].split(",") if k.strip()] | |
| elif os.environ.get("API_KEY", "").strip(): | |
| cfg["api_keys"] = [os.environ["API_KEY"].strip()] | |
| else: | |
| cfg.setdefault("api_keys", ["sk-gemini"]) | |
| # 5. persist resolved config (prefer app dir; fall back to HOME for safety) | |
| cfg_path = os.path.join(APP_DIR, "config.json") | |
| try: | |
| with open(cfg_path, "w") as f: | |
| json.dump(cfg, f, indent=2) | |
| cookie_file_base = "cookie.txt" | |
| except PermissionError: | |
| # read-only app dir -> write into the user home instead | |
| cfg_path = os.path.join(os.path.expanduser("~"), "config.json") | |
| with open(cfg_path, "w") as f: | |
| json.dump(cfg, f, indent=2) | |
| cookie_file_base = os.path.join(os.path.expanduser("~"), "cookie.txt") | |
| # 4. cookie (Pro / authenticated routing). Write to a file and wire it in. | |
| cookie = os.environ.get("COOKIE", "").strip() | |
| if cookie: | |
| cookie_path = cookie_file_base | |
| if not os.path.isabs(cookie_path): | |
| cookie_path = os.path.join(APP_DIR, cookie_path) | |
| with open(cookie_path, "w") as f: | |
| f.write(cookie) | |
| cfg["cookie_file"] = cookie_path | |
| print("[run.py] COOKIE secret detected -> writing", cookie_path) | |
| else: | |
| cfg["cookie_file"] = None | |
| print("[run.py] no COOKIE set -> anonymous mode") | |
| # re-dump config so the final cookie_file value is persisted | |
| with open(cfg_path, "w") as f: | |
| json.dump(cfg, f, indent=2) | |
| print(f"[run.py] listening on {cfg['host']}:{cfg['port']}") | |
| print(f"[run.py] base url http://0.0.0.0:{cfg['port']}/v1") | |
| print(f"[run.py] api keys {'set (' + str(len(cfg['api_keys'])) + ')' if cfg['api_keys'] else 'none (open)'}") | |
| # 6. hand off to the server, passing explicit config so overrides win | |
| os.chdir(APP_DIR) | |
| os.execvp(sys.executable, [sys.executable, "-m", "gemini_web2api", "--config", cfg_path]) | |
| if __name__ == "__main__": | |
| main() | |