usbtoo commited on
Commit
56d1f3b
·
verified ·
1 Parent(s): f8fbe39

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -1261
app.py DELETED
@@ -1,1261 +0,0 @@
1
- import os
2
- import json
3
- import uuid
4
- import time
5
- import base64
6
- import sys
7
- import inspect
8
- import secrets
9
- from loguru import logger
10
- from dotenv import load_dotenv
11
-
12
- import requests
13
- from flask import Flask, request, Response, jsonify, stream_with_context, render_template, redirect, session
14
- from curl_cffi import requests as curl_requests
15
- from werkzeug.middleware.proxy_fix import ProxyFix
16
-
17
- current_dir = os.path.dirname(os.path.abspath(__file__))
18
- env_path = os.path.join(current_dir, '.env')
19
-
20
- load_dotenv(env_path)
21
-
22
- class Logger:
23
- def __init__(self, level="INFO", colorize=True, format=None):
24
- logger.remove()
25
-
26
- if format is None:
27
- format = (
28
- "<green>{time:YYYY-MM-DD HH:mm:ss}</green> | "
29
- "<level>{level: <8}</level> | "
30
- "<cyan>{extra[filename]}</cyan>:<cyan>{extra[function]}</cyan>:<cyan>{extra[lineno]}</cyan> | "
31
- "<level>{message}</level>"
32
- )
33
-
34
- logger.add(
35
- sys.stderr,
36
- level=level,
37
- format=format,
38
- colorize=colorize,
39
- backtrace=True,
40
- diagnose=True
41
- )
42
-
43
- self.logger = logger
44
-
45
- def _get_caller_info(self):
46
- frame = inspect.currentframe()
47
- try:
48
- caller_frame = frame.f_back.f_back
49
- full_path = caller_frame.f_code.co_filename
50
- function = caller_frame.f_code.co_name
51
- lineno = caller_frame.f_lineno
52
-
53
- filename = os.path.basename(full_path)
54
-
55
- return {
56
- 'filename': filename,
57
- 'function': function,
58
- 'lineno': lineno
59
- }
60
- finally:
61
- del frame
62
-
63
- def info(self, message, source="API"):
64
- caller_info = self._get_caller_info()
65
- self.logger.bind(**caller_info).info(f"[{source}] {message}")
66
-
67
- def error(self, message, source="API"):
68
- caller_info = self._get_caller_info()
69
-
70
- if isinstance(message, Exception):
71
- self.logger.bind(**caller_info).exception(f"[{source}] {str(message)}")
72
- else:
73
- self.logger.bind(**caller_info).error(f"[{source}] {message}")
74
-
75
- def warning(self, message, source="API"):
76
- caller_info = self._get_caller_info()
77
- self.logger.bind(**caller_info).warning(f"[{source}] {message}")
78
-
79
- def debug(self, message, source="API"):
80
- caller_info = self._get_caller_info()
81
- self.logger.bind(**caller_info).debug(f"[{source}] {message}")
82
-
83
- async def request_logger(self, request):
84
- caller_info = self._get_caller_info()
85
- self.logger.bind(**caller_info).info(f"请求: {request.method} {request.path}", "Request")
86
-
87
- logger = Logger(level="INFO")
88
-
89
-
90
- CONFIG = {
91
- "MODELS": {
92
- 'grok-2': 'grok-latest',
93
- 'grok-2-imageGen': 'grok-latest',
94
- 'grok-2-search': 'grok-latest',
95
- "grok-3": "grok-3",
96
- "grok-3-search": "grok-3",
97
- "grok-3-imageGen": "grok-3",
98
- "grok-3-deepsearch": "grok-3",
99
- "grok-3-reasoning": "grok-3"
100
- },
101
- "API": {
102
- "IS_TEMP_CONVERSATION": os.getenv("IS_TEMP_CONVERSATION", "true").lower() == "true",
103
- "IS_CUSTOM_SSO": os.getenv("IS_CUSTOM_SSO", "false").lower() == "true",
104
- "BASE_URL": "https://grok.com",
105
- "API_KEY": os.getenv("API_KEY", "sk-123456"),
106
- "SIGNATURE_COOKIE": None,
107
- "PICGO_KEY": os.getenv("PICGO_KEY") or None,
108
- "TUMY_KEY": os.getenv("TUMY_KEY") or None,
109
- "RETRY_TIME": 1000,
110
- "PROXY": os.getenv("PROXY") or None
111
- },
112
- "ADMIN": {
113
- "MANAGER_SWITCH": os.getenv("MANAGER_SWITCH") or None,
114
- "PASSWORD": os.getenv("ADMINPASSWORD") or None
115
- },
116
- "SERVER": {
117
- "COOKIE": None,
118
- "CF_CLEARANCE":os.getenv("CF_CLEARANCE") or None,
119
- "PORT": int(os.getenv("PORT", 5200))
120
- },
121
- "RETRY": {
122
- "RETRYSWITCH": False,
123
- "MAX_ATTEMPTS": 2
124
- },
125
- "SHOW_THINKING": os.getenv("SHOW_THINKING") == "true",
126
- "IS_THINKING": False,
127
- "IS_IMG_GEN": False,
128
- "IS_IMG_GEN2": False,
129
- "ISSHOW_SEARCH_RESULTS": os.getenv("ISSHOW_SEARCH_RESULTS", "true").lower() == "true"
130
- }
131
-
132
-
133
- DEFAULT_HEADERS = {
134
- 'Accept': '*/*',
135
- 'Accept-Language': 'zh-CN,zh;q=0.9',
136
- 'Accept-Encoding': 'gzip, deflate, br, zstd',
137
- 'Content-Type': 'text/plain;charset=UTF-8',
138
- 'Connection': 'keep-alive',
139
- 'Origin': 'https://grok.com',
140
- 'Priority': 'u=1, i',
141
- 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
142
- 'Sec-Ch-Ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"',
143
- 'Sec-Ch-Ua-Mobile': '?0',
144
- 'Sec-Ch-Ua-Platform': '"macOS"',
145
- 'Sec-Fetch-Dest': 'empty',
146
- 'Sec-Fetch-Mode': 'cors',
147
- 'Sec-Fetch-Site': 'same-origin',
148
- 'Baggage': 'sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c'
149
- }
150
-
151
- class AuthTokenManager:
152
- def __init__(self):
153
- self.token_model_map = {}
154
- self.expired_tokens = set()
155
- self.token_status_map = {}
156
-
157
- self.model_config = {
158
- "grok-2": {
159
- "RequestFrequency": 30,
160
- "ExpirationTime": 1 * 60 * 60 * 1000 # 1小时
161
- },
162
- "grok-3": {
163
- "RequestFrequency": 20,
164
- "ExpirationTime": 2 * 60 * 60 * 1000 # 2小时
165
- },
166
- "grok-3-deepsearch": {
167
- "RequestFrequency": 10,
168
- "ExpirationTime": 24 * 60 * 60 * 1000 # 24小时
169
- },
170
- "grok-3-reasoning": {
171
- "RequestFrequency": 10,
172
- "ExpirationTime": 24 * 60 * 60 * 1000 # 24小时
173
- }
174
- }
175
- self.token_reset_switch = False
176
- self.token_reset_timer = None
177
-
178
- def add_token(self, token):
179
- sso = token.split("sso=")[1].split(";")[0]
180
- for model in self.model_config.keys():
181
- if model not in self.token_model_map:
182
- self.token_model_map[model] = []
183
- if sso not in self.token_status_map:
184
- self.token_status_map[sso] = {}
185
-
186
- existing_token_entry = next((entry for entry in self.token_model_map[model] if entry["token"] == token), None)
187
-
188
- if not existing_token_entry:
189
- self.token_model_map[model].append({
190
- "token": token,
191
- "RequestCount": 0,
192
- "AddedTime": int(time.time() * 1000),
193
- "StartCallTime": None
194
- })
195
-
196
- if model not in self.token_status_map[sso]:
197
- self.token_status_map[sso][model] = {
198
- "isValid": True,
199
- "invalidatedTime": None,
200
- "totalRequestCount": 0
201
- }
202
-
203
- def set_token(self, token):
204
- models = list(self.model_config.keys())
205
- self.token_model_map = {model: [{
206
- "token": token,
207
- "RequestCount": 0,
208
- "AddedTime": int(time.time() * 1000),
209
- "StartCallTime": None
210
- }] for model in models}
211
-
212
- sso = token.split("sso=")[1].split(";")[0]
213
- self.token_status_map[sso] = {model: {
214
- "isValid": True,
215
- "invalidatedTime": None,
216
- "totalRequestCount": 0
217
- } for model in models}
218
-
219
- def delete_token(self, token):
220
- try:
221
- sso = token.split("sso=")[1].split(";")[0]
222
- for model in self.token_model_map:
223
- self.token_model_map[model] = [entry for entry in self.token_model_map[model] if entry["token"] != token]
224
-
225
- if sso in self.token_status_map:
226
- del self.token_status_map[sso]
227
-
228
- logger.info(f"令牌已成功移除: {token}", "TokenManager")
229
- return True
230
- except Exception as error:
231
- logger.error(f"令牌删除失败: {str(error)}")
232
- return False
233
- def reduce_token_request_count(self, model_id, count):
234
- try:
235
- normalized_model = self.normalize_model_name(model_id)
236
-
237
- if normalized_model not in self.token_model_map:
238
- logger.error(f"模型 {normalized_model} 不存在", "TokenManager")
239
- return False
240
-
241
- if not self.token_model_map[normalized_model]:
242
- logger.error(f"模型 {normalized_model} 没有可用的token", "TokenManager")
243
- return False
244
-
245
- token_entry = self.token_model_map[normalized_model][0]
246
-
247
- # 确保RequestCount不会小于0
248
- new_count = max(0, token_entry["RequestCount"] - count)
249
- reduction = token_entry["RequestCount"] - new_count
250
-
251
- token_entry["RequestCount"] = new_count
252
-
253
- # 更新token状态
254
- if token_entry["token"]:
255
- sso = token_entry["token"].split("sso=")[1].split(";")[0]
256
- if sso in self.token_status_map and normalized_model in self.token_status_map[sso]:
257
- self.token_status_map[sso][normalized_model]["totalRequestCount"] = max(
258
- 0,
259
- self.token_status_map[sso][normalized_model]["totalRequestCount"] - reduction
260
- )
261
- return True
262
-
263
- except Exception as error:
264
- logger.error(f"重置校对token请求次数时发生错误: {str(error)}", "TokenManager")
265
- return False
266
- def get_next_token_for_model(self, model_id, is_return=False):
267
- normalized_model = self.normalize_model_name(model_id)
268
-
269
- if normalized_model not in self.token_model_map or not self.token_model_map[normalized_model]:
270
- return None
271
-
272
- token_entry = self.token_model_map[normalized_model][0]
273
- if is_return:
274
- return token_entry["token"]
275
-
276
- if token_entry:
277
- if token_entry["StartCallTime"] is None:
278
- token_entry["StartCallTime"] = int(time.time() * 1000)
279
-
280
- if not self.token_reset_switch:
281
- self.start_token_reset_process()
282
- self.token_reset_switch = True
283
-
284
- token_entry["RequestCount"] += 1
285
-
286
- if token_entry["RequestCount"] > self.model_config[normalized_model]["RequestFrequency"]:
287
- self.remove_token_from_model(normalized_model, token_entry["token"])
288
- next_token_entry = self.token_model_map[normalized_model][0] if self.token_model_map[normalized_model] else None
289
- return next_token_entry["token"] if next_token_entry else None
290
-
291
- sso = token_entry["token"].split("sso=")[1].split(";")[0]
292
- if sso in self.token_status_map and normalized_model in self.token_status_map[sso]:
293
- if token_entry["RequestCount"] == self.model_config[normalized_model]["RequestFrequency"]:
294
- self.token_status_map[sso][normalized_model]["isValid"] = False
295
- self.token_status_map[sso][normalized_model]["invalidatedTime"] = int(time.time() * 1000)
296
- self.token_status_map[sso][normalized_model]["totalRequestCount"] += 1
297
-
298
- return token_entry["token"]
299
-
300
- return None
301
-
302
- def remove_token_from_model(self, model_id, token):
303
- normalized_model = self.normalize_model_name(model_id)
304
-
305
- if normalized_model not in self.token_model_map:
306
- logger.error(f"模型 {normalized_model} 不存在", "TokenManager")
307
- return False
308
-
309
- model_tokens = self.token_model_map[normalized_model]
310
- token_index = next((i for i, entry in enumerate(model_tokens) if entry["token"] == token), -1)
311
-
312
- if token_index != -1:
313
- removed_token_entry = model_tokens.pop(token_index)
314
- self.expired_tokens.add((
315
- removed_token_entry["token"],
316
- normalized_model,
317
- int(time.time() * 1000)
318
- ))
319
-
320
- if not self.token_reset_switch:
321
- self.start_token_reset_process()
322
- self.token_reset_switch = True
323
-
324
- logger.info(f"模型{model_id}的令牌已失效,已成功移除令牌: {token}", "TokenManager")
325
- return True
326
-
327
- logger.error(f"在模型 {normalized_model} 中未找到 token: {token}", "TokenManager")
328
- return False
329
-
330
- def get_expired_tokens(self):
331
- return list(self.expired_tokens)
332
-
333
- def normalize_model_name(self, model):
334
- if model.startswith('grok-') and 'deepsearch' not in model and 'reasoning' not in model:
335
- return '-'.join(model.split('-')[:2])
336
- return model
337
-
338
- def get_token_count_for_model(self, model_id):
339
- normalized_model = self.normalize_model_name(model_id)
340
- return len(self.token_model_map.get(normalized_model, []))
341
-
342
- def get_remaining_token_request_capacity(self):
343
- remaining_capacity_map = {}
344
-
345
- for model in self.model_config.keys():
346
- model_tokens = self.token_model_map.get(model, [])
347
- model_request_frequency = self.model_config[model]["RequestFrequency"]
348
-
349
- total_used_requests = sum(token_entry.get("RequestCount", 0) for token_entry in model_tokens)
350
-
351
- remaining_capacity = (len(model_tokens) * model_request_frequency) - total_used_requests
352
- remaining_capacity_map[model] = max(0, remaining_capacity)
353
-
354
- return remaining_capacity_map
355
-
356
- def get_token_array_for_model(self, model_id):
357
- normalized_model = self.normalize_model_name(model_id)
358
- return self.token_model_map.get(normalized_model, [])
359
-
360
- def start_token_reset_process(self):
361
- def reset_expired_tokens():
362
- now = int(time.time() * 1000)
363
-
364
- tokens_to_remove = set()
365
- for token_info in self.expired_tokens:
366
- token, model, expired_time = token_info
367
- expiration_time = self.model_config[model]["ExpirationTime"]
368
-
369
- if now - expired_time >= expiration_time:
370
- if not any(entry["token"] == token for entry in self.token_model_map.get(model, [])):
371
- if model not in self.token_model_map:
372
- self.token_model_map[model] = []
373
-
374
- self.token_model_map[model].append({
375
- "token": token,
376
- "RequestCount": 0,
377
- "AddedTime": now,
378
- "StartCallTime": None
379
- })
380
-
381
- sso = token.split("sso=")[1].split(";")[0]
382
- if sso in self.token_status_map and model in self.token_status_map[sso]:
383
- self.token_status_map[sso][model]["isValid"] = True
384
- self.token_status_map[sso][model]["invalidatedTime"] = None
385
- self.token_status_map[sso][model]["totalRequestCount"] = 0
386
-
387
- tokens_to_remove.add(token_info)
388
-
389
- self.expired_tokens -= tokens_to_remove
390
-
391
- for model in self.model_config.keys():
392
- if model not in self.token_model_map:
393
- continue
394
-
395
- for token_entry in self.token_model_map[model]:
396
- if not token_entry.get("StartCallTime"):
397
- continue
398
-
399
- expiration_time = self.model_config[model]["ExpirationTime"]
400
- if now - token_entry["StartCallTime"] >= expiration_time:
401
- sso = token_entry["token"].split("sso=")[1].split(";")[0]
402
- if sso in self.token_status_map and model in self.token_status_map[sso]:
403
- self.token_status_map[sso][model]["isValid"] = True
404
- self.token_status_map[sso][model]["invalidatedTime"] = None
405
- self.token_status_map[sso][model]["totalRequestCount"] = 0
406
-
407
- token_entry["RequestCount"] = 0
408
- token_entry["StartCallTime"] = None
409
-
410
- import threading
411
- # 启动一个线程执行定时任务,每小时执行一次
412
- def run_timer():
413
- while True:
414
- reset_expired_tokens()
415
- time.sleep(3600)
416
-
417
- timer_thread = threading.Thread(target=run_timer)
418
- timer_thread.daemon = True
419
- timer_thread.start()
420
-
421
- def get_all_tokens(self):
422
- all_tokens = set()
423
- for model_tokens in self.token_model_map.values():
424
- for entry in model_tokens:
425
- all_tokens.add(entry["token"])
426
- return list(all_tokens)
427
- def get_current_token(self, model_id):
428
- normalized_model = self.normalize_model_name(model_id)
429
-
430
- if normalized_model not in self.token_model_map or not self.token_model_map[normalized_model]:
431
- return None
432
-
433
- token_entry = self.token_model_map[normalized_model][0]
434
- return token_entry["token"]
435
-
436
- def get_token_status_map(self):
437
- return self.token_status_map
438
-
439
- class Utils:
440
- @staticmethod
441
- def organize_search_results(search_results):
442
- if not search_results or 'results' not in search_results:
443
- return ''
444
-
445
- results = search_results['results']
446
- formatted_results = []
447
-
448
- for index, result in enumerate(results):
449
- title = result.get('title', '未知标题')
450
- url = result.get('url', '#')
451
- preview = result.get('preview', '无预览内容')
452
-
453
- formatted_result = f"\r\n<details><summary>资料[{index}]: {title}</summary>\r\n{preview}\r\n\n[Link]({url})\r\n</details>"
454
- formatted_results.append(formatted_result)
455
-
456
- return '\n\n'.join(formatted_results)
457
-
458
- @staticmethod
459
- def create_auth_headers(model, is_return=False):
460
- return token_manager.get_next_token_for_model(model, is_return)
461
-
462
- @staticmethod
463
- def get_proxy_options():
464
- proxy = CONFIG["API"]["PROXY"]
465
- proxy_options = {}
466
-
467
- if proxy:
468
- logger.info(f"使用代理: {proxy}", "Server")
469
-
470
- if proxy.startswith("socks5://"):
471
- proxy_options["proxy"] = proxy
472
-
473
- if '@' in proxy:
474
- auth_part = proxy.split('@')[0].split('://')[1]
475
- if ':' in auth_part:
476
- username, password = auth_part.split(':')
477
- proxy_options["proxy_auth"] = (username, password)
478
- else:
479
- proxy_options["proxies"] = {"https": proxy, "http": proxy}
480
- return proxy_options
481
-
482
- class GrokApiClient:
483
- def __init__(self, model_id):
484
- if model_id not in CONFIG["MODELS"]:
485
- raise ValueError(f"不支持的模型: {model_id}")
486
- self.model_id = CONFIG["MODELS"][model_id]
487
-
488
- def process_message_content(self, content):
489
- if isinstance(content, str):
490
- return content
491
- return None
492
-
493
- def get_image_type(self, base64_string):
494
- mime_type = 'image/jpeg'
495
- if 'data:image' in base64_string:
496
- import re
497
- matches = re.search(r'data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+);base64,', base64_string)
498
- if matches:
499
- mime_type = matches.group(1)
500
-
501
- extension = mime_type.split('/')[1]
502
- file_name = f"image.{extension}"
503
-
504
- return {
505
- "mimeType": mime_type,
506
- "fileName": file_name
507
- }
508
- def upload_base64_file(self, message, model):
509
- try:
510
- message_base64 = base64.b64encode(message.encode('utf-8')).decode('utf-8')
511
- upload_data = {
512
- "fileName": "message.txt",
513
- "fileMimeType": "text/plain",
514
- "content": message_base64
515
- }
516
-
517
- logger.info("发送文字文件请求", "Server")
518
- cookie = f"{Utils.create_auth_headers(model, True)};{CONFIG['SERVER']['CF_CLEARANCE']}"
519
- proxy_options = Utils.get_proxy_options()
520
- response = curl_requests.post(
521
- "https://grok.com/rest/app-chat/upload-file",
522
- headers={
523
- **DEFAULT_HEADERS,
524
- "Cookie":cookie
525
- },
526
- json=upload_data,
527
- impersonate="chrome133a",
528
- verify=False,
529
- **proxy_options
530
- )
531
-
532
- if response.status_code != 200:
533
- logger.error(f"上传文件失败,状态码:{response.status_code}", "Server")
534
- raise Exception(f"上传文件失败,状态码:{response.status_code}")
535
-
536
- result = response.json()
537
- logger.info(f"上传文件成功: {result}", "Server")
538
- return result.get("fileMetadataId", "")
539
-
540
- except Exception as error:
541
- logger.error(str(error), "Server")
542
- raise Exception(f"上传文件失败,状态码:{response.status_code}")
543
- def upload_base64_image(self, base64_data, url):
544
- try:
545
- if 'data:image' in base64_data:
546
- image_buffer = base64_data.split(',')[1]
547
- else:
548
- image_buffer = base64_data
549
-
550
- image_info = self.get_image_type(base64_data)
551
- mime_type = image_info["mimeType"]
552
- file_name = image_info["fileName"]
553
-
554
- upload_data = {
555
- "rpc": "uploadFile",
556
- "req": {
557
- "fileName": file_name,
558
- "fileMimeType": mime_type,
559
- "content": image_buffer
560
- }
561
- }
562
-
563
- logger.info("发送图片请求", "Server")
564
-
565
- proxy_options = Utils.get_proxy_options()
566
- response = curl_requests.post(
567
- url,
568
- headers={
569
- **DEFAULT_HEADERS,
570
- "Cookie":CONFIG["SERVER"]['COOKIE']
571
- },
572
- json=upload_data,
573
- impersonate="chrome133a",
574
- verify=False,
575
- **proxy_options
576
- )
577
-
578
- if response.status_code != 200:
579
- logger.error(f"上传图片失败,状态码:{response.status_code}", "Server")
580
- return ''
581
-
582
- result = response.json()
583
- logger.info(f"上传图片成功: {result}", "Server")
584
- return result.get("fileMetadataId", "")
585
-
586
- except Exception as error:
587
- logger.error(str(error), "Server")
588
- return ''
589
-
590
- def prepare_chat_request(self, request):
591
- if ((request["model"] == 'grok-2-imageGen' or request["model"] == 'grok-3-imageGen') and
592
- not CONFIG["API"]["PICGO_KEY"] and not CONFIG["API"]["TUMY_KEY"] and
593
- request.get("stream", False)):
594
- raise ValueError("该模型流式输出需要配置PICGO或者TUMY图床密钥!")
595
-
596
- todo_messages = request["messages"]
597
- if request["model"] in ['grok-2-imageGen', 'grok-3-imageGen', 'grok-3-deepsearch']:
598
- last_message = todo_messages[-1]
599
- if last_message["role"] != 'user':
600
- raise ValueError('此模型最后一条消息必须是用户消息!')
601
- todo_messages = [last_message]
602
- file_attachments = []
603
- messages = ''
604
- last_role = None
605
- last_content = ''
606
- message_length = 0
607
- convert_to_file = False
608
- last_message_content = ''
609
- search = request["model"] in ['grok-2-search', 'grok-3-search']
610
-
611
- # 移除<think>标签及其内容和base64图片
612
- def remove_think_tags(text):
613
- import re
614
- text = re.sub(r'<think>[\s\S]*?<\/think>', '', text).strip()
615
- text = re.sub(r'!\[image\]\(data:.*?base64,.*?\)', '[图片]', text)
616
- return text
617
-
618
- def process_content(content):
619
- if isinstance(content, list):
620
- text_content = ''
621
- for item in content:
622
- if item["type"] == 'image_url':
623
- text_content += ("[图片]" if not text_content else '\n[图片]')
624
- elif item["type"] == 'text':
625
- text_content += (remove_think_tags(item["text"]) if not text_content else '\n' + remove_think_tags(item["text"]))
626
- return text_content
627
- elif isinstance(content, dict) and content is not None:
628
- if content["type"] == 'image_url':
629
- return "[图片]"
630
- elif content["type"] == 'text':
631
- return remove_think_tags(content["text"])
632
- return remove_think_tags(self.process_message_content(content))
633
-
634
- for current in todo_messages:
635
- role = 'assistant' if current["role"] == 'assistant' else 'user'
636
- is_last_message = current == todo_messages[-1]
637
-
638
- if is_last_message and "content" in current:
639
- if isinstance(current["content"], list):
640
- for item in current["content"]:
641
- if item["type"] == 'image_url':
642
- processed_image = self.upload_base64_image(
643
- item["image_url"]["url"],
644
- f"{CONFIG['API']['BASE_URL']}/api/rpc"
645
- )
646
- if processed_image:
647
- file_attachments.append(processed_image)
648
- elif isinstance(current["content"], dict) and current["content"].get("type") == 'image_url':
649
- processed_image = self.upload_base64_image(
650
- current["content"]["image_url"]["url"],
651
- f"{CONFIG['API']['BASE_URL']}/api/rpc"
652
- )
653
- if processed_image:
654
- file_attachments.append(processed_image)
655
-
656
-
657
- text_content = process_content(current.get("content", ""))
658
- if is_last_message and convert_to_file:
659
- last_message_content = f"{role.upper()}: {text_content or '[图片]'}\n"
660
- continue
661
- if text_content or (is_last_message and file_attachments):
662
- if role == last_role and text_content:
663
- last_content += '\n' + text_content
664
- messages = messages[:messages.rindex(f"{role.upper()}: ")] + f"{role.upper()}: {last_content}\n"
665
- else:
666
- messages += f"{role.upper()}: {text_content or '[图片]'}\n"
667
- last_content = text_content
668
- last_role = role
669
- message_length += len(messages)
670
- if message_length >= 40000:
671
- convert_to_file = True
672
-
673
- if convert_to_file:
674
- file_id = self.upload_base64_file(messages, request["model"])
675
- if file_id:
676
- file_attachments.insert(0, file_id)
677
- messages = last_message_content.strip()
678
- if messages.strip() == '':
679
- if convert_to_file:
680
- messages = '基于txt文件内容进行回复:'
681
- else:
682
- raise ValueError('消息内容为空!')
683
- return {
684
- "temporary": CONFIG["API"].get("IS_TEMP_CONVERSATION", False),
685
- "modelName": self.model_id,
686
- "message": messages.strip(),
687
- "fileAttachments": file_attachments[:4],
688
- "imageAttachments": [],
689
- "disableSearch": False,
690
- "enableImageGeneration": True,
691
- "returnImageBytes": False,
692
- "returnRawGrokInXaiRequest": False,
693
- "enableImageStreaming": False,
694
- "imageGenerationCount": 1,
695
- "forceConcise": False,
696
- "toolOverrides": {
697
- "imageGen": request["model"] in ['grok-2-imageGen', 'grok-3-imageGen'],
698
- "webSearch": search,
699
- "xSearch": search,
700
- "xMediaSearch": search,
701
- "trendsSearch": search,
702
- "xPostAnalyze": search
703
- },
704
- "enableSideBySide": True,
705
- "isPreset": False,
706
- "sendFinalMetadata": True,
707
- "customInstructions": "",
708
- "deepsearchPreset": "default" if request["model"] == 'grok-3-deepsearch' else "",
709
- "isReasoning": request["model"] == 'grok-3-reasoning'
710
- }
711
-
712
- class MessageProcessor:
713
- @staticmethod
714
- def create_chat_response(message, model, is_stream=False):
715
- base_response = {
716
- "id": f"chatcmpl-{uuid.uuid4()}",
717
- "created": int(time.time()),
718
- "model": model
719
- }
720
-
721
- if is_stream:
722
- return {
723
- **base_response,
724
- "object": "chat.completion.chunk",
725
- "choices": [{
726
- "index": 0,
727
- "delta": {
728
- "content": message
729
- }
730
- }]
731
- }
732
-
733
- return {
734
- **base_response,
735
- "object": "chat.completion",
736
- "choices": [{
737
- "index": 0,
738
- "message": {
739
- "role": "assistant",
740
- "content": message
741
- },
742
- "finish_reason": "stop"
743
- }],
744
- "usage": None
745
- }
746
-
747
- def process_model_response(response, model):
748
- result = {"token": None, "imageUrl": None}
749
-
750
- if CONFIG["IS_IMG_GEN"]:
751
- if response.get("cachedImageGenerationResponse") and not CONFIG["IS_IMG_GEN2"]:
752
- result["imageUrl"] = response["cachedImageGenerationResponse"]["imageUrl"]
753
- return result
754
-
755
- if model == 'grok-2':
756
- result["token"] = response.get("token")
757
- elif model in ['grok-2-search', 'grok-3-search']:
758
- if response.get("webSearchResults") and CONFIG["ISSHOW_SEARCH_RESULTS"]:
759
- result["token"] = f"\r\n<think>{Utils.organize_search_results(response['webSearchResults'])}</think>\r\n"
760
- else:
761
- result["token"] = response.get("token")
762
- elif model == 'grok-3':
763
- result["token"] = response.get("token")
764
- elif model == 'grok-3-deepsearch':
765
- if response.get("messageStepId") and not CONFIG["SHOW_THINKING"]:
766
- return result
767
- if response.get("messageStepId") and not CONFIG["IS_THINKING"]:
768
- result["token"] = "<think>" + response.get("token", "")
769
- CONFIG["IS_THINKING"] = True
770
- elif not response.get("messageStepId") and CONFIG["IS_THINKING"] and response.get("messageTag") == "final":
771
- result["token"] = "</think>" + response.get("token", "")
772
- CONFIG["IS_THINKING"] = False
773
- elif (response.get("messageStepId") and CONFIG["IS_THINKING"] and response.get("messageTag") == "assistant") or response.get("messageTag") == "final":
774
- result["token"] = response.get("token")
775
- elif model == 'grok-3-reasoning':
776
- if response.get("isThinking") and not CONFIG["SHOW_THINKING"]:
777
- return result
778
-
779
- if response.get("isThinking") and not CONFIG["IS_THINKING"]:
780
- result["token"] = "<think>" + response.get("token", "")
781
- CONFIG["IS_THINKING"] = True
782
- elif not response.get("isThinking") and CONFIG["IS_THINKING"]:
783
- result["token"] = "</think>" + response.get("token", "")
784
- CONFIG["IS_THINKING"] = False
785
- else:
786
- result["token"] = response.get("token")
787
-
788
- return result
789
-
790
- def handle_image_response(image_url):
791
- max_retries = 2
792
- retry_count = 0
793
- image_base64_response = None
794
-
795
- while retry_count < max_retries:
796
- try:
797
- proxy_options = Utils.get_proxy_options()
798
- image_base64_response = curl_requests.get(
799
- f"https://assets.grok.com/{image_url}",
800
- headers={
801
- **DEFAULT_HEADERS,
802
- "Cookie":CONFIG["SERVER"]['COOKIE']
803
- },
804
- impersonate="chrome133a",
805
- **proxy_options
806
- )
807
-
808
- if image_base64_response.status_code == 200:
809
- break
810
-
811
- retry_count += 1
812
- if retry_count == max_retries:
813
- raise Exception(f"上游服务请求失败! status: {image_base64_response.status_code}")
814
-
815
- time.sleep(CONFIG["API"]["RETRY_TIME"] / 1000 * retry_count)
816
-
817
- except Exception as error:
818
- logger.error(str(error), "Server")
819
- retry_count += 1
820
- if retry_count == max_retries:
821
- raise
822
-
823
- time.sleep(CONFIG["API"]["RETRY_TIME"] / 1000 * retry_count)
824
-
825
- image_buffer = image_base64_response.content
826
-
827
- if not CONFIG["API"]["PICGO_KEY"] and not CONFIG["API"]["TUMY_KEY"]:
828
- base64_image = base64.b64encode(image_buffer).decode('utf-8')
829
- image_content_type = image_base64_response.headers.get('content-type', 'image/jpeg')
830
- return f"![image](data:{image_content_type};base64,{base64_image})"
831
-
832
- logger.info("开始上传图床", "Server")
833
-
834
- if CONFIG["API"]["PICGO_KEY"]:
835
- files = {'source': ('image.jpg', image_buffer, 'image/jpeg')}
836
- headers = {
837
- "X-API-Key": CONFIG["API"]["PICGO_KEY"]
838
- }
839
-
840
- response_url = requests.post(
841
- "https://www.picgo.net/api/1/upload",
842
- files=files,
843
- headers=headers
844
- )
845
-
846
- if response_url.status_code != 200:
847
- return "生图失败,请查看PICGO图床密钥是否设置正确"
848
- else:
849
- logger.info("生图成功", "Server")
850
- result = response_url.json()
851
- return f"![image]({result['image']['url']})"
852
-
853
-
854
- elif CONFIG["API"]["TUMY_KEY"]:
855
- files = {'file': ('image.jpg', image_buffer, 'image/jpeg')}
856
- headers = {
857
- "Accept": "application/json",
858
- 'Authorization': f"Bearer {CONFIG['API']['TUMY_KEY']}"
859
- }
860
-
861
- response_url = requests.post(
862
- "https://tu.my/api/v1/upload",
863
- files=files,
864
- headers=headers
865
- )
866
-
867
- if response_url.status_code != 200:
868
- return "生图失败,请查看TUMY图床密钥是否设置正确"
869
- else:
870
- try:
871
- result = response_url.json()
872
- logger.info("生图成功", "Server")
873
- return f"![image]({result['data']['links']['url']})"
874
- except Exception as error:
875
- logger.error(str(error), "Server")
876
- return "生图失败,请查看TUMY图床密钥是否设置正确"
877
-
878
- def handle_non_stream_response(response, model):
879
- try:
880
- logger.info("开始处理非流式响应", "Server")
881
-
882
- stream = response.iter_lines()
883
- full_response = ""
884
-
885
- CONFIG["IS_THINKING"] = False
886
- CONFIG["IS_IMG_GEN"] = False
887
- CONFIG["IS_IMG_GEN2"] = False
888
-
889
- for chunk in stream:
890
- if not chunk:
891
- continue
892
- try:
893
- line_json = json.loads(chunk.decode("utf-8").strip())
894
- if line_json.get("error"):
895
- logger.error(json.dumps(line_json, indent=2), "Server")
896
- return json.dumps({"error": "RateLimitError"}) + "\n\n"
897
-
898
- response_data = line_json.get("result", {}).get("response")
899
- if not response_data:
900
- continue
901
-
902
- if response_data.get("doImgGen") or response_data.get("imageAttachmentInfo"):
903
- CONFIG["IS_IMG_GEN"] = True
904
-
905
- result = process_model_response(response_data, model)
906
-
907
- if result["token"]:
908
- full_response += result["token"]
909
-
910
- if result["imageUrl"]:
911
- CONFIG["IS_IMG_GEN2"] = True
912
- return handle_image_response(result["imageUrl"])
913
-
914
- except json.JSONDecodeError:
915
- continue
916
- except Exception as e:
917
- logger.error(f"处理流式响应行时出错: {str(e)}", "Server")
918
- continue
919
-
920
- return full_response
921
- except Exception as error:
922
- logger.error(str(error), "Server")
923
- raise
924
- def handle_stream_response(response, model):
925
- def generate():
926
- logger.info("开始处理流式响应", "Server")
927
-
928
- stream = response.iter_lines()
929
- CONFIG["IS_THINKING"] = False
930
- CONFIG["IS_IMG_GEN"] = False
931
- CONFIG["IS_IMG_GEN2"] = False
932
-
933
- for chunk in stream:
934
- if not chunk:
935
- continue
936
- try:
937
- line_json = json.loads(chunk.decode("utf-8").strip())
938
- if line_json.get("error"):
939
- logger.error(json.dumps(line_json, indent=2), "Server")
940
- yield json.dumps({"error": "RateLimitError"}) + "\n\n"
941
- return
942
-
943
- response_data = line_json.get("result", {}).get("response")
944
- if not response_data:
945
- continue
946
-
947
- if response_data.get("doImgGen") or response_data.get("imageAttachmentInfo"):
948
- CONFIG["IS_IMG_GEN"] = True
949
-
950
- result = process_model_response(response_data, model)
951
-
952
- if result["token"]:
953
- yield f"data: {json.dumps(MessageProcessor.create_chat_response(result['token'], model, True))}\n\n"
954
-
955
- if result["imageUrl"]:
956
- CONFIG["IS_IMG_GEN2"] = True
957
- image_data = handle_image_response(result["imageUrl"])
958
- yield f"data: {json.dumps(MessageProcessor.create_chat_response(image_data, model, True))}\n\n"
959
-
960
- except json.JSONDecodeError:
961
- continue
962
- except Exception as e:
963
- logger.error(f"处理流式响应行时出错: {str(e)}", "Server")
964
- continue
965
-
966
- yield "data: [DONE]\n\n"
967
- return generate()
968
-
969
- def initialization():
970
- sso_array = os.getenv("SSO", "").split(',')
971
- logger.info("开始加载令牌", "Server")
972
- for sso in sso_array:
973
- if sso:
974
- token_manager.add_token(f"sso-rw={sso};sso={sso}")
975
-
976
- logger.info(f"成功加载令牌: {json.dumps(token_manager.get_all_tokens(), indent=2)}", "Server")
977
- logger.info(f"令牌加载完成,共加载: {len(token_manager.get_all_tokens())}个令牌", "Server")
978
-
979
- if CONFIG["API"]["PROXY"]:
980
- logger.info(f"代理已设置: {CONFIG['API']['PROXY']}", "Server")
981
-
982
- logger.info("初始化完成", "Server")
983
-
984
-
985
- app = Flask(__name__)
986
- app.wsgi_app = ProxyFix(app.wsgi_app)
987
- app.secret_key = os.getenv('FLASK_SECRET_KEY') or secrets.token_hex(16)
988
- app.json.sort_keys = False
989
-
990
- @app.route('/manager/login', methods=['GET', 'POST'])
991
- def manager_login():
992
- if CONFIG["ADMIN"]["MANAGER_SWITCH"]:
993
- if request.method == 'POST':
994
- password = request.form.get('password')
995
- if password == CONFIG["ADMIN"]["PASSWORD"]:
996
- session['is_logged_in'] = True
997
- return redirect('/manager')
998
- return render_template('login.html', error=True)
999
- return render_template('login.html', error=False)
1000
- else:
1001
- return redirect('/')
1002
-
1003
- def check_auth():
1004
- return session.get('is_logged_in', False)
1005
-
1006
- @app.route('/manager')
1007
- def manager():
1008
- if not check_auth():
1009
- return redirect('/manager/login')
1010
- return render_template('manager.html')
1011
-
1012
- @app.route('/manager/api/get')
1013
- def get_manager_tokens():
1014
- if not check_auth():
1015
- return jsonify({"error": "Unauthorized"}), 401
1016
- return jsonify(token_manager.get_token_status_map())
1017
-
1018
- @app.route('/manager/api/add', methods=['POST'])
1019
- def add_manager_token():
1020
- if not check_auth():
1021
- return jsonify({"error": "Unauthorized"}), 401
1022
- try:
1023
- sso = request.json.get('sso')
1024
- if not sso:
1025
- return jsonify({"error": "SSO token is required"}), 400
1026
- token_manager.add_token(f"sso-rw={sso};sso={sso}")
1027
- return jsonify({"success": True})
1028
- except Exception as e:
1029
- return jsonify({"error": str(e)}), 500
1030
-
1031
- @app.route('/manager/api/delete', methods=['POST'])
1032
- def delete_manager_token():
1033
- if not check_auth():
1034
- return jsonify({"error": "Unauthorized"}), 401
1035
- try:
1036
- sso = request.json.get('sso')
1037
- if not sso:
1038
- return jsonify({"error": "SSO token is required"}), 400
1039
- token_manager.delete_token(f"sso-rw={sso};sso={sso}")
1040
- return jsonify({"success": True})
1041
- except Exception as e:
1042
- return jsonify({"error": str(e)}), 500
1043
-
1044
- @app.route('/manager/api/cf_clearance', methods=['POST'])
1045
- def setCf_Manager_clearance():
1046
- if not check_auth():
1047
- return jsonify({"error": "Unauthorized"}), 401
1048
- try:
1049
- cf_clearance = request.json.get('cf_clearance')
1050
- if not cf_clearance:
1051
- return jsonify({"error": "cf_clearance is required"}), 400
1052
- CONFIG["SERVER"]['CF_CLEARANCE'] = cf_clearance
1053
- return jsonify({"success": True})
1054
- except Exception as e:
1055
- return jsonify({"error": str(e)}), 500
1056
-
1057
-
1058
- @app.route('/get/tokens', methods=['GET'])
1059
- def get_tokens():
1060
- auth_token = request.headers.get('Authorization', '').replace('Bearer ', '')
1061
- if CONFIG["API"]["IS_CUSTOM_SSO"]:
1062
- return jsonify({"error": '自定义的SSO令牌模式无法获取轮询sso令牌状态'}), 403
1063
- elif auth_token != CONFIG["API"]["API_KEY"]:
1064
- return jsonify({"error": 'Unauthorized'}), 401
1065
- return jsonify(token_manager.get_token_status_map())
1066
-
1067
- @app.route('/add/token', methods=['POST'])
1068
- def add_token():
1069
- auth_token = request.headers.get('Authorization', '').replace('Bearer ', '')
1070
- if CONFIG["API"]["IS_CUSTOM_SSO"]:
1071
- return jsonify({"error": '自定义的SSO令牌模式无法添加sso令牌'}), 403
1072
- elif auth_token != CONFIG["API"]["API_KEY"]:
1073
- return jsonify({"error": 'Unauthorized'}), 401
1074
-
1075
- try:
1076
- sso = request.json.get('sso')
1077
- token_manager.add_token(f"sso-rw={sso};sso={sso}")
1078
- return jsonify(token_manager.get_token_status_map().get(sso, {})), 200
1079
- except Exception as error:
1080
- logger.error(str(error), "Server")
1081
- return jsonify({"error": '添加sso令牌失败'}), 500
1082
-
1083
- @app.route('/set/cf_clearance', methods=['POST'])
1084
- def setCf_clearance():
1085
- auth_token = request.headers.get('Authorization', '').replace('Bearer ', '')
1086
- if auth_token != CONFIG["API"]["API_KEY"]:
1087
- return jsonify({"error": 'Unauthorized'}), 401
1088
- try:
1089
- cf_clearance = request.json.get('cf_clearance')
1090
- CONFIG["SERVER"]['CF_CLEARANCE'] = cf_clearance
1091
- return jsonify({"message": '设置cf_clearance成功'}), 200
1092
- except Exception as error:
1093
- logger.error(str(error), "Server")
1094
- return jsonify({"error": '设置cf_clearance失败'}), 500
1095
-
1096
- @app.route('/delete/token', methods=['POST'])
1097
- def delete_token():
1098
- auth_token = request.headers.get('Authorization', '').replace('Bearer ', '')
1099
- if CONFIG["API"]["IS_CUSTOM_SSO"]:
1100
- return jsonify({"error": '自定义的SSO令牌模式无法删除sso令牌'}), 403
1101
- elif auth_token != CONFIG["API"]["API_KEY"]:
1102
- return jsonify({"error": 'Unauthorized'}), 401
1103
-
1104
- try:
1105
- sso = request.json.get('sso')
1106
- token_manager.delete_token(f"sso-rw={sso};sso={sso}")
1107
- return jsonify({"message": '删除sso令牌成功'}), 200
1108
- except Exception as error:
1109
- logger.error(str(error), "Server")
1110
- return jsonify({"error": '删除sso令牌失败'}), 500
1111
-
1112
- @app.route('/v1/models', methods=['GET'])
1113
- def get_models():
1114
- return jsonify({
1115
- "object": "list",
1116
- "data": [
1117
- {
1118
- "id": model,
1119
- "object": "model",
1120
- "created": int(time.time()),
1121
- "owned_by": "grok"
1122
- }
1123
- for model in CONFIG["MODELS"].keys()
1124
- ]
1125
- })
1126
-
1127
- @app.route('/v1/chat/completions', methods=['POST'])
1128
- def chat_completions():
1129
- response_status_code = 500
1130
- try:
1131
- auth_token = request.headers.get('Authorization',
1132
- '').replace('Bearer ', '')
1133
- if auth_token:
1134
- if CONFIG["API"]["IS_CUSTOM_SSO"]:
1135
- result = f"sso={auth_token};sso-rw={auth_token}"
1136
- token_manager.set_token(result)
1137
- elif auth_token != CONFIG["API"]["API_KEY"]:
1138
- return jsonify({"error": 'Unauthorized'}), 401
1139
- else:
1140
- return jsonify({"error": 'API_KEY缺失'}), 401
1141
-
1142
- data = request.json
1143
- model = data.get("model")
1144
- stream = data.get("stream", False)
1145
-
1146
- retry_count = 0
1147
- grok_client = GrokApiClient(model)
1148
- request_payload = grok_client.prepare_chat_request(data)
1149
-
1150
-
1151
- while retry_count < CONFIG["RETRY"]["MAX_ATTEMPTS"]:
1152
- retry_count += 1
1153
- CONFIG["API"]["SIGNATURE_COOKIE"] = Utils.create_auth_headers(model)
1154
-
1155
- if not CONFIG["API"]["SIGNATURE_COOKIE"]:
1156
- raise ValueError('该模型无可用令牌')
1157
-
1158
- logger.info(
1159
- f"当前令牌: {json.dumps(CONFIG['API']['SIGNATURE_COOKIE'], indent=2)}","Server")
1160
- logger.info(
1161
- f"当前可用模型的全部可用��量: {json.dumps(token_manager.get_remaining_token_request_capacity(), indent=2)}","Server")
1162
-
1163
- if CONFIG['SERVER']['CF_CLEARANCE']:
1164
- CONFIG["SERVER"]['COOKIE'] = f"{CONFIG['API']['SIGNATURE_COOKIE']};{CONFIG['SERVER']['CF_CLEARANCE']}"
1165
- else:
1166
- CONFIG["SERVER"]['COOKIE'] = CONFIG['API']['SIGNATURE_COOKIE']
1167
- logger.info(json.dumps(request_payload,indent=2),"Server")
1168
- try:
1169
- proxy_options = Utils.get_proxy_options()
1170
- response = curl_requests.post(
1171
- f"{CONFIG['API']['BASE_URL']}/rest/app-chat/conversations/new",
1172
- headers={
1173
- **DEFAULT_HEADERS,
1174
- "Cookie":CONFIG["SERVER"]['COOKIE']
1175
- },
1176
- json=request_payload,
1177
- impersonate="chrome133a",
1178
- verify=False,
1179
- stream=True,
1180
- **proxy_options)
1181
- logger.info(CONFIG["SERVER"]['COOKIE'],"Server")
1182
- if response.status_code == 200:
1183
- response_status_code = 200
1184
- logger.info("请求成功", "Server")
1185
- logger.info(f"当前{model}剩余可用令牌数: {token_manager.get_token_count_for_model(model)}","Server")
1186
-
1187
- try:
1188
- if stream:
1189
- return Response(stream_with_context(
1190
- handle_stream_response(response, model)),content_type='text/event-stream')
1191
- else:
1192
- content = handle_non_stream_response(response, model)
1193
- return jsonify(
1194
- MessageProcessor.create_chat_response(content, model))
1195
-
1196
- except Exception as error:
1197
- logger.error(str(error), "Server")
1198
- if CONFIG["API"]["IS_CUSTOM_SSO"]:
1199
- raise ValueError(f"自定义SSO令牌当前模型{model}的请求次数已失效")
1200
- token_manager.remove_token_from_model(model, CONFIG["API"]["SIGNATURE_COOKIE"])
1201
- if token_manager.get_token_count_for_model(model) == 0:
1202
- raise ValueError(f"{model} 次数已达上限,请切换其他模型或者重新对话")
1203
- elif response.status_code == 403:
1204
- response_status_code = 403
1205
- token_manager.reduce_token_request_count(model,1)#重置去除当前因为错误未成功请求的次数,确保不会因为错误未成功请求的次数导致次数上限
1206
- if token_manager.get_token_count_for_model(model) == 0:
1207
- raise ValueError(f"{model} 次数已达上限,请切换其他模型或者重新对话")
1208
- raise ValueError(f"IP暂时被封无法破盾,请稍后重试或者更换ip")
1209
- elif response.status_code == 429:
1210
- response_status_code = 429
1211
- token_manager.reduce_token_request_count(model,1)
1212
- if CONFIG["API"]["IS_CUSTOM_SSO"]:
1213
- raise ValueError(f"自定义SSO令牌当前模型{model}的请求次数已失效")
1214
-
1215
- token_manager.remove_token_from_model(
1216
- model, CONFIG["API"]["SIGNATURE_COOKIE"])
1217
- if token_manager.get_token_count_for_model(model) == 0:
1218
- raise ValueError(f"{model} 次数已达上限,请切换其他模型或者重新对话")
1219
-
1220
- else:
1221
- if CONFIG["API"]["IS_CUSTOM_SSO"]:
1222
- raise ValueError(f"自定义SSO令牌当前模型{model}的请求次数已失效")
1223
-
1224
- logger.error(f"令牌异常错误状态!status: {response.status_code}","Server")
1225
- token_manager.remove_token_from_model(model, CONFIG["API"]["SIGNATURE_COOKIE"])
1226
- logger.info(
1227
- f"当前{model}剩余可用令牌数: {token_manager.get_token_count_for_model(model)}",
1228
- "Server")
1229
-
1230
- except Exception as e:
1231
- logger.error(f"请求处理异常: {str(e)}", "Server")
1232
- if CONFIG["API"]["IS_CUSTOM_SSO"]:
1233
- raise
1234
- continue
1235
- if response_status_code == 403:
1236
- raise ValueError('IP暂时被封无法破盾,请稍后重试或者更换ip')
1237
- elif response_status_code == 500:
1238
- raise ValueError('当前模型所有令牌暂无可用,请稍后重试')
1239
-
1240
- except Exception as error:
1241
- logger.error(str(error), "ChatAPI")
1242
- return jsonify(
1243
- {"error": {
1244
- "message": str(error),
1245
- "type": "server_error"
1246
- }}), response_status_code
1247
-
1248
- @app.route('/', defaults={'path': ''})
1249
- @app.route('/<path:path>')
1250
- def catch_all(path):
1251
- return 'api运行正常', 200
1252
-
1253
- if __name__ == '__main__':
1254
- token_manager = AuthTokenManager()
1255
- initialization()
1256
-
1257
- app.run(
1258
- host='0.0.0.0',
1259
- port=CONFIG["SERVER"]["PORT"],
1260
- debug=False
1261
- )