dialect-map / app.py
Kakashi75's picture
Made the intial files ready for the hf workflow
c7297b8
#!/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()