File size: 3,642 Bytes
a0c18f1
 
90d59ab
a0c18f1
 
 
 
126f324
a0c18f1
 
 
 
 
 
 
 
 
 
 
 
 
e92a108
126f324
a0c18f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126f324
a0c18f1
 
 
126f324
 
a0c18f1
90d59ab
 
a0c18f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e92a108
 
 
 
 
a0c18f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126f324
a0c18f1
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
114
115
116
117
118
119
120
121
122
123
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