Download app.py from nopoh22/pythonany: direct link, hf CLI and curl.
- Browser
- Download file 3.85 kB
-
https://huggingface.co/spaces/nopoh22/pythonany/resolve/main/app.py
- Command line
-
hf download hf://spaces/nopoh22/pythonany/app.py
-
curl -L -o app.py https://huggingface.co/spaces/nopoh22/pythonany/resolve/main/app.py
3.85 kB
| import os | |
| import threading | |
| import time | |
| import logging | |
| from datetime import datetime | |
| from fastapi import FastAPI | |
| from fastapi.responses import HTMLResponse, JSONResponse | |
| import uvicorn | |
| from keep_alive import start_ping_server | |
| from renewer import load_accounts, save_accounts, renew_account, run_renewals | |
| logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s') | |
| logger = logging.getLogger(__name__) | |
| app = FastAPI() | |
| SCHEDULER_RUNNING = False | |
| SCHEDULER_THREAD = None | |
| LOG_LINES = [] | |
| def add_log(msg): | |
| ts = datetime.utcnow().strftime("%H:%M:%S") | |
| LOG_LINES.append(f"[{ts}] {msg}") | |
| if len(LOG_LINES) > 200: | |
| LOG_LINES.pop(0) | |
| logger.info(msg) | |
| HTML = open("index.html", encoding="utf-8").read() | |
| async def index(): | |
| return HTML | |
| async def get_accounts(): | |
| accounts = load_accounts() | |
| # لا نُرجع كلمة المرور أبداً | |
| safe = [] | |
| for a in accounts: | |
| safe.append({ | |
| "username": a["username"], | |
| "host": a.get("host", "—"), | |
| "last_renewed": a.get("last_renewed"), | |
| "next_renewal": a.get("next_renewal"), | |
| "last_results": a.get("last_results", []), | |
| }) | |
| return safe | |
| async def renew_all(): | |
| add_log("🚀 بدء تجديد جميع الحسابات...") | |
| def do(): | |
| accs = run_renewals() | |
| if accs: | |
| for a in accs: | |
| for r in (a.get("last_results") or []): | |
| add_log(f" [{a['username']}] {r['domain']} → {r['status']}") | |
| add_log("✅ انتهى التجديد.") | |
| threading.Thread(target=do, daemon=True).start() | |
| return {"ok": True} | |
| async def renew_one(username: str): | |
| accounts = load_accounts() | |
| account = next((a for a in accounts if a["username"] == username), None) | |
| if not account: | |
| return JSONResponse({"ok": False, "message": f"⚠️ لم يُعثر على {username} في الـ Secrets"}) | |
| account["next_renewal"] = None | |
| def do(): | |
| add_log(f"🔄 تجديد {username}...") | |
| success, results = renew_account(account) | |
| save_accounts(accounts) | |
| for r in results: | |
| add_log(f" [{username}] {r['domain']} → {r['status']}") | |
| add_log(f"{'✅' if success else '❌'} {'تم' if success else 'فشل'} تجديد {username}") | |
| threading.Thread(target=do, daemon=True).start() | |
| return {"ok": True} | |
| async def toggle_scheduler(): | |
| global SCHEDULER_RUNNING, SCHEDULER_THREAD | |
| if not SCHEDULER_RUNNING: | |
| SCHEDULER_RUNNING = True | |
| def loop(): | |
| while SCHEDULER_RUNNING: | |
| run_renewals() | |
| time.sleep(3600) | |
| SCHEDULER_THREAD = threading.Thread(target=loop, daemon=True) | |
| SCHEDULER_THREAD.start() | |
| add_log("⏰ المجدول التلقائي شغّال — يجدد كل 10 أيام") | |
| else: | |
| SCHEDULER_RUNNING = False | |
| add_log("⏹ تم إيقاف المجدول التلقائي") | |
| return {"running": SCHEDULER_RUNNING} | |
| async def get_log(): | |
| return {"lines": LOG_LINES[-100:]} | |
| async def health(): | |
| return {"status": "alive"} | |
| if __name__ == "__main__": | |
| start_ping_server(port=8080) | |
| add_log("🚀 PythonAnywhere Manager started") | |
| # عرض الحسابات المحملة عند البدء | |
| accounts = load_accounts() | |
| if accounts: | |
| add_log(f"📋 تم تحميل {len(accounts)} حساب من Secrets: {[a['username'] for a in accounts]}") | |
| else: | |
| add_log("⚠️ لم يتم العثور على حسابات — أضف ACCOUNTS في Secrets") | |
| uvicorn.run(app, host="0.0.0.0", port=7860) |