ehhhh / server.py
StarrySkyWorld's picture
Feat: Add failed response
126f324
from datetime import datetime
from concurrent.futures import ThreadPoolExecutor
import traceback
import threading
import uuid
from fastapi import FastAPI, Header, HTTPException
from fastapi.staticfiles import StaticFiles
import main as core
CONFIG = core.load_config()
core.apply_config(CONFIG)
API_KEY = CONFIG.get("api_key", "")
MAX_WORKERS = int(CONFIG.get("max_workers", 2))
app = FastAPI()
executor = ThreadPoolExecutor(max_workers=MAX_WORKERS)
tasks = {}
tasks_lock = threading.Lock()
print(f"[INFO] server startup: max_workers={MAX_WORKERS}")
app.mount("/screenshots", StaticFiles(directory="screenshots", check_dir=False), name="screenshots")
def require_api_key(x_api_key: str | None):
if not API_KEY:
return
if not x_api_key or x_api_key != API_KEY:
raise HTTPException(status_code=401, detail="unauthorized")
def update_task(task_id, **updates):
with tasks_lock:
task = tasks.get(task_id)
if not task:
return
task.update(updates)
task["updated_at"] = datetime.utcnow().isoformat()
def run_task(task_id):
update_task(task_id, status="running")
try:
email, ok, cfg, screenshot = core.register_one_account()
if ok:
update_task(task_id, status="success", result=cfg)
else:
screenshot_url = f"/screenshots/{screenshot}" if screenshot else None
update_task(task_id, status="failed", error=f"register failed: {email}", screenshot_url=screenshot_url)
except Exception as exc:
print(f"[ERR] task {task_id} failed: {exc}")
print(traceback.format_exc())
update_task(task_id, status="failed", error=str(exc))
@app.get("/health")
def health():
with tasks_lock:
total = len(tasks)
running = sum(1 for t in tasks.values() if t["status"] == "running")
pending = sum(1 for t in tasks.values() if t["status"] == "pending")
return {
"status": "ok",
"total_tasks": total,
"running": running,
"pending": pending,
"max_workers": MAX_WORKERS,
}
@app.get("/")
def root():
return {"status": "ok"}
@app.post("/task/create_account")
def create_account(x_api_key: str | None = Header(default=None)):
require_api_key(x_api_key)
task_id = uuid.uuid4().hex
now = datetime.utcnow().isoformat()
with tasks_lock:
tasks[task_id] = {
"status": "pending",
"created_at": now,
"updated_at": now,
"result": None,
"error": None,
}
executor.submit(run_task, task_id)
return {"task_id": task_id}
@app.get("/task/status")
def task_status(task_id: str, x_api_key: str | None = Header(default=None)):
require_api_key(x_api_key)
with tasks_lock:
task = tasks.get(task_id)
if not task:
raise HTTPException(status_code=404, detail="task not found")
return {"task_id": task_id, "status": task["status"]}
@app.get("/task/info")
def task_info(task_id: str, x_api_key: str | None = Header(default=None)):
require_api_key(x_api_key)
with tasks_lock:
task = tasks.get(task_id)
if not task:
raise HTTPException(status_code=404, detail="task not found")
payload = {
"task_id": task_id,
"status": task["status"],
"created_at": task["created_at"],
"updated_at": task["updated_at"],
}
if task["status"] == "success":
payload["result"] = task["result"]
if task["status"] == "failed":
payload["error"] = task["error"]
payload["screenshot_url"] = task.get("screenshot_url")
return payload