Spaces:
Running
Running
Download server.py from Elias207/imageeditingpro1: direct link, hf CLI and curl.
- Browser
- Download file 4.3 kB
-
https://huggingface.co/spaces/Elias207/imageeditingpro1/resolve/main/server.py
- Command line
-
hf download hf://spaces/Elias207/imageeditingpro1/server.py
-
curl -L -o server.py https://huggingface.co/spaces/Elias207/imageeditingpro1/resolve/main/server.py
4.3 kB
| import asyncio | |
| import hmac | |
| import os | |
| import re | |
| import threading | |
| import time | |
| from fastapi import FastAPI, Header, HTTPException | |
| from fastapi.responses import FileResponse, HTMLResponse, JSONResponse | |
| import builder | |
| app = FastAPI(title="Lesson content server") | |
| state = {"status": "idle", "log": [], "errors": {}, "finished": None, "voices": {}} | |
| lock = threading.Lock() | |
| def _log(msg): | |
| state["log"].append(msg) | |
| del state["log"][:-200] | |
| def run_build(): | |
| if not lock.acquire(blocking=False): | |
| return | |
| try: | |
| state.update(status="building", log=[], errors={}) | |
| _, errors = asyncio.run(builder.build_all(_log)) | |
| state.update(status="ready", errors=errors, voices=dict(builder.INFO), finished=time.strftime("%Y-%m-%d %H:%M:%S")) | |
| except Exception as e: # noqa: BLE001 | |
| _log(f"خطای کلی: {e}") | |
| state["status"] = "failed" | |
| finally: | |
| lock.release() | |
| def startup(): | |
| threading.Thread(target=run_build, daemon=True).start() | |
| def check_password(p): | |
| expected = os.getenv("REBUILD_PASSWORD", "") | |
| if expected and not hmac.compare_digest(p or "", expected): | |
| raise HTTPException(401, "رمز اشتباه است") | |
| def manifest(): | |
| f = builder.OUT / "manifest.json" | |
| if not f.exists(): | |
| return JSONResponse({"status": state["status"]}, status_code=503) | |
| return FileResponse(f, media_type="application/json", headers={"Cache-Control": "no-cache"}) | |
| def pack(name: str): | |
| if not re.fullmatch(r"[A-Za-z0-9_.-]+\.zip", name): | |
| raise HTTPException(400, "bad name") | |
| f = builder.OUT / "packs" / name | |
| if not f.exists(): | |
| raise HTTPException(404, "not found") | |
| return FileResponse(f, media_type="application/zip") | |
| def status(): | |
| return state | |
| def rebuild(x_password: str = Header(default="")): | |
| check_password(x_password) | |
| if state["status"] == "building": | |
| return {"ok": False, "msg": "ساخت در حال انجام است"} | |
| threading.Thread(target=run_build, daemon=True).start() | |
| return {"ok": True} | |
| PAGE = """<!doctype html><html lang="fa" dir="rtl"><meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width,initial-scale=1"><title>سرور درسها</title> | |
| <style>body{font-family:system-ui,Tahoma;max-width:720px;margin:24px auto;padding:0 16px;background:#f4f9f9;color:#10282b} | |
| .card{background:#fff;border-radius:14px;padding:16px;margin:12px 0;box-shadow:0 1px 4px #0001} | |
| button{background:#0b7f8b;color:#fff;border:0;border-radius:10px;padding:10px 18px;font-size:15px;cursor:pointer} | |
| input{padding:9px;border-radius:8px;border:1px solid #9bb;font-size:15px} | |
| pre{background:#10282b;color:#cfe;padding:12px;border-radius:10px;max-height:300px;overflow:auto;direction:ltr;text-align:left;white-space:pre-wrap} | |
| .ok{color:#1e9e6a}.bad{color:#d9482b}</style> | |
| <h2>سرور درسها</h2> | |
| <div class="card"><div>وضعیت: <b id="st">…</b></div><div id="fin"></div> | |
| <p>آدرس فهرست: <code id="url" dir="ltr"></code></p> | |
| <p><input id="pw" type="password" placeholder="رمز (اگر تعریف کردهاید)"> <button onclick="rb()">ساخت دوبارهی درسها و صداها</button></p></div> | |
| <div class="card"><b>گزارش</b><pre id="log"></pre><div id="err" class="bad"></div></div> | |
| <script> | |
| document.getElementById('url').textContent=location.origin+'/manifest.json'; | |
| async function load(){const s=await (await fetch('status')).json(); | |
| const m={idle:'آماده',building:'در حال ساخت…',ready:'آماده ✅',failed:'ناموفق ❌'}; | |
| st.textContent=m[s.status]||s.status;fin.textContent=(s.finished?('آخرین ساخت: '+s.finished):'')+(s.voices&&s.voices.words?(' | واژهها: '+s.voices.words+' | جملهها: '+s.voices.sentences):''); | |
| log.textContent=s.log.join('\\n');err.textContent=Object.entries(s.errors).map(([k,v])=>k+': '+v).join('\\n');} | |
| async function rb(){const r=await fetch('rebuild',{method:'POST',headers:{'X-Password':pw.value}}); | |
| if(!r.ok){alert('رمز اشتباه است');return}load()} | |
| load();setInterval(load,3000); | |
| </script></html>""" | |
| def home(): | |
| return PAGE | |