File size: 3,852 Bytes
bcb31ef
 
 
 
0472279
 
bcb31ef
 
 
 
0472279
bcb31ef
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0472279
 
 
 
 
 
 
 
 
 
 
bcb31ef
 
 
 
 
 
 
 
 
 
 
 
9b2da3f
bcb31ef
 
 
 
9b2da3f
bcb31ef
0472279
bcb31ef
 
 
 
0472279
 
bcb31ef
 
 
9b2da3f
bcb31ef
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9b2da3f
bcb31ef
 
 
 
0472279
 
 
 
 
 
9b2da3f
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
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()

@app.get("/", response_class=HTMLResponse)
async def index():
    return HTML

@app.get("/api/accounts")
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

@app.post("/api/renew")
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}

@app.post("/api/renew/{username}")
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}

@app.post("/api/scheduler")
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}

@app.get("/api/log")
async def get_log():
    return {"lines": LOG_LINES[-100:]}

@app.get("/health")
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)