Spaces:
Paused
Paused
Zhi Yang commited on
Commit ·
fcb2d84
1
Parent(s): 9af49ff
feat: support Playwright proxy configuration
Browse files- .env.example +6 -0
- docker-compose.yml +2 -0
- docs/configuration.md +24 -0
- docs/getting-started.md +20 -0
- docs/troubleshooting.md +24 -1
- src/autoteam/api.py +4 -1
- src/autoteam/chatgpt_api.py +2 -4
- src/autoteam/codex_auth.py +2 -4
- src/autoteam/config.py +60 -0
- src/autoteam/invite.py +2 -4
- src/autoteam/manager.py +4 -13
- src/autoteam/setup_wizard.py +3 -1
.env.example
CHANGED
|
@@ -11,6 +11,12 @@ CPA_KEY=your_key
|
|
| 11 |
# API 鉴权(不设置则不启用,任何人都可访问)
|
| 12 |
API_KEY=
|
| 13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
# 轮询配置
|
| 15 |
EMAIL_POLL_INTERVAL=3
|
| 16 |
EMAIL_POLL_TIMEOUT=300
|
|
|
|
| 11 |
# API 鉴权(不设置则不启用,任何人都可访问)
|
| 12 |
API_KEY=
|
| 13 |
|
| 14 |
+
# Playwright 浏览器代理(可选)
|
| 15 |
+
# 示例:socks5://user:pass@host.docker.internal:1080
|
| 16 |
+
PLAYWRIGHT_PROXY_URL=
|
| 17 |
+
# 示例:localhost,127.0.0.1
|
| 18 |
+
PLAYWRIGHT_PROXY_BYPASS=
|
| 19 |
+
|
| 20 |
# 轮询配置
|
| 21 |
EMAIL_POLL_INTERVAL=3
|
| 22 |
EMAIL_POLL_TIMEOUT=300
|
docker-compose.yml
CHANGED
|
@@ -1,6 +1,8 @@
|
|
| 1 |
services:
|
| 2 |
autoteam:
|
| 3 |
build: .
|
|
|
|
|
|
|
| 4 |
ports:
|
| 5 |
- "8787:8787"
|
| 6 |
volumes:
|
|
|
|
| 1 |
services:
|
| 2 |
autoteam:
|
| 3 |
build: .
|
| 4 |
+
extra_hosts:
|
| 5 |
+
- "host.docker.internal:host-gateway"
|
| 6 |
ports:
|
| 7 |
- "8787:8787"
|
| 8 |
volumes:
|
docs/configuration.md
CHANGED
|
@@ -17,10 +17,34 @@ cp .env.example .env
|
|
| 17 |
| `CPA_URL` | CLIProxyAPI 地址 | 否(默认 `http://127.0.0.1:8317`) |
|
| 18 |
| `CPA_KEY` | CPA 管理密钥 | 是 |
|
| 19 |
| `API_KEY` | Web 面板 / API 鉴权密钥 | 否(首次启动自动生成) |
|
|
|
|
|
|
|
| 20 |
| `AUTO_CHECK_THRESHOLD` | 额度低于此百分比触发轮转 | 否(默认 `10`) |
|
| 21 |
| `AUTO_CHECK_INTERVAL` | 巡检间隔(秒) | 否(默认 `300`) |
|
| 22 |
| `AUTO_CHECK_MIN_LOW` | 至少几个账号低于阈值才触发 | 否(默认 `2`) |
|
| 23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
### 内联注释
|
| 25 |
|
| 26 |
`.env` 支持尾部内联注释,例如:
|
|
|
|
| 17 |
| `CPA_URL` | CLIProxyAPI 地址 | 否(默认 `http://127.0.0.1:8317`) |
|
| 18 |
| `CPA_KEY` | CPA 管理密钥 | 是 |
|
| 19 |
| `API_KEY` | Web 面板 / API 鉴权密钥 | 否(首次启动自动生成) |
|
| 20 |
+
| `PLAYWRIGHT_PROXY_URL` | Playwright 浏览器代理 URL,如 `socks5://user:pass@host:port` | 否 |
|
| 21 |
+
| `PLAYWRIGHT_PROXY_BYPASS` | Playwright 代理绕过列表,如 `localhost,127.0.0.1` | 否 |
|
| 22 |
| `AUTO_CHECK_THRESHOLD` | 额度低于此百分比触发轮转 | 否(默认 `10`) |
|
| 23 |
| `AUTO_CHECK_INTERVAL` | 巡检间隔(秒) | 否(默认 `300`) |
|
| 24 |
| `AUTO_CHECK_MIN_LOW` | 至少几个账号低于阈值才触发 | 否(默认 `2`) |
|
| 25 |
|
| 26 |
+
## Playwright 代理
|
| 27 |
+
|
| 28 |
+
AutoTeam 的浏览器流量(ChatGPT 登录、邀请接受、Codex OAuth 等)现在支持单独配置代理。
|
| 29 |
+
|
| 30 |
+
推荐优先使用一个环境变量:
|
| 31 |
+
|
| 32 |
+
```dotenv
|
| 33 |
+
PLAYWRIGHT_PROXY_URL=socks5://host.docker.internal:1080
|
| 34 |
+
PLAYWRIGHT_PROXY_BYPASS=localhost,127.0.0.1
|
| 35 |
+
```
|
| 36 |
+
|
| 37 |
+
如果代理需要认证,也可以直接写进 URL:
|
| 38 |
+
|
| 39 |
+
```dotenv
|
| 40 |
+
PLAYWRIGHT_PROXY_URL=socks5://username:password@host.docker.internal:1080
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
说明:
|
| 44 |
+
|
| 45 |
+
- `PLAYWRIGHT_PROXY_URL` 会被解析为 Playwright 所需的 `server` / `username` / `password` 字段
|
| 46 |
+
- `PLAYWRIGHT_PROXY_BYPASS` 建议至少包含 `localhost,127.0.0.1`,避免本地回调或容器内本地服务误走代理
|
| 47 |
+
|
| 48 |
### 内联注释
|
| 49 |
|
| 50 |
`.env` 支持尾部内联注释,例如:
|
docs/getting-started.md
CHANGED
|
@@ -118,6 +118,26 @@ docker compose restart
|
|
| 118 |
|
| 119 |
直接打开 `http://your-server:8787`,会显示配置向导页面,在浏览器中填写。
|
| 120 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
## 第三步:管理员登录
|
| 122 |
|
| 123 |
配置完成后,需要先用 ChatGPT Team 管理员账号登录。
|
|
|
|
| 118 |
|
| 119 |
直接打开 `http://your-server:8787`,会显示配置向导页面,在浏览器中填写。
|
| 120 |
|
| 121 |
+
如果你需要让浏览器流量走宿主机 SOCKS5 代理,在 Linux Docker 下还需要给容器增加:
|
| 122 |
+
|
| 123 |
+
```yaml
|
| 124 |
+
extra_hosts:
|
| 125 |
+
- "host.docker.internal:host-gateway"
|
| 126 |
+
```
|
| 127 |
+
|
| 128 |
+
然后在 `data/.env` 中加入:
|
| 129 |
+
|
| 130 |
+
```dotenv
|
| 131 |
+
PLAYWRIGHT_PROXY_URL=socks5://host.docker.internal:1080
|
| 132 |
+
PLAYWRIGHT_PROXY_BYPASS=localhost,127.0.0.1
|
| 133 |
+
```
|
| 134 |
+
|
| 135 |
+
如果代理需要认证,可以写成:
|
| 136 |
+
|
| 137 |
+
```dotenv
|
| 138 |
+
PLAYWRIGHT_PROXY_URL=socks5://username:password@host.docker.internal:1080
|
| 139 |
+
```
|
| 140 |
+
|
| 141 |
## 第三步:管理员登录
|
| 142 |
|
| 143 |
配置完成后,需要先用 ChatGPT Team 管理员账号登录。
|
docs/troubleshooting.md
CHANGED
|
@@ -40,10 +40,11 @@ AUTO_CHECK_INTERVAL=300 # 5 分钟
|
|
| 40 |
### Codex OAuth 登录失败:未获取到 authorization code
|
| 41 |
|
| 42 |
常见原因:
|
| 43 |
-
1. **IP 被标记** — VPS 的 IP 被 OpenAI
|
| 44 |
2. **Cloudflare 验证** — 浏览器环境被检测,需更新 Chromium 或切换网络
|
| 45 |
3. **workspace 选择失败** — 页面结构变化,查看 `screenshots/codex_04_*.png`
|
| 46 |
4. **自动回调不可达** — 如果浏览器和 AutoTeam 不在同一台机器,`localhost:1455` 回调可能不会到达 AutoTeam,此时请改用手动粘贴回调 URL
|
|
|
|
| 47 |
|
| 48 |
### 登录后 plan 显示 free 而不是 team
|
| 49 |
|
|
@@ -167,6 +168,28 @@ volumes:
|
|
| 167 |
- ./data:/app/data
|
| 168 |
```
|
| 169 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 170 |
## Web 面板相关
|
| 171 |
|
| 172 |
### 页面显示 `JSON parse error`
|
|
|
|
| 40 |
### Codex OAuth 登录失败:未获取到 authorization code
|
| 41 |
|
| 42 |
常见原因:
|
| 43 |
+
1. **IP 被标记** — VPS 的 IP 被 OpenAI/Cloudflare 拦截,建议换住宅代理
|
| 44 |
2. **Cloudflare 验证** — 浏览器环境被检测,需更新 Chromium 或切换网络
|
| 45 |
3. **workspace 选择失败** — 页面结构变化,查看 `screenshots/codex_04_*.png`
|
| 46 |
4. **自动回调不可达** — 如果浏览器和 AutoTeam 不在同一台机器,`localhost:1455` 回调可能不会到达 AutoTeam,此时请改用手动粘贴回调 URL
|
| 47 |
+
5. **本地回调被代理拦截** — 如果启用了 `PLAYWRIGHT_PROXY_URL`,建议同时设置 `PLAYWRIGHT_PROXY_BYPASS=localhost,127.0.0.1`
|
| 48 |
|
| 49 |
### 登录后 plan 显示 free 而不是 team
|
| 50 |
|
|
|
|
| 168 |
- ./data:/app/data
|
| 169 |
```
|
| 170 |
|
| 171 |
+
### 容器里访问不到宿主机 SOCKS5 代理
|
| 172 |
+
|
| 173 |
+
如果代理在宿主机上,比如 `host.docker.internal:1080`,Linux Docker 需要给容器补一条 host-gateway 映射:
|
| 174 |
+
|
| 175 |
+
```yaml
|
| 176 |
+
extra_hosts:
|
| 177 |
+
- "host.docker.internal:host-gateway"
|
| 178 |
+
```
|
| 179 |
+
|
| 180 |
+
然后在 `data/.env` 中配置:
|
| 181 |
+
|
| 182 |
+
```dotenv
|
| 183 |
+
PLAYWRIGHT_PROXY_URL=socks5://host.docker.internal:1080
|
| 184 |
+
PLAYWRIGHT_PROXY_BYPASS=localhost,127.0.0.1
|
| 185 |
+
```
|
| 186 |
+
|
| 187 |
+
如果代理需要认证,可以直接写成:
|
| 188 |
+
|
| 189 |
+
```dotenv
|
| 190 |
+
PLAYWRIGHT_PROXY_URL=socks5://username:password@host.docker.internal:1080
|
| 191 |
+
```
|
| 192 |
+
|
| 193 |
## Web 面板相关
|
| 194 |
|
| 195 |
### 页面显示 `JSON parse error`
|
src/autoteam/api.py
CHANGED
|
@@ -74,6 +74,8 @@ class SetupConfig(BaseModel):
|
|
| 74 |
CLOUDMAIL_DOMAIN: str = ""
|
| 75 |
CPA_URL: str = "http://127.0.0.1:8317"
|
| 76 |
CPA_KEY: str = ""
|
|
|
|
|
|
|
| 77 |
API_KEY: str = ""
|
| 78 |
|
| 79 |
|
|
@@ -105,8 +107,9 @@ def post_setup_save(config: SetupConfig):
|
|
| 105 |
if not data.get("API_KEY"):
|
| 106 |
data["API_KEY"] = _secrets.token_urlsafe(24)
|
| 107 |
|
|
|
|
| 108 |
for key, value in data.items():
|
| 109 |
-
if value:
|
| 110 |
_write_env(key, value)
|
| 111 |
os.environ[key] = value
|
| 112 |
|
|
|
|
| 74 |
CLOUDMAIL_DOMAIN: str = ""
|
| 75 |
CPA_URL: str = "http://127.0.0.1:8317"
|
| 76 |
CPA_KEY: str = ""
|
| 77 |
+
PLAYWRIGHT_PROXY_URL: str = ""
|
| 78 |
+
PLAYWRIGHT_PROXY_BYPASS: str = ""
|
| 79 |
API_KEY: str = ""
|
| 80 |
|
| 81 |
|
|
|
|
| 107 |
if not data.get("API_KEY"):
|
| 108 |
data["API_KEY"] = _secrets.token_urlsafe(24)
|
| 109 |
|
| 110 |
+
clearable_fields = {"PLAYWRIGHT_PROXY_URL", "PLAYWRIGHT_PROXY_BYPASS"}
|
| 111 |
for key, value in data.items():
|
| 112 |
+
if value or key in clearable_fields:
|
| 113 |
_write_env(key, value)
|
| 114 |
os.environ[key] = value
|
| 115 |
|
src/autoteam/chatgpt_api.py
CHANGED
|
@@ -17,6 +17,7 @@ from autoteam.admin_state import (
|
|
| 17 |
get_chatgpt_workspace_name,
|
| 18 |
update_admin_state,
|
| 19 |
)
|
|
|
|
| 20 |
from autoteam.textio import read_text
|
| 21 |
|
| 22 |
logger = logging.getLogger(__name__)
|
|
@@ -114,10 +115,7 @@ class ChatGPTTeamAPI:
|
|
| 114 |
def _launch_browser(self):
|
| 115 |
SCREENSHOT_DIR.mkdir(exist_ok=True)
|
| 116 |
self.playwright = sync_playwright().start()
|
| 117 |
-
self.browser = self.playwright.chromium.launch(
|
| 118 |
-
headless=False,
|
| 119 |
-
args=["--disable-blink-features=AutomationControlled", "--no-sandbox"],
|
| 120 |
-
)
|
| 121 |
self.context = self.browser.new_context(
|
| 122 |
viewport={"width": 1280, "height": 800},
|
| 123 |
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
|
|
|
| 17 |
get_chatgpt_workspace_name,
|
| 18 |
update_admin_state,
|
| 19 |
)
|
| 20 |
+
from autoteam.config import get_playwright_launch_options
|
| 21 |
from autoteam.textio import read_text
|
| 22 |
|
| 23 |
logger = logging.getLogger(__name__)
|
|
|
|
| 115 |
def _launch_browser(self):
|
| 116 |
SCREENSHOT_DIR.mkdir(exist_ok=True)
|
| 117 |
self.playwright = sync_playwright().start()
|
| 118 |
+
self.browser = self.playwright.chromium.launch(**get_playwright_launch_options())
|
|
|
|
|
|
|
|
|
|
| 119 |
self.context = self.browser.new_context(
|
| 120 |
viewport={"width": 1280, "height": 800},
|
| 121 |
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
src/autoteam/codex_auth.py
CHANGED
|
@@ -20,6 +20,7 @@ from autoteam.admin_state import (
|
|
| 20 |
get_chatgpt_workspace_name,
|
| 21 |
)
|
| 22 |
from autoteam.auth_storage import AUTH_DIR, ensure_auth_dir, ensure_auth_file_permissions
|
|
|
|
| 23 |
from autoteam.textio import write_text
|
| 24 |
|
| 25 |
logger = logging.getLogger(__name__)
|
|
@@ -265,10 +266,7 @@ def login_codex_via_browser(email, password, mail_client=None):
|
|
| 265 |
auth_code = None
|
| 266 |
|
| 267 |
with sync_playwright() as p:
|
| 268 |
-
browser = p.chromium.launch(
|
| 269 |
-
headless=False,
|
| 270 |
-
args=["--disable-blink-features=AutomationControlled", "--no-sandbox"],
|
| 271 |
-
)
|
| 272 |
context = browser.new_context(
|
| 273 |
viewport={"width": 1280, "height": 800},
|
| 274 |
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
|
|
|
| 20 |
get_chatgpt_workspace_name,
|
| 21 |
)
|
| 22 |
from autoteam.auth_storage import AUTH_DIR, ensure_auth_dir, ensure_auth_file_permissions
|
| 23 |
+
from autoteam.config import get_playwright_launch_options
|
| 24 |
from autoteam.textio import write_text
|
| 25 |
|
| 26 |
logger = logging.getLogger(__name__)
|
|
|
|
| 266 |
auth_code = None
|
| 267 |
|
| 268 |
with sync_playwright() as p:
|
| 269 |
+
browser = p.chromium.launch(**get_playwright_launch_options())
|
|
|
|
|
|
|
|
|
|
| 270 |
context = browser.new_context(
|
| 271 |
viewport={"width": 1280, "height": 800},
|
| 272 |
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
src/autoteam/config.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
| 2 |
|
| 3 |
import os
|
| 4 |
from pathlib import Path
|
|
|
|
| 5 |
|
| 6 |
from autoteam.textio import parse_env_line, parse_env_value, read_text
|
| 7 |
|
|
@@ -46,3 +47,62 @@ API_KEY = os.environ.get("API_KEY", "")
|
|
| 46 |
AUTO_CHECK_INTERVAL = _get_int_env("AUTO_CHECK_INTERVAL", 300) # 巡检间隔(秒),默认 5 分钟
|
| 47 |
AUTO_CHECK_THRESHOLD = _get_int_env("AUTO_CHECK_THRESHOLD", 10) # 额度低于此百分比触发轮转,默认 10%
|
| 48 |
AUTO_CHECK_MIN_LOW = _get_int_env("AUTO_CHECK_MIN_LOW", 2) # 至少几个账号低于阈值才触发,默认 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
import os
|
| 4 |
from pathlib import Path
|
| 5 |
+
from urllib.parse import unquote, urlsplit
|
| 6 |
|
| 7 |
from autoteam.textio import parse_env_line, parse_env_value, read_text
|
| 8 |
|
|
|
|
| 47 |
AUTO_CHECK_INTERVAL = _get_int_env("AUTO_CHECK_INTERVAL", 300) # 巡检间隔(秒),默认 5 分钟
|
| 48 |
AUTO_CHECK_THRESHOLD = _get_int_env("AUTO_CHECK_THRESHOLD", 10) # 额度低于此百分比触发轮转,默认 10%
|
| 49 |
AUTO_CHECK_MIN_LOW = _get_int_env("AUTO_CHECK_MIN_LOW", 2) # 至少几个账号低于阈值才触发,默认 2
|
| 50 |
+
|
| 51 |
+
# Playwright 代理配置
|
| 52 |
+
PLAYWRIGHT_PROXY_URL = os.environ.get("PLAYWRIGHT_PROXY_URL", "").strip()
|
| 53 |
+
PLAYWRIGHT_PROXY_SERVER = os.environ.get("PLAYWRIGHT_PROXY_SERVER", "").strip()
|
| 54 |
+
PLAYWRIGHT_PROXY_USERNAME = os.environ.get("PLAYWRIGHT_PROXY_USERNAME", "").strip()
|
| 55 |
+
PLAYWRIGHT_PROXY_PASSWORD = os.environ.get("PLAYWRIGHT_PROXY_PASSWORD", "").strip()
|
| 56 |
+
PLAYWRIGHT_PROXY_BYPASS = os.environ.get("PLAYWRIGHT_PROXY_BYPASS", "").strip()
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
def _format_proxy_host(hostname: str) -> str:
|
| 60 |
+
if ":" in hostname and not hostname.startswith("["):
|
| 61 |
+
return f"[{hostname}]"
|
| 62 |
+
return hostname
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
def _parse_proxy_url(proxy_url: str):
|
| 66 |
+
if "://" not in proxy_url:
|
| 67 |
+
return {"server": proxy_url}
|
| 68 |
+
|
| 69 |
+
parsed = urlsplit(proxy_url)
|
| 70 |
+
if not parsed.scheme or not parsed.hostname:
|
| 71 |
+
return {"server": proxy_url}
|
| 72 |
+
|
| 73 |
+
host = _format_proxy_host(parsed.hostname)
|
| 74 |
+
server = f"{parsed.scheme}://{host}"
|
| 75 |
+
if parsed.port:
|
| 76 |
+
server = f"{server}:{parsed.port}"
|
| 77 |
+
|
| 78 |
+
proxy = {"server": server}
|
| 79 |
+
if parsed.username:
|
| 80 |
+
proxy["username"] = unquote(parsed.username)
|
| 81 |
+
if parsed.password:
|
| 82 |
+
proxy["password"] = unquote(parsed.password)
|
| 83 |
+
return proxy
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def get_playwright_launch_options():
|
| 87 |
+
"""统一的 Playwright Chromium 启动参数。"""
|
| 88 |
+
options = {
|
| 89 |
+
"headless": False,
|
| 90 |
+
"args": ["--disable-blink-features=AutomationControlled", "--no-sandbox"],
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
proxy = None
|
| 94 |
+
if PLAYWRIGHT_PROXY_URL:
|
| 95 |
+
proxy = _parse_proxy_url(PLAYWRIGHT_PROXY_URL)
|
| 96 |
+
elif PLAYWRIGHT_PROXY_SERVER:
|
| 97 |
+
proxy = {"server": PLAYWRIGHT_PROXY_SERVER}
|
| 98 |
+
if PLAYWRIGHT_PROXY_USERNAME:
|
| 99 |
+
proxy["username"] = PLAYWRIGHT_PROXY_USERNAME
|
| 100 |
+
if PLAYWRIGHT_PROXY_PASSWORD:
|
| 101 |
+
proxy["password"] = PLAYWRIGHT_PROXY_PASSWORD
|
| 102 |
+
|
| 103 |
+
if proxy:
|
| 104 |
+
if PLAYWRIGHT_PROXY_BYPASS:
|
| 105 |
+
proxy["bypass"] = PLAYWRIGHT_PROXY_BYPASS
|
| 106 |
+
options["proxy"] = proxy
|
| 107 |
+
|
| 108 |
+
return options
|
src/autoteam/invite.py
CHANGED
|
@@ -26,6 +26,7 @@ from playwright.sync_api import sync_playwright
|
|
| 26 |
|
| 27 |
from autoteam.chatgpt_api import ChatGPTTeamAPI
|
| 28 |
from autoteam.cloudmail import CloudMailClient
|
|
|
|
| 29 |
|
| 30 |
logger = logging.getLogger(__name__)
|
| 31 |
|
|
@@ -403,10 +404,7 @@ def run():
|
|
| 403 |
logger.info("[邀请] 开始注册 ChatGPT 账号")
|
| 404 |
|
| 405 |
with sync_playwright() as p:
|
| 406 |
-
browser = p.chromium.launch(
|
| 407 |
-
headless=False,
|
| 408 |
-
args=["--disable-blink-features=AutomationControlled", "--no-sandbox"],
|
| 409 |
-
)
|
| 410 |
context = browser.new_context(
|
| 411 |
viewport={"width": 1280, "height": 800},
|
| 412 |
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
|
|
|
| 26 |
|
| 27 |
from autoteam.chatgpt_api import ChatGPTTeamAPI
|
| 28 |
from autoteam.cloudmail import CloudMailClient
|
| 29 |
+
from autoteam.config import get_playwright_launch_options
|
| 30 |
|
| 31 |
logger = logging.getLogger(__name__)
|
| 32 |
|
|
|
|
| 404 |
logger.info("[邀请] 开始注册 ChatGPT 账号")
|
| 405 |
|
| 406 |
with sync_playwright() as p:
|
| 407 |
+
browser = p.chromium.launch(**get_playwright_launch_options())
|
|
|
|
|
|
|
|
|
|
| 408 |
context = browser.new_context(
|
| 409 |
viewport={"width": 1280, "height": 800},
|
| 410 |
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
src/autoteam/manager.py
CHANGED
|
@@ -57,6 +57,7 @@ from autoteam.codex_auth import (
|
|
| 57 |
refresh_main_auth_file,
|
| 58 |
save_auth_file,
|
| 59 |
)
|
|
|
|
| 60 |
from autoteam.cpa_sync import sync_from_cpa, sync_main_codex_to_cpa, sync_to_cpa
|
| 61 |
from autoteam.textio import read_text, write_text
|
| 62 |
|
|
@@ -665,10 +666,7 @@ def _complete_registration(email, password, invite_link, mail_client):
|
|
| 665 |
|
| 666 |
logger.info("[注册] 开始注册 %s...", email)
|
| 667 |
with sync_playwright() as p:
|
| 668 |
-
browser = p.chromium.launch(
|
| 669 |
-
headless=False,
|
| 670 |
-
args=["--disable-blink-features=AutomationControlled", "--no-sandbox"],
|
| 671 |
-
)
|
| 672 |
context = browser.new_context(
|
| 673 |
viewport={"width": 1280, "height": 800},
|
| 674 |
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
|
@@ -1140,13 +1138,9 @@ def _register_direct_once(mail_client, email, password, cloudmail_account_id=Non
|
|
| 1140 |
signup_url = "https://chatgpt.com/auth/login"
|
| 1141 |
|
| 1142 |
with sync_playwright() as p:
|
| 1143 |
-
launch_kwargs =
|
| 1144 |
-
"headless": False,
|
| 1145 |
-
"args": ["--disable-blink-features=AutomationControlled", "--no-sandbox"],
|
| 1146 |
-
}
|
| 1147 |
if sys.platform.startswith("win"):
|
| 1148 |
launch_kwargs["slow_mo"] = 100
|
| 1149 |
-
|
| 1150 |
browser = p.chromium.launch(**launch_kwargs)
|
| 1151 |
context = browser.new_context(
|
| 1152 |
viewport={"width": 1280, "height": 800},
|
|
@@ -1503,10 +1497,7 @@ def reinvite_account(chatgpt_api, mail_client, acc):
|
|
| 1503 |
chatgpt_api.stop()
|
| 1504 |
|
| 1505 |
with sync_playwright() as p:
|
| 1506 |
-
browser = p.chromium.launch(
|
| 1507 |
-
headless=False,
|
| 1508 |
-
args=["--disable-blink-features=AutomationControlled", "--no-sandbox"],
|
| 1509 |
-
)
|
| 1510 |
context = browser.new_context(
|
| 1511 |
viewport={"width": 1280, "height": 800},
|
| 1512 |
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
|
|
|
| 57 |
refresh_main_auth_file,
|
| 58 |
save_auth_file,
|
| 59 |
)
|
| 60 |
+
from autoteam.config import get_playwright_launch_options
|
| 61 |
from autoteam.cpa_sync import sync_from_cpa, sync_main_codex_to_cpa, sync_to_cpa
|
| 62 |
from autoteam.textio import read_text, write_text
|
| 63 |
|
|
|
|
| 666 |
|
| 667 |
logger.info("[注册] 开始注册 %s...", email)
|
| 668 |
with sync_playwright() as p:
|
| 669 |
+
browser = p.chromium.launch(**get_playwright_launch_options())
|
|
|
|
|
|
|
|
|
|
| 670 |
context = browser.new_context(
|
| 671 |
viewport={"width": 1280, "height": 800},
|
| 672 |
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
|
|
|
| 1138 |
signup_url = "https://chatgpt.com/auth/login"
|
| 1139 |
|
| 1140 |
with sync_playwright() as p:
|
| 1141 |
+
launch_kwargs = get_playwright_launch_options()
|
|
|
|
|
|
|
|
|
|
| 1142 |
if sys.platform.startswith("win"):
|
| 1143 |
launch_kwargs["slow_mo"] = 100
|
|
|
|
| 1144 |
browser = p.chromium.launch(**launch_kwargs)
|
| 1145 |
context = browser.new_context(
|
| 1146 |
viewport={"width": 1280, "height": 800},
|
|
|
|
| 1497 |
chatgpt_api.stop()
|
| 1498 |
|
| 1499 |
with sync_playwright() as p:
|
| 1500 |
+
browser = p.chromium.launch(**get_playwright_launch_options())
|
|
|
|
|
|
|
|
|
|
| 1501 |
context = browser.new_context(
|
| 1502 |
viewport={"width": 1280, "height": 800},
|
| 1503 |
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
src/autoteam/setup_wizard.py
CHANGED
|
@@ -22,6 +22,8 @@ REQUIRED_CONFIGS = [
|
|
| 22 |
("CLOUDMAIL_DOMAIN", "CloudMail 邮箱域名(如 @example.com)", "", False),
|
| 23 |
("CPA_URL", "CPA (CLIProxyAPI) 地址", "http://127.0.0.1:8317", True),
|
| 24 |
("CPA_KEY", "CPA 管理密钥", "", False),
|
|
|
|
|
|
|
| 25 |
("API_KEY", "API 鉴权密钥(回车自动生成)", "", True),
|
| 26 |
]
|
| 27 |
|
|
@@ -79,7 +81,7 @@ def check_and_setup(interactive: bool = True) -> bool:
|
|
| 79 |
|
| 80 |
for key, prompt, default, optional in REQUIRED_CONFIGS:
|
| 81 |
val = env.get(key, "") or os.environ.get(key, "")
|
| 82 |
-
if not val:
|
| 83 |
missing.append((key, prompt, default, optional))
|
| 84 |
|
| 85 |
if not missing:
|
|
|
|
| 22 |
("CLOUDMAIL_DOMAIN", "CloudMail 邮箱域名(如 @example.com)", "", False),
|
| 23 |
("CPA_URL", "CPA (CLIProxyAPI) 地址", "http://127.0.0.1:8317", True),
|
| 24 |
("CPA_KEY", "CPA 管理密钥", "", False),
|
| 25 |
+
("PLAYWRIGHT_PROXY_URL", "Playwright 浏览器代理 URL(可选,如 socks5://host:port)", "", True),
|
| 26 |
+
("PLAYWRIGHT_PROXY_BYPASS", "Playwright 代理绕过列表(可选,如 localhost,127.0.0.1)", "", True),
|
| 27 |
("API_KEY", "API 鉴权密钥(回车自动生成)", "", True),
|
| 28 |
]
|
| 29 |
|
|
|
|
| 81 |
|
| 82 |
for key, prompt, default, optional in REQUIRED_CONFIGS:
|
| 83 |
val = env.get(key, "") or os.environ.get(key, "")
|
| 84 |
+
if not val and not optional:
|
| 85 |
missing.append((key, prompt, default, optional))
|
| 86 |
|
| 87 |
if not missing:
|