| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- """Pool file helpers for zhuce6 ChatGPT token records."""
- from __future__ import annotations
- from datetime import datetime
- import json
- from pathlib import Path
- import re
- import time
- from typing import Any
- def _safe_component(value: str) -> str:
- cleaned = re.sub(r"[^A-Za-z0-9@._+-]+", "_", str(value or "").strip())
- return cleaned.strip("._") or "chatgpt_account"
- def build_pool_filename(token_data: dict[str, Any]) -> str:
- email = str(token_data.get("email") or "").strip()
- if email:
- return f"{_safe_component(email)}.json"
- account_id = str(token_data.get("account_id") or "").strip()
- if account_id:
- return f"{_safe_component(account_id)}.json"
- return f"chatgpt_{int(time.time())}.json"
- def now_iso() -> str:
- return datetime.now().astimezone().isoformat(timespec="seconds")
- def _apply_pool_defaults(token_data: dict[str, Any], *, assign_created_at: bool) -> dict[str, Any]:
- payload = dict(token_data)
- post_create_gate = str(payload.get("registration_post_create_gate") or "").strip().lower()
- warmup_required = bool(payload.get("warmup_required")) or post_create_gate == "add_phone"
- payload.setdefault("health_status", "unknown")
- payload.setdefault("source", str(payload.get("source") or "register").strip() or "register")
- if assign_created_at:
- payload.setdefault("created_at", now_iso())
- else:
- payload.setdefault("created_at", "")
- payload.setdefault("backup_written", True)
- payload.setdefault("cpa_sync_status", "pending")
- payload.setdefault("last_cpa_sync_at", "")
- payload.setdefault("last_cpa_sync_error", "")
- payload.setdefault("last_probe_at", "")
- payload.setdefault("last_probe_status_code", None)
- payload.setdefault("last_probe_result", "")
- payload.setdefault("last_probe_detail", "")
- payload.setdefault("warmup_required", warmup_required)
- payload.setdefault("warmup_state", "pending" if warmup_required else "not_required")
- payload.setdefault("warmup_passed", False if warmup_required else True)
- payload.setdefault("warmup_completed_at", "")
- payload.setdefault("successful_probe_count", 0)
- payload.setdefault("first_use_proxy_key", "")
- payload.setdefault("first_use_proxy_region", "")
- payload.setdefault("first_invalid_proxy_key", "")
- payload.setdefault("first_invalid_proxy_region", "")
- payload.pop("in_main_pool", None)
- payload.pop("promoted_at", None)
- payload.pop("last_main_pool_attempted_at", None)
- return payload
- def is_warmup_pending_record(payload: dict[str, Any]) -> bool:
- return bool(payload.get("warmup_required")) and not bool(payload.get("warmup_passed"))
- def load_token_record(path: Path) -> dict[str, Any]:
- payload = json.loads(path.read_text(encoding="utf-8"))
- if not isinstance(payload, dict):
- raise ValueError(f"token record must be a JSON object: {path}")
- return _apply_pool_defaults(payload, assign_created_at=False)
- def update_token_record(path: Path, **updates: Any) -> dict[str, Any]:
- payload = load_token_record(path)
- payload.update(updates)
- tmp_path = path.with_name(f"{path.name}.tmp")
- tmp_path.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")
- tmp_path.replace(path)
- return payload
- def write_token_record(token_data: dict[str, Any], pool_dir: Path, filename: str | None = None) -> Path:
- pool_dir.mkdir(parents=True, exist_ok=True)
- target_name = filename or build_pool_filename(token_data)
- target_path = pool_dir / target_name
- payload = _apply_pool_defaults(token_data, assign_created_at=True)
- target_path.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")
- return target_path
|