proxy_manager.py 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. # toolkit/proxy_manager.py
  2. import threading
  3. import time
  4. import random
  5. from typing import List, Optional, Dict, Any
  6. from vs_log_macros import VSC_DEBUG, VSC_WARN, VSC_INFO # type: ignore
  7. class ProxyManager:
  8. """模拟代理管理器,用于获取和锁定代理。"""
  9. _instance = None
  10. _lock = threading.Lock()
  11. def __new__(cls):
  12. with cls._lock:
  13. if cls._instance is None:
  14. cls._instance = super().__new__(cls)
  15. cls._instance._proxies = {
  16. "global_proxy": [
  17. {
  18. "id": 100003,
  19. "ip": "82.152.15.37",
  20. "lock_until": 0,
  21. "password": "idzlar",
  22. "port": 7778,
  23. "scheme": "http",
  24. "username": "4scepfs03sh920"
  25. },
  26. {
  27. "id": 100005,
  28. "ip": "82.152.19.246",
  29. "lock_until": 0,
  30. "password": "idzlar",
  31. "port": 7778,
  32. "scheme": "http",
  33. "username": "4scepfmv4gp9c"
  34. },
  35. {
  36. "id": 100014,
  37. "ip": "82.152.15.33",
  38. "lock_until": 0,
  39. "password": "idzlar",
  40. "port": 7778,
  41. "scheme": "http",
  42. "username": "4scepfpclja918"
  43. },
  44. {
  45. "id": 100018,
  46. "ip": "82.152.19.4",
  47. "lock_until": 0,
  48. "password": "idzlar",
  49. "port": 7778,
  50. "scheme": "http",
  51. "username": "4scepfmv4gp914"
  52. },
  53. {
  54. "id": 100019,
  55. "ip": "82.152.15.8",
  56. "lock_until": 0,
  57. "password": "idzlar",
  58. "port": 7778,
  59. "scheme": "http",
  60. "username": "4scepfmv4gp913"
  61. },
  62. {
  63. "id": 100020,
  64. "ip": "82.152.19.141",
  65. "lock_until": 0,
  66. "password": "idzlar",
  67. "port": 7778,
  68. "scheme": "http",
  69. "username": "4scepfmv4gp912"
  70. },
  71. {
  72. "id": 100023,
  73. "ip": "82.152.19.2",
  74. "lock_until": 0,
  75. "password": "idzlar",
  76. "port": 7778,
  77. "scheme": "http",
  78. "username": "4scepfmv4gp9e"
  79. },
  80. {
  81. "id": 100025,
  82. "ip": "163.5.40.236",
  83. "lock_until": 0,
  84. "password": "idzlar",
  85. "port": 7778,
  86. "scheme": "http",
  87. "username": "4scekff9u6j9a"
  88. },
  89. {
  90. "id": 100026,
  91. "ip": "45.196.65.44",
  92. "lock_until": 0,
  93. "password": "idzlar",
  94. "port": 7778,
  95. "scheme": "http",
  96. "username": "4sj3agscn8592cf"
  97. },
  98. {
  99. "id": 100027,
  100. "ip": "154.82.173.108",
  101. "lock_until": 0,
  102. "password": "M8v0m9b1p4b3",
  103. "port": 9856,
  104. "scheme": "http",
  105. "username": "l9w3z3c4B4O2"
  106. },
  107. {
  108. "id": 100028,
  109. "ip": "45.196.65.25",
  110. "lock_until": 0,
  111. "password": "idzlar",
  112. "port": 7778,
  113. "scheme": "http",
  114. "username": "4sio3rdic7m9184"
  115. },
  116. {
  117. "id": 100029,
  118. "ip": "45.196.65.109",
  119. "lock_until": 0,
  120. "password": "idzlar",
  121. "port": 7778,
  122. "scheme": "http",
  123. "username": "4sibp4qi26n93c"
  124. }
  125. ],
  126. "ireland_proxies": [
  127. {
  128. "id": 100029,
  129. "ip": "95.135.130.73",
  130. "lock_until": 0,
  131. "password": "RTBuPWx1CEr6DfD",
  132. "port": 48306,
  133. "scheme": "http",
  134. "username": "9zMOkhCng5HG8SZ"
  135. },
  136. {
  137. "id": 100029,
  138. "ip": "95.135.130.76",
  139. "lock_until": 0,
  140. "password": "5i4lV3VjNwE4bkL",
  141. "port": 41553,
  142. "scheme": "http",
  143. "username": "aNCaMFjblyODleO"
  144. }
  145. ]
  146. }
  147. cls._instance._proxy_lock = threading.Lock() # 用于保护代理状态
  148. return cls._instance
  149. @staticmethod
  150. def Instance():
  151. return ProxyManager()
  152. def get_next_proxy(self, pool_name: str) -> Optional[Dict[str, Any]]:
  153. """从指定池中获取下一个可用代理。"""
  154. with self._proxy_lock:
  155. proxies = self._proxies.get(pool_name, [])
  156. now = time.time()
  157. available_proxies = [p for p in proxies if p["lock_until"] <= now]
  158. if not available_proxies:
  159. VSC_WARN("proxy_manager", "No available proxies in pool '%s'", pool_name)
  160. return None
  161. proxy = random.choice(available_proxies)
  162. VSC_DEBUG("proxy_manager", "Selected proxy ID %d from pool '%s'", proxy["id"], pool_name)
  163. return proxy
  164. def get_unbind_proxy(self, pool_name: str, bounded_ids: List[int]) -> Optional[Dict[str, Any]]:
  165. """获取一个未绑定(且未锁定)的代理。"""
  166. with self._proxy_lock:
  167. proxies = self._proxies.get(pool_name, [])
  168. now = time.time()
  169. unbound_and_available_proxies = [
  170. p for p in proxies
  171. if p["id"] not in bounded_ids and p["lock_until"] <= now
  172. ]
  173. if not unbound_and_available_proxies:
  174. VSC_WARN("proxy_manager", "No unbind and available proxies in pool '%s'", pool_name)
  175. return None
  176. proxy = random.choice(unbound_and_available_proxies)
  177. VSC_DEBUG("proxy_manager", "Selected unbind proxy ID %d from pool '%s'", proxy["id"], pool_name)
  178. return proxy
  179. def lock_proxy(self, pool_name: str, proxy_id: int, duration_seconds: int):
  180. """锁定指定代理一段时间。"""
  181. with self._proxy_lock:
  182. proxies = self._proxies.get(pool_name, [])
  183. for p in proxies:
  184. if p["id"] == proxy_id:
  185. p["lock_until"] = time.time() + duration_seconds
  186. VSC_INFO("proxy_manager", "Locked proxy ID %d in pool '%s' until %s",
  187. proxy_id, pool_name, time.ctime(p["lock_until"]))
  188. return
  189. VSC_WARN("proxy_manager", "Proxy ID %d not found in pool '%s' for locking", proxy_id, pool_name)