ryry-cli 4.2__tar.gz → 4.4__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.2/ryry_cli.egg-info → ryry_cli-4.4}/PKG-INFO +2 -1
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/constant.py +2 -2
- ryry_cli-4.4/ryry/daemon_base.py +224 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/server_func.py +8 -8
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/upload.py +62 -16
- {ryry_cli-4.2 → ryry_cli-4.4/ryry_cli.egg-info}/PKG-INFO +2 -1
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry_cli.egg-info/requires.txt +1 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/setup.py +2 -1
- ryry_cli-4.2/ryry/daemon_base.py +0 -131
- {ryry_cli-4.2 → ryry_cli-4.4}/LICENSE +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/README.md +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/__init__.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/daemon_manager.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/main.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/ryry_server_socket.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/ryry_service.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/ryry_webapi.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/ryry_widget.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/script_template/__init__.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/script_template/daemon.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/script_template/main.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/script_template/run.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/shared_memory.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/store.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/task.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/taskUtils.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry/utils.py +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry_cli.egg-info/SOURCES.txt +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry_cli.egg-info/dependency_links.txt +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry_cli.egg-info/entry_points.txt +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/ryry_cli.egg-info/top_level.txt +0 -0
- {ryry_cli-4.2 → ryry_cli-4.4}/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.4
|
|
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: mecord-cli>=0.7.405
|
|
26
27
|
|
|
27
28
|
ryry Python Tool
|
|
28
29
|
===============================================
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import os
|
|
3
|
+
import json
|
|
4
|
+
import time
|
|
5
|
+
import signal
|
|
6
|
+
from typing import Optional, Dict, Any
|
|
7
|
+
|
|
8
|
+
class SimpleDaemonBase:
|
|
9
|
+
"""
|
|
10
|
+
简化的Daemon基类
|
|
11
|
+
|
|
12
|
+
用户需要实现的方法:
|
|
13
|
+
- initialize(): 初始化资源
|
|
14
|
+
- loop_function(): 循环执行的任务(可选)
|
|
15
|
+
- on_stop(): 清理资源(可选)
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, widget_id: str):
|
|
19
|
+
# 基础配置
|
|
20
|
+
self.widget_id = widget_id
|
|
21
|
+
self.widget_name = "???"
|
|
22
|
+
self.running = False
|
|
23
|
+
|
|
24
|
+
# 配置加载
|
|
25
|
+
self._load_config()
|
|
26
|
+
|
|
27
|
+
# 信号处理
|
|
28
|
+
self._setup_signal_handlers()
|
|
29
|
+
|
|
30
|
+
print(f"【{self.widget_name}】Daemon实例创建完成", file=sys.stderr)
|
|
31
|
+
|
|
32
|
+
def _load_config(self):
|
|
33
|
+
"""加载配置文件"""
|
|
34
|
+
try:
|
|
35
|
+
self._script_path = os.path.abspath(sys.modules[self.__class__.__module__].__file__)
|
|
36
|
+
self.base_path = sys.argv[2] if len(sys.argv) > 2 else os.path.expanduser("~/.ryry")
|
|
37
|
+
config_path = os.path.join(os.path.dirname(self._script_path), "config.json")
|
|
38
|
+
|
|
39
|
+
if os.path.exists(config_path):
|
|
40
|
+
with open(config_path, 'r', encoding='utf-8') as f:
|
|
41
|
+
config = json.load(f)
|
|
42
|
+
self.timeout = config.get("timeout", 600)
|
|
43
|
+
self.widget_name = config.get("name", self.widget_name)
|
|
44
|
+
else:
|
|
45
|
+
self.timeout = 600
|
|
46
|
+
except Exception as e:
|
|
47
|
+
print(f"配置加载失败: {e}", file=sys.stderr)
|
|
48
|
+
self.timeout = 600
|
|
49
|
+
|
|
50
|
+
def _setup_signal_handlers(self):
|
|
51
|
+
"""设置信号处理器"""
|
|
52
|
+
def signal_handler(signum, frame):
|
|
53
|
+
print(f"【{self.widget_name}】收到信号 {signum},开始停止", file=sys.stderr)
|
|
54
|
+
self.running = False
|
|
55
|
+
|
|
56
|
+
# 注册信号处理器
|
|
57
|
+
signal.signal(signal.SIGINT, signal_handler) # Ctrl+C
|
|
58
|
+
signal.signal(signal.SIGTERM, signal_handler) # 终止信号
|
|
59
|
+
|
|
60
|
+
if hasattr(signal, 'SIGBREAK'):
|
|
61
|
+
signal.signal(signal.SIGBREAK, signal_handler)
|
|
62
|
+
|
|
63
|
+
# ==================== 生命周期方法 ====================
|
|
64
|
+
|
|
65
|
+
def initialize(self):
|
|
66
|
+
"""
|
|
67
|
+
初始化方法 - 子类可选实现
|
|
68
|
+
在这里进行资源初始化,如数据库连接、模型加载等
|
|
69
|
+
"""
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
def loop_function(self):
|
|
73
|
+
"""
|
|
74
|
+
循环执行的方法 - 子类可选实现
|
|
75
|
+
每秒调用一次,用于定时任务、心跳等
|
|
76
|
+
"""
|
|
77
|
+
pass
|
|
78
|
+
|
|
79
|
+
def on_stop(self):
|
|
80
|
+
"""
|
|
81
|
+
停止时的清理方法 - 子类可选实现
|
|
82
|
+
在这里进行资源清理,如关闭连接、保存状态等
|
|
83
|
+
"""
|
|
84
|
+
pass
|
|
85
|
+
|
|
86
|
+
# ==================== 通信方法 ====================
|
|
87
|
+
|
|
88
|
+
def send_ready_signal(self):
|
|
89
|
+
"""发送就绪信号"""
|
|
90
|
+
try:
|
|
91
|
+
ready_file = os.path.join(self.base_path, f"daemon_ready_{self.widget_id}.json")
|
|
92
|
+
with open(ready_file, 'w', encoding='utf-8') as f:
|
|
93
|
+
json.dump({"accept_tasks": False}, f)
|
|
94
|
+
except Exception as e:
|
|
95
|
+
print(f"发送就绪信号失败: {e}", file=sys.stderr)
|
|
96
|
+
|
|
97
|
+
def process_command(self):
|
|
98
|
+
"""处理命令文件"""
|
|
99
|
+
cmd_file = os.path.join(self.base_path, f"daemon_cmd_{self.widget_id}.json")
|
|
100
|
+
if not os.path.exists(cmd_file):
|
|
101
|
+
return
|
|
102
|
+
|
|
103
|
+
try:
|
|
104
|
+
with open(cmd_file, 'r', encoding='utf-8') as f:
|
|
105
|
+
command = json.load(f)
|
|
106
|
+
os.remove(cmd_file)
|
|
107
|
+
|
|
108
|
+
cmd_type = command.get("type")
|
|
109
|
+
if cmd_type == "task":
|
|
110
|
+
self._handle_task_command(command)
|
|
111
|
+
elif cmd_type == "health":
|
|
112
|
+
self._handle_health_command(command)
|
|
113
|
+
elif cmd_type == "stop":
|
|
114
|
+
self._handle_stop_command(command)
|
|
115
|
+
|
|
116
|
+
except Exception as e:
|
|
117
|
+
print(f"处理命令失败: {e}", file=sys.stderr)
|
|
118
|
+
|
|
119
|
+
def _handle_task_command(self, command: Dict[str, Any]):
|
|
120
|
+
"""处理任务命令"""
|
|
121
|
+
task_data = command.get("data", {})
|
|
122
|
+
timeout = command.get("timeout", self.timeout)
|
|
123
|
+
|
|
124
|
+
try:
|
|
125
|
+
result = self.process_task(task_data, timeout)
|
|
126
|
+
self._send_response({
|
|
127
|
+
"type": "task_result",
|
|
128
|
+
"task_id": command.get("task_id"),
|
|
129
|
+
"success": True,
|
|
130
|
+
"data": result
|
|
131
|
+
})
|
|
132
|
+
except Exception as e:
|
|
133
|
+
self._send_response({
|
|
134
|
+
"type": "task_result",
|
|
135
|
+
"task_id": command.get("task_id"),
|
|
136
|
+
"success": False,
|
|
137
|
+
"error": str(e),
|
|
138
|
+
"data": {"result": [], "status": 1, "message": str(e)}
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
def _handle_health_command(self, command: Dict[str, Any]):
|
|
142
|
+
"""处理健康检查命令"""
|
|
143
|
+
health = self.health_check()
|
|
144
|
+
self._send_response({
|
|
145
|
+
"type": "health_result",
|
|
146
|
+
"data": health
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
def _handle_stop_command(self, command: Dict[str, Any]):
|
|
150
|
+
"""处理停止命令"""
|
|
151
|
+
self.running = False
|
|
152
|
+
self._send_response({
|
|
153
|
+
"type": "stop_result",
|
|
154
|
+
"success": True
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
def _send_response(self, response: Dict[str, Any]):
|
|
158
|
+
"""发送响应"""
|
|
159
|
+
try:
|
|
160
|
+
result_file = os.path.join(self.base_path, f"daemon_result_{self.widget_id}.json")
|
|
161
|
+
with open(result_file, 'w', encoding='utf-8') as f:
|
|
162
|
+
json.dump(response, f)
|
|
163
|
+
except Exception as e:
|
|
164
|
+
print(f"发送响应失败: {e}", file=sys.stderr)
|
|
165
|
+
|
|
166
|
+
# ==================== 子类可选重写的方法 ====================
|
|
167
|
+
|
|
168
|
+
def process_task(self, task_data: Dict[str, Any], timeout: Optional[int] = None) -> Dict[str, Any]:
|
|
169
|
+
"""
|
|
170
|
+
处理短链任务 - 子类可选实现
|
|
171
|
+
默认返回空结果
|
|
172
|
+
"""
|
|
173
|
+
return {
|
|
174
|
+
"result": [{"type": "text", "content": [f"Processed: {task_data}"]}],
|
|
175
|
+
"status": 0,
|
|
176
|
+
"message": "Success"
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
def health_check(self) -> Dict[str, Any]:
|
|
180
|
+
"""
|
|
181
|
+
健康检查 - 子类可选重写
|
|
182
|
+
"""
|
|
183
|
+
return {
|
|
184
|
+
"healthy": True,
|
|
185
|
+
"state": "running",
|
|
186
|
+
"accept_tasks": False,
|
|
187
|
+
"timestamp": time.time()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
# ==================== 控制方法 ====================
|
|
191
|
+
|
|
192
|
+
def run(self):
|
|
193
|
+
"""
|
|
194
|
+
运行daemon的主入口方法
|
|
195
|
+
"""
|
|
196
|
+
try:
|
|
197
|
+
# 初始化
|
|
198
|
+
self.initialize()
|
|
199
|
+
|
|
200
|
+
# 发送就绪信号
|
|
201
|
+
self.send_ready_signal()
|
|
202
|
+
|
|
203
|
+
# 主循环
|
|
204
|
+
self.running = True
|
|
205
|
+
while self.running:
|
|
206
|
+
try:
|
|
207
|
+
# 处理命令
|
|
208
|
+
self.process_command()
|
|
209
|
+
# 执行循环函数
|
|
210
|
+
self.loop_function()
|
|
211
|
+
time.sleep(1)
|
|
212
|
+
except KeyboardInterrupt:
|
|
213
|
+
print(f"【{self.widget_name}】收到KeyboardInterrupt", file=sys.stderr)
|
|
214
|
+
break
|
|
215
|
+
except Exception as e:
|
|
216
|
+
print(f"主循环异常: {e}", file=sys.stderr)
|
|
217
|
+
time.sleep(5) # 异常后等待5秒再继续
|
|
218
|
+
# 清理
|
|
219
|
+
self.on_stop()
|
|
220
|
+
|
|
221
|
+
except Exception as e:
|
|
222
|
+
print(f"运行异常: {e}", file=sys.stderr)
|
|
223
|
+
finally:
|
|
224
|
+
print(f"【{self.widget_name}】进程终止", file=sys.stderr)
|
|
@@ -79,10 +79,11 @@ class Task:
|
|
|
79
79
|
if realTaskUUID == None or len(realTaskUUID) <= 0:
|
|
80
80
|
realTaskUUID = taskUtils.taskInfoWithFirstTask()
|
|
81
81
|
|
|
82
|
-
support_subdomain = upload.getFirstSupportSubdomain()
|
|
83
82
|
mayby_domain = ""
|
|
84
|
-
if
|
|
85
|
-
|
|
83
|
+
if "domain" not in multi_params[0]:
|
|
84
|
+
support_subdomain = upload.getFirstSupportSubdomain()
|
|
85
|
+
if support_subdomain:
|
|
86
|
+
mayby_domain = support_subdomain["domain"]
|
|
86
87
|
|
|
87
88
|
def _callback(idx, data):
|
|
88
89
|
self.thread_data[str(idx)]["result"] = data
|
|
@@ -118,12 +119,11 @@ class AsyncTask:
|
|
|
118
119
|
if realTaskUUID == None or len(realTaskUUID) <= 0:
|
|
119
120
|
realTaskUUID = taskUtils.taskInfoWithFirstTask()
|
|
120
121
|
|
|
121
|
-
support_subdomain = upload.getFirstSupportSubdomain()
|
|
122
|
-
domain = ""
|
|
123
|
-
if support_subdomain:
|
|
124
|
-
domain = support_subdomain["readpath"]
|
|
125
122
|
self.params["fromUUID"] = realTaskUUID
|
|
126
|
-
|
|
123
|
+
if "domain" not in self.params:
|
|
124
|
+
support_subdomain = upload.getFirstSupportSubdomain()
|
|
125
|
+
if support_subdomain:
|
|
126
|
+
self.params["domain"] = support_subdomain["domain"]
|
|
127
127
|
|
|
128
128
|
def call(self):
|
|
129
129
|
cmd = task.cmdWithWidgetName(self.func)
|
|
@@ -46,12 +46,17 @@ def additionalUrl(srcFile, ossUrl):
|
|
|
46
46
|
def upload(src, taskUUID=None, needTranscode=True, keepItAlways=False, additionalUrl=False):
|
|
47
47
|
import os
|
|
48
48
|
from pathlib import Path
|
|
49
|
-
from ryry import taskUtils
|
|
49
|
+
from ryry import taskUtils as ryry_taskUtils
|
|
50
50
|
if os.path.exists(src) == False:
|
|
51
51
|
raise Exception(f"upload file not found")
|
|
52
52
|
if taskUUID == None or len(taskUUID) <= 0:
|
|
53
|
-
taskUUID =
|
|
54
|
-
|
|
53
|
+
taskUUID = ryry_taskUtils.taskInfoWithFirstTask()
|
|
54
|
+
targetDomain = ryry_taskUtils.taskDomainWithUUID(taskUUID)
|
|
55
|
+
else:
|
|
56
|
+
targetDomain = ryry_taskUtils.taskDomainWithUUID(taskUUID)
|
|
57
|
+
if targetDomain == None or len(targetDomain) <= 0:
|
|
58
|
+
from mecord import taskUtils as mecord_taskUtils
|
|
59
|
+
targetDomain = mecord_taskUtils.taskDomainWithUUID(taskUUID)
|
|
55
60
|
|
|
56
61
|
if needTranscode:
|
|
57
62
|
needDeleteSrc, newSrc = transcode(src)
|
|
@@ -60,7 +65,7 @@ def upload(src, taskUUID=None, needTranscode=True, keepItAlways=False, additiona
|
|
|
60
65
|
newSrc = src
|
|
61
66
|
|
|
62
67
|
# 根据targetDomain判断使用不同的上传逻辑
|
|
63
|
-
ossurl = uploadByDomain(newSrc, targetDomain, keepItAlways)
|
|
68
|
+
ossurl = uploadByDomain(newSrc, targetDomain, taskUUID, keepItAlways)
|
|
64
69
|
|
|
65
70
|
if additionalUrl:
|
|
66
71
|
ossurl = additionalUrl(newSrc, ossurl)
|
|
@@ -68,7 +73,7 @@ def upload(src, taskUUID=None, needTranscode=True, keepItAlways=False, additiona
|
|
|
68
73
|
os.remove(newSrc)
|
|
69
74
|
return ossurl
|
|
70
75
|
|
|
71
|
-
def uploadByDomain(src, targetDomain, keepItAlways=False):
|
|
76
|
+
def uploadByDomain(src, targetDomain, taskUUID, keepItAlways=False):
|
|
72
77
|
import os
|
|
73
78
|
from pathlib import Path
|
|
74
79
|
import uuid
|
|
@@ -79,6 +84,10 @@ def uploadByDomain(src, targetDomain, keepItAlways=False):
|
|
|
79
84
|
new_file_name = ''.join(str(uuid.uuid4()).split('-'))
|
|
80
85
|
|
|
81
86
|
parsed_domain, upload_path = parseDomainAndPath(targetDomain)
|
|
87
|
+
if isMecordConfig(parsed_domain):
|
|
88
|
+
from mecord import upload as mecord_upload
|
|
89
|
+
return mecord_upload.upload(src, taskUUID)
|
|
90
|
+
|
|
82
91
|
oss_config = getOssConfig(parsed_domain)
|
|
83
92
|
if oss_config:
|
|
84
93
|
return uploadToOss(src, f"{new_file_name}.{ext}", oss_config, upload_path)
|
|
@@ -239,14 +248,34 @@ oss_template_config = {
|
|
|
239
248
|
"domain": "https://oss.zjtemplate.com"
|
|
240
249
|
}
|
|
241
250
|
|
|
251
|
+
def match_wildcard_domain(target_domain, pattern):
|
|
252
|
+
if pattern.startswith("*."):
|
|
253
|
+
suffix = pattern[1:] # 去掉 "*." 前缀
|
|
254
|
+
return target_domain.endswith(suffix)
|
|
255
|
+
return target_domain == pattern
|
|
256
|
+
|
|
257
|
+
def get_domain_config(target_domain):
|
|
258
|
+
# 首先尝试精确匹配
|
|
259
|
+
if target_domain in DOMAIN_CONFIG:
|
|
260
|
+
return DOMAIN_CONFIG[target_domain]
|
|
261
|
+
|
|
262
|
+
# 然后尝试通配符匹配
|
|
263
|
+
for pattern, config in DOMAIN_CONFIG.items():
|
|
264
|
+
if match_wildcard_domain(target_domain, pattern):
|
|
265
|
+
return config
|
|
266
|
+
|
|
267
|
+
return None
|
|
268
|
+
|
|
242
269
|
DOMAIN_CONFIG = {
|
|
270
|
+
"192.168.50.12": {"type": "ftp", "config": ftp_192_168_50_12},
|
|
271
|
+
"183.6.90.205": {"type": "ftp", "config": ftp_183_6_90_205},
|
|
272
|
+
"ftp://192.168.50.12/mnt/NAS/mcn/cache": {"type": "ftp", "config": ftp_192_168_50_12},
|
|
273
|
+
"ftp://183.6.90.205/mnt/NAS/mcn/cache": {"type": "ftp", "config": ftp_183_6_90_205},
|
|
243
274
|
"res.zjtemplate.com": {"type": "oss", "config": oss_res_config},
|
|
244
275
|
"upload.zjtemplate.com": {"type": "oss", "config": oss_upload_config},
|
|
245
276
|
"oss.zjtemplate.com": {"type": "oss", "config": oss_template_config},
|
|
246
|
-
"
|
|
247
|
-
"
|
|
248
|
-
"192.168.50.12": {"type": "ftp", "config": ftp_192_168_50_12},
|
|
249
|
-
"183.6.90.205": {"type": "ftp", "config": ftp_183_6_90_205},
|
|
277
|
+
"*.mecoai.cn": {"type": "mecord-cli", "config": {}},
|
|
278
|
+
"*.mecordai.com": {"type": "mecord-cli", "config": {}},
|
|
250
279
|
}
|
|
251
280
|
|
|
252
281
|
SUBDOMAIN = {
|
|
@@ -261,13 +290,21 @@ SUBDOMAIN = {
|
|
|
261
290
|
}
|
|
262
291
|
|
|
263
292
|
def getOssConfig(targetDomain):
|
|
264
|
-
|
|
265
|
-
|
|
293
|
+
config = get_domain_config(targetDomain)
|
|
294
|
+
if config and config["type"] == "oss":
|
|
295
|
+
return config["config"]
|
|
266
296
|
return None
|
|
267
297
|
|
|
298
|
+
def isMecordConfig(targetDomain):
|
|
299
|
+
config = get_domain_config(targetDomain)
|
|
300
|
+
if config and config["type"] == "mecord-cli":
|
|
301
|
+
return True
|
|
302
|
+
return False
|
|
303
|
+
|
|
268
304
|
def getFtpConfig(targetDomain):
|
|
269
|
-
|
|
270
|
-
|
|
305
|
+
config = get_domain_config(targetDomain)
|
|
306
|
+
if config and config["type"] == "ftp":
|
|
307
|
+
return config["config"]
|
|
271
308
|
return None
|
|
272
309
|
|
|
273
310
|
def getSubdomain(targetDomain):
|
|
@@ -299,11 +336,19 @@ def getFirstSupportSubdomain():
|
|
|
299
336
|
def _getFirstSupportSubdomain():
|
|
300
337
|
for domain, config in DOMAIN_CONFIG.items():
|
|
301
338
|
if config["type"] == "oss":
|
|
302
|
-
return {"type": "oss", "config": config["config"], "domain": domain}
|
|
339
|
+
return {"type": "oss", "config": config["config"], "domain": config["config"]["domain"]}
|
|
340
|
+
if config["type"] == "mecord-cli":
|
|
341
|
+
# 对于通配符域名,返回一个示例域名
|
|
342
|
+
if domain.startswith("*."):
|
|
343
|
+
# 将 *.mecoai.cn 转换为 example.mecoai.cn
|
|
344
|
+
example_domain = "example" + domain[1:]
|
|
345
|
+
return {"type": "mecord-cli", "config": {}, "domain": example_domain}
|
|
346
|
+
else:
|
|
347
|
+
return {"type": "mecord-cli", "config": {}, "domain": domain}
|
|
303
348
|
elif config["type"] == "ftp":
|
|
304
349
|
ftp_config = config["config"]
|
|
305
350
|
if _can_connect_ftp(ftp_config["host"], ftp_config["port"], ftp_config["username"], ftp_config["password"], ftp_config["writepath"]):
|
|
306
|
-
return {"type": "ftp", "config": ftp_config, "domain":
|
|
351
|
+
return {"type": "ftp", "config": ftp_config, "domain": ftp_config["readpath"]}
|
|
307
352
|
|
|
308
353
|
for ip in SUBDOMAIN.keys():
|
|
309
354
|
for host_item in SUBDOMAIN[ip]:
|
|
@@ -322,7 +367,8 @@ def getFirstSupportSubdomain():
|
|
|
322
367
|
sp.write(read_data)
|
|
323
368
|
else:
|
|
324
369
|
last_network_hash = firstSupportDomainConfig.get("hash", "")
|
|
325
|
-
|
|
370
|
+
#网络变化,或者旧版本数据的时候,重新更新
|
|
371
|
+
if last_network_hash != network_hash or "domain" not in firstSupportDomainConfig:
|
|
326
372
|
firstSupportDomainConfig = _getFirstSupportSubdomain()
|
|
327
373
|
if firstSupportDomainConfig:
|
|
328
374
|
firstSupportDomainConfig["hash"] = network_hash
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ryry-cli
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.4
|
|
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: mecord-cli>=0.7.405
|
|
26
27
|
|
|
27
28
|
ryry Python Tool
|
|
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.4"
|
|
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:
|
|
@@ -70,6 +70,7 @@ setuptools.setup(
|
|
|
70
70
|
'urlparser',
|
|
71
71
|
'urllib3',
|
|
72
72
|
'portalocker',
|
|
73
|
+
'mecord-cli>=0.7.405',
|
|
73
74
|
],
|
|
74
75
|
dependency_links=[],
|
|
75
76
|
entry_points={
|
ryry_cli-4.2/ryry/daemon_base.py
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
import os
|
|
3
|
-
import json
|
|
4
|
-
import time
|
|
5
|
-
from threading import Event
|
|
6
|
-
|
|
7
|
-
DEFAULT_ACCEPT_TASKS = False # 默认是否接受短链任务
|
|
8
|
-
|
|
9
|
-
class DaemonBase:
|
|
10
|
-
def __init__(self, widget_id: str):
|
|
11
|
-
self.widget_id = widget_id
|
|
12
|
-
self.running = True
|
|
13
|
-
self.stop_event = Event()
|
|
14
|
-
self.accept_tasks = self.default_accept_tasks()
|
|
15
|
-
self.widget_name = "???"
|
|
16
|
-
# 获取子类文件(即实际widget的daemon.py)所在目录
|
|
17
|
-
self._script_path = os.path.abspath(sys.modules[self.__class__.__module__].__file__)
|
|
18
|
-
self.base_path = sys.argv[2] if len(sys.argv) > 2 else os.path.expanduser("~/.ryry")
|
|
19
|
-
config_path = os.path.join(os.path.dirname(self._script_path), "config.json")
|
|
20
|
-
if os.path.exists(config_path):
|
|
21
|
-
try:
|
|
22
|
-
with open(config_path, 'r', encoding='utf-8') as f:
|
|
23
|
-
config = json.load(f)
|
|
24
|
-
self.timeout = config.get("timeout", 600)
|
|
25
|
-
self.widget_name = config.get("name", self.widget_name)
|
|
26
|
-
except:
|
|
27
|
-
self.timeout = 600
|
|
28
|
-
else:
|
|
29
|
-
self.timeout = 600
|
|
30
|
-
|
|
31
|
-
def default_accept_tasks(self):
|
|
32
|
-
return DEFAULT_ACCEPT_TASKS
|
|
33
|
-
|
|
34
|
-
def initialize(self):
|
|
35
|
-
pass
|
|
36
|
-
|
|
37
|
-
def process_task(self, task_data, timeout=None):
|
|
38
|
-
raise NotImplementedError("process_task必须由子类实现")
|
|
39
|
-
|
|
40
|
-
def on_stop(self):
|
|
41
|
-
pass
|
|
42
|
-
|
|
43
|
-
def health_check(self):
|
|
44
|
-
return {
|
|
45
|
-
"healthy": True,
|
|
46
|
-
"accept_tasks": self.accept_tasks,
|
|
47
|
-
"timestamp": time.time()
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
def loop_function(self):
|
|
51
|
-
pass
|
|
52
|
-
|
|
53
|
-
def _send_ready_signal(self):
|
|
54
|
-
try:
|
|
55
|
-
ready_file = os.path.join(self.base_path, f"daemon_ready_{self.widget_id}.json")
|
|
56
|
-
with open(ready_file, 'w', encoding='utf-8') as f:
|
|
57
|
-
json.dump({"accept_tasks": self.accept_tasks}, f)
|
|
58
|
-
except Exception as e:
|
|
59
|
-
print(f"Failed to send ready signal: {e}", file=sys.stderr)
|
|
60
|
-
|
|
61
|
-
def _send_response(self, response):
|
|
62
|
-
try:
|
|
63
|
-
result_file = os.path.join(self.base_path, f"daemon_result_{self.widget_id}.json")
|
|
64
|
-
with open(result_file, 'w', encoding='utf-8') as f:
|
|
65
|
-
json.dump(response, f)
|
|
66
|
-
except Exception as e:
|
|
67
|
-
print(f"Failed to send response: {e}", file=sys.stderr)
|
|
68
|
-
|
|
69
|
-
def _process_command(self, command):
|
|
70
|
-
cmd_type = command.get("type")
|
|
71
|
-
if cmd_type == "task":
|
|
72
|
-
task_data = command.get("data", {})
|
|
73
|
-
timeout = command.get("timeout", self.timeout)
|
|
74
|
-
try:
|
|
75
|
-
result = self.process_task(task_data, timeout)
|
|
76
|
-
self._send_response({
|
|
77
|
-
"type": "task_result",
|
|
78
|
-
"task_id": command.get("task_id"),
|
|
79
|
-
"success": True,
|
|
80
|
-
"data": result
|
|
81
|
-
})
|
|
82
|
-
except Exception as e:
|
|
83
|
-
self._send_response({
|
|
84
|
-
"type": "task_result",
|
|
85
|
-
"task_id": command.get("task_id"),
|
|
86
|
-
"success": False,
|
|
87
|
-
"error": str(e),
|
|
88
|
-
"data": {"result": [], "status": 1, "message": str(e)}
|
|
89
|
-
})
|
|
90
|
-
elif cmd_type == "health":
|
|
91
|
-
health = self.health_check()
|
|
92
|
-
self._send_response({
|
|
93
|
-
"type": "health_result",
|
|
94
|
-
"data": health
|
|
95
|
-
})
|
|
96
|
-
elif cmd_type == "stop":
|
|
97
|
-
print(f"【{self.widget_name}后台进程】Received stop command", file=sys.stderr)
|
|
98
|
-
self.running = False
|
|
99
|
-
self.stop_event.set()
|
|
100
|
-
self._send_response({
|
|
101
|
-
"type": "stop_result",
|
|
102
|
-
"success": True
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
def run(self):
|
|
106
|
-
try:
|
|
107
|
-
self.initialize()
|
|
108
|
-
self._send_ready_signal()
|
|
109
|
-
cmd_file = os.path.join(self.base_path, f"daemon_cmd_{self.widget_id}.json")
|
|
110
|
-
while self.running:
|
|
111
|
-
try:
|
|
112
|
-
if os.path.exists(cmd_file):
|
|
113
|
-
try:
|
|
114
|
-
with open(cmd_file, 'r', encoding='utf-8') as f:
|
|
115
|
-
command = json.load(f)
|
|
116
|
-
os.remove(cmd_file)
|
|
117
|
-
self._process_command(command)
|
|
118
|
-
except Exception as e:
|
|
119
|
-
print(f"Error processing command: {e}", file=sys.stderr)
|
|
120
|
-
if self.stop_event.is_set():
|
|
121
|
-
break
|
|
122
|
-
self.loop_function()
|
|
123
|
-
time.sleep(1)
|
|
124
|
-
except KeyboardInterrupt:
|
|
125
|
-
break
|
|
126
|
-
except Exception as e:
|
|
127
|
-
print(f"Error in main loop: {e}", file=sys.stderr)
|
|
128
|
-
time.sleep(1)
|
|
129
|
-
finally:
|
|
130
|
-
self.on_stop()
|
|
131
|
-
print(f"【{self.widget_name}】已终止", file=sys.stderr)
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|