isididiidid commited on
Commit
c2bf8cf
·
verified ·
1 Parent(s): a6d3404

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +261 -346
app.py CHANGED
@@ -389,79 +389,6 @@ class AuthTokenManager:
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,17 +401,6 @@ async def initialize_tokens():
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,22 +427,12 @@ class Utils:
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):
@@ -619,13 +525,9 @@ class GrokApiClient:
619
  search = request_data["model"] in ["grok-2-search", "grok-3-search"]
620
 
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'!\[image\]\(data:.*?base64,.*?\)', '[图片]', text)
625
- return text
626
-
627
- image
628
- $$$data:.*?base64,.*?$', '[图片]', text)
629
  return text
630
 
631
  async def process_image_url(content):
@@ -726,7 +628,6 @@ class MessageProcessor:
726
  "choices": [{
727
  "index": 0,
728
  "delta": {
729
-
730
  "content": message
731
  }
732
  }]
@@ -853,15 +754,6 @@ async def stream_response_generator(response, model):
853
  logger.error(f"流式响应总体错误: {str(error)}", "Server")
854
  raise error
855
 
856
- async def handle_image_response(image_url, model):
857
- try:
858
- logger.info(f"处理图片回复: {image_url}", "Server")
859
- image_markdown = f"![image]({image_url})"
860
- return image_markdown
861
- except Exception as error:
862
- logger.error(error, "Server")
863
- return ""
864
-
865
  async def handle_normal_response(response, model):
866
  try:
867
  full_response = ''
@@ -930,271 +822,294 @@ async def handle_normal_response(response, model):
930
  continue
931
 
932
  if CONFIG["IS_IMG_GEN2"] and image_url:
933
- full_response += f"\n![image]({image_url})"
 
 
 
934
 
935
- return full_response
936
-
937
  except Exception as error:
938
- logger.error(error, "Server")
939
  raise error
940
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
941
  app = Quart(__name__)
942
- app = cors(app, allow_origin="*")
943
 
944
  @app.before_request
945
  async def before_request():
946
  await logger.request_logger(request)
947
-
948
- @app.route('/')
949
- async def index():
950
- return 'Grok API is running'
951
 
952
- @app.route('/verify-sso', methods=['POST'])
953
- async def verify_sso():
954
- try:
955
- data = await request.get_json()
956
- sso_token = data.get('sso')
957
-
958
- if not sso_token:
959
- return jsonify({"status": "error", "message": "No SSO token provided"}), 400
960
-
961
- # 构造一个简单的请求来测试令牌
962
- url = f"{CONFIG['API']['BASE_URL']}/api/models"
963
- headers = {
964
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
965
- "Cookie": f"sso-rw={sso_token};sso={sso_token}"
966
- }
967
-
968
- scraper = cloudscraper.create_scraper()
969
- response = await Utils.run_in_executor(
970
- scraper.get,
971
- url,
972
- headers=headers
973
- )
 
974
 
975
- if response.status_code == 200:
976
- return jsonify({"status": "valid", "message": "SSO token is valid"}), 200
977
- else:
978
- return jsonify({"status": "invalid", "message": f"SSO token is invalid, status code: {response.status_code}"}), 200
979
-
980
- except Exception as e:
981
- logger.error(f"验证SSO令牌时出错: {str(e)}", "Server")
982
- return jsonify({"status": "error", "message": str(e)}), 500
983
 
984
- @app.route('/check-proxies', methods=['GET'])
985
- async def check_proxies():
 
 
 
 
 
 
 
986
  try:
987
- use_proxy = os.getenv("USE_PROXY", "false").lower() == "true"
988
- if not use_proxy:
989
- return jsonify({"status": "error", "message": "代理功能未启用"}), 400
990
-
991
- if not proxy_manager or not proxy_manager.proxies:
992
- return jsonify({"status": "error", "message": "没有配置代理"}), 400
993
 
994
- return jsonify({
995
- "status": "success",
996
- "total": len(proxy_manager.proxies),
997
- "active": len(proxy_manager.proxies) - len(proxy_manager.bad_proxies),
998
- "proxies": proxy_manager.proxies,
999
- "usage": proxy_manager.proxy_usage_count
1000
- }), 200
1001
- except Exception as e:
1002
- logger.error(f"检查代理时出错: {str(e)}", "Server")
1003
- return jsonify({"status": "error", "message": str(e)}), 500
1004
 
1005
- @app.route('/verify-all-sso', methods=['GET'])
1006
- async def verify_all_sso():
1007
- try:
1008
- # 从 token_manager 获取所有令牌
1009
- all_tokens = token_manager.get_all_tokens()
1010
- results = {}
1011
- token_info = {}
1012
-
1013
- # 验证每个令牌
1014
- for token in all_tokens:
1015
- try:
1016
- sso = token.split("sso=")[1].split(";")[0]
1017
- token_info[sso] = {
1018
- "usage": {}
1019
- }
1020
-
1021
- for model_name in CONFIG["MODELS"]:
1022
- normalized_model = token_manager.normalize_model_name(model_name)
1023
- if sso in token_manager.token_status_map and normalized_model in token_manager.token_status_map[sso]:
1024
- token_info[sso]["usage"][model_name] = {
1025
- "isValid": token_manager.token_status_map[sso][normalized_model]["isValid"],
1026
- "totalRequestCount": token_manager.token_status_map[sso][normalized_model]["totalRequestCount"],
1027
- "invalidatedTime": token_manager.token_status_map[sso][normalized_model]["invalidatedTime"]
1028
- }
1029
-
1030
- url = f"{CONFIG['API']['BASE_URL']}/api/models"
1031
- headers = {
1032
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
1033
- "Cookie": token
1034
- }
1035
-
1036
- scraper = cloudscraper.create_scraper()
1037
- response = await Utils.run_in_executor(
1038
- scraper.get,
1039
- url,
1040
- headers=headers
1041
- )
1042
-
1043
- results[sso] = {
1044
- "status": "valid" if response.status_code == 200 else "invalid",
1045
- "statusCode": response.status_code
1046
- }
1047
-
1048
- except Exception as e:
1049
- results[sso] = {
1050
- "status": "error",
1051
- "message": str(e)
1052
- }
1053
-
1054
- return jsonify({
1055
- "status": "success",
1056
- "results": results,
1057
- "tokenInfo": token_info,
1058
- "remainingCapacity": token_manager.get_remaining_token_request_capacity()
1059
- }), 200
1060
 
1061
- except Exception as e:
1062
- logger.error(f"验证所有SSO令牌时出错: {str(e)}", "Server")
1063
- return jsonify({"status": "error", "message": str(e)}), 500
1064
-
1065
- @app.route("/v1/models", methods=["GET"])
1066
- async def list_models():
1067
  try:
1068
- auth_key = request.headers.get("Authorization", "").replace("Bearer ", "")
1069
- if CONFIG["API"]["IS_CUSTOM_SSO"] and auth_key != CONFIG["API"]["API_KEY"]:
1070
- return {"error": "Invalid API key"}, 401
1071
-
1072
- models = []
1073
- for model_id in CONFIG["MODELS"]:
1074
- models.append({
1075
- "id": model_id,
1076
- "object": "model",
1077
- "created": int(datetime.now().timestamp())
1078
- })
1079
 
1080
- return jsonify({
1081
- "object": "list",
1082
- "data": models
1083
- })
1084
-
1085
  except Exception as error:
1086
- logger.error(error, "ChatAPI")
1087
- return {"error": str(error)}, 500
1088
 
1089
- @app.route("/v1/chat/completions", methods=["POST"])
1090
  async def chat_completions():
1091
  try:
1092
  data = await request.get_json()
 
 
 
 
 
 
 
 
 
 
 
 
 
1093
 
1094
- # 验证请求
1095
- if "model" not in data:
1096
- return jsonify({"error": "Missing model parameter"}), 400
1097
-
1098
- # 获取代理# 获取代理
1099
- use_proxy=os.getenv("USE_PROXY","false").lower()=="true""USE_PROXY", "false").lower() == "true"
1100
- proxy=无None
1101
-
1102
- 如果使用代理服务器(_P):if use_proxy:
1103
- proxy=等待proxy_manager.get_proxy()await proxy_manager.get_proxy()
1104
- 如果代理:if proxy:
1105
- Logger.info(f"使用代理:{proxy}","Server")f"使用代理: {proxy}", "Server")
1106
-
1107
- # 创建客户端# 创建客户端
1108
- client=GrokApiClient(数据["模型"],proxy=proxy)"model"], proxy=proxy)
1109
-
1110
- Logger.info(f"模型:{data['model']}","ChatAPI")f"模型: {data['model']}", "ChatAPI")
1111
-
1112
- stream=data.get("stream",False)"stream", False)
1113
- prepared_data=等待客户端.preparate_chat_request(数据)await client.prepare_chat_request(data)
1114
-
1115
- auth_key=request.Header.get("Authorization","").replace("Bearer","")"Authorization", "").replace("Bearer ", "")
1116
- 如果CONFIG["API"]["IS_CUSTOM_SSO"]和auth_key!=CONFIG["API"]["API_KEY"]:if CONFIG["API"]["IS_CUSTOM_SSO"] and auth_key != CONFIG["API"]["API_KEY"]:
1117
- token=auth_key
1118
- 其他:else:
1119
- token=token_manager.get_next_token_for_model(数据["model"])"model"])
1120
-
1121
- 如果不是令牌:if not token:
1122
- return jsonify({"错误":"没有可用的令牌"}),500return jsonify({"error": "No available token"}), 500
1123
 
1124
- 标头={
1125
- "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",
1126
- "连接":"保持连接","Connection": "keep-alive",
1127
- "Accept":"文本/事件流","Accept": "text/event-stream",
1128
- "内容类型":"text/plain;charset=UTF-8","Content-Type": "text/plain;charset=UTF-8",
1129
- “Cookie”:令牌"Cookie": token
1130
- }
1131
-
1132
- 对于范围内的尝试(CONFIG["重试"]["MAX_ATTEMPTS"]):for attempt in range(CONFIG["RETRY"]["MAX_ATTEMPTS"]):
1133
- 尝试:try:
1134
- Logger.info(f"开始请求(第{tempt+1}次尝试)","服务器")f"开始请求(第{attempt+1}次尝试)", "Server")
1135
 
1136
- 如果不是令牌:if not token:
1137
- return jsonify({"错误":"没有可用的令牌"}),500return jsonify({"error": "No available token"}), 500
1138
-
1139
- 如果配置["API"]["IS_CUSTOM_SSO"]:if CONFIG["API"]["IS_CUSTOM_SSO"]:
1140
- Logger.info("使用自定义SSO","Server")"使用自定义SSO", "Server")
1141
- 其他:else:
1142
- Logger.info(f"使用令牌:{token}","Server")f"使用令牌: {token}", "Server")
1143
-
1144
- 响应=等待Utils.run_in_executor(await Utils.run_in_executor(
1145
- client.scraper.post,
1146
- F"{CONFIG['API']['BASE_URL']}/api/conversation",f"{CONFIG['API']['BASE_URL']}/api/conversation",
1147
- headers=headers,
1148
- data=json.dumps(prepared_data),
1149
- stream=TrueTrue
1150
- )
1151
 
1152
- 如果response.status_code!=200:if response.status_code != 200:
1153
- token_manager.从模型(data["model"])中删除token_manager,令牌)"model"], token)
1154
- 如果未配置["API"]["IS_CUSTOM_SSO"]:if not CONFIG["API"]["IS_CUSTOM_SSO"]:
1155
- token=token_manager.get_next_token_for_model(数据["model"])"model"])
1156
- 返回jsonify({"错误":f"请求失败,状态代码:{response.status_code}"}),response.status_codereturn jsonify({"error": f"Request failed with status code: {response.status_code}"}), response.status_code
1157
-
1158
- Logger.info("请求成功","服务器")"请求成功", "Server")
1159
 
1160
- if流:if stream:
1161
- 返回响应(return Response(
1162
- stream_response_generator(响应,数据["model"]),"model"]),
1163
- content_type="文本/事件流""text/event-stream"
1164
- )
1165
- 其他:else:
1166
- 结果=等待句柄_正常_响应(响应,数据["模型"])await handle_normal_response(response, data["model"])
1167
- 返回jsonify(MessageProcessor.create_chat_response(结果,数据["模型"]))return jsonify(MessageProcessor.create_chat_response(result, data["model"]))
 
 
1168
 
1169
- 例外情况除外,如e:except Exception as e:
1170
- # 如果使用了代理且出错,标记代理为不可用# 如果使用了代理且出错,标记代理为不可用
1171
- 如果使用代理和代理并("代理连接失败"在str(e)中或str(e)中的“连接被拒绝”):if use_proxy and proxy and ("代理连接失败" in str(e) or "Connection refused" in str(e)):
1172
- 等待proxy_manager.mark_proxy_bad(proxy)await proxy_manager.mark_proxy_bad(proxy)
1173
- # 尝试获取新代理# 尝试获取新代理
1174
- proxy=等待proxy_manager.get_proxy()await proxy_manager.get_proxy()
1175
- 如果代理:if proxy:
1176
- client=GrokApiClient(数据["模型"],proxy=proxy)"model"], proxy=proxy)
1177
-
1178
- logger.error(f"尝试{尝试+1}失败:{str(e)}","服务器")f"尝试 {attempt+1} 失败: {str(e)}", "Server")
1179
-
1180
- 如果尝试==配置["重试"]["MAX_ATTEMPTS"]-1:if attempt == CONFIG["RETRY"]["MAX_ATTEMPTS"] - 1:
1181
- 提高raise
1182
-
1183
- 如果未配置["API"]["IS_CUSTOM_SSO"]:if not CONFIG["API"]["IS_CUSTOM_SSO"]:
1184
- token=token_manager.get_next_token_for_model(数据["model"])"model"])
1185
 
1186
- 例外情况除外,如e:except Exception as e:
1187
- logger.error(e,"ChatAPI")"ChatAPI")
1188
- return jsonify({"error":str(e)}),500return jsonify({"error": str(e)}), 500
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1189
 
1190
- if如果__name__=="__main__":"__main__":
1191
- # 初始化应用# 初始化应用
1192
- 导入异步import asyncio
1193
- asyncio.run(initialize_app())
 
 
 
 
 
 
 
 
1194
 
1195
- # 启动服务器# 启动服务器
1196
- port=int(os.getenv("PORT",CONFIG["SERVER"]["PORT"]))"PORT", CONFIG["SERVER"]["PORT"]))
1197
- App.run(主机="0.0.0.0",端口=端口)"0.0.0.0", port=port)
 
 
 
1198
 
1199
 
1200
 
 
389
 
390
  token_manager = AuthTokenManager()
391
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
392
  async def initialize_tokens():
393
  sso_array = os.getenv("SSO", "").split(',')
394
  logger.info("开始加载令牌", "Server")
 
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
  )
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):
 
525
  search = request_data["model"] in ["grok-2-search", "grok-3-search"]
526
 
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
  "choices": [{
629
  "index": 0,
630
  "delta": {
 
631
  "content": message
632
  }
633
  }]
 
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
  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
+ if __name__ == "__main__":
1102
+ import argparse
1103
+ parser = argparse.ArgumentParser()
1104
+ parser.add_argument("--port", type=int, default=CONFIG["SERVER"]["PORT"])
1105
+ args = parser.parse_args()
1106
 
1107
+ # 使用传入的端口覆盖配置中的端口
1108
+ port = args.port
1109
+
1110
+ # 这里使用修改后的端口启动服务
1111
+ app.run(host="0.0.0.0", port=port)
1112
+
1113
 
1114
 
1115