config.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. """持久化网页配置:账号数 / 接码 URL / 邮件助手 / CPA 等。"""
  2. from __future__ import annotations
  3. import json
  4. import os
  5. import threading
  6. from dataclasses import asdict, dataclass, field, fields
  7. CONFIG_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config.local.json")
  8. _LOCK = threading.Lock()
  9. @dataclass
  10. class AppConfig:
  11. # 注册控制
  12. account_count: int = 1
  13. headless: bool = False
  14. # 注册模式:standard = 标准邮箱注册(需验证码);sso = SSO 单点登录注册(aef.claudeai.life)
  15. signup_mode: str = "sso"
  16. sso_mail_domain: str = "aef.claudeai.life"
  17. # 邮件
  18. mail_helper_url: str = "http://ali.ss5.xyz:17373"
  19. mail_domain: str = "edu.a4sky.com"
  20. mail_poll_interval_sec: int = 4
  21. mail_poll_max_attempts: int = 60 # 4s * 60 = 4min
  22. # PayPal / 接码
  23. phone_e164: str = "+15822201173"
  24. sms_api_url: str = "http://a.62-us.com/api/get_sms?key=a5d3262e05efaba982aba7cfae20b8bc"
  25. # 代理(两个字段独立配置):
  26. # proxy_url — 全局代理(ChatGPT 注册 / 长链 / PayPal 都走)。空 = 全程直连。
  27. # paypal_only_proxy — 仅 PayPal 阶段用的代理。空 = PayPal 沿用 proxy_url(或直连)。
  28. # 典型搭配:proxy_url 留空(注册直连,避免代理屏蔽 chatgpt.com),paypal_only_proxy 填代理。
  29. proxy_url: str = ""
  30. paypal_only_proxy: str = ""
  31. paypal_proxy: str = "" # 旧字段(保留向后兼容;如填了且 paypal_only_proxy/proxy_url 都为空,会迁移到 paypal_only_proxy)
  32. # CPA
  33. cpa_url: str = ""
  34. cpa_management_key: str = ""
  35. # CPA 账号池维护(清理无效账号 + 缺口补号)
  36. pool_maintainer_enabled: bool = False
  37. pool_min_candidates: int = 0
  38. pool_check_interval_sec: int = 60
  39. pool_used_percent_threshold: int = 90
  40. pool_target_type: str = "codex"
  41. pool_probe_workers: int = 10
  42. pool_task_max_attempts: int = 3
  43. # 调试
  44. use_promo: bool = True
  45. # 长链生成方式
  46. # payurl — 走 payurl.ark2.cn 第三方中转(默认)
  47. # local — 本地直连 chatgpt.com/backend-api/payments/checkout(需代理)
  48. long_link_mode: str = "payurl"
  49. long_link_proxy: str = "http://dinzitsz:n6wtkhg64jqq@82.24.43.35:6242/" # 本地长链生成用的代理(仅 local 模式生效)
  50. # API / 外网访问
  51. api_host: str = "0.0.0.0" # 改成 "0.0.0.0" 即可外网访问
  52. api_port: int = 7791
  53. api_token: str = "" # 留空 = 不校验;非空时所有 /api/* 请求需 Authorization: Bearer <token>
  54. api_cors_origin: str = "*" # CORS Allow-Origin,可填具体域名或 *
  55. @classmethod
  56. def load(cls) -> "AppConfig":
  57. if not os.path.exists(CONFIG_PATH):
  58. return cls()
  59. try:
  60. with open(CONFIG_PATH, "r", encoding="utf-8") as f:
  61. raw = json.load(f)
  62. except Exception:
  63. return cls()
  64. valid = {f.name for f in fields(cls)}
  65. cleaned = {k: v for k, v in (raw or {}).items() if k in valid}
  66. return cls(**cleaned)
  67. def save(self):
  68. with _LOCK:
  69. with open(CONFIG_PATH, "w", encoding="utf-8") as f:
  70. json.dump(asdict(self), f, ensure_ascii=False, indent=2)
  71. def update(self, patch: dict) -> "AppConfig":
  72. valid = {f.name for f in fields(self)}
  73. for k, v in (patch or {}).items():
  74. if k not in valid:
  75. continue
  76. current = getattr(self, k)
  77. if isinstance(current, bool):
  78. setattr(self, k, bool(v) if not isinstance(v, str) else v.lower() in ("1", "true", "yes", "on"))
  79. elif isinstance(current, int):
  80. try:
  81. setattr(self, k, int(v))
  82. except Exception:
  83. pass
  84. else:
  85. setattr(self, k, "" if v is None else str(v))
  86. # 向后兼容:旧字段 paypal_proxy → 新字段 paypal_only_proxy(之前一段时间它被错误地等价于 proxy_url)
  87. if self.paypal_proxy and not self.paypal_only_proxy and not self.proxy_url:
  88. self.paypal_only_proxy = self.paypal_proxy
  89. self.save()
  90. return self
  91. @property
  92. def effective_global_proxy(self) -> str:
  93. """ChatGPT 注册 / 长链 / 默认浏览器 context 用的代理。空 = 直连。"""
  94. return (self.proxy_url or "").strip()
  95. @property
  96. def effective_paypal_proxy(self) -> str:
  97. """PayPal 阶段用的代理,独立字段优先;否则继承 proxy_url。空 = 直连。"""
  98. return (self.paypal_only_proxy or self.proxy_url or "").strip()
  99. # 兼容旧调用:先前 chatgpt_flow 用了 effective_proxy
  100. @property
  101. def effective_proxy(self) -> str:
  102. return self.effective_global_proxy