feat(cli): package project as installable command

This commit is contained in:
Logic
2026-03-21 15:10:32 +08:00
parent 013bfed484
commit 380da813c5
11 changed files with 49974 additions and 285 deletions

2
src/__init__.py Normal file
View File

@@ -0,0 +1,2 @@
"""gptplus_auto package."""

5
src/__main__.py Normal file
View File

@@ -0,0 +1,5 @@
from .main import main
if __name__ == "__main__":
raise SystemExit(main())

View File

@@ -1,7 +1,12 @@
"""ChatGPT Plus payment flow."""
import uuid
from http_client import HTTPClient
from captcha_solver import CaptchaSolver
try:
from .http_client import HTTPClient
from .captcha_solver import CaptchaSolver
except ImportError: # pragma: no cover - allow direct script execution from source tree
from http_client import HTTPClient
from captcha_solver import CaptchaSolver
class ChatGPTPayment:

View File

@@ -1,22 +1,28 @@
from __future__ import annotations
"""Pure HTTP registration experiment with detailed auth-state diagnostics."""
import os
import re
import uuid
from pathlib import Path
from typing import Optional
from urllib.parse import unquote, urlencode, urljoin, urlparse
from http_client import HTTPClient
from vmail_client import get_mail_client
from config import settings
try:
from .http_client import HTTPClient
from .vmail_client import BaseMailClient
except ImportError: # pragma: no cover - allow direct script execution from source tree
from http_client import HTTPClient
from vmail_client import BaseMailClient
class ChatGPTRegisterHTTPReverse:
def __init__(self, http: HTTPClient, mail: MailClient):
def __init__(self, http: HTTPClient, mail: BaseMailClient):
self.http = http
self.mail = mail
self.base = "https://chatgpt.com"
self.auth_base = "https://auth.openai.com"
self.root_dir = os.path.dirname(os.path.dirname(__file__))
self.module_dir = Path(__file__).resolve().parent
def _cookie_rows(self) -> list[tuple[str, str, str]]:
rows = []
@@ -74,11 +80,19 @@ class ChatGPTRegisterHTTPReverse:
return None
def _load_captured_sentinel(self, flow_name: str) -> str:
path = os.path.join(self.root_dir, "nodatadog.js")
try:
with open(path, "r", encoding="utf-8") as handle:
content = handle.read()
except FileNotFoundError:
candidates = [
self.module_dir / "nodatadog.js",
self.module_dir.parent / "nodatadog.js",
Path.cwd() / "nodatadog.js",
]
content = ""
for path in candidates:
try:
content = path.read_text(encoding="utf-8")
break
except FileNotFoundError:
continue
if not content:
return ""
pattern = re.compile(r'"openai-sentinel-token": "((?:[^"\\]|\\.)*flow\\"\\"%s(?:[^"\\]|\\.)*)"' % re.escape(flow_name))
match = pattern.search(content)

View File

@@ -9,7 +9,12 @@ from pathlib import Path
from typing import Any
from urllib.parse import urljoin, urlparse
from http_client import HTTPClient
try:
from .config import settings
from .http_client import HTTPClient
except ImportError: # pragma: no cover - allow direct script execution from source tree
from config import settings
from http_client import HTTPClient
try:
from playwright.sync_api import TimeoutError as PlaywrightTimeoutError
@@ -170,23 +175,10 @@ class BrowserSentinelHelper:
def load_proxy() -> str:
proxy = os.getenv("SOCKS5_PROXY", "").strip()
proxy = settings.socks5_proxy.strip()
if proxy:
return proxy
env_path = Path(__file__).resolve().parent.parent / ".env"
if not env_path.exists():
return ""
for raw_line in env_path.read_text(encoding="utf-8").splitlines():
line = raw_line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
if key.strip() != "SOCKS5_PROXY":
continue
return value.strip().strip("\"'")
return ""
return os.getenv("SOCKS5_PROXY", "").strip()
class CodexOAuthHTTPFlow:
@@ -314,7 +306,10 @@ class CodexOAuthHTTPFlow:
return ""
mail = self.mail_client
if not mail:
from vmail_client import get_mail_client
try:
from .vmail_client import get_mail_client
except ImportError: # pragma: no cover - allow direct script execution from source tree
from vmail_client import get_mail_client
mail = get_mail_client()
print("[otp] auto-fetching OTP from mailbox...")
try:

View File

@@ -5,13 +5,22 @@ import random
import string
import sys
from config import settings
from vmail_client import get_mail_client
from captcha_solver import CaptchaSolver
from http_client import HTTPClient
from chatgpt_register_http_reverse import ChatGPTRegisterHTTPReverse
from chatgpt_payment import ChatGPTPayment
from codex_oauth_http_flow import CodexOAuthHTTPFlow, DEFAULT_AUTHORIZE_URL
try:
from .config import settings
from .vmail_client import get_mail_client
from .captcha_solver import CaptchaSolver
from .http_client import HTTPClient
from .chatgpt_register_http_reverse import ChatGPTRegisterHTTPReverse
from .chatgpt_payment import ChatGPTPayment
from .codex_oauth_http_flow import CodexOAuthHTTPFlow, DEFAULT_AUTHORIZE_URL
except ImportError: # pragma: no cover - allow direct script execution from source tree
from config import settings
from vmail_client import get_mail_client
from captcha_solver import CaptchaSolver
from http_client import HTTPClient
from chatgpt_register_http_reverse import ChatGPTRegisterHTTPReverse
from chatgpt_payment import ChatGPTPayment
from codex_oauth_http_flow import CodexOAuthHTTPFlow, DEFAULT_AUTHORIZE_URL
def generate_password(length=16):
@@ -144,7 +153,7 @@ def cmd_codex_login(args):
def build_parser():
parser = argparse.ArgumentParser(
prog="main.py",
prog="gptplus-auto",
description="ChatGPT account tools",
)
sub = parser.add_subparsers(dest="command")

49618
src/nodatadog.js Normal file

File diff suppressed because one or more lines are too long