Files
vosonandCursor 9c5aa5b610 Reorganize repository into pc web shared monorepo
Separate the local recognition, web publishing, and shared data paths while preserving direct script execution and existing site content.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-29 14:29:08 +08:00

86 lines
3.3 KiB
Python

"""Read-only Cloudflare Pages status probe (diagnostic helper).
Prints account id, whether the target project exists, its latest deployment,
and bound custom domains. Credentials come from env (keyzoo inject).
Usage via keyzoo: python _cf_status.py [--project-name NAME]
"""
from __future__ import annotations
import argparse
import json
import os
import urllib.error
import urllib.request
DEFAULT_PROJECT = "climperor-relations"
def cf(method: str, path: str, email: str, key: str, body: dict | None = None) -> dict:
url = "https://api.cloudflare.com/client/v4" + path
headers = {"X-Auth-Email": email, "X-Auth-Key": key, "Content-Type": "application/json"}
data = json.dumps(body).encode() if body is not None else None
req = urllib.request.Request(url, data=data, method=method, headers=headers)
try:
with urllib.request.urlopen(req) as r:
return json.loads(r.read().decode())
except urllib.error.HTTPError as e:
try:
return json.loads(e.read().decode())
except Exception:
return {"success": False, "errors": [{"code": e.code, "message": str(e)}]}
except urllib.error.URLError as e:
return {"success": False, "errors": [{"code": -1, "message": str(e)}]}
def main() -> None:
ap = argparse.ArgumentParser()
ap.add_argument("--project-name", default=DEFAULT_PROJECT)
args = ap.parse_args()
email = os.environ.get("CLOUDFLARE_EMAIL") or os.environ.get("KEYZOO_ASSET_META_USERNAME")
key = os.environ.get("CLOUDFLARE_API_KEY") or os.environ.get("KEYZOO_ASSET_SECRET_GLOBAL_API_KEY")
if not email or not key:
raise SystemExit("missing credentials in env")
d = cf("GET", "/accounts", email, key)
if not d.get("success"):
print("GET /accounts FAILED:", d.get("errors"))
return
accts = d.get("result") or []
print(f"accounts: {[ (a['id'], a.get('name')) for a in accts ]}")
if not accts:
return
aid = accts[0]["id"]
d = cf("GET", f"/accounts/{aid}/pages/projects/{args.project_name}", email, key)
if not d.get("success"):
print(f"project {args.project_name}: NOT created -> {d.get('errors')}")
return
print(f"project: {args.project_name} (created)")
d = cf("GET", f"/accounts/{aid}/pages/projects/{args.project_name}/deployments", email, key)
deps = d.get("result") or []
print(f"deployments: {len(deps)}")
for dep in deps[:3]:
print(f" - {dep.get('latest_stage', {}).get('name')} / {dep.get('latest_stage', {}).get('status')} | env={dep.get('environment')} | created={dep.get('created_on')} | url={dep.get('url')}")
d = cf("GET", f"/accounts/{aid}/pages/projects/{args.project_name}/domains", email, key)
doms = d.get("result") or []
print("custom domains:")
for x in doms:
print(f" - {x.get('name')} status={x.get('status')}")
# Confirm the CNAME was auto-added on the refining.dev zone.
zd = cf("GET", "/zones?name=refining.dev", email, key)
zr = zd.get("result") or []
if zr:
zid = zr[0]["id"]
recs = cf("GET", f"/zones/{zid}/dns_records?name=dota2.refining.dev", email, key)
for rec in (recs.get("result") or []):
print(f" dns: {rec.get('type')} {rec.get('name')} -> {rec.get('content')} (proxied={rec.get('proxied')})")
if __name__ == "__main__":
main()