ErisPulse 1.1.11__tar.gz → 1.1.13__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.
@@ -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
- border_char = "═" * 60
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 = (60 - len(title) - 4) // 2
66
+ title_padding = (width - len(title)) // 2
61
67
  left_pad = " " * title_padding
62
- right_pad = " " * (60 - len(title) - title_padding - 4)
63
- title_line = f"{cls.DIM}{left_pad}{cls.BOLD}{color}{title}{cls.RESET}{cls.DIM}{right_pad}{cls.RESET}\n"
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
- padding = (60 - len(line) - 4) // 2
69
- left_pad = " " * padding
70
- right_pad = " " * (60 - len(line) - padding - 4)
71
- lines.append(f"{cls.DIM}║{cls.RESET}{left_pad}{line}{right_pad}{cls.DIM}║{cls.RESET}")
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
- bottom_border = f"{cls.DIM}╚{border_char}╝{cls.RESET}"
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 = f"{title_line}{border_char}\n"
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"{border_char}\n{bottom_border}\n"
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.confirm("未指定协议,请输入使用的协议", choices=['http', 'https'], default="https")
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
- if response.headers.get('Content-Type', '').startswith('application/json'):
219
+ try:
220
+ content = await response.text()
221
+ json.loads(content)
194
222
  return url
195
- else:
196
- shellprint.panel(f"源 {url} 返回的内容不是有效的 JSON 格式", "错误", "error")
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
- if response.headers.get('Content-Type', '').startswith('application/json'):
234
- content = await response.json()
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
- else:
248
- shellprint.panel(f"源 {origin} 返回的内容不是有效的 JSON 格式", "错误", "error")
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
 
@@ -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.11
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse
3
- Version: 1.1.11
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,6 +1,6 @@
1
1
  [project]
2
2
  name = "ErisPulse"
3
- version = "1.1.11"
3
+ version = "1.1.13"
4
4
  authors = [
5
5
  { name = "艾莉丝·格雷拉特(WSu2059)", email = "wsu2059@qq.com" },
6
6
  { name = "runoneall", email = "runoobsteve@gmail.com" }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes