ErisPulse 1.1.11__py3-none-any.whl → 1.1.13__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.
- ErisPulse/__main__.py +66 -37
- ErisPulse/adapter.py +13 -6
- {erispulse-1.1.11.dist-info → erispulse-1.1.13.dist-info}/METADATA +1 -1
- {erispulse-1.1.11.dist-info → erispulse-1.1.13.dist-info}/RECORD +8 -8
- {erispulse-1.1.11.dist-info → erispulse-1.1.13.dist-info}/WHEEL +0 -0
- {erispulse-1.1.11.dist-info → erispulse-1.1.13.dist-info}/entry_points.txt +0 -0
- {erispulse-1.1.11.dist-info → erispulse-1.1.13.dist-info}/licenses/LICENSE +0 -0
- {erispulse-1.1.11.dist-info → erispulse-1.1.13.dist-info}/top_level.txt +0 -0
ErisPulse/__main__.py
CHANGED
|
@@ -9,6 +9,7 @@ import fnmatch
|
|
|
9
9
|
import asyncio
|
|
10
10
|
import subprocess
|
|
11
11
|
import json
|
|
12
|
+
import json
|
|
12
13
|
from .db import env
|
|
13
14
|
from .mods import mods
|
|
14
15
|
from watchdog.observers import Observer
|
|
@@ -37,7 +38,6 @@ class Shell_Printer:
|
|
|
37
38
|
|
|
38
39
|
@classmethod
|
|
39
40
|
def _get_color(cls, level):
|
|
40
|
-
"""根据消息级别返回颜色"""
|
|
41
41
|
return {
|
|
42
42
|
"info": cls.CYAN,
|
|
43
43
|
"success": cls.GREEN,
|
|
@@ -49,77 +49,87 @@ class Shell_Printer:
|
|
|
49
49
|
|
|
50
50
|
@classmethod
|
|
51
51
|
def panel(cls, msg: str, title: str = None, level: str = "info") -> None:
|
|
52
|
-
"""带标题和边框的面板,支持颜色编码"""
|
|
53
52
|
color = cls._get_color(level)
|
|
54
|
-
|
|
53
|
+
width = 70
|
|
54
|
+
border_char = "─" * width
|
|
55
|
+
|
|
56
|
+
if level == "error":
|
|
57
|
+
border_char = "═" * width
|
|
58
|
+
msg = f"{cls.RED}✗ {msg}{cls.RESET}"
|
|
59
|
+
elif level == "warning":
|
|
60
|
+
border_char = "─" * width
|
|
61
|
+
msg = f"{cls.YELLOW}⚠ {msg}{cls.RESET}"
|
|
55
62
|
|
|
56
|
-
# 标题行
|
|
57
63
|
title_line = ""
|
|
58
64
|
if title:
|
|
59
65
|
title = f" {title.upper()} "
|
|
60
|
-
title_padding = (
|
|
66
|
+
title_padding = (width - len(title)) // 2
|
|
61
67
|
left_pad = " " * title_padding
|
|
62
|
-
right_pad = " " * (
|
|
63
|
-
title_line = f"{cls.DIM}
|
|
68
|
+
right_pad = " " * (width - len(title) - title_padding)
|
|
69
|
+
title_line = f"{cls.DIM}┌{left_pad}{cls.BOLD}{color}{title}{cls.RESET}{cls.DIM}{right_pad}┐{cls.RESET}\n"
|
|
64
70
|
|
|
65
|
-
# 内容行
|
|
66
71
|
lines = []
|
|
67
72
|
for line in msg.split("\n"):
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
if len(line) > width - 4:
|
|
74
|
+
words = line.split()
|
|
75
|
+
current_line = ""
|
|
76
|
+
for word in words:
|
|
77
|
+
if len(current_line) + len(word) + 1 > width - 4:
|
|
78
|
+
lines.append(f"{cls.DIM}│{cls.RESET} {current_line.ljust(width-4)} {cls.DIM}│{cls.RESET}")
|
|
79
|
+
current_line = word
|
|
80
|
+
else:
|
|
81
|
+
current_line += (" " + word) if current_line else word
|
|
82
|
+
if current_line:
|
|
83
|
+
lines.append(f"{cls.DIM}│{cls.RESET} {current_line.ljust(width-4)} {cls.DIM}│{cls.RESET}")
|
|
84
|
+
else:
|
|
85
|
+
lines.append(f"{cls.DIM}│{cls.RESET} {line.ljust(width-4)} {cls.DIM}│{cls.RESET}")
|
|
72
86
|
|
|
73
|
-
|
|
74
|
-
|
|
87
|
+
if level == "error":
|
|
88
|
+
border_style = "╘"
|
|
89
|
+
elif level == "warning":
|
|
90
|
+
border_style = "╧"
|
|
91
|
+
else:
|
|
92
|
+
border_style = "└"
|
|
93
|
+
bottom_border = f"{cls.DIM}{border_style}{border_char}┘{cls.RESET}"
|
|
75
94
|
|
|
76
|
-
|
|
77
|
-
panel
|
|
95
|
+
panel = f"{title_line}"
|
|
96
|
+
panel += f"{cls.DIM}├{border_char}┤{cls.RESET}\n"
|
|
78
97
|
panel += "\n".join(lines) + "\n"
|
|
79
|
-
panel += f"{
|
|
98
|
+
panel += f"{bottom_border}\n"
|
|
80
99
|
|
|
81
100
|
print(panel)
|
|
82
101
|
|
|
83
102
|
@classmethod
|
|
84
103
|
def table(cls, headers, rows, title=None, level="info") -> None:
|
|
85
|
-
"""改进的表格输出,带有颜色和分隔线"""
|
|
86
104
|
color = cls._get_color(level)
|
|
87
105
|
if title:
|
|
88
106
|
print(f"{cls.BOLD}{color}== {title} =={cls.RESET}")
|
|
89
107
|
|
|
90
|
-
# 计算列宽
|
|
91
108
|
col_widths = [len(h) for h in headers]
|
|
92
109
|
for row in rows:
|
|
93
110
|
for i, cell in enumerate(row):
|
|
94
111
|
col_widths[i] = max(col_widths[i], len(str(cell)))
|
|
95
112
|
|
|
96
|
-
# 构建标题格式
|
|
97
113
|
fmt = "│".join(f" {{:<{w}}} " for w in col_widths)
|
|
98
114
|
|
|
99
|
-
# 顶部边框
|
|
100
115
|
top_border = "┌" + "┬".join("─" * (w+2) for w in col_widths) + "┐"
|
|
101
116
|
print(f"{cls.DIM}{top_border}{cls.RESET}")
|
|
102
117
|
|
|
103
|
-
# 表头
|
|
104
118
|
header_line = fmt.format(*headers)
|
|
105
119
|
print(f"{cls.BOLD}{color}│{header_line}│{cls.RESET}")
|
|
106
120
|
|
|
107
|
-
# 表头分隔线
|
|
108
121
|
separator = "├" + "┼".join("─" * (w+2) for w in col_widths) + "┤"
|
|
109
122
|
print(f"{cls.DIM}{separator}{cls.RESET}")
|
|
110
123
|
|
|
111
|
-
# 表格内容
|
|
112
124
|
for row in rows:
|
|
113
125
|
row_line = fmt.format(*row)
|
|
114
126
|
print(f"│{row_line}│")
|
|
115
127
|
|
|
116
|
-
# 底部边框
|
|
117
128
|
bottom_border = "└" + "┴".join("─" * (w+2) for w in col_widths) + "┘"
|
|
118
129
|
print(f"{cls.DIM}{bottom_border}{cls.RESET}")
|
|
119
130
|
|
|
120
131
|
@classmethod
|
|
121
132
|
def progress_bar(cls, current, total, prefix="", suffix="", length=50):
|
|
122
|
-
"""显示进度条"""
|
|
123
133
|
filled_length = int(length * current // total)
|
|
124
134
|
percent = min(100.0, 100 * (current / float(total)))
|
|
125
135
|
bar = f"{cls.GREEN}{'█' * filled_length}{cls.WHITE}{'░' * (length - filled_length)}{cls.RESET}"
|
|
@@ -130,7 +140,6 @@ class Shell_Printer:
|
|
|
130
140
|
|
|
131
141
|
@classmethod
|
|
132
142
|
def confirm(cls, msg, default=False) -> bool:
|
|
133
|
-
"""带颜色和默认选择的确认对话框"""
|
|
134
143
|
yes_options = {'y', 'yes'}
|
|
135
144
|
no_options = {'n', 'no'}
|
|
136
145
|
default_str = "Y/n" if default else "y/N"
|
|
@@ -148,7 +157,6 @@ class Shell_Printer:
|
|
|
148
157
|
|
|
149
158
|
@classmethod
|
|
150
159
|
def ask(cls, msg, choices=None, default=None) -> str | None:
|
|
151
|
-
"""带颜色和选择的提问"""
|
|
152
160
|
prompt = f"{cls.BOLD}{msg}{cls.RESET}"
|
|
153
161
|
if choices:
|
|
154
162
|
prompt += f" ({cls.CYAN}{'/'.join(choices)}{cls.RESET})"
|
|
@@ -166,7 +174,6 @@ class Shell_Printer:
|
|
|
166
174
|
|
|
167
175
|
@classmethod
|
|
168
176
|
def status(cls, msg, success=True):
|
|
169
|
-
"""显示状态指示器"""
|
|
170
177
|
symbol = f"{cls.GREEN}✓" if success else f"{cls.RED}✗"
|
|
171
178
|
print(f"\r{symbol}{cls.RESET} {msg}")
|
|
172
179
|
|
|
@@ -179,10 +186,29 @@ class SourceManager:
|
|
|
179
186
|
def _init_sources(self):
|
|
180
187
|
if not env.get('origins'):
|
|
181
188
|
env.set('origins', [])
|
|
189
|
+
|
|
190
|
+
primary_source = "https://erisdev.com/map.json"
|
|
191
|
+
secondary_source = "https://raw.githubusercontent.com/ErisPulse/ErisPulse-ModuleRepo/refs/heads/main/map.json"
|
|
192
|
+
|
|
193
|
+
shellprint.status("正在验证主源...")
|
|
194
|
+
validated_url = asyncio.run(self._validate_url(primary_source))
|
|
195
|
+
|
|
196
|
+
if validated_url:
|
|
197
|
+
env.set('origins', [validated_url])
|
|
198
|
+
shellprint.status(f"主源 {validated_url} 已成功添加")
|
|
199
|
+
else:
|
|
200
|
+
if secondary_source not in env.get('origins', []):
|
|
201
|
+
env.set('origins', [secondary_source])
|
|
202
|
+
shellprint.panel(
|
|
203
|
+
f"主源不可用,已添加备用源 {secondary_source}\n\n"
|
|
204
|
+
f"{Shell_Printer.YELLOW}提示:{Shell_Printer.RESET} 建议尽快升级 ErisPulse SDK 版本",
|
|
205
|
+
"源初始化",
|
|
206
|
+
"warning"
|
|
207
|
+
)
|
|
182
208
|
|
|
183
209
|
async def _validate_url(self, url):
|
|
184
210
|
if not url.startswith(('http://', 'https://')):
|
|
185
|
-
protocol = shellprint.
|
|
211
|
+
protocol = shellprint.ask("未指定协议,请输入使用的协议", choices=['http', 'https'], default="https")
|
|
186
212
|
url = f"{protocol}://{url}"
|
|
187
213
|
if not url.endswith('.json'):
|
|
188
214
|
url = f"{url}/map.json"
|
|
@@ -190,10 +216,12 @@ class SourceManager:
|
|
|
190
216
|
async with aiohttp.ClientSession() as session:
|
|
191
217
|
async with session.get(url) as response:
|
|
192
218
|
response.raise_for_status()
|
|
193
|
-
|
|
219
|
+
try:
|
|
220
|
+
content = await response.text()
|
|
221
|
+
json.loads(content)
|
|
194
222
|
return url
|
|
195
|
-
|
|
196
|
-
shellprint.panel(f"源 {url} 返回的内容不是有效的 JSON
|
|
223
|
+
except (ValueError, json.JSONDecodeError) as e:
|
|
224
|
+
shellprint.panel(f"源 {url} 返回的内容不是有效的 JSON 格式: {e}", "错误", "error")
|
|
197
225
|
return None
|
|
198
226
|
except Exception as e:
|
|
199
227
|
shellprint.panel(f"访问源 {url} 失败: {e}", "错误", "error")
|
|
@@ -230,8 +258,9 @@ class SourceManager:
|
|
|
230
258
|
async with aiohttp.ClientSession() as session:
|
|
231
259
|
async with session.get(origin) as response:
|
|
232
260
|
response.raise_for_status()
|
|
233
|
-
|
|
234
|
-
|
|
261
|
+
try:
|
|
262
|
+
text = await response.text()
|
|
263
|
+
content = json.loads(text)
|
|
235
264
|
providers[content["name"]] = content["base"]
|
|
236
265
|
for module in content["modules"].keys():
|
|
237
266
|
module_content = content["modules"][module]
|
|
@@ -244,8 +273,8 @@ class SourceManager:
|
|
|
244
273
|
module,
|
|
245
274
|
f"{providers[content['name']]}{module_origin_name}"
|
|
246
275
|
])
|
|
247
|
-
|
|
248
|
-
shellprint.panel(f"源 {origin} 返回的内容不是有效的 JSON
|
|
276
|
+
except (ValueError, json.JSONDecodeError) as e:
|
|
277
|
+
shellprint.panel(f"源 {origin} 返回的内容不是有效的 JSON 格式: {e}", "错误", "error")
|
|
249
278
|
except Exception as e:
|
|
250
279
|
shellprint.panel(f"获取 {origin} 时出错: {e}", "错误", "error")
|
|
251
280
|
|
ErisPulse/adapter.py
CHANGED
|
@@ -36,14 +36,21 @@ class SendDSLBase:
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
class BaseAdapter:
|
|
39
|
+
class Send(SendDSLBase):
|
|
40
|
+
def Text(self, text: str):
|
|
41
|
+
"""基础文本消息发送方法,子类应该重写此方法"""
|
|
42
|
+
return asyncio.create_task(
|
|
43
|
+
self._adapter.call_api(
|
|
44
|
+
endpoint="/send",
|
|
45
|
+
content=text,
|
|
46
|
+
recvId=self._target_id,
|
|
47
|
+
recvType=self._target_type
|
|
48
|
+
)
|
|
49
|
+
)
|
|
50
|
+
|
|
39
51
|
def __init__(self):
|
|
40
52
|
self._handlers = defaultdict(list)
|
|
41
53
|
self._middlewares = []
|
|
42
|
-
|
|
43
|
-
# 检测是否有 Send 子类定义
|
|
44
|
-
if not hasattr(self.__class__, 'Send') or not issubclass(self.__class__.Send, SendDSL):
|
|
45
|
-
raise TypeError(f"{self.__class__.__name__} 必须定义 Send 嵌套类并继承 SendDSL")
|
|
46
|
-
|
|
47
54
|
# 绑定当前适配器的 Send 实例
|
|
48
55
|
self.Send = self.__class__.Send(self)
|
|
49
56
|
|
|
@@ -226,4 +233,4 @@ class AdapterManager:
|
|
|
226
233
|
|
|
227
234
|
|
|
228
235
|
adapter = AdapterManager()
|
|
229
|
-
SendDSL = SendDSLBase
|
|
236
|
+
SendDSL = SendDSLBase
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ErisPulse
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.13
|
|
4
4
|
Summary: ErisPulse 是一个模块化、可扩展的异步 Python SDK 框架,主要用于构建高效、可维护的机器人应用程序。
|
|
5
5
|
Author-email: "艾莉丝·格雷拉特(WSu2059)" <wsu2059@qq.com>, runoneall <runoobsteve@gmail.com>
|
|
6
6
|
Classifier: Development Status :: 5 - Production/Stable
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
ErisPulse/__init__.py,sha256=tCgjl-0rUeiHV_2rdFlQ-CVTFzbKdjdqXvUApRc6Avk,8095
|
|
2
|
-
ErisPulse/__main__.py,sha256=
|
|
3
|
-
ErisPulse/adapter.py,sha256=
|
|
2
|
+
ErisPulse/__main__.py,sha256=WtfHeAfWi-q1KEmrkl9slYsbCm3EI9MWb34406Usch8,49245
|
|
3
|
+
ErisPulse/adapter.py,sha256=5ntqm5Xrzdi1F6N4kWhqiRzMavSO92Fj9WZ-d3-V2VM,8798
|
|
4
4
|
ErisPulse/db.py,sha256=DuIc19GbCQMi17BWfLjaDHnthIbdysTSRxaYVFur07w,4424
|
|
5
5
|
ErisPulse/logger.py,sha256=sMA1mUZvwJ8wHwdyCrgIf_VRICv_uBCkx3tmd1stF3E,6094
|
|
6
6
|
ErisPulse/mods.py,sha256=lNiZP2EcfUhYRnOQwROyVnmhsfmk8JAZhmbhxfC2-VQ,3513
|
|
7
7
|
ErisPulse/raiserr.py,sha256=z8BigWkVrBE9dD_dJa5np2YYREwdugyWXKE4_-LEO_Q,2616
|
|
8
8
|
ErisPulse/util.py,sha256=ux3-QRT0_JjabL6S9KChhyR1E_CSRiVYEFYV5txML1M,3406
|
|
9
|
-
erispulse-1.1.
|
|
10
|
-
erispulse-1.1.
|
|
11
|
-
erispulse-1.1.
|
|
12
|
-
erispulse-1.1.
|
|
13
|
-
erispulse-1.1.
|
|
14
|
-
erispulse-1.1.
|
|
9
|
+
erispulse-1.1.13.dist-info/licenses/LICENSE,sha256=plj4EYVfKAzc0ZWoC5T2vsQ86u0yLpu17NdAPeIcgVo,1066
|
|
10
|
+
erispulse-1.1.13.dist-info/METADATA,sha256=92lw9G8SIHNWMsfMYuKoK1tJJcGc0wo6cBwHxJAWmAY,2751
|
|
11
|
+
erispulse-1.1.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
12
|
+
erispulse-1.1.13.dist-info/entry_points.txt,sha256=AjKvOdYR7QGXVpEJhjUYUwV2JluE4lm9vNbknC3hjOM,155
|
|
13
|
+
erispulse-1.1.13.dist-info/top_level.txt,sha256=Lm_qtkVvNJR8_dXh_qEDdl_12cZGpic-i4HUlVVUMZc,10
|
|
14
|
+
erispulse-1.1.13.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|