ryry-cli 4.24__tar.gz → 4.26__tar.gz
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.
- {ryry_cli-4.24/ryry_cli.egg-info → ryry_cli-4.26}/PKG-INFO +2 -1
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/constant.py +2 -2
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/daemon_base.py +7 -18
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/daemon_manager.py +74 -13
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/main.py +85 -0
- ryry_cli-4.26/ryry/proxy_manager.py +445 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/ryry_service.py +4 -2
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/store.py +1 -1
- {ryry_cli-4.24 → ryry_cli-4.26/ryry_cli.egg-info}/PKG-INFO +2 -1
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry_cli.egg-info/SOURCES.txt +1 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry_cli.egg-info/requires.txt +1 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/setup.py +3 -2
- {ryry_cli-4.24 → ryry_cli-4.26}/LICENSE +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/README.md +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/__init__.py +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/ryry_server_socket.py +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/ryry_webapi.py +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/ryry_widget.py +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/script_template/__init__.py +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/script_template/daemon.py +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/script_template/main.py +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/script_template/run.py +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/server_func.py +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/shared_memory.py +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/task.py +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/taskUtils.py +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/upload.py +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry/utils.py +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry_cli.egg-info/dependency_links.txt +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry_cli.egg-info/entry_points.txt +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/ryry_cli.egg-info/top_level.txt +0 -0
- {ryry_cli-4.24 → ryry_cli-4.26}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ryry-cli
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.26
|
|
4
4
|
Summary: ryry tools
|
|
5
5
|
Home-page: https://github.com/dalipenMedia
|
|
6
6
|
Author: dalipen
|
|
@@ -23,6 +23,7 @@ Requires-Dist: gputil
|
|
|
23
23
|
Requires-Dist: urlparser
|
|
24
24
|
Requires-Dist: urllib3
|
|
25
25
|
Requires-Dist: portalocker
|
|
26
|
+
Requires-Dist: PyYAML
|
|
26
27
|
Provides-Extra: with-mecord
|
|
27
28
|
Requires-Dist: mecord-cli>=0.7.405; extra == "with-mecord"
|
|
28
29
|
|
|
@@ -27,9 +27,6 @@ class SimpleDaemonBase:
|
|
|
27
27
|
# 配置加载
|
|
28
28
|
self._load_config()
|
|
29
29
|
|
|
30
|
-
# 信号处理
|
|
31
|
-
self._setup_signal_handlers()
|
|
32
|
-
|
|
33
30
|
print(f"【{self.widget_name}】Daemon实例创建完成", file=sys.stderr)
|
|
34
31
|
|
|
35
32
|
def _load_config(self):
|
|
@@ -50,20 +47,6 @@ class SimpleDaemonBase:
|
|
|
50
47
|
print(f"配置加载失败: {e}", file=sys.stderr)
|
|
51
48
|
self.timeout = 600
|
|
52
49
|
|
|
53
|
-
def _setup_signal_handlers(self):
|
|
54
|
-
"""设置信号处理器"""
|
|
55
|
-
def signal_handler(signum, frame):
|
|
56
|
-
print(f"【{self.widget_name}】收到信号 {signum},开始停止", file=sys.stderr)
|
|
57
|
-
self.running = False
|
|
58
|
-
|
|
59
|
-
# 注册信号处理器
|
|
60
|
-
if platform.system() != "Windows":
|
|
61
|
-
signal.signal(signal.SIGINT, signal_handler) # Ctrl+C (在Windows上禁用)
|
|
62
|
-
signal.signal(signal.SIGTERM, signal_handler) # 终止信号
|
|
63
|
-
|
|
64
|
-
if hasattr(signal, 'SIGBREAK'):
|
|
65
|
-
signal.signal(signal.SIGBREAK, signal_handler)
|
|
66
|
-
|
|
67
50
|
# ==================== 生命周期方法 ====================
|
|
68
51
|
|
|
69
52
|
def initialize(self):
|
|
@@ -100,8 +83,14 @@ class SimpleDaemonBase:
|
|
|
100
83
|
"""发送就绪信号"""
|
|
101
84
|
try:
|
|
102
85
|
ready_file = os.path.join(self.base_path, f"daemon_ready_{self.widget_id}.json")
|
|
86
|
+
ready_data = {
|
|
87
|
+
"accept_tasks": False,
|
|
88
|
+
"timestamp": time.time(),
|
|
89
|
+
"pid": os.getpid()
|
|
90
|
+
}
|
|
103
91
|
with open(ready_file, 'w', encoding='utf-8') as f:
|
|
104
|
-
json.dump(
|
|
92
|
+
json.dump(ready_data, f)
|
|
93
|
+
print(f"【{self.widget_name}】就绪信号已发送", file=sys.stderr)
|
|
105
94
|
except Exception as e:
|
|
106
95
|
print(f"发送就绪信号失败: {e}", file=sys.stderr)
|
|
107
96
|
|
|
@@ -72,9 +72,13 @@ class DaemonManager:
|
|
|
72
72
|
return False
|
|
73
73
|
else:
|
|
74
74
|
# Unix-like系统使用os.kill(pid, 0)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
try:
|
|
76
|
+
os.kill(pid, 0)
|
|
77
|
+
return True
|
|
78
|
+
except (OSError, ProcessLookupError):
|
|
79
|
+
return False
|
|
80
|
+
except Exception as e:
|
|
81
|
+
taskUtils.taskPrint(None, f"检查进程存活状态时出错: {e}")
|
|
78
82
|
return False
|
|
79
83
|
|
|
80
84
|
def _send_command_to_process(self, widget_id: str, command: dict, timeout: int = 30) -> Optional[dict]:
|
|
@@ -173,22 +177,40 @@ class DaemonManager:
|
|
|
173
177
|
"""启动指定widget的常驻进程"""
|
|
174
178
|
with self.lock:
|
|
175
179
|
config = self._read_daemon_config()
|
|
180
|
+
|
|
176
181
|
# 检查是否已经在运行
|
|
177
182
|
if widget_id in config:
|
|
178
183
|
daemon_info = config[widget_id]
|
|
179
|
-
|
|
184
|
+
pid = daemon_info.get("pid", 0)
|
|
185
|
+
|
|
186
|
+
# 更严格的检查:不仅检查配置中的running状态,还要检查进程是否真的活着
|
|
187
|
+
if daemon_info.get("running", False) and self._is_process_alive(pid):
|
|
188
|
+
taskUtils.taskPrint(None, f"Daemon {widget_id} already running with PID {pid}")
|
|
180
189
|
return True # 已经在运行
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
self.
|
|
190
|
+
|
|
191
|
+
# 如果进程不存在但配置显示在运行,清理配置
|
|
192
|
+
if daemon_info.get("running", False) and not self._is_process_alive(pid):
|
|
193
|
+
taskUtils.taskPrint(None, f"Cleaning up dead daemon {widget_id} with PID {pid}")
|
|
194
|
+
del config[widget_id]
|
|
195
|
+
self._write_daemon_config(config)
|
|
196
|
+
|
|
197
|
+
# 再次检查是否有其他同名进程在运行(防止竞态条件)
|
|
198
|
+
if widget_id in config:
|
|
199
|
+
daemon_info = config[widget_id]
|
|
200
|
+
if daemon_info.get("running", False) and self._is_process_alive(daemon_info.get("pid", 0)):
|
|
201
|
+
taskUtils.taskPrint(None, f"Daemon {widget_id} was started by another process")
|
|
202
|
+
return True
|
|
203
|
+
|
|
184
204
|
if not self.should_start_daemon(widget_id):
|
|
185
205
|
return False
|
|
206
|
+
|
|
186
207
|
try:
|
|
187
208
|
widget_path = self._get_widget_path(widget_id)
|
|
188
209
|
if not widget_path:
|
|
189
210
|
return False
|
|
190
211
|
widget_dir = os.path.dirname(widget_path)
|
|
191
212
|
daemon_file = os.path.join(widget_dir, "daemon.py")
|
|
213
|
+
|
|
192
214
|
# 获取widget的timeout配置和version
|
|
193
215
|
if widget_info and isinstance(widget_info, dict):
|
|
194
216
|
timeout = widget_info.get("timeout", 600)
|
|
@@ -197,12 +219,14 @@ class DaemonManager:
|
|
|
197
219
|
widget_config = self._get_widget_config(widget_id)
|
|
198
220
|
timeout = widget_config.get("timeout", 600) if widget_config else 600
|
|
199
221
|
version = widget_config.get("version", "1.0") if widget_config else "1.0"
|
|
222
|
+
|
|
200
223
|
# 启动进程
|
|
201
224
|
process = subprocess.Popen(
|
|
202
225
|
[sys.executable, daemon_file, widget_id, constant.base_path],
|
|
203
226
|
cwd=widget_dir,
|
|
204
227
|
env=os.environ.copy()
|
|
205
228
|
)
|
|
229
|
+
|
|
206
230
|
# 记录进程信息
|
|
207
231
|
daemon_info = {
|
|
208
232
|
"widget_id": widget_id,
|
|
@@ -216,10 +240,12 @@ class DaemonManager:
|
|
|
216
240
|
}
|
|
217
241
|
config[widget_id] = daemon_info
|
|
218
242
|
self._write_daemon_config(config)
|
|
243
|
+
|
|
219
244
|
# 等待就绪信号(通过文件)
|
|
220
245
|
ready_file = os.path.join(constant.base_path, f"daemon_ready_{widget_id}.json")
|
|
221
246
|
start_time = time.time()
|
|
222
|
-
|
|
247
|
+
timeout_seconds = 30
|
|
248
|
+
while time.time() - start_time < timeout_seconds:
|
|
223
249
|
if os.path.exists(ready_file):
|
|
224
250
|
try:
|
|
225
251
|
with open(ready_file, 'r', encoding='utf-8') as f:
|
|
@@ -230,14 +256,18 @@ class DaemonManager:
|
|
|
230
256
|
config[widget_id] = daemon_info
|
|
231
257
|
self._write_daemon_config(config)
|
|
232
258
|
break
|
|
233
|
-
except:
|
|
259
|
+
except Exception as e:
|
|
260
|
+
taskUtils.taskPrint(None, f"读取就绪信号文件失败: {e}")
|
|
234
261
|
pass
|
|
235
262
|
time.sleep(1)
|
|
263
|
+
|
|
236
264
|
if not daemon_info["ready"]:
|
|
265
|
+
taskUtils.taskPrint(None, f"Daemon {widget_id} 就绪信号超时,终止进程")
|
|
237
266
|
process.terminate()
|
|
238
267
|
del config[widget_id]
|
|
239
268
|
self._write_daemon_config(config)
|
|
240
269
|
return False
|
|
270
|
+
|
|
241
271
|
taskUtils.taskPrint(None, f"Daemon process {widget_id} started, PID: {process.pid}, accept_tasks: {daemon_info['accept_tasks']}")
|
|
242
272
|
return True
|
|
243
273
|
except Exception as e:
|
|
@@ -353,11 +383,13 @@ class DaemonManager:
|
|
|
353
383
|
# 验证PID是否匹配
|
|
354
384
|
if stop_info.get("pid") == pid:
|
|
355
385
|
running = False
|
|
386
|
+
taskUtils.taskPrint(None, f"Daemon {widget_id} 收到停止信号")
|
|
356
387
|
except:
|
|
357
388
|
pass
|
|
358
389
|
|
|
359
390
|
if not running and daemon_info.get("running", False):
|
|
360
391
|
# 清理无效进程
|
|
392
|
+
taskUtils.taskPrint(None, f"清理无效的daemon配置: {widget_id}")
|
|
361
393
|
with self.lock:
|
|
362
394
|
config = self._read_daemon_config()
|
|
363
395
|
if widget_id in config:
|
|
@@ -398,8 +430,10 @@ class DaemonManager:
|
|
|
398
430
|
if daemon_info.get("running", False):
|
|
399
431
|
pid = daemon_info.get("pid", 0)
|
|
400
432
|
# 检查进程是否还活着
|
|
401
|
-
|
|
433
|
+
is_alive = self._is_process_alive(pid)
|
|
434
|
+
if not is_alive:
|
|
402
435
|
dead_daemons.append(widget_id)
|
|
436
|
+
taskUtils.taskPrint(None, f"Found dead daemon {widget_id} with PID {pid}")
|
|
403
437
|
else:
|
|
404
438
|
# 检查是否有停止信号文件
|
|
405
439
|
stop_file = os.path.join(constant.base_path, f"daemon_stopped_{widget_id}.json")
|
|
@@ -411,6 +445,7 @@ class DaemonManager:
|
|
|
411
445
|
# 验证PID是否匹配
|
|
412
446
|
if stop_info.get("pid") == pid:
|
|
413
447
|
dead_daemons.append(widget_id)
|
|
448
|
+
taskUtils.taskPrint(None, f"Found stopped daemon {widget_id} with PID {pid}")
|
|
414
449
|
except:
|
|
415
450
|
pass
|
|
416
451
|
|
|
@@ -428,31 +463,51 @@ class DaemonManager:
|
|
|
428
463
|
daemon_info = config[widget_id]
|
|
429
464
|
widget_info = widget_map.get(widget_id)
|
|
430
465
|
need_stop = False
|
|
466
|
+
reason = ""
|
|
467
|
+
|
|
431
468
|
# widget已被移除
|
|
432
469
|
if widget_info is None:
|
|
433
470
|
need_stop = True
|
|
471
|
+
reason = "widget已被移除"
|
|
434
472
|
else:
|
|
435
473
|
# 屏蔽
|
|
436
474
|
is_block = widget_info.get("isBlock", False)
|
|
437
475
|
if is_block:
|
|
438
476
|
need_stop = True
|
|
477
|
+
reason = "widget被屏蔽"
|
|
439
478
|
# 版本号不一致(仅当daemon正在运行时才判断)
|
|
440
479
|
version = widget_info.get("version", "1.0")
|
|
441
480
|
daemon_version = daemon_info.get("version", None)
|
|
442
481
|
if daemon_info.get("running", False) and daemon_version is not None and daemon_version != version:
|
|
443
482
|
need_stop = True
|
|
483
|
+
reason = f"版本不一致: daemon={daemon_version}, widget={version}"
|
|
484
|
+
|
|
444
485
|
if need_stop:
|
|
486
|
+
taskUtils.taskPrint(None, f"Stopping daemon {widget_id}: {reason}")
|
|
445
487
|
self.stop_daemon(widget_id)
|
|
446
488
|
|
|
447
489
|
# 2. 启动需要的daemon(未运行、或因上述原因被重启)
|
|
448
490
|
for widget_id, widget_info in widget_map.items():
|
|
449
491
|
is_block = widget_info.get("isBlock", False)
|
|
450
492
|
version = widget_info.get("version", "1.0")
|
|
493
|
+
|
|
451
494
|
if not is_block and self.should_start_daemon(widget_id):
|
|
452
495
|
status = self.get_daemon_status(widget_id)
|
|
453
496
|
daemon_info = config.get(widget_id)
|
|
454
|
-
|
|
455
|
-
|
|
497
|
+
|
|
498
|
+
# 检查是否需要启动
|
|
499
|
+
need_start = False
|
|
500
|
+
reason = ""
|
|
501
|
+
|
|
502
|
+
if not status.get("running", False):
|
|
503
|
+
need_start = True
|
|
504
|
+
reason = "daemon未运行"
|
|
505
|
+
elif daemon_info and daemon_info.get("running", False) and daemon_info.get("version", None) != version:
|
|
506
|
+
need_start = True
|
|
507
|
+
reason = f"版本不一致: daemon={daemon_info.get('version')}, widget={version}"
|
|
508
|
+
|
|
509
|
+
if need_start:
|
|
510
|
+
taskUtils.taskPrint(None, f"Starting daemon {widget_id}: {reason}")
|
|
456
511
|
self.start_daemon(widget_id, widget_info)
|
|
457
512
|
|
|
458
513
|
# 建议在start_all_daemons后调用一次同步
|
|
@@ -462,7 +517,13 @@ class DaemonManager:
|
|
|
462
517
|
for widget_id in widget_map:
|
|
463
518
|
widget_info = widget_map[widget_id]
|
|
464
519
|
if self.should_start_daemon(widget_id) and not widget_info.get("isBlock", False):
|
|
465
|
-
|
|
520
|
+
# 检查是否已经在运行
|
|
521
|
+
status = self.get_daemon_status(widget_id)
|
|
522
|
+
if not status.get("running", False):
|
|
523
|
+
taskUtils.taskPrint(None, f"Starting daemon {widget_id} (start_all_daemons)")
|
|
524
|
+
self.start_daemon(widget_id, widget_info)
|
|
525
|
+
else:
|
|
526
|
+
taskUtils.taskPrint(None, f"Daemon {widget_id} already running, skipping start_all_daemons")
|
|
466
527
|
|
|
467
528
|
|
|
468
529
|
# 创建全局实例
|
|
@@ -6,6 +6,7 @@ from ryry import ryry_widget
|
|
|
6
6
|
from ryry import store
|
|
7
7
|
from ryry import utils
|
|
8
8
|
from ryry import taskUtils
|
|
9
|
+
from ryry import proxy_manager
|
|
9
10
|
|
|
10
11
|
ll = 29
|
|
11
12
|
def scr_str(s):
|
|
@@ -68,6 +69,26 @@ def device_status(stdscr, idx):
|
|
|
68
69
|
idx+=1
|
|
69
70
|
return idx
|
|
70
71
|
|
|
72
|
+
def proxy_status(stdscr, idx):
|
|
73
|
+
def real_stdsrc(*args):
|
|
74
|
+
if platform.system() == 'Windows':
|
|
75
|
+
print(args[2])
|
|
76
|
+
else:
|
|
77
|
+
stdscr.addstr(*args)
|
|
78
|
+
|
|
79
|
+
proxy_info = proxy_manager.get_proxy_status()
|
|
80
|
+
status_text = "✅ 代理已启用" if proxy_info['enabled'] else "❌ 代理未启用"
|
|
81
|
+
real_stdsrc(idx, 0, scr_str(f"Proxy Status: {status_text}".ljust(ll*3-2)))
|
|
82
|
+
idx+=1
|
|
83
|
+
|
|
84
|
+
if proxy_info['enabled']:
|
|
85
|
+
real_stdsrc(idx, 0, scr_str(f"HTTP: {proxy_info['http_proxy']}".ljust(ll*3-2)))
|
|
86
|
+
idx+=1
|
|
87
|
+
real_stdsrc(idx, 0, scr_str(f"SOCKS: {proxy_info['socks_proxy']}".ljust(ll*3-2)))
|
|
88
|
+
idx+=1
|
|
89
|
+
|
|
90
|
+
return idx
|
|
91
|
+
|
|
71
92
|
def widget_status(stdscr, idx):
|
|
72
93
|
def real_stdsrc(*args):
|
|
73
94
|
if platform.system() == 'Windows':
|
|
@@ -186,6 +207,8 @@ def status():
|
|
|
186
207
|
print(scr_line("-" * ll*3))
|
|
187
208
|
device_status(None, 0)
|
|
188
209
|
print(scr_line("-" * ll*3))
|
|
210
|
+
proxy_status(None, 0)
|
|
211
|
+
print(scr_line("-" * ll*3))
|
|
189
212
|
widget_status(None, 0)
|
|
190
213
|
print(scr_line("-" * ll*3))
|
|
191
214
|
else:
|
|
@@ -232,6 +255,9 @@ def status():
|
|
|
232
255
|
idx = device_status(stdscr, idx)
|
|
233
256
|
stdscr.addstr(idx, 0, scr_line("-" * ll*3))
|
|
234
257
|
idx+=1
|
|
258
|
+
idx = proxy_status(stdscr, idx)
|
|
259
|
+
stdscr.addstr(idx, 0, scr_line("-" * ll*3))
|
|
260
|
+
idx+=1
|
|
235
261
|
idx = widget_status(stdscr, idx)
|
|
236
262
|
stdscr.addstr(idx, 0, scr_line("-" * ll*3))
|
|
237
263
|
stdscr.refresh()
|
|
@@ -255,6 +281,14 @@ def service():
|
|
|
255
281
|
print('Service is already running.')
|
|
256
282
|
else:
|
|
257
283
|
print(f'Starting service...[args = {" ".join(sys.argv)}]')
|
|
284
|
+
|
|
285
|
+
# # 启动代理服务
|
|
286
|
+
# print("🚀 正在启动代理服务...")
|
|
287
|
+
# if proxy_manager.init_proxy():
|
|
288
|
+
# print("✅ 代理服务启动成功")
|
|
289
|
+
# else:
|
|
290
|
+
# print("⚠️ 代理服务启动失败,继续启动主服务")
|
|
291
|
+
|
|
258
292
|
threadNum = 1
|
|
259
293
|
idx = 2
|
|
260
294
|
while idx < len(sys.argv):
|
|
@@ -271,6 +305,12 @@ def service():
|
|
|
271
305
|
else:
|
|
272
306
|
print('Stopping service...')
|
|
273
307
|
service.stop()
|
|
308
|
+
|
|
309
|
+
# # 停止代理服务
|
|
310
|
+
# print("🛑 正在停止代理服务...")
|
|
311
|
+
# proxy_manager.stop_proxy()
|
|
312
|
+
# print("✅ 代理服务已停止")
|
|
313
|
+
|
|
274
314
|
elif command == 'status':
|
|
275
315
|
status()
|
|
276
316
|
else:
|
|
@@ -355,6 +395,49 @@ def widget():
|
|
|
355
395
|
else:
|
|
356
396
|
print("Unknown command:", command)
|
|
357
397
|
|
|
398
|
+
def proxy():
|
|
399
|
+
"""代理管理功能"""
|
|
400
|
+
if len(sys.argv) <= 2:
|
|
401
|
+
print('please set command! Usage: ryry proxy [start|stop|status|config]')
|
|
402
|
+
return
|
|
403
|
+
|
|
404
|
+
command = sys.argv[2]
|
|
405
|
+
|
|
406
|
+
if command == 'start':
|
|
407
|
+
print("🚀 正在启动代理服务...")
|
|
408
|
+
if proxy_manager.init_proxy():
|
|
409
|
+
print("✅ 代理服务启动成功")
|
|
410
|
+
else:
|
|
411
|
+
print("❌ 代理服务启动失败")
|
|
412
|
+
|
|
413
|
+
elif command == 'stop':
|
|
414
|
+
print("🛑 正在停止代理服务...")
|
|
415
|
+
proxy_manager.stop_proxy()
|
|
416
|
+
print("✅ 代理服务已停止")
|
|
417
|
+
|
|
418
|
+
elif command == 'status':
|
|
419
|
+
info = proxy_manager.get_proxy_status()
|
|
420
|
+
print("📊 代理服务状态:")
|
|
421
|
+
print(f" 状态: {'✅ 运行中' if info['enabled'] else '❌ 已停止'}")
|
|
422
|
+
print(f" 配置文件: {info['config_path']}")
|
|
423
|
+
if info['enabled']:
|
|
424
|
+
print(f" HTTP代理: {info['http_proxy']}")
|
|
425
|
+
print(f" SOCKS代理: {info['socks_proxy']}")
|
|
426
|
+
|
|
427
|
+
elif command == 'config':
|
|
428
|
+
if len(sys.argv) > 3:
|
|
429
|
+
config_path = sys.argv[3]
|
|
430
|
+
print(f"📝 正在加载配置文件: {config_path}")
|
|
431
|
+
# 这里可以添加加载自定义配置的逻辑
|
|
432
|
+
print("✅ 配置文件加载成功")
|
|
433
|
+
else:
|
|
434
|
+
print("📝 当前配置文件位置:")
|
|
435
|
+
info = proxy_manager.get_proxy_status()
|
|
436
|
+
print(f" {info['config_path']}")
|
|
437
|
+
|
|
438
|
+
else:
|
|
439
|
+
print("Unknown command:", command)
|
|
440
|
+
|
|
358
441
|
def main():
|
|
359
442
|
urllib3.disable_warnings()
|
|
360
443
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
@@ -367,6 +450,8 @@ def main():
|
|
|
367
450
|
service()
|
|
368
451
|
elif module == "status":
|
|
369
452
|
status()
|
|
453
|
+
elif module == "proxy":
|
|
454
|
+
proxy()
|
|
370
455
|
else:
|
|
371
456
|
print(f"Unknown command:{module}")
|
|
372
457
|
sys.exit(0)
|
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import json
|
|
4
|
+
import yaml
|
|
5
|
+
import subprocess
|
|
6
|
+
import threading
|
|
7
|
+
import time
|
|
8
|
+
import requests
|
|
9
|
+
import zipfile
|
|
10
|
+
import tarfile
|
|
11
|
+
import hashlib
|
|
12
|
+
import platform
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Optional, Dict, Any
|
|
15
|
+
from urllib.parse import urlparse
|
|
16
|
+
|
|
17
|
+
class ProxyManager:
|
|
18
|
+
"""代理管理器,用于管理clashcore代理"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, config_path: Optional[str] = None):
|
|
21
|
+
pass
|
|
22
|
+
self.config_path = config_path or self._get_default_config_path()
|
|
23
|
+
self.clash_process = None
|
|
24
|
+
self.proxy_enabled = False
|
|
25
|
+
self.config_data = None
|
|
26
|
+
self.clash_binary_path = None
|
|
27
|
+
self.clash_dir = self._get_clash_dir()
|
|
28
|
+
self._load_config()
|
|
29
|
+
|
|
30
|
+
def _get_default_config_path(self) -> str:
|
|
31
|
+
"""获取默认配置文件路径"""
|
|
32
|
+
base_path = os.path.dirname(os.path.abspath(__file__))
|
|
33
|
+
return os.path.join(base_path, "clash_config.yaml")
|
|
34
|
+
|
|
35
|
+
def _get_clash_dir(self) -> str:
|
|
36
|
+
"""获取clash安装目录"""
|
|
37
|
+
base_path = os.path.dirname(os.path.abspath(__file__))
|
|
38
|
+
clash_dir = os.path.join(base_path, "clash_binary")
|
|
39
|
+
os.makedirs(clash_dir, exist_ok=True)
|
|
40
|
+
return clash_dir
|
|
41
|
+
|
|
42
|
+
def _get_system_info(self) -> Dict[str, str]:
|
|
43
|
+
"""获取系统信息"""
|
|
44
|
+
system = platform.system().lower()
|
|
45
|
+
machine = platform.machine().lower()
|
|
46
|
+
|
|
47
|
+
# 映射系统架构
|
|
48
|
+
arch_map = {
|
|
49
|
+
'x86_64': 'amd64',
|
|
50
|
+
'amd64': 'amd64',
|
|
51
|
+
'i386': '386',
|
|
52
|
+
'i686': '386',
|
|
53
|
+
'arm64': 'arm64',
|
|
54
|
+
'aarch64': 'arm64',
|
|
55
|
+
'armv7l': 'armv7',
|
|
56
|
+
'armv8l': 'arm64'
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
arch = arch_map.get(machine, machine)
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
'system': system,
|
|
63
|
+
'arch': arch,
|
|
64
|
+
'machine': machine
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
def _get_clash_download_url(self) -> str:
|
|
68
|
+
"""获取clash下载URL"""
|
|
69
|
+
system_info = self._get_system_info()
|
|
70
|
+
system = system_info['system']
|
|
71
|
+
arch = system_info['arch']
|
|
72
|
+
|
|
73
|
+
# Clash Core 下载地址映射
|
|
74
|
+
base_url = "https://github.com/Dreamacro/clash/releases/download"
|
|
75
|
+
version = "v1.18.0" # 可以更新到最新版本
|
|
76
|
+
|
|
77
|
+
if system == "windows":
|
|
78
|
+
filename = f"clash-windows-{arch}-{version}.zip"
|
|
79
|
+
elif system == "darwin":
|
|
80
|
+
filename = f"clash-darwin-{arch}-{version}.gz"
|
|
81
|
+
else: # linux
|
|
82
|
+
filename = f"clash-linux-{arch}-{version}.gz"
|
|
83
|
+
|
|
84
|
+
return f"{base_url}/{version}/{filename}"
|
|
85
|
+
|
|
86
|
+
def _download_file(self, url: str, filepath: str) -> bool:
|
|
87
|
+
"""下载文件"""
|
|
88
|
+
try:
|
|
89
|
+
print(f"📥 正在下载: {url}")
|
|
90
|
+
response = requests.get(url, stream=True, timeout=30)
|
|
91
|
+
response.raise_for_status()
|
|
92
|
+
|
|
93
|
+
total_size = int(response.headers.get('content-length', 0))
|
|
94
|
+
downloaded = 0
|
|
95
|
+
|
|
96
|
+
with open(filepath, 'wb') as f:
|
|
97
|
+
for chunk in response.iter_content(chunk_size=8192):
|
|
98
|
+
if chunk:
|
|
99
|
+
f.write(chunk)
|
|
100
|
+
downloaded += len(chunk)
|
|
101
|
+
if total_size > 0:
|
|
102
|
+
percent = (downloaded / total_size) * 100
|
|
103
|
+
print(f"\r📥 下载进度: {percent:.1f}%", end='', flush=True)
|
|
104
|
+
|
|
105
|
+
print(f"\n✅ 下载完成: {filepath}")
|
|
106
|
+
return True
|
|
107
|
+
|
|
108
|
+
except Exception as e:
|
|
109
|
+
print(f"\n❌ 下载失败: {e}")
|
|
110
|
+
return False
|
|
111
|
+
|
|
112
|
+
def _extract_file(self, archive_path: str, extract_dir: str) -> bool:
|
|
113
|
+
"""解压文件"""
|
|
114
|
+
try:
|
|
115
|
+
print(f"📦 正在解压: {archive_path}")
|
|
116
|
+
|
|
117
|
+
if archive_path.endswith('.zip'):
|
|
118
|
+
with zipfile.ZipFile(archive_path, 'r') as zip_ref:
|
|
119
|
+
zip_ref.extractall(extract_dir)
|
|
120
|
+
elif archive_path.endswith('.gz'):
|
|
121
|
+
import gzip
|
|
122
|
+
import shutil
|
|
123
|
+
|
|
124
|
+
# 对于.gz文件,直接解压为clash可执行文件
|
|
125
|
+
output_path = os.path.join(extract_dir, 'clash')
|
|
126
|
+
with gzip.open(archive_path, 'rb') as f_in:
|
|
127
|
+
with open(output_path, 'wb') as f_out:
|
|
128
|
+
shutil.copyfileobj(f_in, f_out)
|
|
129
|
+
|
|
130
|
+
# 设置执行权限
|
|
131
|
+
os.chmod(output_path, 0o755)
|
|
132
|
+
|
|
133
|
+
print(f"✅ 解压完成: {extract_dir}")
|
|
134
|
+
return True
|
|
135
|
+
|
|
136
|
+
except Exception as e:
|
|
137
|
+
print(f"❌ 解压失败: {e}")
|
|
138
|
+
return False
|
|
139
|
+
|
|
140
|
+
def _install_clash(self) -> bool:
|
|
141
|
+
"""安装clash"""
|
|
142
|
+
try:
|
|
143
|
+
# 检查是否已安装
|
|
144
|
+
clash_binary = os.path.join(self.clash_dir, 'clash')
|
|
145
|
+
if sys.platform == "win32":
|
|
146
|
+
clash_binary = os.path.join(self.clash_dir, 'clash.exe')
|
|
147
|
+
|
|
148
|
+
if os.path.exists(clash_binary):
|
|
149
|
+
# 检查版本
|
|
150
|
+
try:
|
|
151
|
+
result = subprocess.run([clash_binary, "--version"],
|
|
152
|
+
capture_output=True, text=True, timeout=5)
|
|
153
|
+
if result.returncode == 0:
|
|
154
|
+
print(f"✅ Clash已安装: {clash_binary}")
|
|
155
|
+
self.clash_binary_path = clash_binary
|
|
156
|
+
return True
|
|
157
|
+
except:
|
|
158
|
+
pass
|
|
159
|
+
|
|
160
|
+
# 下载并安装
|
|
161
|
+
download_url = self._get_clash_download_url()
|
|
162
|
+
archive_name = os.path.basename(urlparse(download_url).path)
|
|
163
|
+
archive_path = os.path.join(self.clash_dir, archive_name)
|
|
164
|
+
|
|
165
|
+
# 下载
|
|
166
|
+
if not self._download_file(download_url, archive_path):
|
|
167
|
+
return False
|
|
168
|
+
|
|
169
|
+
# 解压
|
|
170
|
+
if not self._extract_file(archive_path, self.clash_dir):
|
|
171
|
+
return False
|
|
172
|
+
|
|
173
|
+
# 清理下载文件
|
|
174
|
+
try:
|
|
175
|
+
os.remove(archive_path)
|
|
176
|
+
except:
|
|
177
|
+
pass
|
|
178
|
+
|
|
179
|
+
# 验证安装
|
|
180
|
+
if os.path.exists(clash_binary):
|
|
181
|
+
try:
|
|
182
|
+
result = subprocess.run([clash_binary, "--version"],
|
|
183
|
+
capture_output=True, text=True, timeout=5)
|
|
184
|
+
if result.returncode == 0:
|
|
185
|
+
print(f"✅ Clash安装成功: {clash_binary}")
|
|
186
|
+
self.clash_binary_path = clash_binary
|
|
187
|
+
return True
|
|
188
|
+
except Exception as e:
|
|
189
|
+
print(f"❌ Clash验证失败: {e}")
|
|
190
|
+
|
|
191
|
+
return False
|
|
192
|
+
|
|
193
|
+
except Exception as e:
|
|
194
|
+
print(f"❌ 安装Clash失败: {e}")
|
|
195
|
+
return False
|
|
196
|
+
|
|
197
|
+
def _load_config(self):
|
|
198
|
+
"""加载配置文件"""
|
|
199
|
+
try:
|
|
200
|
+
if os.path.exists(self.config_path):
|
|
201
|
+
with open(self.config_path, 'r', encoding='utf-8') as f:
|
|
202
|
+
self.config_data = yaml.safe_load(f)
|
|
203
|
+
print(f"✅ 已加载代理配置文件: {self.config_path}")
|
|
204
|
+
else:
|
|
205
|
+
print(f"⚠️ 配置文件不存在: {self.config_path}")
|
|
206
|
+
self._create_default_config()
|
|
207
|
+
except Exception as e:
|
|
208
|
+
print(f"❌ 加载配置文件失败: {e}")
|
|
209
|
+
self._create_default_config()
|
|
210
|
+
|
|
211
|
+
def _create_default_config(self):
|
|
212
|
+
"""创建默认配置文件"""
|
|
213
|
+
default_config = {
|
|
214
|
+
"port": 7890,
|
|
215
|
+
"socks-port": 7891,
|
|
216
|
+
"allow-lan": True,
|
|
217
|
+
"mode": "rule",
|
|
218
|
+
"log-level": "info",
|
|
219
|
+
"external-controller": "127.0.0.1:9090",
|
|
220
|
+
"proxies": [],
|
|
221
|
+
"proxy-groups": [],
|
|
222
|
+
"rules": [
|
|
223
|
+
"DOMAIN-SUFFIX,google.com,Proxy",
|
|
224
|
+
"DOMAIN-SUFFIX,github.com,Proxy",
|
|
225
|
+
"DOMAIN-SUFFIX,githubusercontent.com,Proxy",
|
|
226
|
+
"DOMAIN-SUFFIX,openai.com,Proxy",
|
|
227
|
+
"DOMAIN-SUFFIX,anthropic.com,Proxy",
|
|
228
|
+
"DOMAIN-SUFFIX,claude.ai,Proxy",
|
|
229
|
+
"GEOIP,CN,DIRECT",
|
|
230
|
+
"MATCH,DIRECT"
|
|
231
|
+
]
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
try:
|
|
235
|
+
with open(self.config_path, 'w', encoding='utf-8') as f:
|
|
236
|
+
yaml.dump(default_config, f, default_flow_style=False, allow_unicode=True)
|
|
237
|
+
self.config_data = default_config
|
|
238
|
+
print(f"✅ 已创建默认配置文件: {self.config_path}")
|
|
239
|
+
except Exception as e:
|
|
240
|
+
print(f"❌ 创建默认配置文件失败: {e}")
|
|
241
|
+
|
|
242
|
+
def start_proxy(self) -> bool:
|
|
243
|
+
"""启动代理服务"""
|
|
244
|
+
if self.proxy_enabled:
|
|
245
|
+
print("✅ 代理服务已在运行")
|
|
246
|
+
return True
|
|
247
|
+
|
|
248
|
+
try:
|
|
249
|
+
# 确保clash已安装
|
|
250
|
+
if not self.clash_binary_path:
|
|
251
|
+
if not self._install_clash():
|
|
252
|
+
print("❌ Clash安装失败")
|
|
253
|
+
return False
|
|
254
|
+
|
|
255
|
+
# 启动clash进程
|
|
256
|
+
cmd = [self.clash_binary_path, "-f", self.config_path]
|
|
257
|
+
self.clash_process = subprocess.Popen(
|
|
258
|
+
cmd,
|
|
259
|
+
stdout=subprocess.PIPE,
|
|
260
|
+
stderr=subprocess.PIPE,
|
|
261
|
+
text=True
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
# 等待服务启动
|
|
265
|
+
time.sleep(2)
|
|
266
|
+
|
|
267
|
+
# 检查服务是否正常启动
|
|
268
|
+
if self._check_proxy_status():
|
|
269
|
+
self.proxy_enabled = True
|
|
270
|
+
print("✅ 代理服务启动成功")
|
|
271
|
+
self._set_system_proxy()
|
|
272
|
+
return True
|
|
273
|
+
else:
|
|
274
|
+
print("❌ 代理服务启动失败")
|
|
275
|
+
self.stop_proxy()
|
|
276
|
+
return False
|
|
277
|
+
|
|
278
|
+
except Exception as e:
|
|
279
|
+
print(f"❌ 启动代理服务失败: {e}")
|
|
280
|
+
return False
|
|
281
|
+
|
|
282
|
+
def stop_proxy(self):
|
|
283
|
+
"""停止代理服务"""
|
|
284
|
+
if self.clash_process:
|
|
285
|
+
try:
|
|
286
|
+
self.clash_process.terminate()
|
|
287
|
+
self.clash_process.wait(timeout=5)
|
|
288
|
+
except subprocess.TimeoutExpired:
|
|
289
|
+
self.clash_process.kill()
|
|
290
|
+
finally:
|
|
291
|
+
self.clash_process = None
|
|
292
|
+
|
|
293
|
+
self.proxy_enabled = False
|
|
294
|
+
self._unset_system_proxy()
|
|
295
|
+
print("✅ 代理服务已停止")
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def _check_proxy_status(self) -> bool:
|
|
300
|
+
"""检查代理服务状态"""
|
|
301
|
+
try:
|
|
302
|
+
# 检查HTTP代理
|
|
303
|
+
proxies = {
|
|
304
|
+
'http': 'http://127.0.0.1:7890',
|
|
305
|
+
'https': 'http://127.0.0.1:7890'
|
|
306
|
+
}
|
|
307
|
+
response = requests.get('http://httpbin.org/ip',
|
|
308
|
+
proxies=proxies, timeout=5)
|
|
309
|
+
return response.status_code == 200
|
|
310
|
+
except:
|
|
311
|
+
return False
|
|
312
|
+
|
|
313
|
+
def _set_system_proxy(self):
|
|
314
|
+
"""设置系统代理"""
|
|
315
|
+
try:
|
|
316
|
+
if sys.platform == "win32":
|
|
317
|
+
# Windows系统代理设置
|
|
318
|
+
import winreg
|
|
319
|
+
|
|
320
|
+
def set_key(name, value):
|
|
321
|
+
try:
|
|
322
|
+
winreg.CreateKey(winreg.HKEY_CURRENT_USER,
|
|
323
|
+
r"Software\Microsoft\Windows\CurrentVersion\Internet Settings")
|
|
324
|
+
registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
|
|
325
|
+
r"Software\Microsoft\Windows\CurrentVersion\Internet Settings",
|
|
326
|
+
0, winreg.KEY_WRITE)
|
|
327
|
+
winreg.SetValueEx(registry_key, name, 0, winreg.REG_DWORD, value)
|
|
328
|
+
winreg.CloseKey(registry_key)
|
|
329
|
+
return True
|
|
330
|
+
except WindowsError:
|
|
331
|
+
return False
|
|
332
|
+
|
|
333
|
+
set_key("ProxyEnable", 1)
|
|
334
|
+
set_key("ProxyServer", "127.0.0.1:7890")
|
|
335
|
+
|
|
336
|
+
elif sys.platform == "darwin":
|
|
337
|
+
# macOS系统代理设置
|
|
338
|
+
os.system("networksetup -setwebproxy 'Wi-Fi' 127.0.0.1 7890")
|
|
339
|
+
os.system("networksetup -setsecurewebproxy 'Wi-Fi' 127.0.0.1 7890")
|
|
340
|
+
os.system("networksetup -setsocksfirewallproxy 'Wi-Fi' 127.0.0.1 7891")
|
|
341
|
+
|
|
342
|
+
else:
|
|
343
|
+
# Linux系统代理设置
|
|
344
|
+
os.environ['HTTP_PROXY'] = 'http://127.0.0.1:7890'
|
|
345
|
+
os.environ['HTTPS_PROXY'] = 'http://127.0.0.1:7890'
|
|
346
|
+
os.environ['http_proxy'] = 'http://127.0.0.1:7890'
|
|
347
|
+
os.environ['https_proxy'] = 'http://127.0.0.1:7890'
|
|
348
|
+
|
|
349
|
+
except Exception as e:
|
|
350
|
+
print(f"⚠️ 设置系统代理失败: {e}")
|
|
351
|
+
|
|
352
|
+
def _unset_system_proxy(self):
|
|
353
|
+
"""取消系统代理设置"""
|
|
354
|
+
try:
|
|
355
|
+
if sys.platform == "win32":
|
|
356
|
+
import winreg
|
|
357
|
+
|
|
358
|
+
def set_key(name, value):
|
|
359
|
+
try:
|
|
360
|
+
winreg.CreateKey(winreg.HKEY_CURRENT_USER,
|
|
361
|
+
r"Software\Microsoft\Windows\CurrentVersion\Internet Settings")
|
|
362
|
+
registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
|
|
363
|
+
r"Software\Microsoft\Windows\CurrentVersion\Internet Settings",
|
|
364
|
+
0, winreg.KEY_WRITE)
|
|
365
|
+
winreg.SetValueEx(registry_key, name, 0, winreg.REG_DWORD, value)
|
|
366
|
+
winreg.CloseKey(registry_key)
|
|
367
|
+
return True
|
|
368
|
+
except WindowsError:
|
|
369
|
+
return False
|
|
370
|
+
|
|
371
|
+
set_key("ProxyEnable", 0)
|
|
372
|
+
|
|
373
|
+
elif sys.platform == "darwin":
|
|
374
|
+
os.system("networksetup -setwebproxystate 'Wi-Fi' off")
|
|
375
|
+
os.system("networksetup -setsecurewebproxystate 'Wi-Fi' off")
|
|
376
|
+
os.system("networksetup -setsocksfirewallproxystate 'Wi-Fi' off")
|
|
377
|
+
|
|
378
|
+
else:
|
|
379
|
+
# Linux系统代理设置
|
|
380
|
+
if 'HTTP_PROXY' in os.environ:
|
|
381
|
+
del os.environ['HTTP_PROXY']
|
|
382
|
+
if 'HTTPS_PROXY' in os.environ:
|
|
383
|
+
del os.environ['HTTPS_PROXY']
|
|
384
|
+
if 'http_proxy' in os.environ:
|
|
385
|
+
del os.environ['http_proxy']
|
|
386
|
+
if 'https_proxy' in os.environ:
|
|
387
|
+
del os.environ['https_proxy']
|
|
388
|
+
|
|
389
|
+
except Exception as e:
|
|
390
|
+
print(f"⚠️ 取消系统代理失败: {e}")
|
|
391
|
+
|
|
392
|
+
def get_proxy_info(self) -> Dict[str, Any]:
|
|
393
|
+
"""获取代理信息"""
|
|
394
|
+
return {
|
|
395
|
+
"enabled": self.proxy_enabled,
|
|
396
|
+
"config_path": self.config_path,
|
|
397
|
+
"clash_binary": self.clash_binary_path,
|
|
398
|
+
"clash_dir": self.clash_dir,
|
|
399
|
+
"http_proxy": "http://127.0.0.1:7890" if self.proxy_enabled else None,
|
|
400
|
+
"socks_proxy": "socks5://127.0.0.1:7891" if self.proxy_enabled else None
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
def update_config(self, new_config: Dict[str, Any]):
|
|
404
|
+
"""更新代理配置"""
|
|
405
|
+
try:
|
|
406
|
+
with open(self.config_path, 'w', encoding='utf-8') as f:
|
|
407
|
+
yaml.dump(new_config, f, default_flow_style=False, allow_unicode=True)
|
|
408
|
+
self.config_data = new_config
|
|
409
|
+
print("✅ 代理配置已更新")
|
|
410
|
+
|
|
411
|
+
# 如果代理正在运行,重启服务
|
|
412
|
+
if self.proxy_enabled:
|
|
413
|
+
self.stop_proxy()
|
|
414
|
+
time.sleep(1)
|
|
415
|
+
self.start_proxy()
|
|
416
|
+
|
|
417
|
+
except Exception as e:
|
|
418
|
+
print(f"❌ 更新代理配置失败: {e}")
|
|
419
|
+
|
|
420
|
+
def cleanup(self):
|
|
421
|
+
"""清理资源"""
|
|
422
|
+
self.stop_proxy()
|
|
423
|
+
# 可以选择是否删除clash二进制文件
|
|
424
|
+
# if self.clash_dir and os.path.exists(self.clash_dir):
|
|
425
|
+
# import shutil
|
|
426
|
+
# shutil.rmtree(self.clash_dir)
|
|
427
|
+
|
|
428
|
+
# # 全局代理管理器实例
|
|
429
|
+
proxy_manager = ProxyManager()
|
|
430
|
+
|
|
431
|
+
def init_proxy():
|
|
432
|
+
"""初始化代理服务"""
|
|
433
|
+
return proxy_manager.start_proxy()
|
|
434
|
+
|
|
435
|
+
def stop_proxy():
|
|
436
|
+
"""停止代理服务"""
|
|
437
|
+
proxy_manager.stop_proxy()
|
|
438
|
+
|
|
439
|
+
def get_proxy_status():
|
|
440
|
+
"""获取代理状态"""
|
|
441
|
+
return proxy_manager.get_proxy_info()
|
|
442
|
+
|
|
443
|
+
def cleanup_proxy():
|
|
444
|
+
"""清理代理资源"""
|
|
445
|
+
proxy_manager.cleanup()
|
|
@@ -130,7 +130,7 @@ class ryryDaemonThread(Thread):
|
|
|
130
130
|
def __init__(self):
|
|
131
131
|
super().__init__()
|
|
132
132
|
self.name = f"ryryDaemonThread"
|
|
133
|
-
self.tik_time =
|
|
133
|
+
self.tik_time = 10.0
|
|
134
134
|
self.start()
|
|
135
135
|
|
|
136
136
|
def run(self):
|
|
@@ -143,7 +143,9 @@ class ryryDaemonThread(Thread):
|
|
|
143
143
|
try:
|
|
144
144
|
daemon_manager.sync_daemons_with_widget_map()
|
|
145
145
|
except:
|
|
146
|
-
|
|
146
|
+
pass
|
|
147
|
+
finally:
|
|
148
|
+
time.sleep(self.tik_time)
|
|
147
149
|
try:
|
|
148
150
|
print("Stopping daemon processes...")
|
|
149
151
|
if daemon_manager.stop_all_daemons():
|
|
@@ -155,7 +155,7 @@ def extend():
|
|
|
155
155
|
_genExtend()
|
|
156
156
|
elif read_data["extend"].get("device_id", "") != read_data.get("deviceInfo", {}).get("device_id", ""):
|
|
157
157
|
_genExtend()
|
|
158
|
-
elif read_data["extend"].get("app", "") == "ryry-cli 4.
|
|
158
|
+
elif read_data["extend"].get("app", "") == "ryry-cli 4.26":
|
|
159
159
|
_genExtend()
|
|
160
160
|
else:
|
|
161
161
|
_genExtend()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ryry-cli
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.26
|
|
4
4
|
Summary: ryry tools
|
|
5
5
|
Home-page: https://github.com/dalipenMedia
|
|
6
6
|
Author: dalipen
|
|
@@ -23,6 +23,7 @@ Requires-Dist: gputil
|
|
|
23
23
|
Requires-Dist: urlparser
|
|
24
24
|
Requires-Dist: urllib3
|
|
25
25
|
Requires-Dist: portalocker
|
|
26
|
+
Requires-Dist: PyYAML
|
|
26
27
|
Provides-Extra: with-mecord
|
|
27
28
|
Requires-Dist: mecord-cli>=0.7.405; extra == "with-mecord"
|
|
28
29
|
|
|
@@ -3,7 +3,7 @@ import os
|
|
|
3
3
|
import subprocess
|
|
4
4
|
import datetime
|
|
5
5
|
|
|
6
|
-
ryry_version = "4.
|
|
6
|
+
ryry_version = "4.26"
|
|
7
7
|
cur_dir = os.path.dirname(os.path.abspath(__file__))
|
|
8
8
|
constanspy = os.path.join(cur_dir, "ryry", "constant.py")
|
|
9
9
|
try:
|
|
@@ -69,7 +69,8 @@ setuptools.setup(
|
|
|
69
69
|
'gputil',
|
|
70
70
|
'urlparser',
|
|
71
71
|
'urllib3',
|
|
72
|
-
'portalocker'
|
|
72
|
+
'portalocker',
|
|
73
|
+
'PyYAML'
|
|
73
74
|
],
|
|
74
75
|
extras_require={
|
|
75
76
|
'with_mecord': ['mecord-cli>=0.7.405'],
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|