letterm commited on
Commit
bbebe92
·
verified ·
1 Parent(s): eaf7532

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +143 -27
index.js CHANGED
@@ -6,13 +6,14 @@ import cors from 'cors';
6
  import Logger from './logger.js';
7
  import dotenv from 'dotenv';
8
 
 
9
  // 初始化环境变量
10
  dotenv.config();
11
 
12
  // 配置管理
13
  const CONFIG = {
14
  SERVER: {
15
- PORT: process.env.PORT || 25526,
16
  BODY_LIMIT: '5mb',
17
  CORS_OPTIONS: {
18
  origin: '*',
@@ -38,6 +39,7 @@ const CONFIG = {
38
  "grok-3-reasoning": "grok-3",
39
  "grok-3-imageGen": "grok-3",
40
  },
 
41
  IS_IMG_GEN: false,
42
  IS_THINKING: false
43
  };
@@ -58,6 +60,82 @@ const DEFAULT_HEADERS = {
58
  'priority': 'u=1, i'
59
  };
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  // 工具类
62
  class Utils {
63
  static generateRandomString(length, charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
@@ -65,12 +143,17 @@ class Utils {
65
  .map(() => charset[Math.floor(Math.random() * charset.length)])
66
  .join('');
67
  }
68
-
 
 
 
 
 
69
  static createAuthHeaders() {
70
  return {
71
  ...DEFAULT_HEADERS,
72
- 'x-csrf-token': CONFIG.API.CT0,
73
- 'cookie': `auth_token=${CONFIG.API.AUTH_TOKEN};ct0=${CONFIG.API.CT0}`
74
  };
75
  }
76
 
@@ -102,6 +185,10 @@ class ConversationManager {
102
  const data = await Utils.handleApiResponse(response, '创建会话失败!');
103
  return data.data.create_grok_conversation.conversation_id;
104
  }
 
 
 
 
105
 
106
  static async deleteConversation(conversationId) {
107
  if (!conversationId) return;
@@ -417,7 +504,6 @@ class ResponseHandler {
417
  let buffer = '';
418
  let fullResponse = '';
419
  let imageUrl = null;
420
-
421
  try {
422
  for await (const chunk of reader) {
423
  const lines = (buffer + chunk.toString()).split('\n');
@@ -435,6 +521,9 @@ class ResponseHandler {
435
  if (imageUrl) {
436
  await this.sendImageResponse(imageUrl, model, res);
437
  } else {
 
 
 
438
  const responseData = MessageProcessor.createChatResponse(fullResponse, model);
439
  res.json(responseData);
440
  }
@@ -515,7 +604,7 @@ app.use(express.json({ limit: CONFIG.SERVER.BODY_LIMIT }));
515
  app.use(express.urlencoded({ extended: true, limit: CONFIG.SERVER.BODY_LIMIT }));
516
 
517
  // API 路由
518
- app.get('/hf/v1/models', (req, res) => {
519
  res.json({
520
  object: "list",
521
  data: Object.keys(CONFIG.MODELS).map(model => ({
@@ -526,30 +615,61 @@ app.get('/hf/v1/models', (req, res) => {
526
  }))
527
  });
528
  });
529
-
530
- app.post('/hf/v1/chat/completions', async (req, res) => {
531
  try {
532
  const authToken = req.headers.authorization?.replace('Bearer ', '');
533
  if (authToken !== CONFIG.API.API_KEY) {
534
  return res.status(401).json({ error: 'Unauthorized' });
535
  }
536
 
537
- const grokClient = new TwitterGrokApiClient(req.body.model);
538
- const requestPayload = await grokClient.prepareChatRequest(req.body);
539
-
540
- const response = await fetch(CONFIG.API.ENDPOINTS.CHAT, {
541
- method: 'POST',
542
- headers: Utils.createAuthHeaders(),
543
- body: JSON.stringify(requestPayload)
544
- });
545
-
546
- if (!response.ok) {
547
- throw new Error(`上游服务请求失败! status: ${response.status}`);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
548
  }
549
 
550
- await (req.body.stream
551
- ? ResponseHandler.handleStreamResponse(response, req.body.model, res)
552
- : ResponseHandler.handleNormalResponse(response, req.body.model, res));
553
 
554
  } catch (error) {
555
  Logger.error('Chat Completions Request Error', error, 'ChatAPI');
@@ -561,16 +681,12 @@ app.post('/hf/v1/chat/completions', async (req, res) => {
561
  code: error.code || null
562
  }
563
  });
564
- } finally {
565
- if (req.body.conversationId) {
566
- await ConversationManager.deleteConversation(req.body.conversationId);
567
- }
568
  }
569
  });
570
 
571
  // 404 处理
572
  app.use((req, res) => {
573
- res.status(404).json({ message: '服务创建成功,正在运行' });
574
  });
575
 
576
  // 启动服务器
 
6
  import Logger from './logger.js';
7
  import dotenv from 'dotenv';
8
 
9
+
10
  // 初始化环境变量
11
  dotenv.config();
12
 
13
  // 配置管理
14
  const CONFIG = {
15
  SERVER: {
16
+ PORT: process.env.PORT || 7860,
17
  BODY_LIMIT: '5mb',
18
  CORS_OPTIONS: {
19
  origin: '*',
 
39
  "grok-3-reasoning": "grok-3",
40
  "grok-3-imageGen": "grok-3",
41
  },
42
+ SIGNATURE_INDEX: 0,
43
  IS_IMG_GEN: false,
44
  IS_THINKING: false
45
  };
 
60
  'priority': 'u=1, i'
61
  };
62
 
63
+
64
+ async function initialization() {
65
+ const auth_tokenArray = CONFIG.API.AUTH_TOKEN.split(',');
66
+ const ct0Array = CONFIG.API.CT0.split(',');
67
+ auth_tokenArray.forEach((auth_token, index) => {
68
+ tokenManager.addToken(`auth_token=${auth_token};ct0=${ct0Array[index]}`);
69
+ });
70
+ Logger.info("初始化完成", 'Server');
71
+ }
72
+ class AuthTokenManager {
73
+ constructor() {
74
+ this.activeTokens = [];
75
+ this.expiredTokens = new Map();
76
+ this.isRecoveryProcess = false;
77
+ }
78
+
79
+ // 添加 token
80
+ addToken(token) {
81
+ if (!this.activeTokens.includes(token)) {
82
+ this.activeTokens.push(token);
83
+ }
84
+ }
85
+
86
+ // 通过下标获取 token
87
+ getTokenByIndex(index) {
88
+ if (index < 0 || index >= this.activeTokens.length) {
89
+ throw new Error(`无效的索引:${index}`);
90
+ }
91
+ return this.activeTokens[index];
92
+ }
93
+
94
+ // 通过下标移除 token
95
+ removeTokenByIndex(index) {
96
+ if (index < 0 || index >= this.activeTokens.length) {
97
+ throw new Error(`无效的索引:${index}`);
98
+ }
99
+
100
+ const token = this.activeTokens[index];
101
+ this.activeTokens.splice(index, 1);
102
+
103
+ // 记录失效时间
104
+ this.expiredTokens.set(token, Date.now());
105
+ return token;
106
+ }
107
+
108
+ // 启动定期恢复机制
109
+ startTokenRecoveryProcess() {
110
+ setInterval(() => {
111
+ const now = Date.now();
112
+
113
+ // 遍历并恢复过期的 token
114
+ for (const [token, expiredTime] of this.expiredTokens.entries()) {
115
+ if (now - expiredTime >= 1 * 60 * 1000) {
116
+ this.activeTokens.push(token);
117
+ this.expiredTokens.delete(token);
118
+ console.log(`Token ${token} recovered`);
119
+ }
120
+ }
121
+ }, 1 * 60 * 1000);
122
+ }
123
+
124
+ // 获取 token 总数
125
+ getTokenCount() {
126
+ return this.activeTokens.length;
127
+ }
128
+
129
+ // 获取所有活跃 token
130
+ getActiveTokens() {
131
+ return [...this.activeTokens];
132
+ }
133
+ }
134
+
135
+ const tokenManager = new AuthTokenManager();
136
+ await initialization();
137
+
138
+
139
  // 工具类
140
  class Utils {
141
  static generateRandomString(length, charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') {
 
143
  .map(() => charset[Math.floor(Math.random() * charset.length)])
144
  .join('');
145
  }
146
+ static getRandomID(size) {
147
+ const customDict = '0123456789';
148
+ return Array(size).fill(null)
149
+ .map(() => customDict[(Math.random() * customDict.length) | 0])
150
+ .join('');
151
+ }
152
  static createAuthHeaders() {
153
  return {
154
  ...DEFAULT_HEADERS,
155
+ 'x-csrf-token': tokenManager.getTokenByIndex(CONFIG.SIGNATURE_INDEX).split(';')[1].split('=')[1],
156
+ 'cookie': `${tokenManager.getTokenByIndex(CONFIG.SIGNATURE_INDEX)}`
157
  };
158
  }
159
 
 
185
  const data = await Utils.handleApiResponse(response, '创建会话失败!');
186
  return data.data.create_grok_conversation.conversation_id;
187
  }
188
+ // static generateNewId() {
189
+ // this.conversationId = `1875${Utils.getRandomID(15)}`;
190
+ // return this.conversationId;
191
+ // }
192
 
193
  static async deleteConversation(conversationId) {
194
  if (!conversationId) return;
 
504
  let buffer = '';
505
  let fullResponse = '';
506
  let imageUrl = null;
 
507
  try {
508
  for await (const chunk of reader) {
509
  const lines = (buffer + chunk.toString()).split('\n');
 
521
  if (imageUrl) {
522
  await this.sendImageResponse(imageUrl, model, res);
523
  } else {
524
+ if (fullResponse.includes("You've reached your limit of 15 Grok")) {
525
+ throw new Error('You have reached your limit of 15 Grok');
526
+ }
527
  const responseData = MessageProcessor.createChatResponse(fullResponse, model);
528
  res.json(responseData);
529
  }
 
604
  app.use(express.urlencoded({ extended: true, limit: CONFIG.SERVER.BODY_LIMIT }));
605
 
606
  // API 路由
607
+ app.get('/v1/models', (req, res) => {
608
  res.json({
609
  object: "list",
610
  data: Object.keys(CONFIG.MODELS).map(model => ({
 
615
  }))
616
  });
617
  });
618
+ app.post('/v1/chat/completions', async (req, res) => {
 
619
  try {
620
  const authToken = req.headers.authorization?.replace('Bearer ', '');
621
  if (authToken !== CONFIG.API.API_KEY) {
622
  return res.status(401).json({ error: 'Unauthorized' });
623
  }
624
 
625
+ while (tokenManager.getTokenCount() > 0) {
626
+ const grokClient = new TwitterGrokApiClient(req.body.model);
627
+ const requestPayload = await grokClient.prepareChatRequest(req.body);
628
+ Logger.info(`当前令牌索引: ${CONFIG.SIGNATURE_INDEX}`, 'Server');
629
+ const response = await fetch(CONFIG.API.ENDPOINTS.CHAT, {
630
+ method: 'POST',
631
+ headers: Utils.createAuthHeaders(),
632
+ body: JSON.stringify(requestPayload)
633
+ });
634
+
635
+ if (response.ok) {
636
+ Logger.info(`请求成功`, 'Server');
637
+ CONFIG.SIGNATURE_INDEX = (CONFIG.SIGNATURE_INDEX + 1) % tokenManager.getTokenCount();
638
+ Logger.info(`当前剩余可用令牌数: ${tokenManager.getTokenCount()}`, 'Server');
639
+ try {
640
+ await (req.body.stream
641
+ ? ResponseHandler.handleStreamResponse(response, req.body.model, res)
642
+ : ResponseHandler.handleNormalResponse(response, req.body.model, res));
643
+ return; // 成功后直接返回
644
+ } catch (error) {
645
+ tokenManager.removeTokenByIndex(CONFIG.SIGNATURE_INDEX);
646
+ if (!tokenManager.isRecoveryProcess) {
647
+ tokenManager.startTokenRecoveryProcess();
648
+ }
649
+ Logger.warn(`当前令牌失效,已移除令牌,剩余令牌数: ${tokenManager.getTokenCount()}`, 'Server');
650
+ // 更新签名索引
651
+ CONFIG.SIGNATURE_INDEX = (CONFIG.SIGNATURE_INDEX + 1) % tokenManager.getTokenCount();
652
+ }
653
+ } else {
654
+ // 处理429错误
655
+ if (response.status === 429) {
656
+ tokenManager.removeTokenByIndex(CONFIG.SIGNATURE_INDEX);
657
+ if (!tokenManager.isRecoveryProcess) {
658
+ tokenManager.startTokenRecoveryProcess();
659
+ }
660
+ Logger.warn(`当前令牌失效,已移除令牌,剩余令牌数: ${tokenManager.getTokenCount()}`, 'Server');
661
+ // 更新签名索引
662
+ CONFIG.SIGNATURE_INDEX = (CONFIG.SIGNATURE_INDEX + 1) % tokenManager.getTokenCount();
663
+ Logger.warn(`请求被限流,剩余重试次数: ${tokenManager.getTokenCount()}`, 'ChatAPI');
664
+ } else {
665
+ // 非429错误直接抛出
666
+ throw new Error(`上游服务请求失败! status: ${response.status}`);
667
+ }
668
+ }
669
  }
670
 
671
+ // 如果重试次数用完仍然是429
672
+ throw new Error('所有令牌都已耗尽,请求被限流');
 
673
 
674
  } catch (error) {
675
  Logger.error('Chat Completions Request Error', error, 'ChatAPI');
 
681
  code: error.code || null
682
  }
683
  });
 
 
 
 
684
  }
685
  });
686
 
687
  // 404 处理
688
  app.use((req, res) => {
689
+ res.status(404).json({ error: '请求路径不存在' });
690
  });
691
 
692
  // 启动服务器