isididiidid commited on
Commit
c36ccd7
·
verified ·
1 Parent(s): 5d1621a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +343 -266
app.py CHANGED
@@ -389,6 +389,79 @@ class AuthTokenManager:
389
 
390
  token_manager = AuthTokenManager()
391
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
392
  async def initialize_tokens():
393
  sso_array = os.getenv("SSO", "").split(',')
394
  logger.info("开始加载令牌", "Server")
@@ -401,6 +474,17 @@ async def initialize_tokens():
401
  logger.info(f"令牌加载完成,共加载: {len(token_manager.get_all_tokens())}个令牌", "Server")
402
  logger.info("初始化完成", "Server")
403
 
 
 
 
 
 
 
 
 
 
 
 
404
  class Utils:
405
  @staticmethod
406
  async def organize_search_results(search_results):
@@ -427,12 +511,22 @@ class Utils:
427
  )
428
 
429
  class GrokApiClient:
430
- def __init__(self, model_id):
431
  if model_id not in CONFIG["MODELS"]:
432
  raise ValueError(f"不支持的模型: {model_id}")
433
  self.model = model_id
434
  self.model_id = CONFIG["MODELS"][model_id]
435
- self.scraper = cloudscraper.create_scraper()
 
 
 
 
 
 
 
 
 
 
436
 
437
  def process_message_content(self, content):
438
  if isinstance(content, str):
@@ -527,7 +621,9 @@ class GrokApiClient:
527
  def remove_think_tags(text):
528
  import re
529
  text = re.sub(r'<think>[\s\S]*?<\/think>', '', text).strip()
530
- text = re.sub(r'!\[image\]\(data:.*?base64,.*?\)', '[图片]', text)
 
 
531
  return text
532
 
533
  async def process_image_url(content):
@@ -628,6 +724,7 @@ class MessageProcessor:
628
  "choices": [{
629
  "index": 0,
630
  "delta": {
 
631
  "content": message
632
  }
633
  }]
@@ -754,6 +851,15 @@ async def stream_response_generator(response, model):
754
  logger.error(f"流式响应总体错误: {str(error)}", "Server")
755
  raise error
756
 
 
 
 
 
 
 
 
 
 
757
  async def handle_normal_response(response, model):
758
  try:
759
  full_response = ''
@@ -822,301 +928,272 @@ async def handle_normal_response(response, model):
822
  continue
823
 
824
  if CONFIG["IS_IMG_GEN2"] and image_url:
825
- data_image = await handle_image_response(image_url, model)
826
- return MessageProcessor.create_chat_response(data_image, model)
827
- else:
828
- return MessageProcessor.create_chat_response(full_response, model)
829
 
 
 
830
  except Exception as error:
831
- logger.error(f"非流式响应总体错误: {str(error)}", "Server")
832
  raise error
833
 
834
- async def handle_image_response(image_url,model):
835
- MAX_RETRIES = 2
836
- retry_count = 0
837
- scraper = cloudscraper.create_scraper()
838
-
839
- while retry_count < MAX_RETRIES:
840
- try:
841
- token = token_manager.get_next_token_for_model(model)
842
- if not token:
843
- raise ValueError("没有可用的token")
844
-
845
- image_response = await Utils.run_in_executor(
846
- scraper.get,
847
- f"https://assets.grok.com/{image_url}",
848
- headers={
849
- **CONFIG["DEFAULT_HEADERS"],
850
- "cookie": token
851
- }
852
- )
853
-
854
- if image_response.status_code == 200:
855
- break
856
-
857
- retry_count += 1
858
- if retry_count == MAX_RETRIES:
859
- raise ValueError(f"上游服务请求失败! status: {image_response.status_code}")
860
-
861
- await asyncio.sleep(1 * retry_count)
862
-
863
- except Exception as error:
864
- logger.error(error, "Server")
865
- retry_count += 1
866
- if retry_count == MAX_RETRIES:
867
- raise error
868
-
869
- await asyncio.sleep(1 * retry_count)
870
-
871
- image_content = image_response.content
872
-
873
- if CONFIG["API"]["PICGO_KEY"]:
874
- form = aiohttp.FormData()
875
- form.add_field('source',
876
- io.BytesIO(image_content),
877
- filename=f'image-{int(datetime.now().timestamp())}.jpg',
878
- content_type='image/jpeg')
879
-
880
- async with aiohttp.ClientSession() as session:
881
- async with session.post(
882
- "https://www.picgo.net/api/1/upload",
883
- data=form,
884
- headers={"X-API-Key": CONFIG["API"]["PICGO_KEY"]}
885
- ) as response_url:
886
- if response_url.status != 200:
887
- return "生图失败,请查看PICGO图床密钥是否设置正确"
888
- else:
889
- logger.info("生图成功", "Server")
890
- result = await response_url.json()
891
- return f"![image]({result['image']['url']})"
892
- elif CONFIG["API"]["TUMY_KEY"]:
893
- form = aiohttp.FormData()
894
- form.add_field('file',
895
- io.BytesIO(image_content),
896
- filename=f'image-{int(datetime.now().timestamp())}.jpg',
897
- content_type='image/jpeg')
898
-
899
- async with aiohttp.ClientSession() as session:
900
- async with session.post(
901
- "https://tu.my/api/v1/upload",
902
- data=form,
903
- headers={
904
- "Accept": "application/json",
905
- "Authorization": f"Bearer {CONFIG['API']['TUMY_KEY']}"
906
- }
907
- ) as response_url:
908
- if response_url.status != 200:
909
- return "生图失败,请查看TUMY图床密钥是否设置正确"
910
- else:
911
- logger.info("生图成功", "Server")
912
- result = await response_url.json()
913
- return f"![image]({result['image']['url']})"
914
- # 如果没有PICGO_KEY或者TUMY_KEY则返回base64图片
915
- image_base64 = base64.b64encode(image_content).decode('utf-8')
916
- return f"![image](data:image/jpeg;base64,{image_base64})"
917
-
918
-
919
  app = Quart(__name__)
920
- app = cors(app, allow_origin="*", allow_methods=["GET", "POST", "OPTIONS"], allow_headers=["Content-Type", "Authorization"])
921
 
922
  @app.before_request
923
  async def before_request():
924
  await logger.request_logger(request)
925
-
926
- @app.route('/v1/models', methods=['GET'])
927
- async def models():
928
- return jsonify({
929
- "object": "list",
930
- "data": [
931
- {
932
- "id": model,
933
- "object": "model",
934
- "created": int(datetime.now().timestamp()),
935
- "owned_by": "grok"
936
- } for model in CONFIG["MODELS"].keys()
937
- ]
938
- })
939
-
940
-
941
- @app.route('/get/tokens', methods=['GET'])
942
- async def get_tokens():
943
- auth_token = request.headers.get('Authorization', '').replace('Bearer ', '')
944
 
945
- if CONFIG["API"]["IS_CUSTOM_SSO"]:
946
- return jsonify({"error": '自定义的SSO令牌模式无法获取轮询sso令牌状态'}), 403
947
- elif auth_token != CONFIG["API"]["API_KEY"]:
948
- return jsonify({"error": 'Unauthorized'}), 401
949
-
950
- return jsonify(token_manager.get_token_status_map())
951
 
952
- @app.route('/add/token', methods=['POST'])
953
- async def add_token():
954
- auth_token = request.headers.get('Authorization', '').replace('Bearer ', '')
955
-
956
- if CONFIG["API"]["IS_CUSTOM_SSO"]:
957
- return jsonify({"error": '自定义的SSO令牌模式无法添加sso令牌'}), 403
958
- elif auth_token != CONFIG["API"]["API_KEY"]:
959
- return jsonify({"error": 'Unauthorized'}), 401
960
-
961
  try:
962
  data = await request.get_json()
963
- sso = data.get('sso')
964
- if not sso:
965
- return jsonify({"error": 'SSO令牌不能为空'}), 400
 
966
 
967
- await token_manager.add_token(f"sso-rw={sso};sso={sso}")
968
- return jsonify(token_manager.get_token_status_map().get(sso, {}))
969
- except Exception as error:
970
- logger.error(error, "Server")
971
- return jsonify({"error": '添加sso令牌失败'}), 500
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
972
 
973
- @app.route('/delete/token', methods=['POST'])
974
- async def delete_token():
975
- auth_token = request.headers.get('Authorization', '').replace('Bearer ', '')
976
-
977
- if CONFIG["API"]["IS_CUSTOM_SSO"]:
978
- return jsonify({"error": '自定义的SSO令牌模式无法删除sso令牌'}), 403
979
- elif auth_token != CONFIG["API"]["API_KEY"]:
980
- return jsonify({"error": 'Unauthorized'}), 401
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
981
 
 
 
 
 
 
 
982
  try:
983
- data = await request.get_json()
984
- sso = data.get('sso')
985
- if not sso:
986
- return jsonify({"error": 'SSO令牌不能为空'}), 400
987
 
988
- success = await token_manager.delete_token(f"sso-rw={sso};sso={sso}")
989
- if success:
990
- return jsonify({"message": '删除sso令牌成功'})
991
- else:
992
- return jsonify({"error": '删除sso令牌失败'}), 500
 
 
 
 
 
 
 
 
993
  except Exception as error:
994
- logger.error(error, "Server")
995
- return jsonify({"error": '删除sso令牌失败'}), 500
996
 
997
- @app.route('/v1/chat/completions', methods=['POST'])
998
  async def chat_completions():
999
  try:
1000
  data = await request.get_json()
1001
- auth_token = request.headers.get('Authorization', '').replace('Bearer ', '')
1002
-
1003
- if auth_token:
1004
- if CONFIG["API"]["IS_CUSTOM_SSO"]:
1005
- await token_manager.set_token(f"sso-rw={auth_token};sso={auth_token}")
1006
- elif auth_token != CONFIG["API"]["API_KEY"]:
1007
- return jsonify({"error": "Unauthorized"}), 401
1008
- else:
1009
- return jsonify({"error": "Unauthorized"}), 401
1010
-
1011
- model = data.get("model")
1012
- stream = data.get("stream", False)
1013
- retry_count = 0
1014
 
1015
- try:
1016
- grok_client = GrokApiClient(model)
1017
- request_payload = await grok_client.prepare_chat_request(data)
1018
 
1019
- while retry_count < CONFIG["RETRY"]["MAX_ATTEMPTS"]:
1020
- retry_count += 1
1021
- logger.info(f"开始请求(第{retry_count}次尝试)", "Server")
1022
-
1023
- token = token_manager.get_next_token_for_model(model)
1024
- if not token:
1025
- logger.error(f"没有可用的{model}模型令牌", "Server")
1026
- if retry_count == CONFIG["RETRY"]["MAX_ATTEMPTS"]:
1027
- raise ValueError(f"没有可用的{model}模型令牌")
1028
- continue
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1029
 
1030
- scraper = cloudscraper.create_scraper()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1031
 
1032
- try:
1033
- headers = {
1034
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
1035
- "Connection": "keep-alive",
1036
- "Accept": "text/event-stream",
1037
- "Content-Type": "text/plain;charset=UTF-8",
1038
- "Cookie": token,
1039
- "baggage": "sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c"
1040
- }
1041
- logger.info(f"使用令牌: {token}", "Server")
1042
 
1043
- response = await Utils.run_in_executor(
1044
- scraper.post,
1045
- f"{CONFIG['API']['BASE_URL']}/rest/app-chat/conversations/new",
1046
- headers=headers,
1047
- data=json.dumps(request_payload),
1048
- stream=True
1049
- )
 
 
 
1050
 
1051
- if response.status_code == 200:
1052
- logger.info("请求成功", "Server")
1053
-
1054
- if stream:
1055
- return Response(
1056
- stream_response_generator(response, model),
1057
- content_type='text/event-stream',
1058
- headers={
1059
- 'Cache-Control': 'no-cache',
1060
- 'Connection': 'keep-alive'
1061
- }
1062
- )
1063
- else:
1064
- result = await handle_normal_response(response, model)
1065
- return jsonify(result)
1066
- else:
1067
- logger.error(f"请求失败: 状态码 {response.status_code}", "Server")
1068
- token_manager.remove_token_from_model(model, token)
1069
-
1070
- except Exception as e:
1071
- logger.error(f"请求异常: {str(e)}", "Server")
1072
- token_manager.remove_token_from_model(model, token)
1073
 
1074
- raise ValueError("请求失败,已达到最大重试次数")
1075
-
1076
- except Exception as e:
1077
- logger.error(e, "ChatAPI")
1078
- return jsonify({
1079
- "error": {
1080
- "message": str(e),
1081
- "type": "server_error"
1082
- }
1083
- }), 500
1084
-
1085
- except Exception as e:
1086
- logger.error(e, "ChatAPI")
1087
- return jsonify({
1088
- "error": {
1089
- "message": str(e),
1090
- "type": "server_error"
1091
- }
1092
- }), 500
1093
 
1094
- @app.route('/', methods=['GET'])
1095
- async def index():
1096
- return "api运行正常"
1097
-
1098
- if __name__ == "__main__":
1099
- asyncio.run(initialize_tokens())
1100
- app.run(host="0.0.0.0", port=CONFIG["SERVER"]["PORT"])
1101
- # 在现有app.py文件的最底部添加或修改这段代码
1102
- if __name__ == "__main__":
1103
- # 初始化令牌
1104
- import asyncio
1105
- asyncio.run(initialize_tokens())
1106
 
1107
- # 获取端口,优先使用环境变量
1108
- port = int(os.getenv("PORT", CONFIG["SERVER"]["PORT"]))
1109
-
1110
- # 启动服务器
1111
- from hypercorn.asyncio import serve
1112
- from hypercorn.config import Config as HyperConfig
1113
-
1114
- config = HyperConfig()
1115
- config.bind = [f"0.0.0.0:{port}"]
1116
- config.use_reloader = True
1117
-
1118
- logger.info(f"服务器正在启动,端口:{port}", "Server")
1119
- asyncio.run(serve(app, config))
1120
 
1121
 
1122
 
 
389
 
390
  token_manager = AuthTokenManager()
391
 
392
+ class ProxyManager:
393
+ def __init__(self):
394
+ self.proxies = []
395
+ self.current_index = 0
396
+ self.proxy_lock = asyncio.Lock()
397
+ self.bad_proxies = set()
398
+ self.proxy_usage_count = {}
399
+ self.max_uses_per_proxy = int(os.getenv("PROXY_MAX_USES", "20"))
400
+
401
+ async def load_proxies_from_env(self):
402
+ proxy_list = os.getenv("PROXIES", "").strip().split(",")
403
+ valid_proxies = [p.strip() for p in proxy_list if p.strip()]
404
+
405
+ if not valid_proxies:
406
+ logger.warning("没有配置代理,将不使用代理服务", "ProxyManager")
407
+ return
408
+
409
+ async with self.proxy_lock:
410
+ self.proxies = valid_proxies
411
+ self.proxy_usage_count = {proxy: 0 for proxy in valid_proxies}
412
+ logger.info(f"已加载 {len(valid_proxies)} 个代理", "ProxyManager")
413
+
414
+ async def get_proxy(self):
415
+ """获取下一个可用代理"""
416
+ async with self.proxy_lock:
417
+ if not self.proxies:
418
+ return None
419
+
420
+ # 按顺序尝试代理,跳过不可用的和使用次数过多的
421
+ tries = 0
422
+ while tries < len(self.proxies):
423
+ proxy = self.proxies[self.current_index]
424
+ self.current_index = (self.current_index + 1) % len(self.proxies)
425
+
426
+ # 检查代理是否可用
427
+ if proxy in self.bad_proxies:
428
+ tries += 1
429
+ continue
430
+
431
+ # 检查使用次数
432
+ if self.proxy_usage_count.get(proxy, 0) >= self.max_uses_per_proxy:
433
+ logger.info(f"代理 {proxy} 已达到最大使用次数,标记为不可用", "ProxyManager")
434
+ self.bad_proxies.add(proxy)
435
+ tries += 1
436
+ continue
437
+
438
+ # 增加使用计数
439
+ self.proxy_usage_count[proxy] = self.proxy_usage_count.get(proxy, 0) + 1
440
+ return proxy
441
+
442
+ # 所有代理都不可用
443
+ logger.warning("没有可用的代理", "ProxyManager")
444
+ return None
445
+
446
+ async def mark_proxy_bad(self, proxy):
447
+ """标记不可用的代理"""
448
+ if not proxy:
449
+ return
450
+
451
+ async with self.proxy_lock:
452
+ if proxy in self.proxies and proxy not in self.bad_proxies:
453
+ logger.info(f"标记代理 {proxy} 为不可用", "ProxyManager")
454
+ self.bad_proxies.add(proxy)
455
+
456
+ async def reset_proxies(self):
457
+ """重置代理状态"""
458
+ async with self.proxy_lock:
459
+ self.bad_proxies.clear()
460
+ self.proxy_usage_count = {proxy: 0 for proxy in self.proxies}
461
+ logger.info("已重置所有代理状态", "ProxyManager")
462
+
463
+ proxy_manager = ProxyManager()
464
+
465
  async def initialize_tokens():
466
  sso_array = os.getenv("SSO", "").split(',')
467
  logger.info("开始加载令牌", "Server")
 
474
  logger.info(f"令牌加载完成,共加载: {len(token_manager.get_all_tokens())}个令牌", "Server")
475
  logger.info("初始化完成", "Server")
476
 
477
+ async def initialize_app():
478
+ # 初始化令牌
479
+ await initialize_tokens()
480
+
481
+ # 加载代理
482
+ use_proxy = os.getenv("USE_PROXY", "false").lower() == "true"
483
+ if use_proxy:
484
+ # 从环境变量加载代理
485
+ await proxy_manager.load_proxies_from_env()
486
+ logger.info("代理初始化完成", "Server")
487
+
488
  class Utils:
489
  @staticmethod
490
  async def organize_search_results(search_results):
 
511
  )
512
 
513
  class GrokApiClient:
514
+ def __init__(self, model_id, proxy=None):
515
  if model_id not in CONFIG["MODELS"]:
516
  raise ValueError(f"不支持的模型: {model_id}")
517
  self.model = model_id
518
  self.model_id = CONFIG["MODELS"][model_id]
519
+ self.proxy = proxy
520
+ self.scraper = self._create_scraper()
521
+
522
+ def _create_scraper(self):
523
+ scraper = cloudscraper.create_scraper()
524
+ if self.proxy:
525
+ scraper.proxies = {
526
+ "http": self.proxy,
527
+ "https": self.proxy
528
+ }
529
+ return scraper
530
 
531
  def process_message_content(self, content):
532
  if isinstance(content, str):
 
621
  def remove_think_tags(text):
622
  import re
623
  text = re.sub(r'<think>[\s\S]*?<\/think>', '', text).strip()
624
+ text = re.sub(r'!$$
625
+ image
626
+ $$$data:.*?base64,.*?$', '[图片]', text)
627
  return text
628
 
629
  async def process_image_url(content):
 
724
  "choices": [{
725
  "index": 0,
726
  "delta": {
727
+
728
  "content": message
729
  }
730
  }]
 
851
  logger.error(f"流式响应总体错误: {str(error)}", "Server")
852
  raise error
853
 
854
+ async def handle_image_response(image_url, model):
855
+ try:
856
+ logger.info(f"处理图片回复: {image_url}", "Server")
857
+ image_markdown = f"![image]({image_url})"
858
+ return image_markdown
859
+ except Exception as error:
860
+ logger.error(error, "Server")
861
+ return ""
862
+
863
  async def handle_normal_response(response, model):
864
  try:
865
  full_response = ''
 
928
  continue
929
 
930
  if CONFIG["IS_IMG_GEN2"] and image_url:
931
+ full_response += f"\n![image]({image_url})"
 
 
 
932
 
933
+ return full_response
934
+
935
  except Exception as error:
936
+ logger.error(error, "Server")
937
  raise error
938
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
939
  app = Quart(__name__)
940
+ app = cors(app, allow_origin="*")
941
 
942
  @app.before_request
943
  async def before_request():
944
  await logger.request_logger(request)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
945
 
946
+ @app.route('/')
947
+ async def index():
948
+ return 'Grok API is running'
 
 
 
949
 
950
+ @app.route('/verify-sso', methods=['POST'])
951
+ async def verify_sso():
 
 
 
 
 
 
 
952
  try:
953
  data = await request.get_json()
954
+ sso_token = data.get('sso')
955
+
956
+ if not sso_token:
957
+ return jsonify({"status": "error", "message": "No SSO token provided"}), 400
958
 
959
+ # 构造一个简单的请求来测试令牌
960
+ url = f"{CONFIG['API']['BASE_URL']}/api/models"
961
+ headers = {
962
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
963
+ "Cookie": f"sso-rw={sso_token};sso={sso_token}"
964
+ }
965
+
966
+ scraper = cloudscraper.create_scraper()
967
+ response = await Utils.run_in_executor(
968
+ scraper.get,
969
+ url,
970
+ headers=headers
971
+ )
972
+
973
+ if response.status_code == 200:
974
+ return jsonify({"status": "valid", "message": "SSO token is valid"}), 200
975
+ else:
976
+ return jsonify({"status": "invalid", "message": f"SSO token is invalid, status code: {response.status_code}"}), 200
977
+
978
+ except Exception as e:
979
+ logger.error(f"验证SSO令牌时出错: {str(e)}", "Server")
980
+ return jsonify({"status": "error", "message": str(e)}), 500
981
 
982
+ @app.route('/check-proxies', methods=['GET'])
983
+ async def check_proxies():
984
+ try:
985
+ use_proxy = os.getenv("USE_PROXY", "false").lower() == "true"
986
+ if not use_proxy:
987
+ return jsonify({"status": "error", "message": "代理功能未启用"}), 400
988
+
989
+ if not proxy_manager or not proxy_manager.proxies:
990
+ return jsonify({"status": "error", "message": "没有配置代理"}), 400
991
+
992
+ return jsonify({
993
+ "status": "success",
994
+ "total": len(proxy_manager.proxies),
995
+ "active": len(proxy_manager.proxies) - len(proxy_manager.bad_proxies),
996
+ "proxies": proxy_manager.proxies,
997
+ "usage": proxy_manager.proxy_usage_count
998
+ }), 200
999
+ except Exception as e:
1000
+ logger.error(f"检查代理时出错: {str(e)}", "Server")
1001
+ return jsonify({"status": "error", "message": str(e)}), 500
1002
+
1003
+ @app.route('/verify-all-sso', methods=['GET'])
1004
+ async def verify_all_sso():
1005
+ try:
1006
+ # 从 token_manager 获取所有令牌
1007
+ all_tokens = token_manager.get_all_tokens()
1008
+ results = {}
1009
+ token_info = {}
1010
+
1011
+ # 验证每个令牌
1012
+ for token in all_tokens:
1013
+ try:
1014
+ sso = token.split("sso=")[1].split(";")[0]
1015
+ token_info[sso] = {
1016
+ "usage": {}
1017
+ }
1018
+
1019
+ for model_name in CONFIG["MODELS"]:
1020
+ normalized_model = token_manager.normalize_model_name(model_name)
1021
+ if sso in token_manager.token_status_map and normalized_model in token_manager.token_status_map[sso]:
1022
+ token_info[sso]["usage"][model_name] = {
1023
+ "isValid": token_manager.token_status_map[sso][normalized_model]["isValid"],
1024
+ "totalRequestCount": token_manager.token_status_map[sso][normalized_model]["totalRequestCount"],
1025
+ "invalidatedTime": token_manager.token_status_map[sso][normalized_model]["invalidatedTime"]
1026
+ }
1027
+
1028
+ url = f"{CONFIG['API']['BASE_URL']}/api/models"
1029
+ headers = {
1030
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
1031
+ "Cookie": token
1032
+ }
1033
+
1034
+ scraper = cloudscraper.create_scraper()
1035
+ response = await Utils.run_in_executor(
1036
+ scraper.get,
1037
+ url,
1038
+ headers=headers
1039
+ )
1040
+
1041
+ results[sso] = {
1042
+ "status": "valid" if response.status_code == 200 else "invalid",
1043
+ "statusCode": response.status_code
1044
+ }
1045
+
1046
+ except Exception as e:
1047
+ results[sso] = {
1048
+ "status": "error",
1049
+ "message": str(e)
1050
+ }
1051
+
1052
+ return jsonify({
1053
+ "status": "success",
1054
+ "results": results,
1055
+ "tokenInfo": token_info,
1056
+ "remainingCapacity": token_manager.get_remaining_token_request_capacity()
1057
+ }), 200
1058
 
1059
+ except Exception as e:
1060
+ logger.error(f"验证所有SSO令牌时出错: {str(e)}", "Server")
1061
+ return jsonify({"status": "error", "message": str(e)}), 500
1062
+
1063
+ @app.route("/v1/models", methods=["GET"])
1064
+ async def list_models():
1065
  try:
1066
+ auth_key = request.headers.get("Authorization", "").replace("Bearer ", "")
1067
+ if CONFIG["API"]["IS_CUSTOM_SSO"] and auth_key != CONFIG["API"]["API_KEY"]:
1068
+ return {"error": "Invalid API key"}, 401
 
1069
 
1070
+ models = []
1071
+ for model_id in CONFIG["MODELS"]:
1072
+ models.append({
1073
+ "id": model_id,
1074
+ "object": "model",
1075
+ "created": int(datetime.now().timestamp())
1076
+ })
1077
+
1078
+ return jsonify({
1079
+ "object": "list",
1080
+ "data": models
1081
+ })
1082
+
1083
  except Exception as error:
1084
+ logger.error(error, "ChatAPI")
1085
+ return {"error": str(error)}, 500
1086
 
1087
+ @app.route("/v1/chat/completions", methods=["POST"])
1088
  async def chat_completions():
1089
  try:
1090
  data = await request.get_json()
 
 
 
 
 
 
 
 
 
 
 
 
 
1091
 
1092
+ # 验证请求
1093
+ if "model" not in data:
1094
+ return jsonify({"error": "Missing model parameter"}), 400
1095
 
1096
+ # 获取代理# 获取代理
1097
+ use_proxy=os.getenv("USE_PROXY","false").lower()=="true""USE_PROXY", "false").lower() == "true"
1098
+ proxy=无None
1099
+
1100
+ 如果使用代理服务器(_P):if use_proxy:
1101
+ proxy=等待proxy_manager.get_proxy()await proxy_manager.get_proxy()
1102
+ 如果代理:if proxy:
1103
+ Logger.info(f"使用代理:{proxy}","Server")f"使用代理: {proxy}", "Server")
1104
+
1105
+ # 创建客户端# 创建客户端
1106
+ client=GrokApiClient(数据["模型"],proxy=proxy)"model"], proxy=proxy)
1107
+
1108
+ Logger.info(f"模型:{data['model']}","ChatAPI")f"模型: {data['model']}", "ChatAPI")
1109
+
1110
+ stream=data.get("stream",False)"stream", False)
1111
+ prepared_data=等待客户端.preparate_chat_request(数据)await client.prepare_chat_request(data)
1112
+
1113
+ auth_key=request.Header.get("Authorization","").replace("Bearer","")"Authorization", "").replace("Bearer ", "")
1114
+ 如果CONFIG["API"]["IS_CUSTOM_SSO"]和auth_key!=CONFIG["API"]["API_KEY"]:if CONFIG["API"]["IS_CUSTOM_SSO"] and auth_key != CONFIG["API"]["API_KEY"]:
1115
+ token=auth_key
1116
+ 其他:else:
1117
+ token=token_manager.get_next_token_for_model(数据["model"])"model"])
1118
+
1119
+ 如果不是令牌:if not token:
1120
+ return jsonify({"错误":"没有可用的令牌"}),500return jsonify({"error": "No available token"}), 500
1121
+
1122
+ 标头={
1123
+ "User-Agent":"Mozilla/5.0(Windows NT10.0;Win64;x64)AppleWebKit/537.36(KHTML,如Gecko)Chrome/133.0.0.0 Safari/537.36","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
1124
+ "连接":"保持连接","Connection": "keep-alive",
1125
+ "Accept":"文本/事件流","Accept": "text/event-stream",
1126
+ "内容类型":"text/plain;charset=UTF-8","Content-Type": "text/plain;charset=UTF-8",
1127
+ “Cookie”:令牌"Cookie": token
1128
+ }
1129
+
1130
+ 对于范围内的尝试(CONFIG["重试"]["MAX_ATTEMPTS"]):for attempt in range(CONFIG["RETRY"]["MAX_ATTEMPTS"]):
1131
+ 尝试:try:
1132
+ Logger.info(f"开始请求(第{tempt+1}次尝试)","服务器")f"开始请求(第{attempt+1}次尝试)", "Server")
1133
 
1134
+ 如果不是令牌:if not token:
1135
+ return jsonify({"错误":"没有可用的令牌"}),500return jsonify({"error": "No available token"}), 500
1136
+
1137
+ 如果配置["API"]["IS_CUSTOM_SSO"]:if CONFIG["API"]["IS_CUSTOM_SSO"]:
1138
+ Logger.info("使用自定义SSO","Server")"使用自定义SSO", "Server")
1139
+ 其他:else:
1140
+ Logger.info(f"使用令牌:{token}","Server")f"使用令牌: {token}", "Server")
1141
+
1142
+ 响应=等待Utils.run_in_executor(await Utils.run_in_executor(
1143
+ client.scraper.post,
1144
+ F"{CONFIG['API']['BASE_URL']}/api/conversation",f"{CONFIG['API']['BASE_URL']}/api/conversation",
1145
+ headers=headers,
1146
+ data=json.dumps(prepared_data),
1147
+ stream=TrueTrue
1148
+ )
1149
 
1150
+ 如果response.status_code!=200:if response.status_code != 200:
1151
+ token_manager.从模型(data["model"])中删除token_manager,令牌)"model"], token)
1152
+ 如果未配置["API"]["IS_CUSTOM_SSO"]:if not CONFIG["API"]["IS_CUSTOM_SSO"]:
1153
+ token=token_manager.get_next_token_for_model(数据["model"])"model"])
1154
+ 返回jsonify({"错误":f"请求失败,状态代码:{response.status_code}"}),response.status_codereturn jsonify({"error": f"Request failed with status code: {response.status_code}"}), response.status_code
 
 
 
 
 
1155
 
1156
+ Logger.info("请求成功","服务器")"请求成功", "Server")
1157
+
1158
+ if流:if stream:
1159
+ 返回响应(return Response(
1160
+ stream_response_generator(响应,数据["model"]),"model"]),
1161
+ content_type="文本/事件流""text/event-stream"
1162
+ )
1163
+ 其他:else:
1164
+ 结果=等待句柄_正常_响应(响应,数据["模型"])await handle_normal_response(response, data["model"])
1165
+ 返回jsonify(MessageProcessor.create_chat_response(结果,数据["模型"]))return jsonify(MessageProcessor.create_chat_response(result, data["model"]))
1166
 
1167
+ 例外情况除外,如e:except Exception as e:
1168
+ # 如果使用了代理且出错,标记代理为不可用# 如果使用了代理且出错,标记代理为不可用
1169
+ 如果使用代理和代理并("代理连接失败"在str(e)中或str(e)中的“连接被拒绝”):if use_proxy and proxy and ("代理连接失败" in str(e) or "Connection refused" in str(e)):
1170
+ 等待proxy_manager.mark_proxy_bad(proxy)await proxy_manager.mark_proxy_bad(proxy)
1171
+ # 尝试获取新代理# 尝试获取新代理
1172
+ proxy=等待proxy_manager.get_proxy()await proxy_manager.get_proxy()
1173
+ 如果代理:if proxy:
1174
+ client=GrokApiClient(数据["模型"],proxy=proxy)"model"], proxy=proxy)
1175
+
1176
+ logger.error(f"尝试{尝试+1}失败:{str(e)}","服务器")f"尝试 {attempt+1} 失败: {str(e)}", "Server")
1177
+
1178
+ 如果尝试==配置["重试"]["MAX_ATTEMPTS"]-1:if attempt == CONFIG["RETRY"]["MAX_ATTEMPTS"] - 1:
1179
+ 提高raise
1180
+
1181
+ 如果未配置["API"]["IS_CUSTOM_SSO"]:if not CONFIG["API"]["IS_CUSTOM_SSO"]:
1182
+ token=token_manager.get_next_token_for_model(数据["model"])"model"])
 
 
 
 
 
 
1183
 
1184
+ 例外情况除外,如e:except Exception as e:
1185
+ logger.error(e,"ChatAPI")"ChatAPI")
1186
+ return jsonify({"error":str(e)}),500return jsonify({"error": str(e)}), 500
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1187
 
1188
+ if如果__name__=="__main__":"__main__":
1189
+ # 初始化应用# 初始化应用
1190
+ 导入异步import asyncio
1191
+ asyncio.run(initialize_app())
 
 
 
 
 
 
 
 
1192
 
1193
+ # 启动服务器# 启动服务器
1194
+ port=int(os.getenv("PORT",CONFIG["SERVER"]["PORT"]))"PORT", CONFIG["SERVER"]["PORT"]))
1195
+ App.run(主机="0.0.0.0",端口=端口)"0.0.0.0", port=port)
1196
+
 
 
 
 
 
 
 
 
 
1197
 
1198
 
1199