import os, paramiko, json PW = os.environ["REMOTE_PASS"] c = paramiko.SSHClient() c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) c.connect("207.57.129.228", port=19717, username="root", password=PW, timeout=15, allow_agent=False, look_for_keys=False) def run(cmd, t=30): si, so, se = c.exec_command(cmd, timeout=t) out = so.read().decode("utf-8", "replace") err = se.read().decode("utf-8", "replace") rc = so.channel.recv_exit_status() return out, err, rc pw = run("cat /root/.owner_pass")[0].strip() print(f"owner 密码: {pw}\n") # 1) 登录 out, _, _ = run(f"curl -s -X POST http://localhost/api/v1/auth/login -H 'Content-Type: application/json' -d '{{\"username\":\"owner\",\"password\":\"{pw}\"}}'") data = json.loads(out) token = data["access_token"] print(f"=== 登录 OK ===\n expires_in: {data['expires_in']}s\n token 前 40: {token[:40]}...\n") # 2) 拉 articles (5 条) out, _, _ = run(f"curl -s -H 'Authorization: Bearer {token}' 'http://localhost/api/v1/articles?limit=5'") ad = json.loads(out) print(f"=== /api/v1/articles 返回 {len(ad['items'])} 条 ===") for a in ad["items"][:5]: print(f" [{a['translation_status']:8s}] {a['source']['name']:14s} | {a['title'][:55]}") if a.get("title_zh"): print(f" zh: {a['title_zh'][:55]}") # 3) /me/usage out, _, _ = run(f"curl -s -H 'Authorization: Bearer {token}' 'http://localhost/api/v1/me/usage'") u = json.loads(out) print(f"\n=== /me/usage ===\n {json.dumps(u, indent=2, ensure_ascii=False)}") # 4) 详情 if ad["items"]: aid = ad["items"][0]["id"] out, _, _ = run(f"curl -s -H 'Authorization: Bearer {token}' 'http://localhost/api/v1/articles/{aid}'") det = json.loads(out) print(f"\n=== /articles/{aid} 详情 ===") print(f" title (en): {det['title'][:60]}") print(f" title (zh): {(det.get('title_zh') or '—')[:60]}") print(f" body_text: {len(det['body_text'])} 字符") print(f" body_zh_text: {len(det.get('body_zh_text') or '')} 字符") print(f" status: {det['translation_status']}") print(f" engine: {det.get('translation_engine', '—')}") # 5) sources out, _, _ = run(f"curl -s -H 'Authorization: Bearer {token}' 'http://localhost/api/v1/sources'") slist = json.loads(out) print(f"\n=== /api/v1/sources ({len(slist)} 个) ===") for s in slist: enabled = "✓" if s["enabled"] else "✗" print(f" {enabled} [{s['priority']:3d}] {s['slug']:18s} | {s['name']:25s} | {s['region'] or '—':8s} | {s['fetch_interval_min']}m") # 6) 容器状态 out, _, _ = run("cd /srv/news && sg docker -c 'docker compose ps --format \"table {{.Name}}\\t{{.Status}}\\t{{.Ports}}\"' 2>&1 | tail -10") print(f"\n=== Docker 状态 ===\n{out}") c.close()