github-actions[bot] commited on
Commit
df986b8
·
1 Parent(s): bf38626

Update from GitHub Actions

Browse files
Files changed (1) hide show
  1. src/index.ts +112 -143
src/index.ts CHANGED
@@ -11,10 +11,7 @@ const app = new Hono()
11
  let browser: Browser | null = null
12
  let gensparkContext: BrowserContext | null = null
13
 
14
- const userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
15
- const RECAPTCHA_SITE_KEY = "6Leq7KYqAAAAAGdd1NaUBJF9dHTPAKP7DcnaRc66";
16
- const GENSPARK_URL = 'https://www.genspark.ai/agents?type=moa_chat';
17
-
18
  // 初始化浏览器
19
  async function initBrowser() {
20
  if (!browser) {
@@ -37,7 +34,7 @@ async function initGensparkContext() {
37
 
38
  if (!gensparkContext) {
39
  gensparkContext = await browser.newContext({
40
- userAgent,
41
  viewport: { width: 1920, height: 1080 },
42
  deviceScaleFactor: 1,
43
  hasTouch: false,
@@ -64,29 +61,6 @@ function isValidHeaderValue(value: string): boolean {
64
  return true;
65
  }
66
 
67
- // 获取reCAPTCHA令牌
68
- async function getReCaptchaToken(page: Page): Promise<string> {
69
- return page.evaluate(() => {
70
- return new Promise<string>((resolve, reject) => {
71
- // @ts-ignore
72
- window.grecaptcha.ready(function() {
73
- // @ts-ignore
74
- grecaptcha.execute(
75
- RECAPTCHA_SITE_KEY,
76
- { action: 'copilot' },
77
- ).then(function(token: string) {
78
- resolve(token)
79
- }).catch(function(error: Error) {
80
- reject(error)
81
- });
82
- });
83
-
84
- // 设置超时
85
- setTimeout(() => reject(new Error("获取令牌超时")), 10000);
86
- });
87
- });
88
- }
89
-
90
  // 处理请求转发
91
  async function handleRequest(url: string, method: string, headers: any, body?: any) {
92
  const browser = await initBrowser()
@@ -94,108 +68,103 @@ async function handleRequest(url: string, method: string, headers: any, body?: a
94
 
95
  try {
96
  // 只移除确实需要移除的请求头
97
- const filteredHeaders = { ...headers };
98
- const headersToRemove = [
99
- 'host', 'connection', 'content-length', 'accept-encoding',
100
- 'cdn-loop', 'cf-connecting-ip', 'cf-connecting-o2o', 'cf-ew-via',
101
- 'cf-ray', 'cf-visitor', 'cf-worker', 'x-direct-url',
102
- 'x-forwarded-for', 'x-forwarded-port', 'x-forwarded-proto'
103
- ];
104
-
105
- headersToRemove.forEach(header => delete filteredHeaders[header]);
106
- filteredHeaders['user-agent'] = userAgent;
107
-
108
- console.log('处理请求:', method, url, filteredHeaders, body);
109
-
 
 
 
 
 
 
 
 
 
110
  // 设置请求拦截器
111
  await page.route('**/*', async (route: Route) => {
112
- const request = route.request();
113
  if (request.url() === url) {
114
  await route.continue({
115
  method: method,
116
  headers: {
117
  ...request.headers(),
118
- ...filteredHeaders
119
  },
120
  postData: body
121
- });
122
  } else {
123
  // 允许其他资源加载
124
- await route.continue();
125
  }
126
- });
127
 
128
  // 配置页面请求选项
129
  const response = await page.goto(url, {
130
  waitUntil: 'domcontentloaded', // 改为更快的加载策略
131
- timeout: 60000 // 60秒超时,更合理的值
132
- });
133
 
134
  if (!response) {
135
- throw new Error('未收到响应');
136
  }
137
 
138
- // 等待页面加载完成,使用更短的超时时间
139
- await page.waitForLoadState('networkidle', { timeout: 5000 }).catch(() => {
140
- console.log('等待页面加载超时,继续处理');
141
- });
142
 
143
  // 获取响应数据
144
- const status = response.status();
145
- const responseHeaders = response.headers();
146
 
147
  // 确保移除可能导致解码问题的响应头
148
- delete responseHeaders['content-encoding'];
149
- delete responseHeaders['content-length'];
150
 
151
  // 过滤无效的响应头
152
- const validHeaders: Record<string, string> = {};
153
  for (const [key, value] of Object.entries(responseHeaders)) {
154
  if (isValidHeaderValue(value as string)) {
155
- validHeaders[key] = value as string;
156
  } else {
157
- console.warn(`跳过无效的响应头: ${key}: ${value}`);
158
  }
159
  }
160
 
161
  // 直接获取响应体的二进制数据
162
- const responseBody = await response.body();
163
 
164
- console.log('请求处理完成:', status);
165
 
166
- await page.close();
167
 
168
  return {
169
  status,
170
  headers: validHeaders,
171
  body: responseBody
172
- };
173
  } catch (error: any) {
174
- await page.close();
175
- console.error('请求处理错误:', error);
176
- throw new Error(`请求失败: ${error.message}`);
177
  }
178
  }
179
 
180
- // 解析cookie字符串为对象数组
181
- function parseCookies(cookieString: string) {
182
- return cookieString.split(';')
183
- .map(cookie => {
184
- const [name, value] = cookie.trim().split('=');
185
- return {
186
- name,
187
- value,
188
- domain: 'www.genspark.ai',
189
- path: '/'
190
- };
191
- })
192
- .filter(cookie => cookie.name && cookie.value);
193
- }
194
 
195
  // 添加静态文件服务
196
  app.use('/public/*', serveStatic({ root: './' }))
197
 
198
- // 处理根路由直接返回 index.html 内容,而不是重定向
199
  app.get('/', async (c) => {
200
  try {
201
  const htmlContent = fs.readFileSync('./index.html', 'utf-8')
@@ -206,71 +175,71 @@ app.get('/', async (c) => {
206
  }
207
  })
208
 
209
- // 获取reCAPTCHA令牌的路由
210
  app.get('/genspark', async (c) => {
211
- const headers = Object.fromEntries(c.req.raw.headers);
212
- const cookieString = headers.cookie || '';
213
- const cookies = parseCookies(cookieString);
214
 
215
- let page = null;
216
- let error = null;
217
-
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  try {
219
- gensparkContext = await initGensparkContext();
220
-
221
- // 设置cookies
222
- if (cookies.length > 0) {
223
- await gensparkContext.clearCookies();
224
- await gensparkContext.addCookies(cookies);
225
- }
226
-
227
-
228
- //等待一段时间
229
- await new Promise((resolve) => setTimeout(resolve, 1000));
230
-
231
- page = await gensparkContext.newPage();
232
-
233
- // 导航到Genspark页面
234
- await page.goto(GENSPARK_URL, {
235
  waitUntil: 'networkidle',
236
- timeout: 30000 // 30秒超时,更合理
237
- });
238
-
239
- // 等待页面加载完成
240
- await page.waitForTimeout(1000);
241
-
242
- // 获取reCAPTCHA令牌
243
- const token = await getReCaptchaToken(page);
244
-
245
- if (!token) {
246
- return c.json({ code: 500, message: '获取令牌失败:令牌为空' });
247
- }
248
-
249
- return c.json({
250
- code: 200,
251
- message: '获取令牌成功',
252
- token: token
253
- });
254
- } catch (e) {
255
- error = e
256
- console.error('获取令牌失败:', e);
257
- return c.json({
258
- code: 500,
259
- message: `获取令牌失败: ${e instanceof Error ? e.message : '未知错误'}`
260
  });
261
- } finally {
262
- if (page) {
263
- await page.close().catch(() => {});
264
- }
265
-
266
- // 不要在每次请求后关闭上下文,保持它以便重用
267
- // 只有在出错时才重置上下文
268
- if (error && gensparkContext) {
269
- await gensparkContext.close().catch(() => {});
270
  gensparkContext = null;
271
  }
272
  }
273
- });
 
 
 
 
 
274
 
275
  // 处理所有 HTTP 方法
276
  app.all('*', async (c) => {
@@ -310,12 +279,12 @@ app.all('*', async (c) => {
310
  // 清理函数
311
  async function cleanup() {
312
  if (gensparkContext) {
313
- await gensparkContext.close().catch(() => {});
314
  gensparkContext = null;
315
  }
316
 
317
  if (browser) {
318
- await browser.close().catch(() => {});
319
  browser = null;
320
  }
321
  process.exit(0)
@@ -326,10 +295,10 @@ process.on('SIGINT', cleanup)
326
  process.on('SIGTERM', cleanup)
327
 
328
  const port = Number(process.env.PORT || '7860');
329
- console.log(`Server is running on port http://localhost:${port}`)
330
 
331
  // 启动服务器
332
  serve({
333
  fetch: app.fetch,
334
  port: port
335
- })
 
11
  let browser: Browser | null = null
12
  let gensparkContext: BrowserContext | null = null
13
 
14
+ const userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3';
 
 
 
15
  // 初始化浏览器
16
  async function initBrowser() {
17
  if (!browser) {
 
34
 
35
  if (!gensparkContext) {
36
  gensparkContext = await browser.newContext({
37
+ userAgent: userAgent,
38
  viewport: { width: 1920, height: 1080 },
39
  deviceScaleFactor: 1,
40
  hasTouch: false,
 
61
  return true;
62
  }
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  // 处理请求转发
65
  async function handleRequest(url: string, method: string, headers: any, body?: any) {
66
  const browser = await initBrowser()
 
68
 
69
  try {
70
  // 只移除确实需要移除的请求头
71
+ delete headers['host']
72
+ delete headers['connection']
73
+ delete headers['content-length']
74
+ delete headers['accept-encoding']
75
+ // 移除cf相关的头
76
+ delete headers['cdn-loop']
77
+ delete headers['cf-connecting-ip']
78
+ delete headers['cf-connecting-o2o']
79
+ delete headers['cf-ew-via']
80
+ delete headers['cf-ray']
81
+ delete headers['cf-visitor']
82
+ delete headers['cf-worker']
83
+
84
+ //移除其他无效的请求头
85
+ delete headers['x-direct-url']
86
+ delete headers['x-forwarded-for']
87
+ delete headers['x-forwarded-port']
88
+ delete headers['x-forwarded-proto']
89
+
90
+ headers['user-agent'] = userAgent
91
+
92
+ console.log('处理请求:', method, url, headers, body)
93
  // 设置请求拦截器
94
  await page.route('**/*', async (route: Route) => {
95
+ const request = route.request()
96
  if (request.url() === url) {
97
  await route.continue({
98
  method: method,
99
  headers: {
100
  ...request.headers(),
101
+ ...headers
102
  },
103
  postData: body
104
+ })
105
  } else {
106
  // 允许其他资源加载
107
+ await route.continue()
108
  }
109
+ })
110
 
111
  // 配置页面请求选项
112
  const response = await page.goto(url, {
113
  waitUntil: 'domcontentloaded', // 改为更快的加载策略
114
+ timeout: 600000
115
+ })
116
 
117
  if (!response) {
118
+ throw new Error('未收到响应')
119
  }
120
 
121
+ // 等待页面加载完成
122
+ await page.waitForLoadState('networkidle', { timeout: 600000 }).catch(() => {
123
+ console.log('等待页面加载超时,继续处理')
124
+ })
125
 
126
  // 获取响应数据
127
+ const status = response.status()
128
+ const responseHeaders = response.headers()
129
 
130
  // 确保移除可能导致解码问题的响应头
131
+ delete responseHeaders['content-encoding']
132
+ delete responseHeaders['content-length']
133
 
134
  // 过滤无效的响应头
135
+ const validHeaders: Record<string, string> = {}
136
  for (const [key, value] of Object.entries(responseHeaders)) {
137
  if (isValidHeaderValue(value as string)) {
138
+ validHeaders[key] = value as string
139
  } else {
140
+ console.warn(`跳过无效的响应头: ${key}: ${value}`)
141
  }
142
  }
143
 
144
  // 直接获取响应体的二进制数据
145
+ const responseBody = await response.body()
146
 
147
+ console.log('请求处理完成:', status, responseBody.toString())
148
 
149
+ await page.close()
150
 
151
  return {
152
  status,
153
  headers: validHeaders,
154
  body: responseBody
155
+ }
156
  } catch (error: any) {
157
+ await page.close()
158
+ console.error('请求处理错误:', error)
159
+ throw new Error(`请求失败: ${error.message}`)
160
  }
161
  }
162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
 
164
  // 添加静态文件服务
165
  app.use('/public/*', serveStatic({ root: './' }))
166
 
167
+ // 修改点 1: 处理根路由直接返回 index.html 内容,而不是重定向
168
  app.get('/', async (c) => {
169
  try {
170
  const htmlContent = fs.readFileSync('./index.html', 'utf-8')
 
175
  }
176
  })
177
 
178
+ // 修改点 2: 添加 /genspark 路由来获取reCAPTCHA令牌
179
  app.get('/genspark', async (c) => {
 
 
 
180
 
181
+ const headers = Object.fromEntries(c.req.raw.headers)
182
+ // Get the cookie string from headers
183
+ const cookieString = headers.cookie || '';
184
+ // Parse cookies into an array of objects with name and value properties
185
+ const cookies = cookieString.split(';').map(cookie => {
186
+ const [name, value] = cookie.trim().split('=');
187
+ return { name, value, domain: 'www.genspark.ai', path: '/' };
188
+ }).filter(cookie => cookie.name && cookie.value);
189
+
190
+ gensparkContext = await initGensparkContext()
191
+ if (cookies && cookies.length > 0) {
192
+ await gensparkContext.clearCookies()
193
+ await gensparkContext.addCookies(cookies);
194
+ }
195
+ await new Promise(resolve => setTimeout(resolve, 1000))
196
+ const gensparkPage = await gensparkContext.newPage()
197
  try {
198
+ await gensparkPage.waitForTimeout(500)
199
+ //刷新页面以确保获取新令牌
200
+ await gensparkPage.goto('https://www.genspark.ai/agents?type=moa_chat', {
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  waitUntil: 'networkidle',
202
+ timeout: 3600000
203
+ })
204
+ await gensparkPage.waitForTimeout(500)
205
+ // 执行脚本获取令牌
206
+ const token = await gensparkPage.evaluate(() => {
207
+ return new Promise((resolve, reject) => {
208
+ // @ts-ignore
209
+ window.grecaptcha.ready(function () {
210
+ // @ts-ignore
211
+ grecaptcha.execute(
212
+ "6Leq7KYqAAAAAGdd1NaUBJF9dHTPAKP7DcnaRc66",
213
+ { action: 'copilot' },
214
+ ).then(function (token: string) {
215
+ resolve(token)
216
+ }).catch(function (error: Error) {
217
+ reject(error)
218
+ });
219
+ });
220
+
221
+ // 设置超时
222
+ setTimeout(() => reject(new Error("获取令牌超时")), 10000);
223
+ });
224
+ }).catch(error => {
225
+ return c.json({ code: 500, message: '获取令牌失败' })
226
  });
227
+
228
+ return c.json({ code: 200, message: '获取令牌成功', token: token })
229
+ }
230
+ catch (error) {
231
+ console.error('获取令牌失败:', error)
232
+ if (gensparkContext) {
233
+ await gensparkContext.close().catch(() => { });
 
 
234
  gensparkContext = null;
235
  }
236
  }
237
+ finally {
238
+ await gensparkPage.close().catch(() => { });
239
+ }
240
+
241
+ return c.json({ code: 500, message: '获取令牌失败' })
242
+ })
243
 
244
  // 处理所有 HTTP 方法
245
  app.all('*', async (c) => {
 
279
  // 清理函数
280
  async function cleanup() {
281
  if (gensparkContext) {
282
+ await gensparkContext.close().catch(() => { });
283
  gensparkContext = null;
284
  }
285
 
286
  if (browser) {
287
+ await browser.close().catch(() => { });
288
  browser = null;
289
  }
290
  process.exit(0)
 
295
  process.on('SIGTERM', cleanup)
296
 
297
  const port = Number(process.env.PORT || '7860');
298
+ console.log(`Server is running on port http://localhost:${port}`)
299
 
300
  // 启动服务器
301
  serve({
302
  fetch: app.fetch,
303
  port: port
304
+ })