gemini-proxy-client 1.0.11 → 1.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,13 +6,13 @@
6
6
 
7
7
  - **反指纹检测**: 使用 Camoufox (基于 Firefox) 防止 Google 检测多账号
8
8
  - **自动登录管理**: 首次需要手动登录,之后自动保持登录状态
9
+ - **自动连接**: 自动点击 "Continue to the app" 和 "Connect WS" 按钮
10
+ - **连接验证**: 自动检测 WebSocket 连接是否成功(按钮文字变为 "Disconnect WS")
9
11
  - **自动保活**: 每 2 小时检查登录状态,断线自动重连
10
12
  - **无头运行**: 登录后可在后台无头运行,节省资源
11
13
 
12
14
  ## 安装
13
15
 
14
- ### 方式 1: 从 npm 安装(推荐)
15
-
16
16
  ```bash
17
17
  npm install -g gemini-proxy-client
18
18
  ```
@@ -23,19 +23,9 @@ npm install -g gemini-proxy-client
23
23
  npx camoufox-js fetch
24
24
  ```
25
25
 
26
- ### 方式 2: 从源码安装
27
-
28
- ```bash
29
- git clone https://github.com/user/gemini-proxy-panel.git
30
- cd gemini-proxy-panel/client
31
- npm install
32
- npm run build
33
- npm link # 可选,全局安装
34
- ```
35
-
36
26
  ## 使用方法
37
27
 
38
- ### 1. 启动客户端
28
+ ### 启动客户端
39
29
 
40
30
  ```bash
41
31
  # 连接到代理服务器
@@ -47,17 +37,81 @@ gemini-client start -s wss://your-server.com/v1/ws
47
37
 
48
38
  **首次运行**会打开浏览器窗口,请登录您的 Google 账号。登录成功后,cookies 会自动保存,之后运行将使用无头模式。
49
39
 
50
- ### 2. 指定 Token
40
+ **成功启动**后会显示:
41
+
42
+ ```
43
+ ✅ 点击了 "Continue to the app" 按钮
44
+ ✅ 点击了连接按钮
45
+ 检测按钮文字: "Disconnect WS"
46
+ ✅ WebSocket 连接成功!
47
+ ```
48
+
49
+ ### 后台运行
50
+
51
+ #### 方式 1: 使用 nohup(简单)
51
52
 
52
53
  ```bash
53
- # 不指定 token 会自动生成 gp_client_YYYY_MM_DD_HH_mm_ss 格式
54
- gemini-client start -s wss://your-server.com/v1/ws
54
+ nohup gemini-client start -s wss://your-server.com/v1/ws > gemini-client.log 2>&1 &
55
+
56
+ # 查看日志
57
+ tail -f gemini-client.log
55
58
 
56
- # 指定自定义 token
57
- gemini-client start -s wss://your-server.com/v1/ws -t my-custom-token
59
+ # 停止
60
+ kill $(ps aux | grep 'gemini-client start' | grep -v grep | awk '{print $2}')
58
61
  ```
59
62
 
60
- ### 3. 其他命令
63
+ #### 方式 2: 使用 screen
64
+
65
+ ```bash
66
+ # 安装 screen
67
+ sudo apt-get install screen # Ubuntu/Debian
68
+ sudo yum install screen # CentOS/RHEL
69
+
70
+ # 创建会话并运行
71
+ screen -S gemini
72
+ gemini-client start
73
+
74
+ # 按 Ctrl+A 然后按 D 分离会话
75
+ # 重新连接: screen -r gemini
76
+ # 查看所有会话: screen -ls
77
+ ```
78
+
79
+ #### 方式 3: 使用 pm2(推荐)
80
+
81
+ ```bash
82
+ # 安装 pm2
83
+ npm install -g pm2
84
+
85
+ # 启动
86
+ pm2 start "gemini-client start" --name gemini-client
87
+
88
+ # 查看日志
89
+ pm2 logs gemini-client
90
+
91
+ # 停止
92
+ pm2 stop gemini-client
93
+
94
+ # 重启
95
+ pm2 restart gemini-client
96
+
97
+ # 开机自启
98
+ pm2 startup
99
+ pm2 save
100
+ ```
101
+
102
+ #### 方式 4: 使用 Xvfb(无图形界面服务器)
103
+
104
+ 如果是纯命令行服务器,需要安装虚拟显示:
105
+
106
+ ```bash
107
+ # Ubuntu/Debian
108
+ sudo apt-get install xvfb
109
+
110
+ # 使用 xvfb-run 运行
111
+ nohup xvfb-run gemini-client start -s wss://your-server.com/v1/ws > gemini-client.log 2>&1 &
112
+ ```
113
+
114
+ ### 其他命令
61
115
 
62
116
  ```bash
63
117
  # 单独登录 Google 账号
@@ -77,42 +131,14 @@ gemini-client --help
77
131
 
78
132
  ### start - 启动客户端
79
133
 
80
- ```bash
81
- gemini-client start [options]
82
- ```
83
-
84
134
  | 选项 | 说明 | 默认值 |
85
135
  |------|------|--------|
86
136
  | `-s, --server <url>` | 代理服务器 WebSocket 地址 | `ws://localhost:5345/v1/ws` |
87
- | `-t, --token <token>` | 客户端认证令牌 | 自动生成 |
137
+ | `-t, --token <token>` | 客户端认证令牌 | 自动生成 `gp_client_YYYY_MM_DD_HH_mm_ss` |
88
138
  | `-d, --daemon` | 后台运行模式 | false |
89
139
  | `--headless` | 强制无头模式 | 自动判断 |
90
140
  | `--data-dir <path>` | 数据目录路径 | `~/.gemini-client` |
91
141
 
92
- ### login - 登录 Google
93
-
94
- ```bash
95
- gemini-client login [options]
96
- ```
97
-
98
- 打开浏览器让用户登录 Google 账号,保存 cookies 供后续使用。
99
-
100
- ### status - 查看状态
101
-
102
- ```bash
103
- gemini-client status [options]
104
- ```
105
-
106
- 显示当前登录状态和配置信息。
107
-
108
- ### logout - 清除登录
109
-
110
- ```bash
111
- gemini-client logout [options]
112
- ```
113
-
114
- 清除保存的 Google 登录 cookies。
115
-
116
142
  ## 数据存储
117
143
 
118
144
  默认数据目录: `~/.gemini-client/`
@@ -122,10 +148,21 @@ gemini-client logout [options]
122
148
  | `cookies.json` | Google 登录 cookies |
123
149
  | `config.json` | 配置信息 |
124
150
 
151
+ ## 工作流程
152
+
153
+ 1. 启动 Camoufox 浏览器
154
+ 2. 打开 Build App 页面
155
+ 3. 检查 Google 登录状态,未登录则等待用户手动登录
156
+ 4. 点击 "Continue to the app" 按钮(如果存在)
157
+ 5. 关闭可能遮挡的模态框
158
+ 6. 在 Build App iframe 中点击 "Connect WS" 按钮
159
+ 7. 验证连接成功(按钮文字变为 "Disconnect WS")
160
+ 8. 启动保活机制(每 2 小时检查登录状态)
161
+
125
162
  ## 保活机制
126
163
 
127
164
  - **登录状态检查**: 每 2 小时检查一次 Google 登录状态
128
- - **连接状态检查**: 每 30 秒检查一次 WebSocket 连接
165
+ - **连接状态检查**: 每 30 秒检查一次页面是否正常
129
166
  - **自动重连**: 连接断开时自动尝试重新连接
130
167
  - **登录过期处理**: 登录过期时会弹出浏览器让用户重新登录
131
168
 
@@ -134,39 +171,36 @@ gemini-client logout [options]
134
171
  - Node.js >= 18.0.0
135
172
  - 能够访问 GitHub(下载 Camoufox 浏览器)
136
173
  - 能够访问 Google AI Studio(非中国大陆 IP)
174
+ - 图形界面或 Xvfb(虚拟显示)
137
175
 
138
176
  ## 常见问题
139
177
 
140
178
  ### Q: Camoufox 下载失败怎么办?
141
179
 
142
- A: 可能是网络问题,尝试使用代理或手动下载:
180
+ 设置代理或手动下载:
143
181
 
144
182
  ```bash
145
- # 设置代理
146
183
  export https_proxy=http://127.0.0.1:7890
147
-
148
- # 重新下载
149
184
  npx camoufox-js fetch
150
185
  ```
151
186
 
152
187
  ### Q: Google 登录状态能保持多久?
153
188
 
154
- A: 通常 1-2 周,但可能因以下原因提前失效:
155
- - IP 地址变化
156
- - 长时间无活动
157
- - Google 安全检测
158
-
159
- 客户端会每 2 小时检查一次,失效时会提示重新登录。
189
+ 通常 1-2 周,但可能因 IP 变化、长时间无活动或 Google 安全检测而提前失效。
160
190
 
161
191
  ### Q: 可以同时运行多个客户端吗?
162
192
 
163
- A: 可以,使用不同的 `--data-dir` 参数:
193
+ 可以,使用不同的 `--data-dir` 参数:
164
194
 
165
195
  ```bash
166
196
  gemini-client start -s wss://server.com/v1/ws --data-dir ~/.gemini-client-1
167
197
  gemini-client start -s wss://server.com/v1/ws --data-dir ~/.gemini-client-2
168
198
  ```
169
199
 
200
+ ### Q: 如何查看客户端是否连接成功?
201
+
202
+ 启动后查看日志,如果看到 `✅ WebSocket 连接成功!` 和 `检测按钮文字: "Disconnect WS"`,说明连接成功。
203
+
170
204
  ## License
171
205
 
172
206
  MIT
@@ -2,7 +2,7 @@ import { Camoufox } from 'camoufox-js';
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
4
  import chalk from 'chalk';
5
- import { sleep, formatUptime } from '../utils/helpers.js';
5
+ import { sleep, formatUptime, getRandomFingerprint } from '../utils/helpers.js';
6
6
  // Build App URL
7
7
  const BUILD_APP_URL = 'https://aistudio.google.com/apps/drive/1JqM2cAKs9japdW99aJwkg2k6GZSeCSHR?showPreview=true&pli=1&showAssistant=true';
8
8
  const GOOGLE_LOGIN_URL = 'https://accounts.google.com/';
@@ -28,12 +28,16 @@ export class BrowserManager {
28
28
  * 启动浏览器
29
29
  */
30
30
  async launch() {
31
+ // 获取随机指纹配置(同一 dataDir 会保持一致)
32
+ const fingerprint = getRandomFingerprint(this.options.dataDir);
33
+ console.log(chalk.gray(`指纹配置: ${fingerprint.viewport.width}x${fingerprint.viewport.height}, ${fingerprint.locale}, ${fingerprint.timezoneId}`));
31
34
  this.browser = await Camoufox({
32
35
  headless: this.options.headless,
33
36
  });
34
37
  this.context = await this.browser.newContext({
35
- viewport: { width: 1280, height: 800 },
36
- locale: 'en-US',
38
+ viewport: fingerprint.viewport,
39
+ locale: fingerprint.locale,
40
+ timezoneId: fingerprint.timezoneId,
37
41
  });
38
42
  // 加载已保存的 cookies
39
43
  await this.loadCookies();
package/dist/cli.js CHANGED
@@ -12,7 +12,7 @@ const program = new Command();
12
12
  program
13
13
  .name('gemini-client')
14
14
  .description('Gemini Proxy Build App 客户端 - 使用 Camoufox 自动保持连接')
15
- .version('1.0.11');
15
+ .version('1.0.13');
16
16
  program
17
17
  .command('start')
18
18
  .description('启动客户端,连接到代理服务器')
@@ -79,7 +79,7 @@ export async function startClient(options) {
79
79
  }
80
80
  const spinner = ora('启动 Camoufox 浏览器...').start();
81
81
  try {
82
- const browserManager = new BrowserManager({
82
+ let browserManager = new BrowserManager({
83
83
  headless,
84
84
  dataDir,
85
85
  serverUrl: server,
@@ -103,14 +103,29 @@ export async function startClient(options) {
103
103
  // 保存 cookies
104
104
  await browserManager.saveCookies();
105
105
  console.log(chalk.green('✅ Google 登录成功!已保存登录状态'));
106
- spinner.start('继续连接...');
106
+ // 关闭有界面的浏览器,以无头模式重新启动
107
+ console.log(chalk.gray('🔄 切换到无头模式...'));
108
+ await browserManager.close();
109
+ // 创建新的无头浏览器实例
110
+ browserManager = new BrowserManager({
111
+ headless: true,
112
+ dataDir,
113
+ serverUrl: server,
114
+ token,
115
+ });
116
+ // 重新设置信号处理
117
+ setupSignalHandlers(browserManager);
118
+ spinner.start('以无头模式重新启动...');
119
+ await browserManager.launch();
120
+ spinner.text = '打开 Build App 页面...';
121
+ await browserManager.openBuildApp();
107
122
  }
108
123
  // 点击连接按钮
109
124
  spinner.text = '点击 ws connect 按钮...';
110
125
  await browserManager.clickConnectButton();
111
126
  spinner.succeed(chalk.green('已连接到代理服务器!'));
112
127
  console.log(chalk.gray('─'.repeat(50)));
113
- console.log(chalk.green(`✅ 客户端已启动`));
128
+ console.log(chalk.green(`✅ 客户端已启动 (无头模式)`));
114
129
  console.log(chalk.white(` Token: ${token}`));
115
130
  console.log(chalk.gray(' 按 Ctrl+C 退出'));
116
131
  console.log(chalk.gray('─'.repeat(50)));
@@ -55,3 +55,75 @@ export function formatUptime(startTime) {
55
55
  export function sleep(ms) {
56
56
  return new Promise(resolve => setTimeout(resolve, ms));
57
57
  }
58
+ // 常见的屏幕分辨率
59
+ const VIEWPORTS = [
60
+ { width: 1920, height: 1080 },
61
+ { width: 1366, height: 768 },
62
+ { width: 1536, height: 864 },
63
+ { width: 1440, height: 900 },
64
+ { width: 1280, height: 720 },
65
+ { width: 1600, height: 900 },
66
+ { width: 1280, height: 800 },
67
+ { width: 1680, height: 1050 },
68
+ { width: 1360, height: 768 },
69
+ { width: 1280, height: 1024 },
70
+ ];
71
+ // 常见的语言区域
72
+ const LOCALES = [
73
+ 'en-US',
74
+ 'en-GB',
75
+ 'en-AU',
76
+ 'en-CA',
77
+ 'zh-CN',
78
+ 'zh-TW',
79
+ 'ja-JP',
80
+ 'ko-KR',
81
+ 'de-DE',
82
+ 'fr-FR',
83
+ ];
84
+ // 常见的时区
85
+ const TIMEZONES = [
86
+ 'America/New_York',
87
+ 'America/Los_Angeles',
88
+ 'America/Chicago',
89
+ 'Europe/London',
90
+ 'Europe/Paris',
91
+ 'Europe/Berlin',
92
+ 'Asia/Tokyo',
93
+ 'Asia/Shanghai',
94
+ 'Asia/Seoul',
95
+ 'Australia/Sydney',
96
+ ];
97
+ /**
98
+ * 生成随机指纹配置
99
+ * 如果提供了 dataDir,会尝试加载/保存固定的指纹配置
100
+ */
101
+ export function getRandomFingerprint(dataDir) {
102
+ const fingerprintPath = dataDir ? path.join(dataDir, 'fingerprint.json') : null;
103
+ // 尝试加载已保存的指纹
104
+ if (fingerprintPath && fs.existsSync(fingerprintPath)) {
105
+ try {
106
+ const saved = JSON.parse(fs.readFileSync(fingerprintPath, 'utf-8'));
107
+ return saved;
108
+ }
109
+ catch (e) {
110
+ // 忽略,生成新的
111
+ }
112
+ }
113
+ // 生成新的随机指纹
114
+ const fingerprint = {
115
+ viewport: VIEWPORTS[Math.floor(Math.random() * VIEWPORTS.length)],
116
+ locale: LOCALES[Math.floor(Math.random() * LOCALES.length)],
117
+ timezoneId: TIMEZONES[Math.floor(Math.random() * TIMEZONES.length)],
118
+ };
119
+ // 保存指纹以便下次使用(同一账号应该保持一致的指纹)
120
+ if (fingerprintPath) {
121
+ try {
122
+ fs.writeFileSync(fingerprintPath, JSON.stringify(fingerprint, null, 2));
123
+ }
124
+ catch (e) {
125
+ // 忽略保存错误
126
+ }
127
+ }
128
+ return fingerprint;
129
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gemini-proxy-client",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "Gemini Proxy Build App 客户端 - 使用 Camoufox 自动保持连接",
5
5
  "main": "dist/index.js",
6
6
  "bin": {