dan92 commited on
Commit
4b2fa2b
·
verified ·
1 Parent(s): 30b9adc

Upload 3 files

Browse files
Files changed (3) hide show
  1. Dockerfile +4 -11
  2. app.py +31 -191
  3. requirements.txt +0 -1
Dockerfile CHANGED
@@ -6,16 +6,9 @@ WORKDIR /app
6
  # 复制依赖文件
7
  COPY requirements.txt .
8
 
9
- # 安装系统依赖和 Python
10
- RUN apt-get update && \
11
- apt-get install -y --no-install-recommends \
12
- gcc \
13
- python3-dev \
14
- && pip install --upgrade pip \
15
- && pip install --no-cache-dir -r requirements.txt gunicorn \
16
- && apt-get purge -y --auto-remove gcc python3-dev \
17
- && apt-get clean \
18
- && rm -rf /var/lib/apt/lists/*
19
 
20
  # 复制应用程序文件
21
  COPY app.py .
@@ -30,4 +23,4 @@ ENV PYTHONUNBUFFERED=1
30
  EXPOSE 3000
31
 
32
  # 使用 gunicorn 作为生产级 WSGI 服务器
33
- CMD ["gunicorn", "--bind", "0.0.0.0:3000", "--workers", "4", "--timeout", "120", "--worker-class", "sync", "app:app"]
 
6
  # 复制依赖文件
7
  COPY requirements.txt .
8
 
9
+ # 安装 gunicorn 和其他依赖
10
+ RUN pip install --upgrade pip && \
11
+ pip install --no-cache-dir -r requirements.txt gunicorn
 
 
 
 
 
 
 
12
 
13
  # 复制应用程序文件
14
  COPY app.py .
 
23
  EXPOSE 3000
24
 
25
  # 使用 gunicorn 作为生产级 WSGI 服务器
26
+ CMD ["gunicorn", "--bind", "0.0.0.0:3000", "--workers", "4", "app:app"]
app.py CHANGED
@@ -8,7 +8,7 @@ import re
8
  import socket
9
  from concurrent.futures import ThreadPoolExecutor
10
  from functools import lru_cache, wraps
11
- from typing import Dict, Any, Callable, List, Tuple, Optional, Union
12
  import requests
13
  import tiktoken
14
  from flask import Flask, Response, jsonify, request, stream_with_context
@@ -20,9 +20,6 @@ from cachetools import TTLCache
20
  import threading
21
  from time import sleep
22
  from datetime import datetime, timedelta
23
- import aiohttp
24
- import asyncio
25
- import atexit
26
 
27
  # 新增导入
28
  import register_bot
@@ -374,8 +371,7 @@ def get_notdiamond_headers(auth_manager):
374
  'accept-language': 'zh-CN,zh;q=0.9',
375
  'content-type': 'application/json',
376
  'user-agent': _USER_AGENT,
377
- 'authorization': f'Bearer {auth_manager.get_jwt_value()}',
378
- 'Host': NOTDIAMOND_DOMAIN # 添加 Host 头
379
  }
380
  headers_cache[cache_key] = headers
381
  return headers
@@ -782,145 +778,8 @@ def build_payload(request_data, model_id):
782
 
783
  return payload
784
 
785
- # 修改理相关的常量和配置
786
- PROXY_API_BASE = "https://269900.xyz"
787
- PROXY_CHECK_INTERVAL = 300 # 5分钟检查一次代理可用性
788
- PROXY_MAX_LATENCY = 5000 # 最大延迟(毫秒)
789
- MAX_PROXIES = 10 # 保持的最大代理数量
790
- PROXY_TIMEOUT = 5 # 代理请求超时时间(秒)
791
-
792
- class ProxyManager:
793
- def __init__(self):
794
- self.proxies: List[Dict[str, Union[str, int, float]]] = []
795
- self.last_update = 0
796
- self.lock = threading.Lock()
797
- self.session = requests.Session()
798
-
799
- def fetch_proxies(self):
800
- """同步获取代理列表"""
801
- try:
802
- endpoint = f"{PROXY_API_BASE}/fetch_all?region=cn&count=5"
803
- response = self.session.get(endpoint, timeout=PROXY_TIMEOUT)
804
-
805
- if response.status_code == 200:
806
- # 解析文本响应
807
- proxy_list = [p.strip() for p in response.text.split(',') if p.strip()]
808
-
809
- with self.lock:
810
- self.proxies = []
811
- for proxy_str in proxy_list:
812
- proxy_info = self._parse_proxy_string(proxy_str)
813
- if proxy_info:
814
- self.proxies.append(proxy_info)
815
-
816
- self.last_update = time.time()
817
- logger.info(f"Successfully fetched {len(self.proxies)} proxies")
818
- else:
819
- logger.error(f"Failed to fetch proxies, status: {response.status_code}")
820
-
821
- except requests.exceptions.RequestException as e:
822
- logger.error(f"Error fetching proxies: {e}")
823
- except Exception as e:
824
- logger.error(f"Unexpected error in fetch_proxies: {e}")
825
- finally:
826
- if not self.proxies:
827
- logger.warning("No proxies available, will retry later")
828
-
829
- def get_proxy(self) -> Optional[str]:
830
- """获取一个可用的代理"""
831
- with self.lock:
832
- current_time = time.time()
833
-
834
- if not self.proxies or (current_time - self.last_update) > PROXY_CHECK_INTERVAL:
835
- self.fetch_proxies()
836
-
837
- if not self.proxies:
838
- return None
839
-
840
- valid_proxies = [p for p in self.proxies if p['fails'] < 3]
841
- if not valid_proxies:
842
- self.fetch_proxies()
843
- valid_proxies = [p for p in self.proxies if p['fails'] < 3]
844
- if not valid_proxies:
845
- return None
846
-
847
- proxy = min(valid_proxies, key=lambda x: (x['fails'], x['last_use']))
848
- proxy['last_use'] = current_time
849
- return proxy['url']
850
-
851
- def mark_proxy_failed(self, proxy_url: str) -> None:
852
- """标记代理失败"""
853
- with self.lock:
854
- for proxy in self.proxies:
855
- if proxy['url'] == proxy_url:
856
- proxy['fails'] += 1
857
- if proxy['fails'] >= 3:
858
- self.proxies.remove(proxy)
859
- logger.info(f"Removed failed proxy: {proxy_url}")
860
- break
861
-
862
- def check_proxy(self, proxy_url: str) -> bool:
863
- """同步检查代理是否可用"""
864
- try:
865
- response = self.session.get(
866
- 'https://www.google.com',
867
- proxies={'https': proxy_url},
868
- timeout=PROXY_TIMEOUT
869
- )
870
- return response.status_code == 200
871
- except Exception:
872
- return False
873
-
874
- def _parse_proxy_string(self, proxy_str: str) -> Optional[Dict[str, Union[str, int, float]]]:
875
- """解析代理字符串"""
876
- try:
877
- proxy_str = proxy_str.strip()
878
- if not proxy_str:
879
- return None
880
-
881
- if proxy_str.startswith(('http://', 'https://', 'socks4://', 'socks5://')):
882
- proxy_type = proxy_str.split('://')[0]
883
- address = proxy_str.split('://')[1]
884
- else:
885
- proxy_type = 'http'
886
- address = proxy_str
887
-
888
- if ':' in address:
889
- ip, port = address.split(':')
890
- port = int(port)
891
- else:
892
- return None
893
-
894
- return {
895
- 'url': proxy_str if proxy_str.startswith(('http://', 'https://', 'socks4://', 'socks5://'))
896
- else f"http://{proxy_str}",
897
- 'type': proxy_type,
898
- 'ip': ip,
899
- 'port': port,
900
- 'last_use': 0,
901
- 'fails': 0
902
- }
903
- except Exception as e:
904
- logger.error(f"Error parsing proxy string '{proxy_str}': {e}")
905
- return None
906
-
907
- def __del__(self):
908
- """清理资源"""
909
- if hasattr(self, 'session'):
910
- self.session.close()
911
-
912
- # 修改代理管理器的创建方式
913
- proxy_manager = None
914
-
915
- def get_proxy_manager():
916
- """获取或创建代理管理器实例"""
917
- global proxy_manager
918
- if proxy_manager is None:
919
- proxy_manager = ProxyManager()
920
- return proxy_manager
921
-
922
  def make_request(payload, auth_manager, model_id):
923
- """改进的请求函数,支持代理"""
924
  global multi_auth_manager
925
  max_retries = 3
926
  retry_delay = 1
@@ -940,6 +799,7 @@ def make_request(payload, auth_manager, model_id):
940
  else:
941
  raise Exception("无法注册新账号")
942
 
 
943
  tried_accounts = set()
944
 
945
  while len(tried_accounts) < len(multi_auth_manager.auth_managers):
@@ -947,6 +807,7 @@ def make_request(payload, auth_manager, model_id):
947
  if not auth_manager:
948
  break
949
 
 
950
  if auth_manager._email in tried_accounts:
951
  continue
952
 
@@ -957,61 +818,46 @@ def make_request(payload, auth_manager, model_id):
957
  try:
958
  url = get_notdiamond_url()
959
  headers = get_notdiamond_headers(auth_manager)
 
 
 
 
 
 
 
960
 
961
- # 创建新的会话
962
- session = requests.Session()
963
- adapter = CustomHTTPAdapter(max_retries=3)
964
- session.mount('https://', adapter)
965
- session.mount('http://', adapter)
966
 
967
- # 直接使用IP而不是域名
968
- url = url.replace(NOTDIAMOND_DOMAIN, NOTDIAMOND_IP)
 
 
 
 
 
 
 
 
 
 
 
969
 
970
- try:
971
- response = session.post(
972
- url,
973
- headers=headers,
974
- json=payload,
975
- stream=True,
976
- timeout=(5, 30), # (连接超时, 读取超时)
977
- verify=False # 禁用SSL验证
978
- )
979
-
980
- if response.status_code == 200:
981
- return response
982
-
983
- if response.status_code == 401:
984
- logger.info(f"Token expired for account {auth_manager._email}, attempting refresh")
985
- if auth_manager.ensure_valid_token():
986
- continue
987
-
988
- if response.status_code == 403:
989
- logger.warning(f"Model {model_id} usage limit reached for account {auth_manager._email}")
990
- auth_manager.set_model_unavailable(model_id)
991
- break
992
-
993
- logger.error(f"Request failed with status {response.status_code}")
994
-
995
- except requests.exceptions.RequestException as e:
996
- logger.error(f"Request attempt {attempt + 1} failed: {e}")
997
- if attempt < max_retries - 1:
998
- time.sleep(retry_delay)
999
- continue
1000
-
1001
  except Exception as e:
1002
- logger.error(f"Unexpected error during request: {e}")
1003
  if attempt < max_retries - 1:
1004
  time.sleep(retry_delay)
1005
  continue
1006
- finally:
1007
- session.close()
1008
 
 
1009
  if len(tried_accounts) == len(multi_auth_manager.auth_managers):
1010
  logger.info("所有现有账号都已尝试,开始注册新账号")
1011
  successful_accounts = register_bot.register_and_verify(5)
1012
  if successful_accounts:
1013
  credentials = [(account['email'], account['password']) for account in successful_accounts]
1014
  multi_auth_manager = MultiAuthManager(credentials)
 
1015
  return make_request(payload, None, model_id)
1016
 
1017
  raise Exception("所有账号均不可用,且注册新账号失败")
@@ -1067,9 +913,3 @@ if __name__ == "__main__":
1067
  port = int(os.environ.get("PORT", 3000))
1068
  app.run(debug=False, host='0.0.0.0', port=port, threaded=True)
1069
 
1070
- @atexit.register
1071
- def cleanup():
1072
- """清理资源"""
1073
- if proxy_manager:
1074
- logger.info("Cleaning up resources...")
1075
-
 
8
  import socket
9
  from concurrent.futures import ThreadPoolExecutor
10
  from functools import lru_cache, wraps
11
+ from typing import Dict, Any, Callable, List, Tuple
12
  import requests
13
  import tiktoken
14
  from flask import Flask, Response, jsonify, request, stream_with_context
 
20
  import threading
21
  from time import sleep
22
  from datetime import datetime, timedelta
 
 
 
23
 
24
  # 新增导入
25
  import register_bot
 
371
  'accept-language': 'zh-CN,zh;q=0.9',
372
  'content-type': 'application/json',
373
  'user-agent': _USER_AGENT,
374
+ 'authorization': f'Bearer {auth_manager.get_jwt_value()}'
 
375
  }
376
  headers_cache[cache_key] = headers
377
  return headers
 
778
 
779
  return payload
780
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
781
  def make_request(payload, auth_manager, model_id):
782
+ """发送请求并处理可能的认证刷新和模型特定错误。"""
783
  global multi_auth_manager
784
  max_retries = 3
785
  retry_delay = 1
 
799
  else:
800
  raise Exception("无法注册新账号")
801
 
802
+ # 记录已尝试的账号
803
  tried_accounts = set()
804
 
805
  while len(tried_accounts) < len(multi_auth_manager.auth_managers):
 
807
  if not auth_manager:
808
  break
809
 
810
+ # 如果这个账号已经尝试过,继续下一个
811
  if auth_manager._email in tried_accounts:
812
  continue
813
 
 
818
  try:
819
  url = get_notdiamond_url()
820
  headers = get_notdiamond_headers(auth_manager)
821
+ response = executor.submit(
822
+ requests.post,
823
+ url,
824
+ headers=headers,
825
+ json=payload,
826
+ stream=True
827
+ ).result()
828
 
829
+ if response.status_code == 200 and response.headers.get('Content-Type') == 'text/event-stream':
830
+ logger.info(f"请求成功,使用账号 {auth_manager._email}")
831
+ return response
 
 
832
 
833
+ headers_cache.clear()
834
+
835
+ if response.status_code == 401: # Unauthorized
836
+ logger.info(f"Token expired for account {auth_manager._email}, attempting refresh")
837
+ if auth_manager.ensure_valid_token():
838
+ continue
839
+
840
+ if response.status_code == 403: # Forbidden, 模型使用限制
841
+ logger.warning(f"Model {model_id} usage limit reached for account {auth_manager._email}")
842
+ auth_manager.set_model_unavailable(model_id)
843
+ break # 跳出重试循环,尝试下一个账号
844
+
845
+ logger.error(f"Request failed with status {response.status_code} for account {auth_manager._email}")
846
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
847
  except Exception as e:
848
+ logger.error(f"Request attempt {attempt + 1} failed for account {auth_manager._email}: {e}")
849
  if attempt < max_retries - 1:
850
  time.sleep(retry_delay)
851
  continue
 
 
852
 
853
+ # 所有账号都尝试过且失败后,才进行注册
854
  if len(tried_accounts) == len(multi_auth_manager.auth_managers):
855
  logger.info("所有现有账号都已尝试,开始注册新账号")
856
  successful_accounts = register_bot.register_and_verify(5)
857
  if successful_accounts:
858
  credentials = [(account['email'], account['password']) for account in successful_accounts]
859
  multi_auth_manager = MultiAuthManager(credentials)
860
+ # 使用新注册的账号重试请求
861
  return make_request(payload, None, model_id)
862
 
863
  raise Exception("所有账号均不可用,且注册新账号失败")
 
913
  port = int(os.environ.get("PORT", 3000))
914
  app.run(debug=False, host='0.0.0.0', port=port, threaded=True)
915
 
 
 
 
 
 
 
requirements.txt CHANGED
@@ -8,4 +8,3 @@ urllib3==1.26.9
8
  beautifulsoup4==4.11.1
9
  Pillow==9.2.0
10
  lxml==4.9.1
11
- aiohttp==3.8.1
 
8
  beautifulsoup4==4.11.1
9
  Pillow==9.2.0
10
  lxml==4.9.1