#!/usr/bin/env python3 """ Hugging Face Spaces Entry Point This script: 1. Loads secrets from HF Spaces environment variables 2. Creates config.json and credentials.json from those secrets 3. Starts the automation runner in the background 4. Serves the static web interface """ import os import json import subprocess import signal import sys import time import threading from pathlib import Path from http.server import HTTPServer, SimpleHTTPRequestHandler from functools import partial # Configuration PORT = int(os.getenv('PORT', 7860)) BASE_DIR = Path(__file__).parent AUTOMATION_RUNNER = BASE_DIR / "scripts" / "automation_runner.py" # Global process reference for cleanup automation_process = None def load_secrets_from_env(): """Load secrets from HF Spaces environment variables and create config files""" print("πŸ” Loading secrets from environment variables...") # Load config.json from environment config_json_str = os.getenv('HF_CONFIG_JSON') if config_json_str: try: config_data = json.loads(config_json_str) config_file = BASE_DIR / "config.json" with open(config_file, 'w') as f: json.dump(config_data, f, indent=2) print(f"βœ… Created config.json from HF_CONFIG_JSON secret") except json.JSONDecodeError as e: print(f"❌ Error parsing HF_CONFIG_JSON: {e}") sys.exit(1) else: config_file = BASE_DIR / "config.json" if not config_file.exists(): print("⚠️ HF_CONFIG_JSON not found in environment") print("⚠️ Please set HF_CONFIG_JSON secret in your Hugging Face Space settings") print("⚠️ See SECRETS_SETUP.md for instructions") # Don't exit - allow the app to run without automation # Load credentials.json from environment credentials_json_str = os.getenv('HF_CREDENTIALS_JSON') if credentials_json_str: try: credentials_data = json.loads(credentials_json_str) credentials_file = BASE_DIR / "credentials.json" with open(credentials_file, 'w') as f: json.dump(credentials_data, f, indent=2) print(f"βœ… Created credentials.json from HF_CREDENTIALS_JSON secret") except json.JSONDecodeError as e: print(f"❌ Error parsing HF_CREDENTIALS_JSON: {e}") sys.exit(1) else: credentials_file = BASE_DIR / "credentials.json" if not credentials_file.exists(): print("⚠️ HF_CREDENTIALS_JSON not found in environment") print("⚠️ Google Sheets sync will not work without credentials") print() def start_automation(): """Start the automation runner in the background""" global automation_process # Check if automation script exists if not AUTOMATION_RUNNER.exists(): print(f"⚠️ Automation runner not found: {AUTOMATION_RUNNER}") return # Check if config exists config_file = BASE_DIR / "config.json" if not config_file.exists(): print("⚠️ config.json not found, skipping automation startup") return print("πŸš€ Starting automation runner...") try: automation_process = subprocess.Popen( [sys.executable, str(AUTOMATION_RUNNER)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1 ) # Stream automation output in a separate thread def stream_output(): for line in automation_process.stdout: print(f"[AUTOMATION] {line}", end='') threading.Thread(target=stream_output, daemon=True).start() print("βœ… Automation runner started\n") except Exception as e: print(f"❌ Failed to start automation: {e}\n") def cleanup(signum=None, frame=None): """Cleanup function to terminate background processes""" global automation_process print("\n\nπŸ›‘ Shutting down...") if automation_process: print("🧹 Stopping automation runner...") automation_process.terminate() automation_process.wait(timeout=5) print("βœ… Cleanup complete\n") sys.exit(0) class CustomHTTPRequestHandler(SimpleHTTPRequestHandler): """Custom handler to serve from the correct directory""" def __init__(self, *args, **kwargs): super().__init__(*args, directory=str(BASE_DIR), **kwargs) def log_message(self, format, *args): """Custom logging to show requests""" print(f"[WEB] {self.address_string()} - {format % args}") def start_web_server(): """Start the HTTP server to serve the static files""" print(f"🌐 Starting web server on port {PORT}...") handler = CustomHTTPRequestHandler httpd = HTTPServer(('0.0.0.0', PORT), handler) print(f"βœ… Web server running at http://0.0.0.0:{PORT}") print(f"πŸ“Š Open the map: http://0.0.0.0:{PORT}/index.html") print(f"πŸ’‘ Press Ctrl+C to stop\n") try: httpd.serve_forever() except KeyboardInterrupt: pass finally: httpd.shutdown() def main(): """Main entry point""" print("=" * 70) print("πŸ—ΊοΈ Telugu Dialect Map - Hugging Face Spaces") print("=" * 70) print() # Register signal handlers for graceful shutdown signal.signal(signal.SIGINT, cleanup) signal.signal(signal.SIGTERM, cleanup) # Load secrets from environment variables load_secrets_from_env() # Start background automation start_automation() # Give automation a moment to start time.sleep(2) # Start web server (blocks here) start_web_server() # Cleanup (if we ever get here) cleanup() if __name__ == "__main__": main()