xiaoyukkkk commited on
Commit
2586f2a
·
verified ·
1 Parent(s): a54cca5

Upload 12 files

Browse files
Files changed (8) hide show
  1. .env.example +2 -23
  2. .gitignore +2 -0
  3. deploy.bat +121 -0
  4. deploy.sh +123 -0
  5. main.py +146 -3
  6. requirements.txt +18 -14
  7. update.bat +111 -0
  8. update.sh +104 -0
.env.example CHANGED
@@ -5,10 +5,6 @@
5
  # 管理员密钥(必需,用于登录管理面板)
6
  # 明文示例:
7
  ADMIN_KEY=your-admin-secret-key
8
- # Hash 示例(SHA256):ADMIN_KEY=sha256:你的32字节hex
9
-
10
- # API密钥(可选,用于API端点认证,优先级:环境变量 > settings.yaml)
11
- # API_KEY=your-api-key
12
 
13
  # 服务端口(可选,默认 7860)
14
  # PORT=7860
@@ -34,24 +30,7 @@ ADMIN_KEY=your-admin-secret-key
34
  # ============================================
35
  # 账户配置
36
  # ============================================
37
- # 方式1:使用 accounts.json 文件(推荐)
38
  # 账户配置保存在 accounts.json 文件中
39
  # 首次启动时会自动创建空配置
40
- # 请在管理面板中添加账户,或直接编辑 accounts.json
41
- #
42
- # 方式2:使用环境变量(适用于容器化部署,如抱脸等平台)
43
- # 设置 ACCOUNTS_CONFIG 环境变量,值为 JSON 数组字符串
44
- # 优先级:环境变量 > 文件
45
- #
46
- # ACCOUNTS_CONFIG='[{"id":"account_1","secure_c_ses":"your-cookie","csesidx":"your-idx","config_id":"your-config","expires_at":"2025-12-31 23:59:59"}]'
47
- #
48
- # 账户配置格式示例:
49
- # [
50
- # {
51
- # "id": "account_1",
52
- # "secure_c_ses": "your-cookie-here",
53
- # "csesidx": "your-idx",
54
- # "config_id": "your-config",
55
- # "expires_at": "2025-12-31 23:59:59"
56
- # }
57
- # ]
 
5
  # 管理员密钥(必需,用于登录管理面板)
6
  # 明文示例:
7
  ADMIN_KEY=your-admin-secret-key
 
 
 
 
8
 
9
  # 服务端口(可选,默认 7860)
10
  # PORT=7860
 
30
  # ============================================
31
  # 账户配置
32
  # ============================================
33
+ # 使用 accounts.json 文件
34
  # 账户配置保存在 accounts.json 文件中
35
  # 首次启动时会自动创建空配置
36
+ # 请在管理面板中添加账户,或直接编辑 accounts.json
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.gitignore CHANGED
@@ -39,7 +39,9 @@ ENV/
39
  # Generated files
40
  data/
41
  logs/
 
42
 
43
  # OS
44
  .DS_Store
45
  Thumbs.db
 
 
39
  # Generated files
40
  data/
41
  logs/
42
+ static/
43
 
44
  # OS
45
  .DS_Store
46
  Thumbs.db
47
+ old_version.py
deploy.bat ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @echo off
2
+ REM Gemini Business2API Deployment Script for Windows
3
+ REM This script automates the initial deployment process
4
+
5
+ setlocal enabledelayedexpansion
6
+
7
+ echo ==========================================
8
+ echo Gemini Business2API Deployment Script
9
+ echo ==========================================
10
+ echo.
11
+
12
+ REM Check if git is installed
13
+ where git >nul 2>nul
14
+ if %errorlevel% neq 0 (
15
+ echo [ERROR] Git is not installed. Please install git first.
16
+ exit /b 1
17
+ )
18
+
19
+ REM Check if python is installed
20
+ where python >nul 2>nul
21
+ if %errorlevel% neq 0 (
22
+ echo [ERROR] Python is not installed. Please install Python 3.11+ first.
23
+ exit /b 1
24
+ )
25
+
26
+ REM Check if npm is installed
27
+ where npm >nul 2>nul
28
+ if %errorlevel% neq 0 (
29
+ echo [ERROR] npm is not installed. Please install Node.js and npm first.
30
+ exit /b 1
31
+ )
32
+
33
+ REM Step 1: Build frontend
34
+ echo [STEP] Step 1: Building frontend...
35
+ if exist "frontend" (
36
+ cd frontend
37
+ echo [INFO] Installing frontend dependencies...
38
+ call npm install
39
+ if %errorlevel% neq 0 (
40
+ echo [ERROR] Failed to install frontend dependencies
41
+ exit /b 1
42
+ )
43
+
44
+ echo [INFO] Building frontend...
45
+ call npm run build
46
+ if %errorlevel% neq 0 (
47
+ echo [ERROR] Failed to build frontend
48
+ exit /b 1
49
+ )
50
+
51
+ echo [SUCCESS] Frontend built successfully
52
+ cd ..
53
+ ) else (
54
+ echo [ERROR] Frontend directory not found. Are you in the project root?
55
+ exit /b 1
56
+ )
57
+
58
+ REM Step 2: Create virtual environment
59
+ echo [STEP] Step 2: Setting up Python virtual environment...
60
+ if exist ".venv" (
61
+ echo [INFO] Virtual environment already exists, skipping creation
62
+ ) else (
63
+ echo [INFO] Creating virtual environment...
64
+ python -m venv .venv
65
+ if %errorlevel% neq 0 (
66
+ echo [ERROR] Failed to create virtual environment
67
+ exit /b 1
68
+ )
69
+ echo [SUCCESS] Virtual environment created
70
+ )
71
+
72
+ REM Activate virtual environment
73
+ echo [INFO] Activating virtual environment...
74
+ call .venv\Scripts\activate.bat
75
+
76
+ REM Step 3: Install Python dependencies
77
+ echo [STEP] Step 3: Installing Python dependencies...
78
+ python -m pip install --upgrade pip
79
+ python -m pip install -r requirements.txt
80
+ if %errorlevel% neq 0 (
81
+ echo [ERROR] Failed to install Python dependencies
82
+ exit /b 1
83
+ )
84
+ echo [SUCCESS] Python dependencies installed
85
+
86
+ REM Step 4: Setup .env file
87
+ echo [STEP] Step 4: Setting up configuration...
88
+ if exist ".env" (
89
+ echo [INFO] .env file already exists, skipping
90
+ ) else (
91
+ if exist ".env.example" (
92
+ copy /Y ".env.example" ".env" >nul
93
+ echo [SUCCESS] .env file created from .env.example
94
+ ) else (
95
+ echo [ERROR] .env.example not found
96
+ exit /b 1
97
+ )
98
+ )
99
+
100
+ REM Step 5: Show completion message
101
+ echo.
102
+ echo ==========================================
103
+ echo [SUCCESS] Deployment completed successfully!
104
+ echo ==========================================
105
+ echo.
106
+ echo [INFO] Next steps:
107
+ echo.
108
+ echo 1. Edit .env file and set your ADMIN_KEY:
109
+ echo notepad .env
110
+ echo.
111
+ echo 2. Start the service:
112
+ echo python main.py
113
+ echo.
114
+ echo 3. Access the admin panel:
115
+ echo http://localhost:7860/
116
+ echo.
117
+ echo [INFO] Optional: To activate virtual environment later, run:
118
+ echo .venv\Scripts\activate.bat
119
+ echo.
120
+
121
+ endlocal
deploy.sh ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ # Gemini Business2API Deployment Script for Linux/macOS
4
+ # This script automates the initial deployment process
5
+
6
+ set -e # Exit on error
7
+
8
+ echo "=========================================="
9
+ echo "Gemini Business2API Deployment Script"
10
+ echo "=========================================="
11
+ echo ""
12
+
13
+ # Color codes for output
14
+ RED='\033[0;31m'
15
+ GREEN='\033[0;32m'
16
+ YELLOW='\033[1;33m'
17
+ BLUE='\033[0;34m'
18
+ NC='\033[0m' # No Color
19
+
20
+ # Function to print colored messages
21
+ print_success() {
22
+ echo -e "${GREEN}[SUCCESS] $1${NC}"
23
+ }
24
+
25
+ print_error() {
26
+ echo -e "${RED}[ERROR] $1${NC}"
27
+ }
28
+
29
+ print_info() {
30
+ echo -e "${YELLOW}[INFO] $1${NC}"
31
+ }
32
+
33
+ print_step() {
34
+ echo -e "${BLUE}[STEP] $1${NC}"
35
+ }
36
+
37
+ # Check if git is installed
38
+ if ! command -v git &> /dev/null; then
39
+ print_error "Git is not installed. Please install git first."
40
+ exit 1
41
+ fi
42
+
43
+ # Check if python3 is installed
44
+ if ! command -v python3 &> /dev/null; then
45
+ print_error "Python3 is not installed. Please install Python 3.11+ first."
46
+ exit 1
47
+ fi
48
+
49
+ # Check if npm is installed
50
+ if ! command -v npm &> /dev/null; then
51
+ print_error "npm is not installed. Please install Node.js and npm first."
52
+ exit 1
53
+ fi
54
+
55
+ # Step 1: Build frontend
56
+ print_step "Step 1: Building frontend..."
57
+ if [ -d "frontend" ]; then
58
+ cd frontend
59
+ print_info "Installing frontend dependencies..."
60
+ npm install
61
+ print_info "Building frontend..."
62
+ npm run build
63
+ print_success "Frontend built successfully"
64
+ cd ..
65
+ else
66
+ print_error "Frontend directory not found. Are you in the project root?"
67
+ exit 1
68
+ fi
69
+
70
+ # Step 2: Create virtual environment
71
+ print_step "Step 2: Setting up Python virtual environment..."
72
+ if [ -d ".venv" ]; then
73
+ print_info "Virtual environment already exists, skipping creation"
74
+ else
75
+ print_info "Creating virtual environment..."
76
+ python3 -m venv .venv
77
+ print_success "Virtual environment created"
78
+ fi
79
+
80
+ # Activate virtual environment
81
+ print_info "Activating virtual environment..."
82
+ source .venv/bin/activate
83
+
84
+ # Step 3: Install Python dependencies
85
+ print_step "Step 3: Installing Python dependencies..."
86
+ pip install --upgrade pip
87
+ pip install -r requirements.txt
88
+ print_success "Python dependencies installed"
89
+
90
+ # Step 4: Setup .env file
91
+ print_step "Step 4: Setting up configuration..."
92
+ if [ -f ".env" ]; then
93
+ print_info ".env file already exists, skipping"
94
+ else
95
+ if [ -f ".env.example" ]; then
96
+ cp .env.example .env
97
+ print_success ".env file created from .env.example"
98
+ else
99
+ print_error ".env.example not found"
100
+ exit 1
101
+ fi
102
+ fi
103
+
104
+ # Step 5: Show completion message
105
+ echo ""
106
+ echo "=========================================="
107
+ print_success "Deployment completed successfully!"
108
+ echo "=========================================="
109
+ echo ""
110
+ print_info "Next steps:"
111
+ echo ""
112
+ echo " 1. Edit .env file and set your ADMIN_KEY:"
113
+ echo " ${BLUE}nano .env${NC} or ${BLUE}vim .env${NC}"
114
+ echo ""
115
+ echo " 2. Start the service:"
116
+ echo " ${BLUE}python main.py${NC}"
117
+ echo ""
118
+ echo " 3. Access the admin panel:"
119
+ echo " ${BLUE}http://localhost:7860/${NC}"
120
+ echo ""
121
+ print_info "Optional: To activate virtual environment later, run:"
122
+ echo " ${BLUE}source .venv/bin/activate${NC}"
123
+ echo ""
main.py CHANGED
@@ -321,6 +321,49 @@ multi_account_mgr = load_multi_account_config(
321
  global_stats
322
  )
323
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
  # 验证必需的环境变量
325
  if not ADMIN_KEY:
326
  logger.error("[SYSTEM] 未配置 ADMIN_KEY 环境变量,请设置后重启")
@@ -534,6 +577,16 @@ async def startup_event():
534
  elif storage.is_database_enabled():
535
  logger.info("[SYSTEM] 自动刷新账号功能已禁用(配置为0)")
536
 
 
 
 
 
 
 
 
 
 
 
537
  # ---------- 日志脱敏函数 ----------
538
  def get_sanitized_logs(limit: int = 100) -> list:
539
  """获取脱敏后的日志列表,按请求ID分组并提取关键事件"""
@@ -943,6 +996,70 @@ async def admin_update_config(request: Request, accounts_data: list = Body(...))
943
  logger.error(f"[CONFIG] 更新配置失败: {str(e)}")
944
  raise HTTPException(500, f"更新失败: {str(e)}")
945
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
946
  @app.delete("/admin/accounts/{account_id}")
947
  @require_login()
948
  async def admin_delete_account(request: Request, account_id: str):
@@ -1010,7 +1127,14 @@ async def admin_get_settings(request: Request):
1010
  "basic": {
1011
  "api_key": config.basic.api_key,
1012
  "base_url": config.basic.base_url,
1013
- "proxy": config.basic.proxy
 
 
 
 
 
 
 
1014
  },
1015
  "image_generation": {
1016
  "enabled": config.image_generation.enabled,
@@ -1023,7 +1147,8 @@ async def admin_get_settings(request: Request):
1023
  "max_account_switch_tries": config.retry.max_account_switch_tries,
1024
  "account_failure_threshold": config.retry.account_failure_threshold,
1025
  "rate_limit_cooldown_seconds": config.retry.rate_limit_cooldown_seconds,
1026
- "session_cache_ttl_seconds": config.retry.session_cache_ttl_seconds
 
1027
  },
1028
  "public_display": {
1029
  "logo_url": config.public_display.logo_url,
@@ -1041,10 +1166,23 @@ async def admin_update_settings(request: Request, new_settings: dict = Body(...)
1041
  global API_KEY, PROXY, BASE_URL, LOGO_URL, CHAT_URL
1042
  global IMAGE_GENERATION_ENABLED, IMAGE_GENERATION_MODELS
1043
  global MAX_NEW_SESSION_TRIES, MAX_REQUEST_RETRIES, MAX_ACCOUNT_SWITCH_TRIES
1044
- global ACCOUNT_FAILURE_THRESHOLD, RATE_LIMIT_COOLDOWN_SECONDS, SESSION_CACHE_TTL_SECONDS
1045
  global SESSION_EXPIRE_HOURS, multi_account_mgr, http_client
1046
 
1047
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
1048
  image_generation = dict(new_settings.get("image_generation") or {})
1049
  output_format = str(image_generation.get("output_format") or config_manager.image_output_format).lower()
1050
  if output_format not in ("base64", "url"):
@@ -1052,6 +1190,10 @@ async def admin_update_settings(request: Request, new_settings: dict = Body(...)
1052
  image_generation["output_format"] = output_format
1053
  new_settings["image_generation"] = image_generation
1054
 
 
 
 
 
1055
  # 保存旧配置用于对比
1056
  old_proxy = PROXY
1057
  old_retry_config = {
@@ -1080,6 +1222,7 @@ async def admin_update_settings(request: Request, new_settings: dict = Body(...)
1080
  ACCOUNT_FAILURE_THRESHOLD = config.retry.account_failure_threshold
1081
  RATE_LIMIT_COOLDOWN_SECONDS = config.retry.rate_limit_cooldown_seconds
1082
  SESSION_CACHE_TTL_SECONDS = config.retry.session_cache_ttl_seconds
 
1083
  SESSION_EXPIRE_HOURS = config.session.expire_hours
1084
 
1085
  # 检查是否需要重建 HTTP 客户端(代理变化)
 
321
  global_stats
322
  )
323
 
324
+ # ---------- 自动注册/刷新服务 ----------
325
+ register_service = None
326
+ login_service = None
327
+
328
+ def _set_multi_account_mgr(new_mgr):
329
+ global multi_account_mgr
330
+ multi_account_mgr = new_mgr
331
+ if register_service:
332
+ register_service.multi_account_mgr = new_mgr
333
+ if login_service:
334
+ login_service.multi_account_mgr = new_mgr
335
+
336
+ def _get_global_stats():
337
+ return global_stats
338
+
339
+ try:
340
+ from core.register_service import RegisterService
341
+ from core.login_service import LoginService
342
+ register_service = RegisterService(
343
+ multi_account_mgr,
344
+ http_client,
345
+ USER_AGENT,
346
+ ACCOUNT_FAILURE_THRESHOLD,
347
+ RATE_LIMIT_COOLDOWN_SECONDS,
348
+ SESSION_CACHE_TTL_SECONDS,
349
+ _get_global_stats,
350
+ _set_multi_account_mgr,
351
+ )
352
+ login_service = LoginService(
353
+ multi_account_mgr,
354
+ http_client,
355
+ USER_AGENT,
356
+ ACCOUNT_FAILURE_THRESHOLD,
357
+ RATE_LIMIT_COOLDOWN_SECONDS,
358
+ SESSION_CACHE_TTL_SECONDS,
359
+ _get_global_stats,
360
+ _set_multi_account_mgr,
361
+ )
362
+ except Exception as e:
363
+ logger.warning("[SYSTEM] 自动注册/刷新服务不可用: %s", e)
364
+ register_service = None
365
+ login_service = None
366
+
367
  # 验证必需的环境变量
368
  if not ADMIN_KEY:
369
  logger.error("[SYSTEM] 未配置 ADMIN_KEY 环境变量,请设置后重启")
 
577
  elif storage.is_database_enabled():
578
  logger.info("[SYSTEM] 自动刷新账号功能已禁用(配置为0)")
579
 
580
+ # 启动自动登录刷新轮询
581
+ if login_service:
582
+ try:
583
+ asyncio.create_task(login_service.start_polling())
584
+ logger.info("[SYSTEM] 账户过期检查轮询已启动(间隔: 30分钟)")
585
+ except Exception as e:
586
+ logger.error(f"[SYSTEM] 启动登录服务失败: {e}")
587
+ else:
588
+ logger.info("[SYSTEM] 自动登录刷新未启用或依赖不可用")
589
+
590
  # ---------- 日志脱敏函数 ----------
591
  def get_sanitized_logs(limit: int = 100) -> list:
592
  """获取脱敏后的日志列表,按请求ID分组并提取关键事件"""
 
996
  logger.error(f"[CONFIG] 更新配置失败: {str(e)}")
997
  raise HTTPException(500, f"更新失败: {str(e)}")
998
 
999
+ @app.post("/admin/register/start")
1000
+ @require_login()
1001
+ async def admin_start_register(request: Request, count: Optional[int] = Body(default=None), domain: Optional[str] = Body(default=None)):
1002
+ if not register_service:
1003
+ raise HTTPException(503, "register service unavailable")
1004
+ task = await register_service.start_register(count=count, domain=domain)
1005
+ return task.to_dict()
1006
+
1007
+ @app.get("/admin/register/task/{task_id}")
1008
+ @require_login()
1009
+ async def admin_get_register_task(request: Request, task_id: str):
1010
+ if not register_service:
1011
+ raise HTTPException(503, "register service unavailable")
1012
+ task = register_service.get_task(task_id)
1013
+ if not task:
1014
+ raise HTTPException(404, "task not found")
1015
+ return task.to_dict()
1016
+
1017
+ @app.get("/admin/register/current")
1018
+ @require_login()
1019
+ async def admin_get_current_register_task(request: Request):
1020
+ if not register_service:
1021
+ raise HTTPException(503, "register service unavailable")
1022
+ task = register_service.get_current_task()
1023
+ if not task:
1024
+ return {"status": "idle"}
1025
+ return task.to_dict()
1026
+
1027
+ @app.post("/admin/login/start")
1028
+ @require_login()
1029
+ async def admin_start_login(request: Request, account_ids: List[str] = Body(...)):
1030
+ if not login_service:
1031
+ raise HTTPException(503, "login service unavailable")
1032
+ task = await login_service.start_login(account_ids)
1033
+ return task.to_dict()
1034
+
1035
+ @app.get("/admin/login/task/{task_id}")
1036
+ @require_login()
1037
+ async def admin_get_login_task(request: Request, task_id: str):
1038
+ if not login_service:
1039
+ raise HTTPException(503, "login service unavailable")
1040
+ task = login_service.get_task(task_id)
1041
+ if not task:
1042
+ raise HTTPException(404, "task not found")
1043
+ return task.to_dict()
1044
+
1045
+ @app.get("/admin/login/current")
1046
+ @require_login()
1047
+ async def admin_get_current_login_task(request: Request):
1048
+ if not login_service:
1049
+ raise HTTPException(503, "login service unavailable")
1050
+ task = login_service.get_current_task()
1051
+ if not task:
1052
+ return {"status": "idle"}
1053
+ return task.to_dict()
1054
+
1055
+ @app.post("/admin/login/check")
1056
+ @require_login()
1057
+ async def admin_check_login_refresh(request: Request):
1058
+ if not login_service:
1059
+ raise HTTPException(503, "login service unavailable")
1060
+ await login_service.check_and_refresh()
1061
+ return {"status": "ok"}
1062
+
1063
  @app.delete("/admin/accounts/{account_id}")
1064
  @require_login()
1065
  async def admin_delete_account(request: Request, account_id: str):
 
1127
  "basic": {
1128
  "api_key": config.basic.api_key,
1129
  "base_url": config.basic.base_url,
1130
+ "proxy": config.basic.proxy,
1131
+ "duckmail_base_url": config.basic.duckmail_base_url,
1132
+ "duckmail_api_key": config.basic.duckmail_api_key,
1133
+ "duckmail_verify_ssl": config.basic.duckmail_verify_ssl,
1134
+ "browser_headless": config.basic.browser_headless,
1135
+ "refresh_window_hours": config.basic.refresh_window_hours,
1136
+ "register_default_count": config.basic.register_default_count,
1137
+ "register_domain": config.basic.register_domain,
1138
  },
1139
  "image_generation": {
1140
  "enabled": config.image_generation.enabled,
 
1147
  "max_account_switch_tries": config.retry.max_account_switch_tries,
1148
  "account_failure_threshold": config.retry.account_failure_threshold,
1149
  "rate_limit_cooldown_seconds": config.retry.rate_limit_cooldown_seconds,
1150
+ "session_cache_ttl_seconds": config.retry.session_cache_ttl_seconds,
1151
+ "auto_refresh_accounts_seconds": config.retry.auto_refresh_accounts_seconds
1152
  },
1153
  "public_display": {
1154
  "logo_url": config.public_display.logo_url,
 
1166
  global API_KEY, PROXY, BASE_URL, LOGO_URL, CHAT_URL
1167
  global IMAGE_GENERATION_ENABLED, IMAGE_GENERATION_MODELS
1168
  global MAX_NEW_SESSION_TRIES, MAX_REQUEST_RETRIES, MAX_ACCOUNT_SWITCH_TRIES
1169
+ global ACCOUNT_FAILURE_THRESHOLD, RATE_LIMIT_COOLDOWN_SECONDS, SESSION_CACHE_TTL_SECONDS, AUTO_REFRESH_ACCOUNTS_SECONDS
1170
  global SESSION_EXPIRE_HOURS, multi_account_mgr, http_client
1171
 
1172
  try:
1173
+ basic = dict(new_settings.get("basic") or {})
1174
+ basic.setdefault("duckmail_base_url", config.basic.duckmail_base_url)
1175
+ basic.setdefault("duckmail_api_key", config.basic.duckmail_api_key)
1176
+ basic.setdefault("duckmail_verify_ssl", config.basic.duckmail_verify_ssl)
1177
+ basic.setdefault("browser_headless", config.basic.browser_headless)
1178
+ basic.setdefault("refresh_window_hours", config.basic.refresh_window_hours)
1179
+ basic.setdefault("register_default_count", config.basic.register_default_count)
1180
+ basic.setdefault("register_domain", config.basic.register_domain)
1181
+ if not isinstance(basic.get("register_domain"), str):
1182
+ basic["register_domain"] = ""
1183
+ basic.pop("duckmail_proxy", None)
1184
+ new_settings["basic"] = basic
1185
+
1186
  image_generation = dict(new_settings.get("image_generation") or {})
1187
  output_format = str(image_generation.get("output_format") or config_manager.image_output_format).lower()
1188
  if output_format not in ("base64", "url"):
 
1190
  image_generation["output_format"] = output_format
1191
  new_settings["image_generation"] = image_generation
1192
 
1193
+ retry = dict(new_settings.get("retry") or {})
1194
+ retry.setdefault("auto_refresh_accounts_seconds", config.retry.auto_refresh_accounts_seconds)
1195
+ new_settings["retry"] = retry
1196
+
1197
  # 保存旧配置用于对比
1198
  old_proxy = PROXY
1199
  old_retry_config = {
 
1222
  ACCOUNT_FAILURE_THRESHOLD = config.retry.account_failure_threshold
1223
  RATE_LIMIT_COOLDOWN_SECONDS = config.retry.rate_limit_cooldown_seconds
1224
  SESSION_CACHE_TTL_SECONDS = config.retry.session_cache_ttl_seconds
1225
+ AUTO_REFRESH_ACCOUNTS_SECONDS = config.retry.auto_refresh_accounts_seconds
1226
  SESSION_EXPIRE_HOURS = config.session.expire_hours
1227
 
1228
  # 检查是否需要重建 HTTP 客户端(代理变化)
requirements.txt CHANGED
@@ -1,14 +1,18 @@
1
- fastapi==0.110.0
2
- uvicorn[standard]==0.29.0
3
- httpx==0.27.0
4
- pydantic==2.7.0
5
- aiofiles==24.1.0
6
- python-dotenv==1.0.1
7
- itsdangerous==2.1.2
8
- python-multipart==0.0.6
9
- pyyaml>=6.0
10
- jinja2>=3.1.0
11
-
12
- # 可选:PostgreSQL 数据库支持(用于 HF Spaces 等无持久化存储的环境)
13
- # 如需使用,请取消下行注释并设置 DATABASE_URL 环境变量
14
- asyncpg>=0.29.0
 
 
 
 
 
1
+ fastapi==0.110.0
2
+ uvicorn[standard]==0.29.0
3
+ httpx==0.27.0
4
+ pydantic==2.7.0
5
+ aiofiles==24.1.0
6
+ python-dotenv==1.0.1
7
+ itsdangerous==2.1.2
8
+ python-multipart==0.0.6
9
+ pyyaml>=6.0
10
+ jinja2>=3.1.0
11
+ requests==2.32.3
12
+ DrissionPage==4.0.5.6
13
+ undetected-chromedriver>=3.5.5
14
+ selenium>=4.15.0
15
+
16
+ # 可选:PostgreSQL 数据库支持(用于 HF Spaces 等无持久化存储的环境)
17
+ # 如需使用,请取消下行注释并设置 DATABASE_URL 环境变量
18
+ asyncpg>=0.29.0
update.bat ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @echo off
2
+ REM Gemini Business2API Update Script for Windows
3
+ REM This script updates the project to the latest version
4
+
5
+ setlocal enabledelayedexpansion
6
+
7
+ echo ==========================================
8
+ echo Gemini Business2API Update Script
9
+ echo ==========================================
10
+ echo.
11
+
12
+ REM Check if git is installed
13
+ where git >nul 2>nul
14
+ if %errorlevel% neq 0 (
15
+ echo [ERROR] Git is not installed. Please install git first.
16
+ exit /b 1
17
+ )
18
+
19
+ REM Check if python is installed
20
+ where python >nul 2>nul
21
+ if %errorlevel% neq 0 (
22
+ echo [ERROR] Python is not installed. Please install Python 3.11+ first.
23
+ exit /b 1
24
+ )
25
+
26
+ REM Step 1: Backup current .env file
27
+ echo [INFO] Backing up .env file...
28
+ if exist ".env" (
29
+ copy /Y ".env" ".env.backup" >nul
30
+ echo [SUCCESS] .env backed up to .env.backup
31
+ ) else (
32
+ echo [INFO] No .env file found, skipping backup
33
+ )
34
+
35
+ REM Step 2: Pull latest code from git
36
+ echo [INFO] Pulling latest code from git...
37
+ git fetch origin
38
+ git pull origin main 2>nul
39
+ if %errorlevel% neq 0 (
40
+ git pull origin master 2>nul
41
+ if %errorlevel% neq 0 (
42
+ echo [ERROR] Failed to pull latest code
43
+ exit /b 1
44
+ )
45
+ )
46
+ echo [SUCCESS] Code updated successfully
47
+
48
+ REM Step 3: Restore .env file
49
+ if exist ".env.backup" (
50
+ echo [INFO] Restoring .env file...
51
+ move /Y ".env.backup" ".env" >nul
52
+ echo [SUCCESS] .env restored
53
+ )
54
+
55
+ REM Step 4: Update Python dependencies
56
+ echo [INFO] Updating Python dependencies...
57
+
58
+ REM Check if virtual environment exists
59
+ if exist ".venv\Scripts\activate.bat" (
60
+ echo [INFO] Virtual environment detected, activating...
61
+ call .venv\Scripts\activate.bat
62
+ )
63
+
64
+ python -m pip install -r requirements.txt --upgrade
65
+ if %errorlevel% neq 0 (
66
+ echo [ERROR] Failed to update Python dependencies
67
+ exit /b 1
68
+ )
69
+ echo [SUCCESS] Python dependencies updated
70
+
71
+ REM Step 5: Update frontend dependencies
72
+ if exist "frontend" (
73
+ echo [INFO] Updating frontend dependencies...
74
+ cd frontend
75
+
76
+ REM Check if npm is installed
77
+ where npm >nul 2>nul
78
+ if %errorlevel% equ 0 (
79
+ call npm install
80
+ if %errorlevel% equ 0 (
81
+ call npm run build
82
+ if %errorlevel% equ 0 (
83
+ echo [SUCCESS] Frontend dependencies updated and built
84
+ ) else (
85
+ echo [ERROR] Frontend build failed
86
+ )
87
+ ) else (
88
+ echo [ERROR] npm install failed
89
+ )
90
+ ) else (
91
+ echo [WARNING] npm is not installed. Skipping frontend update.
92
+ )
93
+
94
+ cd ..
95
+ )
96
+
97
+ REM Step 6: Show completion message
98
+ echo.
99
+ echo ==========================================
100
+ echo [SUCCESS] Update completed successfully!
101
+ echo ==========================================
102
+ echo.
103
+ echo [INFO] To restart the service, run:
104
+ echo python main.py
105
+ echo.
106
+ echo [INFO] Or if running as a Windows service:
107
+ echo net stop gemini-business2api
108
+ echo net start gemini-business2api
109
+ echo.
110
+
111
+ endlocal
update.sh ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ # Gemini Business2API Update Script for Linux/macOS
4
+ # This script updates the project to the latest version
5
+
6
+ set -e # Exit on error
7
+
8
+ echo "=========================================="
9
+ echo "Gemini Business2API Update Script"
10
+ echo "=========================================="
11
+ echo ""
12
+
13
+ # Color codes for output
14
+ RED='\033[0;31m'
15
+ GREEN='\033[0;32m'
16
+ YELLOW='\033[1;33m'
17
+ NC='\033[0m' # No Color
18
+
19
+ # Function to print colored messages
20
+ print_success() {
21
+ echo -e "${GREEN}✓ $1${NC}"
22
+ }
23
+
24
+ print_error() {
25
+ echo -e "${RED}✗ $1${NC}"
26
+ }
27
+
28
+ print_info() {
29
+ echo -e "${YELLOW}→ $1${NC}"
30
+ }
31
+
32
+ # Check if git is installed
33
+ if ! command -v git &> /dev/null; then
34
+ print_error "Git is not installed. Please install git first."
35
+ exit 1
36
+ fi
37
+
38
+ # Check if python3 is installed
39
+ if ! command -v python3 &> /dev/null; then
40
+ print_error "Python3 is not installed. Please install Python 3.11+ first."
41
+ exit 1
42
+ fi
43
+
44
+ # Step 1: Backup current .env file
45
+ print_info "Backing up .env file..."
46
+ if [ -f ".env" ]; then
47
+ cp .env .env.backup
48
+ print_success ".env backed up to .env.backup"
49
+ else
50
+ print_info "No .env file found, skipping backup"
51
+ fi
52
+
53
+ # Step 2: Pull latest code from git
54
+ print_info "Pulling latest code from git..."
55
+ git fetch origin
56
+ git pull origin main || git pull origin master
57
+ print_success "Code updated successfully"
58
+
59
+ # Step 3: Restore .env file
60
+ if [ -f ".env.backup" ]; then
61
+ print_info "Restoring .env file..."
62
+ mv .env.backup .env
63
+ print_success ".env restored"
64
+ fi
65
+
66
+ # Step 4: Update Python dependencies
67
+ print_info "Updating Python dependencies..."
68
+ if [ -d ".venv" ]; then
69
+ print_info "Virtual environment detected, activating..."
70
+ source .venv/bin/activate
71
+ fi
72
+
73
+ pip install -r requirements.txt --upgrade
74
+ print_success "Python dependencies updated"
75
+
76
+ # Step 5: Update frontend dependencies
77
+ if [ -d "frontend" ]; then
78
+ print_info "Updating frontend dependencies..."
79
+ cd frontend
80
+
81
+ # Check if npm is installed
82
+ if command -v npm &> /dev/null; then
83
+ npm install
84
+ npm run build
85
+ print_success "Frontend dependencies updated and built"
86
+ else
87
+ print_error "npm is not installed. Skipping frontend update."
88
+ fi
89
+
90
+ cd ..
91
+ fi
92
+
93
+ # Step 6: Show completion message
94
+ echo ""
95
+ echo "=========================================="
96
+ print_success "Update completed successfully!"
97
+ echo "=========================================="
98
+ echo ""
99
+ print_info "To restart the service, run:"
100
+ echo " python main.py"
101
+ echo ""
102
+ print_info "Or if using systemd:"
103
+ echo " sudo systemctl restart gemini-business2api"
104
+ echo ""