Merge pull request #111 from openChatGpts/master

fixbug: 在 f-string 中统一使用单引号替代双引号,避免嵌套引号问题
This commit is contained in:
演变
2026-03-28 00:47:37 +08:00
committed by GitHub
9 changed files with 117 additions and 32 deletions

View File

@@ -5,8 +5,8 @@
# 监听主机(默认 0.0.0.0
# APP_HOST=0.0.0.0
# 监听端口(默认 8000
# APP_PORT=8000
# 监听端口(默认 15555
# APP_PORT=15555
# Web UI 访问密钥(默认 admin123强烈建议修改
# APP_ACCESS_PASSWORD=your_secret_password

View File

@@ -4,12 +4,14 @@ FROM python:3.11-slim
# 设置工作目录
WORKDIR /app
ARG DEFAULT_WEBUI_PORT=15555
# 设置环境变量
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
# WebUI 默认配置
WEBUI_HOST=0.0.0.0 \
WEBUI_PORT=15555 \
WEBUI_PORT=${DEFAULT_WEBUI_PORT} \
LOG_LEVEL=info \
DEBUG=0
@@ -30,7 +32,7 @@ RUN pip install --no-cache-dir --upgrade pip \
COPY . .
# 暴露端口
EXPOSE 15555
EXPOSE ${DEFAULT_WEBUI_PORT}
# 启动 WebUI
CMD ["python", "webui.py"]

View File

@@ -104,6 +104,20 @@ cp .env.example .env
> 优先级:命令行参数 > 环境变量(`.env`> 数据库设置 > 默认值
### 修改端口
默认端口是 `15555`。现在已经收敛到少数几个固定入口:
- 本地临时启动改端口:直接用 `python webui.py --port 18080`
- 本地通过 `.env` 改端口:设置 `APP_PORT=18080`
- 源码里的默认端口:修改 `src/config/constants.py` 里的 `DEFAULT_WEBUI_PORT`
- Docker Compose 默认端口:修改 `docker-compose.yml` 顶部的 `x-webui-port`
- Docker 镜像构建默认端口:修改 `Dockerfile` 里的 `ARG DEFAULT_WEBUI_PORT`
补充说明:
- `src/config/constants.py``DEFAULT_WEBUI_PORT` 会同时影响默认 Web UI 端口、默认回调地址和 e2e 脚本默认地址。
- `docker-compose.yml` 里已经把端口映射、容器内 `WEBUI_PORT` 和健康检查统一绑到同一个 `x-webui-port`,改一处就够。
### 启动 Web UI
```bash
@@ -141,6 +155,18 @@ docker-compose up -d
```
你可以在 `docker-compose.yml` 中修改相关的环境变量,例如配置端口或者设置 `WEBUI_ACCESS_PASSWORD` 访问密码。
如果要修改 Docker Compose 对外端口,直接改文件顶部这一行即可:
```yaml
x-webui-port: &webui-port 15555
```
这一个值会同时同步到:
- 宿主机端口映射
- 容器内 `WEBUI_PORT`
- 健康检查访问地址
#### 直接使用 docker run
如果你不想使用 docker-compose也可以直接拉取并运行镜像
@@ -165,6 +191,19 @@ docker run -d \
> **注意**`-v $(pwd)/data:/app/data` 挂载参数非常重要,它确保了你的数据库文件和账户信息在容器重启或更新后不会丢失。
如果你要把容器端口改成 `18080``-p``WEBUI_PORT` 需要一起改:
```bash
docker run -d \
-p 18080:18080 \
-e WEBUI_HOST=0.0.0.0 \
-e WEBUI_PORT=18080 \
-e WEBUI_ACCESS_PASSWORD=your_secure_password \
-v $(pwd)/data:/app/data \
--name codex-register \
ghcr.io/yunxilyf/codex-register:latest
```
### 使用远程 PostgreSQL
通过环境变量指定数据库连接字符串:
@@ -335,7 +374,7 @@ docker-compose up -d
### 配置说明
**端口映射**:默认 `15555` 端口,可在 `docker-compose.yml` 中修改
**端口映射**:默认 `15555` 端口,修改 `docker-compose.yml` 顶部的 `x-webui-port` 即可
**数据持久化**
```yaml
@@ -347,9 +386,9 @@ volumes:
**环境变量配置**
```yaml
environment:
- APP_ACCESS_PASSWORD=mypassword
- APP_HOST=0.0.0.0
- APP_PORT=15555
WEBUI_ACCESS_PASSWORD: mypassword
WEBUI_HOST: 0.0.0.0
WEBUI_PORT: 15555
```
### 常用命令

View File

@@ -1,24 +1,26 @@
x-webui-port: &webui-port 15555
services:
webui:
build: .
ports:
- "15555:15555"
- target: *webui-port
published: *webui-port
protocol: tcp
environment:
- WEBUI_HOST=0.0.0.0
- WEBUI_PORT=15555
- WEBUI_ACCESS_PASSWORD=admin123
- DEBUG=0
- LOG_LEVEL=info
WEBUI_HOST: 0.0.0.0
WEBUI_PORT: *webui-port
WEBUI_ACCESS_PASSWORD: admin123
DEBUG: 0
LOG_LEVEL: info
volumes:
# 挂载数据目录以持久化数据库和日志
- ./data:/app/data
- ./logs:/app/logs
healthcheck:
test:
- CMD
- python
- -c
- import urllib.request; urllib.request.urlopen('http://127.0.0.1:15555/', timeout=5).read()
- CMD-SHELL
- python -c "import os, urllib.request; urllib.request.urlopen('http://127.0.0.1:' + os.environ['WEBUI_PORT'] + '/', timeout=5).read()"
interval: 10s
timeout: 5s
retries: 5

View File

@@ -48,6 +48,25 @@ class EmailServiceType(str, Enum):
APP_NAME = "OpenAI/Codex CLI 自动注册系统"
APP_VERSION = "2.0.0"
APP_DESCRIPTION = "自动注册 OpenAI/Codex CLI 账号的系统"
DEFAULT_WEBUI_HOST = "0.0.0.0"
DEFAULT_WEBUI_PORT = 15555
DEFAULT_WEBUI_LOCAL_HOST = "127.0.0.1"
def build_http_url(host: str, port: int, path: str = "") -> str:
"""构造本地 HTTP URL。"""
normalized_path = path if not path or path.startswith("/") else f"/{path}"
return f"http://{host}:{port}{normalized_path}"
def build_ws_url(host: str, port: int, path: str = "") -> str:
"""构造本地 WebSocket URL。"""
normalized_path = path if not path or path.startswith("/") else f"/{path}"
return f"ws://{host}:{port}{normalized_path}"
DEFAULT_WEBUI_BASE_URL = build_http_url(DEFAULT_WEBUI_LOCAL_HOST, DEFAULT_WEBUI_PORT)
DEFAULT_WEBUI_WS_BASE_URL = build_ws_url(DEFAULT_WEBUI_LOCAL_HOST, DEFAULT_WEBUI_PORT)
# ============================================================================
# OpenAI OAuth 相关常量
@@ -57,7 +76,7 @@ APP_DESCRIPTION = "自动注册 OpenAI/Codex CLI 账号的系统"
OAUTH_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann"
OAUTH_AUTH_URL = "https://auth.openai.com/oauth/authorize"
OAUTH_TOKEN_URL = "https://auth.openai.com/oauth/token"
OAUTH_REDIRECT_URI = "http://localhost:15555/auth/callback"
OAUTH_REDIRECT_URI = build_http_url("localhost", DEFAULT_WEBUI_PORT, "/auth/callback")
OAUTH_SCOPE = "openid email profile offline_access"
# Codex CLI 专用 OAuth 参数(用于生成 Codex 兼容的 auth.json
@@ -280,8 +299,8 @@ DEFAULT_SETTINGS = [
("registration.max_retries", "3", "最大重试次数", "registration"),
("registration.timeout", "120", "超时时间(秒)", "registration"),
("registration.default_password_length", "12", "默认密码长度", "registration"),
("webui.host", "0.0.0.0", "Web UI 监听主机", "webui"),
("webui.port", "15555", "Web UI 监听端口", "webui"),
("webui.host", DEFAULT_WEBUI_HOST, "Web UI 监听主机", "webui"),
("webui.port", str(DEFAULT_WEBUI_PORT), "Web UI 监听端口", "webui"),
("webui.debug", "true", "调试模式", "webui"),
]

View File

@@ -10,6 +10,8 @@ from pydantic import BaseModel, field_validator
from pydantic.types import SecretStr
from dataclasses import dataclass
from .constants import APP_NAME, APP_VERSION, DEFAULT_WEBUI_HOST, DEFAULT_WEBUI_PORT
class SettingCategory(str, Enum):
"""设置分类"""
@@ -42,13 +44,13 @@ SETTING_DEFINITIONS: Dict[str, SettingDefinition] = {
# 应用信息
"app_name": SettingDefinition(
db_key="app.name",
default_value="OpenAI/Codex CLI 自动注册系统",
default_value=APP_NAME,
category=SettingCategory.GENERAL,
description="应用名称"
),
"app_version": SettingDefinition(
db_key="app.version",
default_value="2.0.0",
default_value=APP_VERSION,
category=SettingCategory.GENERAL,
description="应用版本"
),
@@ -70,13 +72,13 @@ SETTING_DEFINITIONS: Dict[str, SettingDefinition] = {
# Web UI 配置
"webui_host": SettingDefinition(
db_key="webui.host",
default_value="0.0.0.0",
default_value=DEFAULT_WEBUI_HOST,
category=SettingCategory.WEBUI,
description="Web UI 监听地址"
),
"webui_port": SettingDefinition(
db_key="webui.port",
default_value=15555,
default_value=DEFAULT_WEBUI_PORT,
category=SettingCategory.WEBUI,
description="Web UI 监听端口"
),
@@ -584,8 +586,8 @@ class Settings(BaseModel):
"""
# 应用信息
app_name: str = "OpenAI/Codex CLI 自动注册系统"
app_version: str = "2.0.0"
app_name: str = APP_NAME
app_version: str = APP_VERSION
debug: bool = False
# 数据库配置
@@ -608,8 +610,8 @@ class Settings(BaseModel):
return v
# Web UI 配置
webui_host: str = "0.0.0.0"
webui_port: int = 15555
webui_host: str = DEFAULT_WEBUI_HOST
webui_port: int = DEFAULT_WEBUI_PORT
webui_secret_key: SecretStr = SecretStr("your-secret-key-change-in-production")
webui_access_password: SecretStr = SecretStr("admin123")

View File

@@ -202,7 +202,7 @@ def generate_team_link(
"&elements_session_client[is_aggregation_expected]=false"
"&client_attribution_metadata[merchant_integration_additional_elements][0]=payment"
"&client_attribution_metadata[merchant_integration_additional_elements][1]=address"
f"&key={data["publishable_key"]}"
f"&key={data['publishable_key']}"
,
proxies=_build_proxies(proxy),
timeout=30,

View File

@@ -10,6 +10,8 @@ from typing import Any, Dict, List
import httpx
import websockets
from src.config.constants import DEFAULT_WEBUI_BASE_URL, DEFAULT_WEBUI_WS_BASE_URL
STALE_ERROR = "服务启动时检测到未完成的历史任务,已标记失败,请重新发起。"
@@ -254,8 +256,8 @@ def run_verify_recovery_mode(base_url: str, db_path: Path, state_path: Path, rep
def main() -> None:
parser = argparse.ArgumentParser(description="真实服务功能可用性验证脚本")
parser.add_argument("--mode", choices=["live", "prepare-recovery", "verify-recovery"], required=True)
parser.add_argument("--base-url", default="http://127.0.0.1:15555")
parser.add_argument("--ws-url", default="ws://127.0.0.1:15555")
parser.add_argument("--base-url", default=DEFAULT_WEBUI_BASE_URL)
parser.add_argument("--ws-url", default=DEFAULT_WEBUI_WS_BASE_URL)
parser.add_argument("--db-path", required=True)
parser.add_argument("--report-path", default="tests_runtime/runtime_functionality_report.json")
parser.add_argument("--state-path", default="tests_runtime/runtime_recovery_state.json")

View File

@@ -0,0 +1,19 @@
from src.config.constants import (
DEFAULT_SETTINGS,
DEFAULT_WEBUI_BASE_URL,
DEFAULT_WEBUI_PORT,
DEFAULT_WEBUI_WS_BASE_URL,
OAUTH_REDIRECT_URI,
)
from src.config.settings import SETTING_DEFINITIONS, Settings
def test_default_webui_port_is_shared_from_one_constant():
default_settings_map = {key: value for key, value, *_ in DEFAULT_SETTINGS}
assert SETTING_DEFINITIONS["webui_port"].default_value == DEFAULT_WEBUI_PORT
assert Settings().webui_port == DEFAULT_WEBUI_PORT
assert default_settings_map["webui.port"] == str(DEFAULT_WEBUI_PORT)
assert DEFAULT_WEBUI_BASE_URL == f"http://127.0.0.1:{DEFAULT_WEBUI_PORT}"
assert DEFAULT_WEBUI_WS_BASE_URL == f"ws://127.0.0.1:{DEFAULT_WEBUI_PORT}"
assert OAUTH_REDIRECT_URI == f"http://localhost:{DEFAULT_WEBUI_PORT}/auth/callback"