Spaces:
Running
Running
File size: 5,868 Bytes
c7297b8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
#!/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()
|