issaocean commited on
Commit
af0d9d3
·
verified ·
1 Parent(s): 1fa635a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +156 -43
app.py CHANGED
@@ -93,6 +93,7 @@ CONFIG = {
93
  "grok-3-reasoning": "grok-3"
94
  },
95
  "API": {
 
96
  "IS_CUSTOM_SSO": os.environ.get("IS_CUSTOM_SSO", "false").lower() == "true",
97
  "BASE_URL": "https://grok.com",
98
  "API_KEY": os.environ.get("API_KEY", "sk-123456"),
@@ -103,9 +104,12 @@ CONFIG = {
103
  "PROXY": os.environ.get("PROXY") or None
104
  },
105
  "SERVER": {
 
 
106
  "PORT": int(os.environ.get("PORT", 5200))
107
  },
108
  "RETRY": {
 
109
  "MAX_ATTEMPTS": 2
110
  },
111
  "SHOW_THINKING": os.environ.get("SHOW_THINKING") == "true",
@@ -216,14 +220,48 @@ class AuthTokenManager:
216
  except Exception as error:
217
  logger.error(f"令牌删除失败: {str(error)}")
218
  return False
219
-
220
- def get_next_token_for_model(self, model_id):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  normalized_model = self.normalize_model_name(model_id)
222
 
223
  if normalized_model not in self.token_model_map or not self.token_model_map[normalized_model]:
224
  return None
225
 
226
  token_entry = self.token_model_map[normalized_model][0]
 
 
227
 
228
  if token_entry:
229
  if token_entry["StartCallTime"] is None:
@@ -376,6 +414,14 @@ class AuthTokenManager:
376
  for entry in model_tokens:
377
  all_tokens.add(entry["token"])
378
  return list(all_tokens)
 
 
 
 
 
 
 
 
379
 
380
  def get_token_status_map(self):
381
  return self.token_status_map
@@ -400,8 +446,8 @@ class Utils:
400
  return '\n\n'.join(formatted_results)
401
 
402
  @staticmethod
403
- def create_auth_headers(model):
404
- return token_manager.get_next_token_for_model(model)
405
 
406
  @staticmethod
407
  def get_proxy_options():
@@ -410,12 +456,17 @@ class Utils:
410
 
411
  if proxy:
412
  logger.info(f"使用代理: {proxy}", "Server")
413
- proxy_options["proxies"] = {"https": proxy, "http": proxy}
414
-
415
  if proxy.startswith("socks5://"):
416
- proxy_options["proxies"] = {"https": proxy, "http": proxy}
417
- proxy_options["proxy_type"] = "socks5"
418
-
 
 
 
 
 
 
419
  return proxy_options
420
 
421
  class GrokApiClient:
@@ -444,7 +495,40 @@ class GrokApiClient:
444
  "mimeType": mime_type,
445
  "fileName": file_name
446
  }
 
 
 
 
 
 
 
 
447
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
448
  def upload_base64_image(self, base64_data, url):
449
  try:
450
  if 'data:image' in base64_data:
@@ -472,7 +556,7 @@ class GrokApiClient:
472
  url,
473
  headers={
474
  **DEFAULT_HEADERS,
475
- "Cookie": CONFIG["API"]["SIGNATURE_COOKIE"]
476
  },
477
  json=upload_data,
478
  impersonate="chrome133a",
@@ -508,6 +592,9 @@ class GrokApiClient:
508
  messages = ''
509
  last_role = None
510
  last_content = ''
 
 
 
511
  search = request["model"] in ['grok-2-search', 'grok-3-search']
512
 
513
  # 移除<think>标签及其内容和base64图片
@@ -557,7 +644,9 @@ class GrokApiClient:
557
 
558
 
559
  text_content = process_content(current.get("content", ""))
560
-
 
 
561
  if text_content or (is_last_message and file_attachments):
562
  if role == last_role and text_content:
563
  last_content += '\n' + text_content
@@ -566,7 +655,14 @@ class GrokApiClient:
566
  messages += f"{role.upper()}: {text_content or '[图片]'}\n"
567
  last_content = text_content
568
  last_role = role
569
-
 
 
 
 
 
 
 
570
  return {
571
  "temporary": CONFIG["API"].get("IS_TEMP_CONVERSATION", False),
572
  "modelName": self.model_id,
@@ -686,7 +782,7 @@ def handle_image_response(image_url):
686
  f"https://assets.grok.com/{image_url}",
687
  headers={
688
  **DEFAULT_HEADERS,
689
- "Cookie": CONFIG["API"]["SIGNATURE_COOKIE"]
690
  },
691
  impersonate="chrome120",
692
  **proxy_options
@@ -902,7 +998,20 @@ def add_token():
902
  except Exception as error:
903
  logger.error(str(error), "Server")
904
  return jsonify({"error": '添加sso令牌失败'}), 500
905
-
 
 
 
 
 
 
 
 
 
 
 
 
 
906
  @app.route('/delete/token', methods=['POST'])
907
  def delete_token():
908
  auth_token = request.headers.get('Authorization', '').replace('Bearer ', '')
@@ -936,6 +1045,7 @@ def get_models():
936
 
937
  @app.route('/v1/chat/completions', methods=['POST'])
938
  def chat_completions():
 
939
  try:
940
  auth_token = request.headers.get('Authorization',
941
  '').replace('Bearer ', '')
@@ -955,63 +1065,66 @@ def chat_completions():
955
  retry_count = 0
956
  grok_client = GrokApiClient(model)
957
  request_payload = grok_client.prepare_chat_request(data)
 
958
 
959
  while retry_count < CONFIG["RETRY"]["MAX_ATTEMPTS"]:
960
  retry_count += 1
961
- CONFIG["API"]["SIGNATURE_COOKIE"] = Utils.create_auth_headers(
962
- model)
963
 
964
  if not CONFIG["API"]["SIGNATURE_COOKIE"]:
965
  raise ValueError('该模型无可用令牌')
966
 
967
  logger.info(
968
- f"当前令牌: {json.dumps(CONFIG['API']['SIGNATURE_COOKIE'], indent=2)}",
969
- "Server")
970
  logger.info(
971
- f"当前可用模型的全部可用数量: {json.dumps(token_manager.get_remaining_token_request_capacity(), indent=2)}",
972
- "Server")
973
-
 
 
974
  try:
975
  proxy_options = Utils.get_proxy_options()
976
  response = curl_requests.post(
977
  f"{CONFIG['API']['BASE_URL']}/rest/app-chat/conversations/new",
978
  headers={
979
- **DEFAULT_HEADERS, "Cookie":
980
- CONFIG["API"]["SIGNATURE_COOKIE"]
981
  },
982
  data=json.dumps(request_payload),
983
  impersonate="chrome133a",
984
  stream=True,
985
  **proxy_options)
 
986
  if response.status_code == 200:
 
987
  logger.info("请求成功", "Server")
988
- logger.info(
989
- f"当前{model}剩余可用令牌数: {token_manager.get_token_count_for_model(model)}",
990
- "Server")
991
 
992
  try:
993
  if stream:
994
  return Response(stream_with_context(
995
- handle_stream_response(response, model)),
996
- content_type='text/event-stream')
997
  else:
998
- content = handle_non_stream_response(
999
- response, model)
1000
  return jsonify(
1001
- MessageProcessor.create_chat_response(
1002
- content, model))
1003
 
1004
  except Exception as error:
1005
  logger.error(str(error), "Server")
1006
  if CONFIG["API"]["IS_CUSTOM_SSO"]:
1007
  raise ValueError(f"自定义SSO令牌当前模型{model}的请求次数已失效")
1008
-
1009
- token_manager.remove_token_from_model(
1010
- model, CONFIG["API"]["SIGNATURE_COOKIE"])
1011
  if token_manager.get_token_count_for_model(model) == 0:
1012
  raise ValueError(f"{model} 次数已达上限,请切换其他模型或者重新对话")
1013
-
 
 
 
 
 
1014
  elif response.status_code == 429:
 
 
1015
  if CONFIG["API"]["IS_CUSTOM_SSO"]:
1016
  raise ValueError(f"自定义SSO令牌当前模型{model}的请求次数已失效")
1017
 
@@ -1024,10 +1137,8 @@ def chat_completions():
1024
  if CONFIG["API"]["IS_CUSTOM_SSO"]:
1025
  raise ValueError(f"自定义SSO令牌当前模���{model}的请求次数已失效")
1026
 
1027
- logger.error(f"令牌异常错误状态!status: {response.status_code}",
1028
- "Server")
1029
- token_manager.remove_token_from_model(
1030
- model, CONFIG["API"]["SIGNATURE_COOKIE"])
1031
  logger.info(
1032
  f"当前{model}剩余可用令牌数: {token_manager.get_token_count_for_model(model)}",
1033
  "Server")
@@ -1037,8 +1148,10 @@ def chat_completions():
1037
  if CONFIG["API"]["IS_CUSTOM_SSO"]:
1038
  raise
1039
  continue
1040
-
1041
- raise ValueError('当前模型所有令牌都已耗尽')
 
 
1042
 
1043
  except Exception as error:
1044
  logger.error(str(error), "ChatAPI")
@@ -1046,7 +1159,7 @@ def chat_completions():
1046
  {"error": {
1047
  "message": str(error),
1048
  "type": "server_error"
1049
- }}), 500
1050
 
1051
  @app.route('/', defaults={'path': ''})
1052
  @app.route('/<path:path>')
 
93
  "grok-3-reasoning": "grok-3"
94
  },
95
  "API": {
96
+ "IS_TEMP_CONVERSATION": os.environ.get("IS_TEMP_CONVERSATION", "true").lower() == "true",
97
  "IS_CUSTOM_SSO": os.environ.get("IS_CUSTOM_SSO", "false").lower() == "true",
98
  "BASE_URL": "https://grok.com",
99
  "API_KEY": os.environ.get("API_KEY", "sk-123456"),
 
104
  "PROXY": os.environ.get("PROXY") or None
105
  },
106
  "SERVER": {
107
+ "COOKIE": None,
108
+ "CF_CLEARANCE":os.environ.get("CF_CLEARANCE") or None,
109
  "PORT": int(os.environ.get("PORT", 5200))
110
  },
111
  "RETRY": {
112
+ "RETRYSWITCH": False,
113
  "MAX_ATTEMPTS": 2
114
  },
115
  "SHOW_THINKING": os.environ.get("SHOW_THINKING") == "true",
 
220
  except Exception as error:
221
  logger.error(f"令牌删除失败: {str(error)}")
222
  return False
223
+ def reduce_token_request_count(self, model_id, count):
224
+ try:
225
+ normalized_model = self.normalize_model_name(model_id)
226
+
227
+ if normalized_model not in self.token_model_map:
228
+ logger.error(f"模型 {normalized_model} 不存在", "TokenManager")
229
+ return False
230
+
231
+ if not self.token_model_map[normalized_model]:
232
+ logger.error(f"模型 {normalized_model} 没有可用的token", "TokenManager")
233
+ return False
234
+
235
+ token_entry = self.token_model_map[normalized_model][0]
236
+
237
+ # 确保RequestCount不会小于0
238
+ new_count = max(0, token_entry["RequestCount"] - count)
239
+ reduction = token_entry["RequestCount"] - new_count
240
+
241
+ token_entry["RequestCount"] = new_count
242
+
243
+ # 更新token状态
244
+ if token_entry["token"]:
245
+ sso = token_entry["token"].split("sso=")[1].split(";")[0]
246
+ if sso in self.token_status_map and normalized_model in self.token_status_map[sso]:
247
+ self.token_status_map[sso][normalized_model]["totalRequestCount"] = max(
248
+ 0,
249
+ self.token_status_map[sso][normalized_model]["totalRequestCount"] - reduction
250
+ )
251
+ return True
252
+
253
+ except Exception as error:
254
+ logger.error(f"重置校对token请求次数时发生错误: {str(error)}", "TokenManager")
255
+ return False
256
+ def get_next_token_for_model(self, model_id, is_return=False):
257
  normalized_model = self.normalize_model_name(model_id)
258
 
259
  if normalized_model not in self.token_model_map or not self.token_model_map[normalized_model]:
260
  return None
261
 
262
  token_entry = self.token_model_map[normalized_model][0]
263
+ if is_return:
264
+ return token_entry["token"]
265
 
266
  if token_entry:
267
  if token_entry["StartCallTime"] is None:
 
414
  for entry in model_tokens:
415
  all_tokens.add(entry["token"])
416
  return list(all_tokens)
417
+ def get_current_token(self, model_id):
418
+ normalized_model = self.normalize_model_name(model_id)
419
+
420
+ if normalized_model not in self.token_model_map or not self.token_model_map[normalized_model]:
421
+ return None
422
+
423
+ token_entry = self.token_model_map[normalized_model][0]
424
+ return token_entry["token"]
425
 
426
  def get_token_status_map(self):
427
  return self.token_status_map
 
446
  return '\n\n'.join(formatted_results)
447
 
448
  @staticmethod
449
+ def create_auth_headers(model, is_return=False):
450
+ return token_manager.get_next_token_for_model(model, is_return)
451
 
452
  @staticmethod
453
  def get_proxy_options():
 
456
 
457
  if proxy:
458
  logger.info(f"使用代理: {proxy}", "Server")
459
+
 
460
  if proxy.startswith("socks5://"):
461
+ proxy_options["proxy"] = proxy
462
+
463
+ if '@' in proxy:
464
+ auth_part = proxy.split('@')[0].split('://')[1]
465
+ if ':' in auth_part:
466
+ username, password = auth_part.split(':')
467
+ proxy_options["proxy_auth"] = (username, password)
468
+ else:
469
+ proxy_options["proxies"] = {"https": proxy, "http": proxy}
470
  return proxy_options
471
 
472
  class GrokApiClient:
 
495
  "mimeType": mime_type,
496
  "fileName": file_name
497
  }
498
+ def upload_base64_file(self, message, model):
499
+ try:
500
+ message_base64 = base64.b64encode(message.encode('utf-8')).decode('utf-8')
501
+ upload_data = {
502
+ "fileName": "message.txt",
503
+ "fileMimeType": "text/plain",
504
+ "content": message_base64
505
+ }
506
 
507
+ logger.info("发送文字文件请求", "Server")
508
+ cookie = f"{Utils.create_auth_headers(model, True)};{CONFIG['SERVER']['CF_CLEARANCE']}"
509
+ proxy_options = Utils.get_proxy_options()
510
+ response = curl_requests.post(
511
+ "https://grok.com/rest/app-chat/upload-file",
512
+ headers={
513
+ **DEFAULT_HEADERS,
514
+ "Cookie":cookie
515
+ },
516
+ json=upload_data,
517
+ impersonate="chrome133a",
518
+ **proxy_options
519
+ )
520
+
521
+ if response.status_code != 200:
522
+ logger.error(f"上传文件失败,状态码:{response.status_code}", "Server")
523
+ return ''
524
+
525
+ result = response.json()
526
+ logger.info(f"上传文件成功: {result}", "Server")
527
+ return result.get("fileMetadataId", "")
528
+
529
+ except Exception as error:
530
+ logger.error(str(error), "Server")
531
+ return ''
532
  def upload_base64_image(self, base64_data, url):
533
  try:
534
  if 'data:image' in base64_data:
 
556
  url,
557
  headers={
558
  **DEFAULT_HEADERS,
559
+ "Cookie":CONFIG["SERVER"]['COOKIE']
560
  },
561
  json=upload_data,
562
  impersonate="chrome133a",
 
592
  messages = ''
593
  last_role = None
594
  last_content = ''
595
+ message_length = 0
596
+ convert_to_file = False
597
+ last_message_content = ''
598
  search = request["model"] in ['grok-2-search', 'grok-3-search']
599
 
600
  # 移除<think>标签及其内容和base64图片
 
644
 
645
 
646
  text_content = process_content(current.get("content", ""))
647
+ if is_last_message:
648
+ last_message_content = f"{role.upper()}: {text_content or '[图片]'}\n"
649
+ continue
650
  if text_content or (is_last_message and file_attachments):
651
  if role == last_role and text_content:
652
  last_content += '\n' + text_content
 
655
  messages += f"{role.upper()}: {text_content or '[图片]'}\n"
656
  last_content = text_content
657
  last_role = role
658
+ message_length += len(messages)
659
+ if message_length >= 40000:
660
+ convert_to_file = True
661
+ if convert_to_file:
662
+ file_id = self.upload_base64_file(messages, request["model"])
663
+ if file_id:
664
+ file_attachments.insert(0, file_id)
665
+ messages = last_message_content.strip()
666
  return {
667
  "temporary": CONFIG["API"].get("IS_TEMP_CONVERSATION", False),
668
  "modelName": self.model_id,
 
782
  f"https://assets.grok.com/{image_url}",
783
  headers={
784
  **DEFAULT_HEADERS,
785
+ "Cookie":CONFIG["SERVER"]['COOKIE']
786
  },
787
  impersonate="chrome120",
788
  **proxy_options
 
998
  except Exception as error:
999
  logger.error(str(error), "Server")
1000
  return jsonify({"error": '添加sso令牌失败'}), 500
1001
+
1002
+ @app.route('/set/cf_clearance', methods=['POST'])
1003
+ def setCf_clearance():
1004
+ auth_token = request.headers.get('Authorization', '').replace('Bearer ', '')
1005
+ if auth_token != CONFIG["API"]["API_KEY"]:
1006
+ return jsonify({"error": 'Unauthorized'}), 401
1007
+ try:
1008
+ cf_clearance = request.json.get('cf_clearance')
1009
+ CONFIG["SERVER"]['CF_CLEARANCE'] = cf_clearance
1010
+ return jsonify({"message": '设置cf_clearance成功'}), 200
1011
+ except Exception as error:
1012
+ logger.error(str(error), "Server")
1013
+ return jsonify({"error": '设置cf_clearance失败'}), 500
1014
+
1015
  @app.route('/delete/token', methods=['POST'])
1016
  def delete_token():
1017
  auth_token = request.headers.get('Authorization', '').replace('Bearer ', '')
 
1045
 
1046
  @app.route('/v1/chat/completions', methods=['POST'])
1047
  def chat_completions():
1048
+ response_status_code = 500
1049
  try:
1050
  auth_token = request.headers.get('Authorization',
1051
  '').replace('Bearer ', '')
 
1065
  retry_count = 0
1066
  grok_client = GrokApiClient(model)
1067
  request_payload = grok_client.prepare_chat_request(data)
1068
+
1069
 
1070
  while retry_count < CONFIG["RETRY"]["MAX_ATTEMPTS"]:
1071
  retry_count += 1
1072
+ CONFIG["API"]["SIGNATURE_COOKIE"] = Utils.create_auth_headers(model)
 
1073
 
1074
  if not CONFIG["API"]["SIGNATURE_COOKIE"]:
1075
  raise ValueError('该模型无可用令牌')
1076
 
1077
  logger.info(
1078
+ f"当前令牌: {json.dumps(CONFIG['API']['SIGNATURE_COOKIE'], indent=2)}","Server")
 
1079
  logger.info(
1080
+ f"当前可用模型的全部可用数量: {json.dumps(token_manager.get_remaining_token_request_capacity(), indent=2)}","Server")
1081
+ if CONFIG['SERVER']['CF_CLEARANCE']:
1082
+ CONFIG["SERVER"]['COOKIE'] = f"{CONFIG['API']['SIGNATURE_COOKIE']};{CONFIG['SERVER']['CF_CLEARANCE']}"
1083
+ else:
1084
+ CONFIG["SERVER"]['COOKIE'] = CONFIG['API']['SIGNATURE_COOKIE']
1085
  try:
1086
  proxy_options = Utils.get_proxy_options()
1087
  response = curl_requests.post(
1088
  f"{CONFIG['API']['BASE_URL']}/rest/app-chat/conversations/new",
1089
  headers={
1090
+ **DEFAULT_HEADERS,
1091
+ "Cookie":CONFIG["SERVER"]['COOKIE']
1092
  },
1093
  data=json.dumps(request_payload),
1094
  impersonate="chrome133a",
1095
  stream=True,
1096
  **proxy_options)
1097
+ logger.info(CONFIG["SERVER"]['COOKIE'],"Server")
1098
  if response.status_code == 200:
1099
+ response_status_code = 200
1100
  logger.info("请求成功", "Server")
1101
+ logger.info(f"当前{model}剩余可用令牌数: {token_manager.get_token_count_for_model(model)}","Server")
 
 
1102
 
1103
  try:
1104
  if stream:
1105
  return Response(stream_with_context(
1106
+ handle_stream_response(response, model)),content_type='text/event-stream')
 
1107
  else:
1108
+ content = handle_non_stream_response(response, model)
 
1109
  return jsonify(
1110
+ MessageProcessor.create_chat_response(content, model))
 
1111
 
1112
  except Exception as error:
1113
  logger.error(str(error), "Server")
1114
  if CONFIG["API"]["IS_CUSTOM_SSO"]:
1115
  raise ValueError(f"自定义SSO令牌当前模型{model}的请求次数已失效")
1116
+ token_manager.remove_token_from_model(model, CONFIG["API"]["SIGNATURE_COOKIE"])
 
 
1117
  if token_manager.get_token_count_for_model(model) == 0:
1118
  raise ValueError(f"{model} 次数已达上限,请切换其他模型或者重新对话")
1119
+ elif response.status_code == 403:
1120
+ response_status_code = 403
1121
+ token_manager.reduce_token_request_count(model,1)#重置去除当前因为错误未成功请求的次数,确保不会因为错误未成功请求的次数导致次数上限
1122
+ if token_manager.get_token_count_for_model(model) == 0:
1123
+ raise ValueError(f"{model} 次数已达上限,请切换其他模型或者重新对话")
1124
+ raise ValueError(f"IP暂时被封无法破盾,请稍后重试或者更换ip")
1125
  elif response.status_code == 429:
1126
+ response_status_code = 429
1127
+ token_manager.reduce_token_request_count(model,1)
1128
  if CONFIG["API"]["IS_CUSTOM_SSO"]:
1129
  raise ValueError(f"自定义SSO令牌当前模型{model}的请求次数已失效")
1130
 
 
1137
  if CONFIG["API"]["IS_CUSTOM_SSO"]:
1138
  raise ValueError(f"自定义SSO令牌当前模���{model}的请求次数已失效")
1139
 
1140
+ logger.error(f"令牌异常错误状态!status: {response.status_code}","Server")
1141
+ token_manager.remove_token_from_model(model, CONFIG["API"]["SIGNATURE_COOKIE"])
 
 
1142
  logger.info(
1143
  f"当前{model}剩余可用令牌数: {token_manager.get_token_count_for_model(model)}",
1144
  "Server")
 
1148
  if CONFIG["API"]["IS_CUSTOM_SSO"]:
1149
  raise
1150
  continue
1151
+ if response_status_code == 403:
1152
+ raise ValueError('IP暂时被封无法破盾,请稍后重试或者更换ip')
1153
+ elif response_status_code == 500:
1154
+ raise ValueError('当前模型所有令牌暂无可用,请稍后重试')
1155
 
1156
  except Exception as error:
1157
  logger.error(str(error), "ChatAPI")
 
1159
  {"error": {
1160
  "message": str(error),
1161
  "type": "server_error"
1162
+ }}), response_status_code
1163
 
1164
  @app.route('/', defaults={'path': ''})
1165
  @app.route('/<path:path>')