from flask import Flask, jsonify import requests import schedule import time from datetime import datetime import logging import threading import os # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[logging.StreamHandler()] ) app = Flask(__name__) # Global state scheduler_thread = None scheduler_running = False last_run_status = { "last_run": None, "last_status": "never", "results": {} } # ==================== BACKUP FUNCTIONS ==================== def backup_main_db(): try: url = "https://dooratre-db.hf.space/admin/backup" headers = {"X-Admin-Secret": "Dbpassword2000$"} response = requests.post(url, headers=headers, timeout=60) logging.info(f"[Main DB] Status: {response.status_code}") return {"status": response.status_code, "ok": response.ok} except Exception as e: logging.error(f"[Main DB] Error: {e}") return {"status": "error", "ok": False, "error": str(e)} def backup_tele_db(): try: url = "https://dooratre-tele-db.hf.space/api/backup" headers = {"X-API-Key": "Telegrampassword2000$"} response = requests.post(url, headers=headers, timeout=60) logging.info(f"[Tele DB] Status: {response.status_code}") return {"status": response.status_code, "ok": response.ok} except Exception as e: logging.error(f"[Tele DB] Error: {e}") return {"status": "error", "ok": False, "error": str(e)} def backup_cards_db(): try: url = "https://dooratre-cards.hf.space/admin/backup?secret=Cardspassword2000$" response = requests.post(url, timeout=60) logging.info(f"[Cards DB] Status: {response.status_code}") return {"status": response.status_code, "ok": response.ok} except Exception as e: logging.error(f"[Cards DB] Error: {e}") return {"status": "error", "ok": False, "error": str(e)} def backup_main_app(server_num): try: url = f"https://serverclass{server_num}-app.hf.space/backup_db" headers = {"X-Admin-Secret": "Adminpassword2000$"} response = requests.post(url, headers=headers, timeout=60) logging.info(f"[Server {server_num}] Status: {response.status_code}") return {"status": response.status_code, "ok": response.ok} except Exception as e: logging.error(f"[Server {server_num}] Error: {e}") return {"status": "error", "ok": False, "error": str(e)} def backup_all_servers(): results = {} logging.info("Starting backup for all 55 servers...") for i in range(1, 56): results[f"server{i}"] = backup_main_app(i) time.sleep(1) logging.info("Finished backup for all 55 servers.") return results def run_all_backups(): global last_run_status logging.info("=" * 60) logging.info(f"Starting daily backup at {datetime.now()}") logging.info("=" * 60) results = { "main_db": backup_main_db(), "tele_db": backup_tele_db(), "cards_db": backup_cards_db(), "servers": backup_all_servers() } last_run_status["last_run"] = datetime.now().isoformat() last_run_status["last_status"] = "completed" last_run_status["results"] = results logging.info("=" * 60) logging.info(f"Daily backup completed at {datetime.now()}") logging.info("=" * 60) return results # ==================== SCHEDULER ==================== def scheduler_loop(): global scheduler_running logging.info("Scheduler loop started.") while scheduler_running: schedule.run_pending() time.sleep(30) logging.info("Scheduler loop stopped.") # ==================== ROUTES ==================== @app.route("/") def home(): return jsonify({ "service": "Backup Scheduler", "version": "1.0", "endpoints": ["/start", "/stop", "/health", "/run-now", "/status"], "scheduler_running": scheduler_running, "schedule": "Every 6 hours" }) @app.route("/start", methods=["GET", "POST"]) def start(): global scheduler_thread, scheduler_running if scheduler_running: return jsonify({ "status": "already_running", "message": "Scheduler is already running." }), 200 schedule.clear() schedule.every(6).hours.do(run_all_backups) scheduler_running = True scheduler_thread = threading.Thread(target=scheduler_loop, daemon=True) scheduler_thread.start() logging.info("Scheduler STARTED via API.") return jsonify({ "status": "started", "message": "Scheduler started. Will run every 6 hours.", "interval": "every 6 hours" }), 200 @app.route("/stop", methods=["GET", "POST"]) def stop(): global scheduler_running if not scheduler_running: return jsonify({ "status": "not_running", "message": "Scheduler is not running." }), 200 scheduler_running = False schedule.clear() logging.info("Scheduler STOPPED via API.") return jsonify({ "status": "stopped", "message": "Scheduler has been stopped." }), 200 @app.route("/health", methods=["GET"]) def health(): next_run = None jobs = schedule.get_jobs() if jobs: next_run = str(jobs[0].next_run) return jsonify({ "status": "healthy", "scheduler_running": scheduler_running, "current_time": datetime.now().isoformat(), "next_scheduled_run": next_run, "last_run": last_run_status["last_run"], "last_status": last_run_status["last_status"] }), 200 @app.route("/run-now", methods=["GET", "POST"]) def run_now(): threading.Thread(target=run_all_backups, daemon=True).start() return jsonify({ "status": "triggered", "message": "Backup started in background. Check /health for status." }), 200 @app.route("/status", methods=["GET"]) def status(): return jsonify({ "scheduler_running": scheduler_running, "last_run": last_run_status["last_run"], "last_status": last_run_status["last_status"], "last_results": last_run_status["results"] }), 200 # ==================== MAIN ==================== if __name__ == "__main__": # Auto-start scheduler schedule.every(6).hours.do(run_all_backups) scheduler_running = True scheduler_thread = threading.Thread(target=scheduler_loop, daemon=True) scheduler_thread.start() logging.info("Scheduler auto-started on app launch.") port = int(os.environ.get("PORT", 7860)) app.run(host="0.0.0.0", port=port, debug=False)