xtn-tools-pro 1.0.0.9.1__py3-none-any.whl → 1.0.0.9.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ # 说明:
5
+ # 程序说明xxxxxxxxxxxxxxxxxxx
6
+ # History:
7
+ # Date Author Version Modification
8
+ # --------------------------------------------------------------------------------------------------
9
+ # 2025/1/22 xiatn V00.01.000 新建
10
+ # --------------------------------------------------------------------------------------------------
11
+ import time
12
+ import queue
13
+ import random
14
+ import inspect
15
+ import requests
16
+ import threading
17
+ import multiprocessing
18
+ import concurrent.futures
19
+ from multiprocessing import Process
20
+ from xtn_tools_pro.utils.crypto import get_base64_encode
21
+ from xtn_tools_pro.utils.time_utils import get_time_now_timestamp
22
+
23
+
24
+ class GoFunTaskAirV1:
25
+ def __init__(self, ini_dict, logger, go_task_function):
26
+ self.logger = logger
27
+
28
+ # 读取配置信息
29
+ host = ini_dict.get('host', '') # 域名
30
+ port = ini_dict.get('port', 0) # 端口
31
+ task = ini_dict.get('task', '') # 任务
32
+ auto = ini_dict.get('auto', '') # token
33
+
34
+ thread_num = ini_dict.get('thread_num', 0) # 线程数
35
+ restart_time = ini_dict.get('restart_time', 0) # 间隔x秒强制重启
36
+ restart_time = 60 * 60 if restart_time <= 0 else restart_time # 间隔x秒强制重启时间不传默认60分钟
37
+ update_proxies_time = ini_dict.get('update_proxies_time', 0) # 间隔x秒更新代理
38
+ upload_task_time = ini_dict.get('upload_task_time', 0) # 回写间隔
39
+ download_not_task_time = ini_dict.get('download_not_task_time', 0) # 当遇到下载任务接口返回空任务时,间隔x秒再继续请求
40
+ download_task_qsize = ini_dict.get('download_task_qsize', 10) # 触发下载任务队列的最低阈值(当下载队列小于等于x时就立刻请求下载任务接口获取任务),默认10个
41
+ download_task_qsize = 10 if download_task_qsize < 0 else download_task_qsize # 触发下载任务队列的最低阈值(当下载队列小于等于x时就立刻请求下载任务接口获取任务),默认10个
42
+
43
+ thread_num = 1 if thread_num <= 0 else thread_num
44
+
45
+ # 拼接地址
46
+ if port:
47
+ task_host = f"http://{host}:{port}"
48
+ else:
49
+ task_host = f"http://{host}"
50
+
51
+ headers = {
52
+ 'Authorization': f"Basic {get_base64_encode(f'{auto}:')}"
53
+ }
54
+
55
+ download_url = task_host + "/filter_server/phone/get"
56
+ upload_url = task_host + "/filter_server/phone/update"
57
+ update_proxy_url = task_host + f"/filter_server/proxy/random/get?taskType={task}&limit=1"
58
+
59
+ # 全部配置信息
60
+ self.__ini_info = {
61
+ "host": host,
62
+ "port": int(port),
63
+ "task": task,
64
+ "auto": auto,
65
+ "thread_num": int(thread_num),
66
+ "restart_time": int(restart_time),
67
+ "update_proxies_time": int(update_proxies_time),
68
+ "upload_task_time": int(upload_task_time),
69
+ "download_url": download_url, # 获取任务地址
70
+ "upload_url": upload_url, # 回写任务地址
71
+ "update_proxy_url": update_proxy_url, # 更新代理地址
72
+ "download_not_task_time": download_not_task_time,
73
+ "download_task_qsize": download_task_qsize,
74
+ }
75
+
76
+ # 共享任务队列
77
+ self.download_queue = multiprocessing.Queue()
78
+ self.upload_queue = multiprocessing.Queue()
79
+ manager = multiprocessing.Manager() # 进程1
80
+ self.manager_info = manager.dict()
81
+
82
+ # 获取任务
83
+ thread_download_task = threading.Thread(target=self.__download_task,
84
+ args=(self.download_queue, self.manager_info, self.__ini_info, logger))
85
+ thread_download_task.start()
86
+
87
+ # 回写任务
88
+ thread_upload_task = threading.Thread(target=self.__upload_task,
89
+ args=(self.upload_queue, self.__ini_info, logger))
90
+ thread_upload_task.start()
91
+
92
+ def __download_task(self, download_queue, manager_info, ini_info, logger):
93
+ """
94
+ 获取任务
95
+ :param queue:
96
+ :return:
97
+ """
98
+ download_url = ini_info["download_url"]
99
+ auto = ini_info["auto"]
100
+ task = ini_info["task"]
101
+ download_not_task_time = ini_info["download_not_task_time"]
102
+ download_task_qsize = ini_info["download_task_qsize"]
103
+ headers = {"Authorization": auto}
104
+ params = {"taskType": task}
105
+ logger.warning("下载队列启动成功...")
106
+ download_queue_exist_cnt = 3
107
+ while True:
108
+ try:
109
+ qsize = download_queue.qsize()
110
+ logger.info(f"当前队列剩余任务数:{qsize}")
111
+ if qsize > download_task_qsize:
112
+ time.sleep(download_not_task_time)
113
+ continue
114
+ resp = requests.get(download_url, headers=headers, params=params, timeout=5)
115
+ json_data = resp.json()
116
+ result_list = json_data.get("result", [])
117
+ if not result_list or len(result_list) <= 0:
118
+ # 判断任务响应是否为空
119
+ download_queue_exist_cnt -= 1
120
+ if download_queue_exist_cnt <= 0 and not manager_info["gofun_kill_status"]:
121
+ manager_info["gofun_kill_status"] = True
122
+ logger.warning("获取任务个数为0已超设置值,判断为无任务将关闭相关进程")
123
+ time.sleep(10)
124
+ continue
125
+
126
+ download_queue_exist_cnt = 10
127
+ manager_info["gofun_kill_status"] = False
128
+
129
+ for task_item in result_list:
130
+ phone_item = task_item["phone"]
131
+ if not phone_item.isdigit(): # 判断是否全是整数(不包括小数点或负号)
132
+ continue
133
+ download_queue.put(task_item)
134
+ logger.warning(f"成功获取任务个数:{len(result_list)}")
135
+ except Exception as e:
136
+ logger.critical(f"获取任务请求异常:{e}")
137
+ time.sleep(2)
138
+
139
+ def __upload_task(self, upload_queue, ini_info, logger):
140
+ """
141
+ 回写任务
142
+ :return:
143
+ """
144
+ upload_url = ini_info["upload_url"]
145
+ external_ip = ini_info["external_ip"]
146
+ auto = ini_info["auto"]
147
+ task = ini_info["task"]
148
+ upload_task_time = ini_info["upload_task_time"]
149
+ headers = {"Authorization": auto}
150
+ params = {"taskType": task}
151
+ logger.warning("回写队列启动成功...")
152
+ while True:
153
+ # 判断队列是否有值
154
+ empty = upload_queue.empty()
155
+ if empty:
156
+ time.sleep(2)
157
+ continue
158
+
159
+ # 循环全部获取队列的任务
160
+ result_list = []
161
+ try:
162
+ while True:
163
+ task_item = upload_queue.get_nowait()
164
+ taskNo = task_item["taskNo"]
165
+ phone = task_item["phone"]
166
+ isRegistered = task_item["isRegistered"]
167
+ country_region = task_item["country_region"]
168
+ full_phone = f"{country_region}{phone}"
169
+ task_item = {
170
+ 'taskNo': taskNo,
171
+ 'phone': full_phone,
172
+ 'isRegistered': isRegistered
173
+ }
174
+ result_list.append(task_item)
175
+ except Exception as e:
176
+ pass
177
+ # logger.critical(f"循环全部获取队列的任务{e}")
178
+
179
+ # 回写任务
180
+ data = {"result": result_list, "remoteAddr": external_ip}
181
+ while True:
182
+ try:
183
+ resp = requests.post(upload_url, json=data, headers=headers, params=params, timeout=5)
184
+ json_data = resp.json()
185
+ # logger.warning(f"成功回写任务个数:{len(result_list)},{json_data},{data}")
186
+ logger.warning(f"成功回写任务个数:{len(result_list)},{json_data}")
187
+ break
188
+ except Exception as e:
189
+ logger.critical(f"回写异常,{len(result_list)},{e}")
190
+ time.sleep(2)
191
+
192
+ if not upload_task_time:
193
+ # 一直执行 不退出
194
+ continue
195
+ time.sleep(upload_task_time)
196
+
197
+ def _run_with_timeout(self, download_queue, upload_queue, proxies_dict, thread_num, logger, go_task_function):
198
+ caller = inspect.stack()[1] # 获取调用者的调用栈信息
199
+ caller_name = caller.function # 获取调用者的函数名
200
+ caller_class = caller.frame.f_locals.get('self', None) # 获取调用者的类实例
201
+ if caller_name != "run" or caller_class is None:
202
+ raise Exception("错误调用")
203
+
204
+ with concurrent.futures.ThreadPoolExecutor(max_workers=thread_num) as executor:
205
+ # 提交10个函数到线程池中执行
206
+ futures = [executor.submit(go_task_function, self, proxies_dict, logger)
207
+ for _ in range(thread_num)]
208
+
209
+ # 等待所有线程完成
210
+ for future in concurrent.futures.as_completed(futures):
211
+ future.result()
212
+
213
+ def get_gofun_task_status(self):
214
+ status = not self.manager_info["gofun_kill_status"]
215
+ # self.logger.debug(f"get_gofun_task_status {status}")
216
+ return status
217
+
218
+ def get_download_task(self, block, timeout):
219
+ """
220
+ 获取下载任务
221
+ :param block: 是否阻塞等待 True阻塞/False不阻塞
222
+ :param timeout:
223
+ :return:
224
+ error_code:1001 队列为空;
225
+ """
226
+ try:
227
+ task_item = self.download_queue.get(block=block, timeout=timeout)
228
+ task_item["success"] = True
229
+ return task_item
230
+ except queue.Empty as e:
231
+ # 捕获队列为空的异常
232
+ # self.logger.info(f"get_download_task 获取下载任务 {download_queue, block, timeout} 报错 队列为空: {e}")
233
+ return {"error": "队列为空", "error_code": 1001}
234
+ except Exception as e:
235
+ self.logger.critical(f"get_download_task 获取下载任务 {self.download_queue, block, timeout} 报错 {e}")
236
+ return False
237
+
238
+ def update_upload_task(self, task_item):
239
+ """
240
+ 更新任务
241
+ :param task_item:
242
+ :return:
243
+ """
244
+ try:
245
+ task_item = self.upload_queue.put(task_item)
246
+ return task_item
247
+ except Exception as e:
248
+ self.logger.critical(f"update_upload_task 更新任务 {self.upload_queue, task_item} 报错 {e}")
249
+ return False
@@ -369,6 +369,19 @@ class GoFunTaskV3:
369
369
  self.logger.critical(f"update_upload_task 更新任务 {self.upload_queue, task_item} 报错 {e}")
370
370
  return False
371
371
 
372
+ def retry_download_task(self, task_item):
373
+ """
374
+ 更新重试任务
375
+ :param task_item:
376
+ :return:
377
+ """
378
+ try:
379
+ task_item = self.download_queue.put(task_item)
380
+ return task_item
381
+ except Exception as e:
382
+ self.logger.critical(f"download_queue 更新重试任务 {self.upload_queue, task_item} 报错 {e}")
383
+ return False
384
+
372
385
  def help(self):
373
386
  help_txt = """
374
387
  参数说明:
@@ -148,5 +148,23 @@ def generate_secret_key(length=32):
148
148
  return secrets.token_hex(length)
149
149
 
150
150
 
151
+ def img_bytes_to_str(img_data: bytes):
152
+ """
153
+ 图片数据 bytes_to_str
154
+ :param img_data:
155
+ :return:
156
+ """
157
+ return img_data.decode('latin1')
158
+
159
+
160
+ def img_str_to_bytes(img_data: str):
161
+ """
162
+ 图片数据 str_to_bytes
163
+ :param img_data:
164
+ :return:
165
+ """
166
+ return img_data.encode('latin1')
167
+
168
+
151
169
  if __name__ == '__main__':
152
170
  print(get_base64_encode(''))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xtn-tools-pro
3
- Version: 1.0.0.9.1
3
+ Version: 1.0.0.9.3
4
4
  Summary: xtn 开发工具
5
5
  Author: xtn
6
6
  Author-email: czw011122@gmail.com
@@ -49,10 +49,11 @@ xtn_tools_pro/proxy/__init__.py,sha256=WRwh6s2lruMu5buh0ejo9EK54kWT_VQhCsFGNFAmc
49
49
  xtn_tools_pro/proxy/proxy.py,sha256=No6E1pFY5yx2F4976pXPrLtq-QEVp79KupzcufjSN58,8703
50
50
  xtn_tools_pro/task_pro/__init__.py,sha256=nK3U47hWwE1H875ieEToH9r-jzXHS-PXk8cDstOvRE8,418
51
51
  xtn_tools_pro/task_pro/go_fun.py,sha256=hWEt2uJ9FCvJH7PhVZttS-11A7J6zbRKwX7c5YLYQag,19144
52
+ xtn_tools_pro/task_pro/go_fun_air_v1.py,sha256=25gHmW5aAV6nMY9Y6-wD7uQ_wqE39dr-eaegqVbYKM8,11035
52
53
  xtn_tools_pro/task_pro/go_fun_v2.py,sha256=SgcXgtEBGSVL1V2LyqO0z8Md2H8JZxucYrLLIwqtiLM,18489
53
- xtn_tools_pro/task_pro/go_fun_v3.py,sha256=PdmT59wTJYS3gYS8d3LQX8JvQcREqfZENiy3MARb0UY,17991
54
+ xtn_tools_pro/task_pro/go_fun_v3.py,sha256=Gz4BK9b0KQq2ztgm81jaMInDf4sG9154zw8HRxPVIbY,18419
54
55
  xtn_tools_pro/utils/__init__.py,sha256=I1_n_NP23F2lBqlF4EOlnOdLYxM8M4pbn63UhJN1hRE,418
55
- xtn_tools_pro/utils/crypto.py,sha256=oyzFqWum_oimUtzhfVCELQhdMjxDbLu-nOWfcNmazcc,4087
56
+ xtn_tools_pro/utils/crypto.py,sha256=YOdWB8yVauVEyT2d5i9M_bXUJVFTq4BQoUy2NLPhmts,4427
56
57
  xtn_tools_pro/utils/file_utils.py,sha256=obaBP7CaBCsXxzqGeWzV2l0yw7vicgKOaXzmpMV8ips,2567
57
58
  xtn_tools_pro/utils/helpers.py,sha256=H-a3gnahIah3kJqyKzzKlPWtVQYcFlJncz2rAfBqIiw,4444
58
59
  xtn_tools_pro/utils/log.py,sha256=mf5huJDA8xVxxFWPG_tl_vOsAA2_ywGDFycYSGHIDCo,10202
@@ -60,9 +61,9 @@ xtn_tools_pro/utils/retry.py,sha256=0wjHsR5DBBKpv4naMfxiky8kprrZes4WURIfFQ4H708,
60
61
  xtn_tools_pro/utils/set_data.py,sha256=IthfAclck7AbaxOIKOgJZ2wdcfEmlvC-C63Tywcr4bA,11180
61
62
  xtn_tools_pro/utils/sql.py,sha256=EAKzbkZP7Q09j15Gm6o0_uq0qgQmcCQT6EAawbpp4v0,6263
62
63
  xtn_tools_pro/utils/time_utils.py,sha256=TUtzG61PeVYXhaQd6pBrXAdlz7tBispNIRQRcGhE2No,4859
63
- xtn_tools_pro-1.0.0.9.1.dist-info/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
- xtn_tools_pro-1.0.0.9.1.dist-info/METADATA,sha256=Iq-XIpN4T-Y8ahnprGrrCu-Pvp4Eho55piq0XpSHrEw,498
65
- xtn_tools_pro-1.0.0.9.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
66
- xtn_tools_pro-1.0.0.9.1.dist-info/entry_points.txt,sha256=t8CtXWOgw7nRDW3XNlZh8MT_P4l8EzsFnyWi5b3ovrc,68
67
- xtn_tools_pro-1.0.0.9.1.dist-info/top_level.txt,sha256=jyB3FLDEr8zE1U7wHczTgIbvUpALhR-ULF7RVEO7O2U,14
68
- xtn_tools_pro-1.0.0.9.1.dist-info/RECORD,,
64
+ xtn_tools_pro-1.0.0.9.3.dist-info/LICENSE,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
65
+ xtn_tools_pro-1.0.0.9.3.dist-info/METADATA,sha256=PNzGzPQXZ1wXfUf_3aenyIrzYhRWeANk1KTn7zgYXJ0,498
66
+ xtn_tools_pro-1.0.0.9.3.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
67
+ xtn_tools_pro-1.0.0.9.3.dist-info/entry_points.txt,sha256=t8CtXWOgw7nRDW3XNlZh8MT_P4l8EzsFnyWi5b3ovrc,68
68
+ xtn_tools_pro-1.0.0.9.3.dist-info/top_level.txt,sha256=jyB3FLDEr8zE1U7wHczTgIbvUpALhR-ULF7RVEO7O2U,14
69
+ xtn_tools_pro-1.0.0.9.3.dist-info/RECORD,,