ErisPulse 1.1.8__py3-none-any.whl → 1.1.11__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 CHANGED
@@ -1,6 +1,7 @@
1
1
  import argparse
2
2
  import os
3
3
  import sys
4
+ import time
4
5
  import shutil
5
6
  import aiohttp
6
7
  import zipfile
@@ -10,53 +11,166 @@ import subprocess
10
11
  import json
11
12
  from .db import env
12
13
  from .mods import mods
14
+ from watchdog.observers import Observer
15
+ from watchdog.events import FileSystemEventHandler
13
16
 
14
- def print_panel(msg, title=None, border_style=None):
15
- print("=" * 60)
16
- if title:
17
- print(f"[{title}]")
18
- print(msg)
19
- print("=" * 60)
20
-
21
- def print_table(headers, rows, title=None):
22
- if title:
23
- print(f"== {title} ==")
24
- col_widths = [len(h) for h in headers]
25
- for row in rows:
26
- for i, cell in enumerate(row):
27
- col_widths[i] = max(col_widths[i], len(str(cell)))
28
- fmt = " | ".join("{:<" + str(w) + "}" for w in col_widths)
29
- print(fmt.format(*headers))
30
- print("-" * (sum(col_widths) + 3 * (len(headers) - 1)))
31
- for row in rows:
32
- print(fmt.format(*row))
33
-
34
- def confirm(msg, default=False):
35
- yes = {'y', 'yes', ''}
36
- no = {'n', 'no'}
37
- prompt = f"{msg} [{'Y/n' if default else 'y/N'}]: "
38
- while True:
39
- ans = input(prompt).strip().lower()
40
- if not ans:
41
- return default
42
- if ans in yes:
43
- return True
44
- if ans in no:
45
- return False
17
+ class Shell_Printer:
18
+ # ANSI 颜色代码
19
+ RESET = "\033[0m"
20
+ BOLD = "\033[1m"
21
+ RED = "\033[91m"
22
+ GREEN = "\033[92m"
23
+ YELLOW = "\033[93m"
24
+ BLUE = "\033[94m"
25
+ MAGENTA = "\033[95m"
26
+ CYAN = "\033[96m"
27
+ WHITE = "\033[97m"
28
+ DIM = "\033[2m"
29
+ UNDERLINE = "\033[4m"
30
+ BG_BLUE = "\033[44m"
31
+ BG_GREEN = "\033[42m"
32
+ BG_YELLOW = "\033[43m"
33
+ BG_RED = "\033[41m"
34
+
35
+ def __init__(self):
36
+ pass
37
+
38
+ @classmethod
39
+ def _get_color(cls, level):
40
+ """根据消息级别返回颜色"""
41
+ return {
42
+ "info": cls.CYAN,
43
+ "success": cls.GREEN,
44
+ "warning": cls.YELLOW,
45
+ "error": cls.RED,
46
+ "title": cls.MAGENTA,
47
+ "default": cls.RESET,
48
+ }.get(level, cls.RESET)
49
+
50
+ @classmethod
51
+ def panel(cls, msg: str, title: str = None, level: str = "info") -> None:
52
+ """带标题和边框的面板,支持颜色编码"""
53
+ color = cls._get_color(level)
54
+ border_char = "═" * 60
55
+
56
+ # 标题行
57
+ title_line = ""
58
+ if title:
59
+ title = f" {title.upper()} "
60
+ title_padding = (60 - len(title) - 4) // 2
61
+ 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"
64
+
65
+ # 内容行
66
+ lines = []
67
+ 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}")
72
+
73
+ # 底部边框
74
+ bottom_border = f"{cls.DIM}╚{border_char}╝{cls.RESET}"
75
+
76
+ # 组合所有部分
77
+ panel = f"{title_line}{border_char}\n"
78
+ panel += "\n".join(lines) + "\n"
79
+ panel += f"{border_char}\n{bottom_border}\n"
80
+
81
+ print(panel)
46
82
 
47
- def ask(msg, choices=None, default=None):
48
- prompt = f"{msg}"
49
- if choices:
50
- prompt += f" ({'/'.join(choices)})"
51
- if default:
52
- prompt += f" [default: {default}]"
53
- prompt += ": "
54
- while True:
55
- ans = input(prompt).strip()
56
- if not ans and default:
57
- return default
58
- if not choices or ans in choices:
59
- return ans
83
+ @classmethod
84
+ def table(cls, headers, rows, title=None, level="info") -> None:
85
+ """改进的表格输出,带有颜色和分隔线"""
86
+ color = cls._get_color(level)
87
+ if title:
88
+ print(f"{cls.BOLD}{color}== {title} =={cls.RESET}")
89
+
90
+ # 计算列宽
91
+ col_widths = [len(h) for h in headers]
92
+ for row in rows:
93
+ for i, cell in enumerate(row):
94
+ col_widths[i] = max(col_widths[i], len(str(cell)))
95
+
96
+ # 构建标题格式
97
+ fmt = "│".join(f" {{:<{w}}} " for w in col_widths)
98
+
99
+ # 顶部边框
100
+ top_border = "┌" + "┬".join("─" * (w+2) for w in col_widths) + "┐"
101
+ print(f"{cls.DIM}{top_border}{cls.RESET}")
102
+
103
+ # 表头
104
+ header_line = fmt.format(*headers)
105
+ print(f"{cls.BOLD}{color}│{header_line}│{cls.RESET}")
106
+
107
+ # 表头分隔线
108
+ separator = "├" + "┼".join("─" * (w+2) for w in col_widths) + "┤"
109
+ print(f"{cls.DIM}{separator}{cls.RESET}")
110
+
111
+ # 表格内容
112
+ for row in rows:
113
+ row_line = fmt.format(*row)
114
+ print(f"│{row_line}│")
115
+
116
+ # 底部边框
117
+ bottom_border = "└" + "┴".join("─" * (w+2) for w in col_widths) + "┘"
118
+ print(f"{cls.DIM}{bottom_border}{cls.RESET}")
119
+
120
+ @classmethod
121
+ def progress_bar(cls, current, total, prefix="", suffix="", length=50):
122
+ """显示进度条"""
123
+ filled_length = int(length * current // total)
124
+ percent = min(100.0, 100 * (current / float(total)))
125
+ bar = f"{cls.GREEN}{'█' * filled_length}{cls.WHITE}{'░' * (length - filled_length)}{cls.RESET}"
126
+ sys.stdout.write(f"\r{cls.BOLD}{prefix}{cls.RESET} {bar} {cls.BOLD}{percent:.1f}%{cls.RESET} {suffix}")
127
+ sys.stdout.flush()
128
+ if current == total:
129
+ print()
130
+
131
+ @classmethod
132
+ def confirm(cls, msg, default=False) -> bool:
133
+ """带颜色和默认选择的确认对话框"""
134
+ yes_options = {'y', 'yes'}
135
+ no_options = {'n', 'no'}
136
+ default_str = "Y/n" if default else "y/N"
137
+ prompt = f"{cls.BOLD}{msg}{cls.RESET} [{cls.CYAN}{default_str}{cls.RESET}]: "
138
+
139
+ while True:
140
+ ans = input(prompt).strip().lower()
141
+ if not ans:
142
+ return default
143
+ if ans in yes_options:
144
+ return True
145
+ if ans in no_options:
146
+ return False
147
+ print(f"{cls.YELLOW}请输入 'y' 或 'n'{cls.RESET}")
148
+
149
+ @classmethod
150
+ def ask(cls, msg, choices=None, default=None) -> str | None:
151
+ """带颜色和选择的提问"""
152
+ prompt = f"{cls.BOLD}{msg}{cls.RESET}"
153
+ if choices:
154
+ prompt += f" ({cls.CYAN}{'/'.join(choices)}{cls.RESET})"
155
+ if default:
156
+ prompt += f" [{cls.BLUE}默认: {default}{cls.RESET}]"
157
+ prompt += ": "
158
+
159
+ while True:
160
+ ans = input(prompt).strip()
161
+ if not ans and default:
162
+ return default
163
+ if not choices or ans in choices:
164
+ return ans
165
+ print(f"{cls.YELLOW}请输入有效选项: {', '.join(choices)}{cls.RESET}")
166
+
167
+ @classmethod
168
+ def status(cls, msg, success=True):
169
+ """显示状态指示器"""
170
+ symbol = f"{cls.GREEN}✓" if success else f"{cls.RED}✗"
171
+ print(f"\r{symbol}{cls.RESET} {msg}")
172
+
173
+ shellprint = Shell_Printer()
60
174
 
61
175
  class SourceManager:
62
176
  def __init__(self):
@@ -68,7 +182,7 @@ class SourceManager:
68
182
 
69
183
  async def _validate_url(self, url):
70
184
  if not url.startswith(('http://', 'https://')):
71
- protocol = ask("未指定协议,请输入使用的协议", choices=['http', 'https'], default="https")
185
+ protocol = shellprint.confirm("未指定协议,请输入使用的协议", choices=['http', 'https'], default="https")
72
186
  url = f"{protocol}://{url}"
73
187
  if not url.endswith('.json'):
74
188
  url = f"{url}/map.json"
@@ -79,38 +193,41 @@ class SourceManager:
79
193
  if response.headers.get('Content-Type', '').startswith('application/json'):
80
194
  return url
81
195
  else:
82
- print_panel(f"源 {url} 返回的内容不是有效的 JSON 格式", "错误")
196
+ shellprint.panel(f"源 {url} 返回的内容不是有效的 JSON 格式", "错误", "error")
83
197
  return None
84
198
  except Exception as e:
85
- print_panel(f"访问源 {url} 失败: {e}", "错误")
199
+ shellprint.panel(f"访问源 {url} 失败: {e}", "错误", "error")
86
200
  return None
87
201
 
88
202
  def add_source(self, value):
203
+ shellprint.status(f"验证源: {value}")
89
204
  validated_url = asyncio.run(self._validate_url(value))
90
205
  if not validated_url:
91
- print_panel("提供的源不是一个有效源,请检查后重试", "错误")
206
+ shellprint.panel("提供的源不是一个有效源,请检查后重试", "错误", "error")
92
207
  return False
208
+
93
209
  origins = env.get('origins')
94
210
  if validated_url not in origins:
95
211
  origins.append(validated_url)
96
212
  env.set('origins', origins)
97
- print_panel(f"源 {validated_url} 已成功添加", "成功")
213
+ shellprint.panel(f"源 {validated_url} 已成功添加", "成功", "success")
98
214
  return True
99
215
  else:
100
- print_panel(f"源 {validated_url} 已存在,无需重复添加", "提示")
216
+ shellprint.panel(f"源 {validated_url} 已存在,无需重复添加", "提示", "info")
101
217
  return False
102
218
 
103
219
  def update_sources(self):
220
+ shellprint.status("更新模块源...")
104
221
  origins = env.get('origins')
105
222
  providers = {}
106
223
  modules = {}
107
224
  module_alias = {}
108
225
  table_rows = []
109
226
  async def fetch_source_data():
110
- async with aiohttp.ClientSession() as session:
111
- for origin in origins:
112
- print(f"正在获取 {origin}...")
113
- try:
227
+ for i, origin in enumerate(origins):
228
+ shellprint.status(f"获取源数据 ({i+1}/{len(origins)}): {origin}")
229
+ try:
230
+ async with aiohttp.ClientSession() as session:
114
231
  async with session.get(origin) as response:
115
232
  response.raise_for_status()
116
233
  if response.headers.get('Content-Type', '').startswith('application/json'):
@@ -128,74 +245,176 @@ class SourceManager:
128
245
  f"{providers[content['name']]}{module_origin_name}"
129
246
  ])
130
247
  else:
131
- print_panel(f"源 {origin} 返回的内容不是有效的 JSON 格式", "错误")
132
- except Exception as e:
133
- print_panel(f"获取 {origin} 时出错: {e}", "错误")
248
+ shellprint.panel(f"源 {origin} 返回的内容不是有效的 JSON 格式", "错误", "error")
249
+ except Exception as e:
250
+ shellprint.panel(f"获取 {origin} 时出错: {e}", "错误", "error")
251
+
134
252
  asyncio.run(fetch_source_data())
135
- print_table(["源", "模块", "地址"], table_rows, "源更新状态")
253
+ shellprint.table(["源", "模块", "地址"], table_rows, "源更新状态", "success")
136
254
  from datetime import datetime
137
255
  env.set('providers', providers)
138
256
  env.set('modules', modules)
139
257
  env.set('module_alias', module_alias)
140
258
  env.set('last_origin_update_time', datetime.now().isoformat())
141
- print_panel("源更新完成", "成功")
259
+ shellprint.panel("源更新完成", "成功", "success")
142
260
 
143
261
  def list_sources(self):
144
262
  origins = env.get('origins')
145
263
  if not origins:
146
- print_panel("当前没有配置任何源", "提示")
264
+ shellprint.panel("当前没有配置任何源", "提示", "info")
147
265
  return
266
+
148
267
  rows = [[str(idx), origin] for idx, origin in enumerate(origins, 1)]
149
- print_table(["序号", "源地址"], rows, "已配置的源")
268
+ shellprint.table(["序号", "源地址"], rows, "已配置的源", "info")
150
269
 
151
270
  def del_source(self, value):
152
271
  origins = env.get('origins')
153
272
  if value in origins:
154
273
  origins.remove(value)
155
274
  env.set('origins', origins)
156
- print_panel(f"源 {value} 已成功删除", "成功")
275
+ shellprint.panel(f"源 {value} 已成功删除", "成功", "success")
157
276
  else:
158
- print_panel(f"源 {value} 不存在", "错误")
277
+ shellprint.panel(f"源 {value} 不存在", "错误", "error")
278
+
279
+ source_manager = SourceManager()
280
+
281
+ class ReloadHandler(FileSystemEventHandler):
282
+ def __init__(self, script_path, *args, **kwargs):
283
+ super().__init__(*args, **kwargs)
284
+ self.script_path = script_path
285
+ self.process = None
286
+ self.last_reload = time.time()
287
+ self.start_process()
288
+
289
+ def start_process(self):
290
+ if self.process:
291
+ self.process.terminate()
292
+ self.process.wait()
293
+
294
+ shellprint.status(f"启动进程: {self.script_path}")
295
+ self.process = subprocess.Popen([sys.executable, self.script_path])
296
+ self.last_reload = time.time()
297
+
298
+ def on_modified(self, event):
299
+ now = time.time()
300
+ # 1秒后再次触发
301
+ if now - self.last_reload < 1.0:
302
+ return
303
+
304
+ if event.src_path.endswith(".py"):
305
+ print(f"\n{Shell_Printer.CYAN}[热重载] 检测到文件变动: {event.src_path}{Shell_Printer.RESET}")
306
+ self.start_process()
307
+
308
+ def start_reloader(script_path):
309
+ project_root = os.path.dirname(os.path.abspath(__file__))
310
+ watch_dirs = [
311
+ os.path.dirname(os.path.abspath(script_path)),
312
+ os.path.join(project_root, "modules")
313
+ ]
314
+
315
+ handler = ReloadHandler(script_path)
316
+ observer = Observer()
317
+
318
+ for d in watch_dirs:
319
+ if os.path.exists(d):
320
+ observer.schedule(handler, d, recursive=True)
321
+
322
+ observer.start()
323
+ print(f"\n{Shell_Printer.GREEN}{Shell_Printer.BOLD}[热重载] 已启动{Shell_Printer.RESET}")
324
+ print(f"{Shell_Printer.DIM}监控目录: {', '.join(watch_dirs)}{Shell_Printer.RESET}\n")
325
+ try:
326
+ while True:
327
+ time.sleep(1)
328
+ except KeyboardInterrupt:
329
+ observer.stop()
330
+ if handler.process:
331
+ handler.process.terminate()
332
+ observer.join()
159
333
 
160
334
  def enable_module(module_name):
335
+ shellprint.status(f"启用模块: {module_name}")
161
336
  module_info = mods.get_module(module_name)
162
337
  if module_info:
163
338
  mods.set_module_status(module_name, True)
164
- print_panel(f"模块 {module_name} 已成功启用", "成功")
339
+ shellprint.panel(f"模块 {module_name} 已成功启用", "成功", "success")
165
340
  else:
166
- print_panel(f"模块 {module_name} 不存在", "错误")
341
+ shellprint.panel(f"模块 {module_name} 不存在", "错误", "error")
167
342
 
168
343
  def disable_module(module_name):
344
+ shellprint.status(f"禁用模块: {module_name}")
169
345
  module_info = mods.get_module(module_name)
170
346
  if module_info:
171
347
  mods.set_module_status(module_name, False)
172
- print_panel(f"模块 {module_name} 已成功禁用", "成功")
348
+ shellprint.panel(f"模块 {module_name} 已成功禁用", "成功", "success")
173
349
  else:
174
- print_panel(f"模块 {module_name} 不存在", "错误")
350
+ shellprint.panel(f"模块 {module_name} 不存在", "错误", "error")
175
351
 
176
- async def fetch_url(session, url):
352
+ async def fetch_url(session, url, progress_callback=None):
177
353
  try:
178
354
  async with session.get(url) as response:
179
355
  response.raise_for_status()
180
- return await response.read()
356
+ total_size = int(response.headers.get('Content-Length', 0))
357
+ downloaded = 0
358
+ data = b''
359
+
360
+ async for chunk in response.content.iter_any():
361
+ data += chunk
362
+ downloaded += len(chunk)
363
+ if total_size and progress_callback:
364
+ progress_callback(downloaded, total_size)
365
+
366
+ return data
181
367
  except Exception as e:
182
368
  print(f"请求失败: {e}")
183
369
  return None
184
370
 
185
371
  def extract_and_setup_module(module_name, module_url, zip_path, module_dir):
186
372
  try:
187
- print(f"正在从 {module_url} 下载模块...")
373
+ print(f"正在下载模块: {Shell_Printer.BOLD}{module_name}{Shell_Printer.RESET}")
374
+ current_downloaded = [0]
375
+ total_size = [0]
376
+
377
+ def progress_callback(downloaded, total):
378
+ if total > 0 and total_size[0] == 0:
379
+ total_size[0] = total
380
+ if downloaded > current_downloaded[0]:
381
+ current_downloaded[0] = downloaded
382
+ prefix = f"{Shell_Printer.BOLD}{module_name}{Shell_Printer.RESET} {Shell_Printer.DIM}下载中{Shell_Printer.RESET}"
383
+ suffix = f"{downloaded/1024:.1f}KB/{total/1024:.1f}KB" if total > 0 else f"{downloaded/1024:.1f}KB"
384
+ shellprint.progress_bar(downloaded, total or downloaded, prefix, suffix, 40)
385
+
188
386
  async def download_module():
189
387
  async with aiohttp.ClientSession() as session:
190
- content = await fetch_url(session, module_url)
388
+ content = await fetch_url(session, module_url, progress_callback)
191
389
  if content is None:
192
390
  return False
391
+
193
392
  with open(zip_path, 'wb') as zip_file:
194
393
  zip_file.write(content)
394
+
395
+ if total_size[0] > 0:
396
+ shellprint.progress_bar(total_size[0], total_size[0],
397
+ f"{Shell_Printer.BOLD}{module_name}{Shell_Printer.RESET}",
398
+ "下载完成", 40)
399
+
195
400
  if not os.path.exists(module_dir):
196
401
  os.makedirs(module_dir)
402
+
403
+ shellprint.status(f"解压模块: {module_name}")
197
404
  with zipfile.ZipFile(zip_path, 'r') as zip_ref:
198
- zip_ref.extractall(module_dir)
405
+ file_list = zip_ref.namelist()
406
+ for i, file in enumerate(file_list):
407
+ zip_ref.extract(file, module_dir)
408
+ if len(file_list) > 10 and i % (len(file_list) // 10) == 0:
409
+ shellprint.progress_bar(i, len(file_list),
410
+ f"{Shell_Printer.BOLD}{module_name}{Shell_Printer.RESET}",
411
+ "解压中", 30)
412
+ if len(file_list) > 10:
413
+ shellprint.progress_bar(len(file_list), len(file_list),
414
+ f"{Shell_Printer.BOLD}{module_name}{Shell_Printer.RESET}",
415
+ "解压完成", 30)
416
+ print()
417
+
199
418
  init_file_path = os.path.join(module_dir, '__init__.py')
200
419
  if not os.path.exists(init_file_path):
201
420
  sub_module_dir = os.path.join(module_dir, module_name)
@@ -211,9 +430,10 @@ def extract_and_setup_module(module_name, module_url, zip_path, module_dir):
211
430
  os.rmdir(sub_dir)
212
431
  print(f"模块 {module_name} 文件已成功解压并设置")
213
432
  return True
433
+
214
434
  return asyncio.run(download_module())
215
435
  except Exception as e:
216
- print_panel(f"处理模块 {module_name} 文件失败: {e}", "错误")
436
+ shellprint.panel(f"处理模块 {module_name} 文件失败: {e}", "错误", "error")
217
437
  if os.path.exists(zip_path):
218
438
  try:
219
439
  os.remove(zip_path)
@@ -230,45 +450,60 @@ def extract_and_setup_module(module_name, module_url, zip_path, module_dir):
230
450
  def install_pip_dependencies(dependencies):
231
451
  if not dependencies:
232
452
  return True
233
- print("正在安装pip依赖...")
453
+
454
+ print(f"{Shell_Printer.CYAN}正在安装pip依赖: {', '.join(dependencies)}{Shell_Printer.RESET}")
234
455
  try:
235
- result = subprocess.run(
456
+ # 使用子进程获取安装进度
457
+ process = subprocess.Popen(
236
458
  [sys.executable, "-m", "pip", "install"] + dependencies,
237
- check=True,
238
459
  stdout=subprocess.PIPE,
239
- stderr=subprocess.PIPE
460
+ stderr=subprocess.STDOUT,
461
+ universal_newlines=True
240
462
  )
241
- print(result.stdout.decode())
242
- return True
463
+
464
+ # 实时输出安装过程
465
+ while True:
466
+ output = process.stdout.readline()
467
+ if output == '' and process.poll() is not None:
468
+ break
469
+ if output:
470
+ print(f"{Shell_Printer.DIM}{output.strip()}{Shell_Printer.RESET}")
471
+
472
+ return process.returncode == 0
473
+
243
474
  except subprocess.CalledProcessError as e:
244
- print_panel(f"安装pip依赖失败: {e.stderr.decode()}", "错误")
475
+ shellprint.panel(f"安装pip依赖失败: {e.stderr}", "错误", "error")
245
476
  return False
246
477
 
247
478
  def install_module(module_name, force=False):
248
- print_panel(f"准备安装模块: {module_name}", "安装摘要")
479
+ shellprint.panel(f"准备安装模块: {Shell_Printer.BOLD}{module_name}{Shell_Printer.RESET}", "安装摘要", "info")
249
480
  last_update_time = env.get('last_origin_update_time', None)
250
481
  if last_update_time:
251
482
  from datetime import datetime, timedelta
252
483
  last_update = datetime.fromisoformat(last_update_time)
253
484
  if datetime.now() - last_update > timedelta(hours=720):
254
- print_panel("距离上次源更新已超过30天,源内可能有新模块或更新。", "提示")
255
- if confirm("是否在安装模块前更新源?", default=True):
256
- SourceManager().update_sources()
485
+ shellprint.panel("距离上次源更新已超过30天,源内可能有新模块或更新。", "提示", "warning")
486
+ if shellprint.confirm("是否在安装模块前更新源?", default=True):
487
+ source_manager.update_sources()
257
488
  env.set('last_origin_update_time', datetime.now().isoformat())
258
- print("源更新完成")
489
+ shellprint.status("源更新完成")
490
+
259
491
  module_info = mods.get_module(module_name)
260
492
  if module_info and not force:
261
493
  meta = module_info.get('info', {}).get('meta', {})
262
- print_panel(
263
- f"模块 {module_name} 已存在\n版本: {meta.get('version', '未知')}\n描述: {meta.get('description', '无描述')}",
264
- "模块已存在"
494
+ shellprint.panel(
495
+ f"{Shell_Printer.BOLD}{module_name}{Shell_Printer.RESET}\n版本: {meta.get('version', '未知')}\n描述: {meta.get('description', '无描述')}",
496
+ "模块已存在",
497
+ "info"
265
498
  )
266
- if not confirm("是否要强制重新安装?", default=False):
499
+ if not shellprint.confirm("是否要强制重新安装?", default=False):
267
500
  return
501
+
268
502
  providers = env.get('providers', {})
269
503
  if isinstance(providers, str):
270
504
  providers = json.loads(providers)
271
505
  module_info_list = []
506
+
272
507
  for provider, url in providers.items():
273
508
  module_key = f"{module_name}@{provider}"
274
509
  modules_data = env.get('modules', {})
@@ -289,43 +524,57 @@ def install_module(module_name, force=False):
289
524
  'optional_dependencies': depsinfo.get("optional", []),
290
525
  'pip_dependencies': depsinfo.get("pip", [])
291
526
  })
527
+
292
528
  if not module_info_list:
293
- print_panel(f"未找到模块 {module_name}", "错误")
529
+ shellprint.panel(f"未找到模块 {module_name}", "错误", "error")
294
530
  if providers:
295
- print("当前可用源:")
531
+ print(f"{Shell_Printer.BOLD}当前可用源:{Shell_Printer.RESET}")
296
532
  for provider in providers:
297
- print(f" - {provider}")
533
+ print(f" {Shell_Printer.CYAN}- {provider}{Shell_Printer.RESET}")
298
534
  return
535
+
299
536
  if len(module_info_list) > 1:
300
- print(f"找到 {len(module_info_list)} 个源的 {module_name} 模块:")
537
+ print(f"找到 {Shell_Printer.BOLD}{len(module_info_list)}{Shell_Printer.RESET} 个源的 {Shell_Printer.BOLD}{module_name}{Shell_Printer.RESET} 模块:")
301
538
  rows = []
302
539
  for i, info in enumerate(module_info_list):
303
540
  rows.append([
304
- str(i+1), info['provider'], info['version'], info['description'], info['author']
541
+ f"{Shell_Printer.CYAN}{i+1}{Shell_Printer.RESET}",
542
+ info['provider'],
543
+ info['version'],
544
+ info['description'],
545
+ info['author']
305
546
  ])
306
- print_table(["编号", "源", "版本", "描述", "作者"], rows, "可选模块源")
547
+ shellprint.table(["编号", "源", "版本", "描述", "作者"], rows, "可选模块源", "info")
548
+
307
549
  while True:
308
- choice = ask("请选择要安装的源 (输入编号)", default="1")
309
- if choice.isdigit() and 1 <= int(choice) <= len(module_info_list):
550
+ choice = shellprint.ask("请选择要安装的源 (输入编号)", [str(i) for i in range(1, len(module_info_list)+1)])
551
+ if choice and 1 <= int(choice) <= len(module_info_list):
310
552
  selected_module = module_info_list[int(choice)-1]
311
553
  break
312
554
  else:
313
- print("输入无效,请重新选择")
555
+ print(f"{Shell_Printer.YELLOW}输入无效,请重新选择{Shell_Printer.RESET}")
314
556
  else:
315
557
  selected_module = module_info_list[0]
558
+
559
+ # 安装依赖
316
560
  for dep in selected_module['dependencies']:
317
- print(f"正在安装依赖模块 {dep}...")
561
+ print(f"\n{Shell_Printer.BOLD}处理依赖: {dep}{Shell_Printer.RESET}")
318
562
  install_module(dep)
563
+
564
+ # 安装pip依赖
319
565
  third_party_deps = selected_module.get('pip_dependencies', [])
320
566
  if third_party_deps:
321
- print(f"模块 {module_name} 需要以下pip依赖: {', '.join(third_party_deps)}")
567
+ print(f"{Shell_Printer.YELLOW}模块 {module_name} 需要以下pip依赖: {', '.join(third_party_deps)}{Shell_Printer.RESET}")
322
568
  if not install_pip_dependencies(third_party_deps):
323
- print(f"无法安装模块 {module_name} 的pip依赖,安装终止")
569
+ print(f"{Shell_Printer.RED}无法安装模块 {module_name} 的pip依赖,安装终止{Shell_Printer.RESET}")
324
570
  return
571
+
572
+ # 下载并安装模块
325
573
  module_url = selected_module['url'] + selected_module['path']
326
574
  script_dir = os.path.dirname(os.path.abspath(__file__))
327
575
  module_dir = os.path.join(script_dir, 'modules', module_name)
328
576
  zip_path = os.path.join(script_dir, f"{module_name}.zip")
577
+
329
578
  if not extract_and_setup_module(
330
579
  module_name=module_name,
331
580
  module_url=module_url,
@@ -333,6 +582,8 @@ def install_module(module_name, force=False):
333
582
  module_dir=module_dir
334
583
  ):
335
584
  return
585
+
586
+ # 注册模块信息
336
587
  mods.set_module(module_name, {
337
588
  'status': True,
338
589
  'info': {
@@ -349,39 +600,50 @@ def install_module(module_name, force=False):
349
600
  }
350
601
  }
351
602
  })
352
- print(f"模块 {module_name} 安装成功")
603
+
604
+ shellprint.panel(f"模块 {Shell_Printer.BOLD}{module_name}{Shell_Printer.RESET} 安装成功", "成功", "success")
353
605
 
354
606
  def uninstall_module(module_name):
355
- print_panel(f"准备卸载模块: {module_name}", "卸载摘要")
607
+ shellprint.panel(f"准备卸载模块: {Shell_Printer.BOLD}{module_name}{Shell_Printer.RESET}", "卸载摘要", "warning")
356
608
  module_info = mods.get_module(module_name)
357
609
  if not module_info:
358
- print_panel(f"模块 {module_name} 不存在", "错误")
610
+ shellprint.panel(f"模块 {module_name} 不存在", "错误", "error")
359
611
  return
612
+
360
613
  meta = module_info.get('info', {}).get('meta', {})
361
614
  depsinfo = module_info.get('info', {}).get('dependencies', {})
362
- print_panel(
363
- f"版本: {meta.get('version', '未知')}\n描述: {meta.get('description', '无描述')}\npip依赖: {', '.join(depsinfo.get('pip', [])) or '无'}",
364
- "模块信息"
615
+ shellprint.panel(
616
+ f"版本: {Shell_Printer.BOLD}{meta.get('version', '未知')}{Shell_Printer.RESET}\n"
617
+ f"描述: {meta.get('description', '无描述')}\n"
618
+ f"pip依赖: {Shell_Printer.YELLOW}{', '.join(depsinfo.get('pip', [])) or '无'}{Shell_Printer.RESET}",
619
+ "模块信息",
620
+ "info"
365
621
  )
366
- if not confirm("确认要卸载此模块吗?", default=False):
367
- print("卸载已取消")
622
+
623
+ if not shellprint.confirm("确认要卸载此模块吗?", default=False):
624
+ print(f"{Shell_Printer.BLUE}卸载已取消{Shell_Printer.RESET}")
368
625
  return
626
+
369
627
  script_dir = os.path.dirname(os.path.abspath(__file__))
370
628
  module_path = os.path.join(script_dir, 'modules', module_name)
371
629
  module_file_path = module_path + '.py'
630
+
372
631
  if os.path.exists(module_file_path):
373
632
  try:
633
+ shellprint.status(f"删除模块文件: {module_name}.py")
374
634
  os.remove(module_file_path)
375
635
  except Exception as e:
376
- print_panel(f"删除模块文件 {module_name} 时出错: {e}", "错误")
636
+ shellprint.panel(f"删除模块文件 {module_name} 时出错: {e}", "错误", "error")
377
637
  elif os.path.exists(module_path) and os.path.isdir(module_path):
378
638
  try:
639
+ shellprint.status(f"删除模块目录: {module_name}")
379
640
  shutil.rmtree(module_path)
380
641
  except Exception as e:
381
- print_panel(f"删除模块目录 {module_name} 时出错: {e}", "错误")
642
+ shellprint.panel(f"删除模块目录 {module_name} 时出错: {e}", "错误", "error")
382
643
  else:
383
- print_panel(f"模块 {module_name} 不存在", "错误")
644
+ shellprint.panel(f"模块 {module_name} 文件不存在", "错误", "error")
384
645
  return
646
+
385
647
  pip_dependencies = depsinfo.get('pip', [])
386
648
  if pip_dependencies:
387
649
  all_modules = mods.get_all_modules()
@@ -389,55 +651,66 @@ def uninstall_module(module_name):
389
651
  essential_packages = {'aiohttp'}
390
652
  for dep in pip_dependencies:
391
653
  if dep in essential_packages:
392
- print(f"跳过必要模块 {dep} 的卸载")
654
+ print(f"{Shell_Printer.CYAN}跳过必要模块 {dep} 的卸载{Shell_Printer.RESET}")
393
655
  continue
656
+
394
657
  is_dependency_used = False
395
658
  for name, info in all_modules.items():
396
659
  if name != module_name and dep in info.get('info', {}).get('dependencies', {}).get('pip', []):
397
660
  is_dependency_used = True
398
661
  break
662
+
399
663
  if not is_dependency_used:
400
664
  unused_pip_dependencies.append(dep)
665
+
401
666
  if unused_pip_dependencies:
402
- print_panel(
403
- f"以下 pip 依赖不再被其他模块使用:\n{', '.join(unused_pip_dependencies)}",
404
- "可卸载依赖"
667
+ shellprint.panel(
668
+ f"以下 pip 依赖不再被其他模块使用:\n{Shell_Printer.YELLOW}{', '.join(unused_pip_dependencies)}{Shell_Printer.RESET}",
669
+ "可卸载依赖",
670
+ "info"
405
671
  )
406
- if confirm("是否卸载这些 pip 依赖?", default=False):
672
+ if shellprint.confirm("是否卸载这些 pip 依赖?", default=False):
407
673
  try:
674
+ shellprint.status(f"卸载pip依赖: {', '.join(unused_pip_dependencies)}")
408
675
  subprocess.run(
409
676
  [sys.executable, "-m", "pip", "uninstall", "-y"] + unused_pip_dependencies,
410
677
  check=True,
411
678
  stdout=subprocess.PIPE,
412
679
  stderr=subprocess.PIPE
413
680
  )
414
- print_panel(
681
+ shellprint.panel(
415
682
  f"成功卸载 pip 依赖: {', '.join(unused_pip_dependencies)}",
416
- "成功"
683
+ "成功",
684
+ "success"
417
685
  )
418
686
  except subprocess.CalledProcessError as e:
419
- print_panel(
687
+ shellprint.panel(
420
688
  f"卸载 pip 依赖失败: {e.stderr.decode()}",
421
- "错误"
689
+ "错误",
690
+ "error"
422
691
  )
692
+
423
693
  if mods.remove_module(module_name):
424
- print_panel(f"模块 {module_name} 已成功卸载", "成功")
694
+ shellprint.panel(f"模块 {Shell_Printer.BOLD}{module_name}{Shell_Printer.RESET} 已成功卸载", "成功", "success")
425
695
  else:
426
- print_panel(f"模块 {module_name} 不存在", "错误")
696
+ shellprint.panel(f"模块 {module_name} 不存在", "错误", "error")
427
697
 
428
698
  def upgrade_all_modules(force=False):
429
699
  all_modules = mods.get_all_modules()
430
700
  if not all_modules:
431
- print("未找到任何模块,无法更新")
701
+ print(f"{Shell_Printer.YELLOW}未找到任何模块,无法更新{Shell_Printer.RESET}")
432
702
  return
703
+
433
704
  providers = env.get('providers', {})
434
705
  if isinstance(providers, str):
435
706
  providers = json.loads(providers)
436
707
  modules_data = env.get('modules', {})
437
708
  if isinstance(modules_data, str):
438
709
  modules_data = json.loads(modules_data)
710
+
439
711
  updates_available = []
440
712
  for module_name, module_info in all_modules.items():
713
+ shellprint.status(f"检查更新: {module_name}")
441
714
  local_version = module_info.get('info', {}).get('meta', {}).get('version', '0.0.0')
442
715
  for provider, url in providers.items():
443
716
  module_key = f"{module_name}@{provider}"
@@ -453,24 +726,39 @@ def upgrade_all_modules(force=False):
453
726
  'url': url,
454
727
  'path': remote_module.get('path', ''),
455
728
  })
729
+
456
730
  if not updates_available:
457
- print("所有模块已是最新版本,无需更新")
731
+ print(f"{Shell_Printer.GREEN}所有模块已是最新版本,无需更新{Shell_Printer.RESET}")
458
732
  return
459
- print("\n以下模块有可用更新:")
733
+
734
+ print(f"\n{Shell_Printer.BOLD}以下模块有可用更新:{Shell_Printer.RESET}")
460
735
  rows = []
461
736
  for update in updates_available:
462
- rows.append([update['name'], update['local_version'], update['remote_version'], update['provider']])
463
- print_table(["模块", "当前版本", "最新版本", "源"], rows, "可用更新")
737
+ rows.append([
738
+ update['name'],
739
+ update['local_version'],
740
+ f"{Shell_Printer.GREEN}{update['remote_version']}{Shell_Printer.RESET}",
741
+ update['provider']
742
+ ])
743
+ shellprint.table(["模块", "当前版本", "最新版本", "源"], rows, "可用更新", "info")
744
+
464
745
  if not force:
465
- if not confirm("警告:更新模块可能会导致兼容性问题,请在更新前查看插件作者的相关声明。\n是否继续?", default=False):
466
- print("更新已取消")
746
+ warning_msg = (
747
+ f"{Shell_Printer.BOLD}{Shell_Printer.RED}警告:{Shell_Printer.RESET} "
748
+ "更新模块可能会导致兼容性问题,请在更新前查看插件作者的相关声明。\n"
749
+ "是否继续?"
750
+ )
751
+ if not shellprint.confirm(warning_msg, default=False):
752
+ print(f"{Shell_Printer.BLUE}更新已取消{Shell_Printer.RESET}")
467
753
  return
468
- for update in updates_available:
469
- print(f"正在更新模块 {update['name']}...")
754
+
755
+ for i, update in enumerate(updates_available, 1):
756
+ print(f"\n{Shell_Printer.BOLD}[{i}/{len(updates_available)}]{Shell_Printer.RESET} 更新模块 {Shell_Printer.BOLD}{update['name']}{Shell_Printer.RESET}")
470
757
  module_url = update['url'] + update['path']
471
758
  script_dir = os.path.dirname(os.path.abspath(__file__))
472
759
  module_dir = os.path.join(script_dir, 'modules', update['name'])
473
760
  zip_path = os.path.join(script_dir, f"{update['name']}.zip")
761
+
474
762
  if not extract_and_setup_module(
475
763
  module_name=update['name'],
476
764
  module_url=module_url,
@@ -478,27 +766,37 @@ def upgrade_all_modules(force=False):
478
766
  module_dir=module_dir
479
767
  ):
480
768
  continue
769
+
481
770
  all_modules[update['name']]['info']['version'] = update['remote_version']
482
771
  mods.set_all_modules(all_modules)
483
- print(f"模块 {update['name']} 已更新至版本 {update['remote_version']}")
772
+ print(f"{Shell_Printer.GREEN}模块 {update['name']} 已更新至版本 {update['remote_version']}{Shell_Printer.RESET}")
773
+
774
+ shellprint.panel("所有可用更新已处理完成", "完成", "success")
484
775
 
485
776
  def list_modules(module_name=None):
486
777
  all_modules = mods.get_all_modules()
487
778
  if not all_modules:
488
- print_panel("未在数据库中发现注册模块,正在初始化模块列表...", "提示")
779
+ shellprint.panel("未在数据库中发现注册模块,正在初始化模块列表...", "提示", "info")
489
780
  from . import init as init_module
490
781
  init_module()
491
782
  all_modules = mods.get_all_modules()
783
+
492
784
  if not all_modules:
493
- print_panel("未找到任何模块", "错误")
785
+ shellprint.panel("未找到任何模块", "错误", "error")
494
786
  return
495
- print_panel(f"找到 {len(all_modules)} 个模块", "统计")
787
+
788
+ shellprint.panel(f"找到 {Shell_Printer.BOLD}{len(all_modules)}{Shell_Printer.RESET} 个模块", "统计", "info")
789
+
496
790
  rows = []
497
791
  for name, info in all_modules.items():
498
- status = "✓" if info.get("status", True) else "✗"
792
+ # 根据状态设置颜色
793
+ status_color = Shell_Printer.GREEN if info.get("status", True) else Shell_Printer.RED
794
+ status = f"{status_color}✓" if info.get("status", True) else f"{Shell_Printer.RED}✗"
795
+
499
796
  meta = info.get('info', {}).get('meta', {})
500
797
  depsinfo = info.get('info', {}).get('dependencies', {})
501
798
  optional_deps = depsinfo.get('optional', [])
799
+
502
800
  available_optional_deps = []
503
801
  missing_optional_deps = []
504
802
  if optional_deps:
@@ -513,183 +811,287 @@ def list_modules(module_name=None):
513
811
  available_optional_deps.append(dep)
514
812
  else:
515
813
  missing_optional_deps.append(dep)
814
+
516
815
  if missing_optional_deps:
517
- optional_dependencies = f"可用: {', '.join(available_optional_deps)} 缺失: {', '.join(missing_optional_deps)}"
816
+ optional_dependencies = f"可用: {', '.join(available_optional_deps)} 缺失: {Shell_Printer.RED}{', '.join(missing_optional_deps)}{Shell_Printer.RESET}"
518
817
  else:
519
818
  optional_dependencies = ', '.join(available_optional_deps) or '无'
520
819
  else:
521
820
  optional_dependencies = '无'
522
- dependencies = ', '.join(depsinfo.get('requires', [])) or '无'
523
- pip_dependencies = ', '.join(depsinfo.get('pip', [])) or '无'
821
+
822
+ # 依赖项使用不同颜色标识
823
+ dependencies = Shell_Printer.YELLOW + ', '.join(depsinfo.get('requires', [])) + Shell_Printer.RESET or '无'
824
+ pip_dependencies = Shell_Printer.CYAN + ', '.join(depsinfo.get('pip', [])) + Shell_Printer.RESET or '无'
825
+
524
826
  rows.append([
525
- name, status, meta.get('version', '未知'), meta.get('description', '无描述'),
526
- dependencies, optional_dependencies, pip_dependencies
827
+ Shell_Printer.BOLD + name + Shell_Printer.RESET,
828
+ status,
829
+ Shell_Printer.BLUE + meta.get('version', '未知') + Shell_Printer.RESET,
830
+ meta.get('description', '无描述'),
831
+ dependencies,
832
+ optional_dependencies,
833
+ pip_dependencies
527
834
  ])
528
- print_table(
835
+
836
+ shellprint.table(
529
837
  ["模块名称", "状态", "版本", "描述", "依赖", "可选依赖", "pip依赖"],
530
838
  rows,
531
- "模块列表"
839
+ "模块列表",
840
+ "info"
532
841
  )
842
+
533
843
  enabled_count = sum(1 for m in all_modules.values() if m.get("status", True))
534
844
  disabled_count = len(all_modules) - enabled_count
535
- print_panel(f"已启用: {enabled_count} 已禁用: {disabled_count}", "模块状态统计")
845
+ shellprint.panel(
846
+ f"{Shell_Printer.GREEN}已启用: {enabled_count}{Shell_Printer.RESET} "
847
+ f"{Shell_Printer.RED}已禁用: {disabled_count}{Shell_Printer.RESET}",
848
+ "模块状态统计",
849
+ "info"
850
+ )
536
851
 
537
852
  def main():
538
853
  parser = argparse.ArgumentParser(
539
- description="ErisPulse 命令行工具",
540
- prog="ep"
854
+
855
+ prog="epsdk",
856
+ formatter_class=argparse.RawTextHelpFormatter
541
857
  )
542
- subparsers = parser.add_subparsers(dest='command', help='可用命令')
543
- enable_parser = subparsers.add_parser('enable', help='启用指定模块')
544
- enable_parser.add_argument('module_names', nargs='+', help='要启用的模块名称(支持多个模块,用空格分隔)')
545
- enable_parser.add_argument('--init', action='store_true', help='在启用模块前初始化模块数据库')
546
- disable_parser = subparsers.add_parser('disable', help='禁用指定模块')
547
- disable_parser.add_argument('module_names', nargs='+', help='要禁用的模块名称(支持多个模块,用空格分隔)')
548
- disable_parser.add_argument('--init', action='store_true', help='在禁用模块前初始化模块数据库')
858
+ parser._positionals.title = f"{Shell_Printer.BOLD}{Shell_Printer.CYAN}基本命令{Shell_Printer.RESET}"
859
+ parser._optionals.title = f"{Shell_Printer.BOLD}{Shell_Printer.MAGENTA}可选参数{Shell_Printer.RESET}"
860
+
861
+ subparsers = parser.add_subparsers(
862
+ dest='command',
863
+ title='可用的命令',
864
+ metavar=f"{Shell_Printer.GREEN}<命令>{Shell_Printer.RESET}",
865
+ help='具体命令的帮助信息'
866
+ )
867
+
868
+ command_help = {
869
+ 'enable': '启用指定模块',
870
+ 'disable': '禁用指定模块',
871
+ 'list': '列出所有模块信息',
872
+ 'update': '更新模块列表',
873
+ 'upgrade': '升级所有可用模块',
874
+ 'uninstall': '删除指定模块',
875
+ 'install': '安装指定模块',
876
+ 'origin': '管理模块源',
877
+ 'run': '运行指定主程序'
878
+ }
879
+
880
+ # 模块管理
881
+ def add_module_command(name, help_text):
882
+ cmd = subparsers.add_parser(name, help=help_text, description=help_text)
883
+ cmd.add_argument('module_names', nargs='+', help='模块名称')
884
+ if name in ['enable', 'disable', 'install']:
885
+ cmd.add_argument('--init', action='store_true', help='在操作前初始化模块数据库')
886
+ if name in ['install']:
887
+ cmd.add_argument('--force', action='store_true', help='强制重新安装模块')
888
+ return cmd
889
+
890
+ enable_parser = add_module_command('enable', '启用指定模块')
891
+ disable_parser = add_module_command('disable', '禁用指定模块')
892
+ uninstall_parser = add_module_command('uninstall', '删除指定模块')
893
+ install_parser = add_module_command('install', '安装指定模块')
894
+
895
+ # 其他命令
549
896
  list_parser = subparsers.add_parser('list', help='列出所有模块信息')
550
897
  list_parser.add_argument('--module', '-m', type=str, help='指定要展示的模块名称')
898
+
551
899
  update_parser = subparsers.add_parser('update', help='更新模块列表')
900
+
552
901
  upgrade_parser = subparsers.add_parser('upgrade', help='升级模块列表')
553
902
  upgrade_parser.add_argument('--force', action='store_true', help='跳过二次确认,强制更新')
554
- uninstall_parser = subparsers.add_parser('uninstall', help='删除指定模块')
555
- uninstall_parser.add_argument('module_names', nargs='+', help='要卸载的模块名称(支持多个模块,用空格分隔)')
556
- install_parser = subparsers.add_parser('install', help='安装指定模块(支持多个模块,用空格分隔)')
557
- install_parser.add_argument('module_name', nargs='+', help='要安装的模块名称(支持多个模块,用空格分隔)')
558
- install_parser.add_argument('--force', action='store_true', help='强制重新安装模块')
559
- install_parser.add_argument('--init', action='store_true', help='在安装模块前初始化模块数据库')
903
+
560
904
  origin_parser = subparsers.add_parser('origin', help='管理模块源')
561
- origin_subparsers = origin_parser.add_subparsers(dest='origin_command', help='源管理命令')
905
+ origin_subparsers = origin_parser.add_subparsers(
906
+ dest='origin_command',
907
+ title='源管理命令',
908
+ metavar=f"{Shell_Printer.CYAN}<子命令>{Shell_Printer.RESET}"
909
+ )
910
+
562
911
  add_origin_parser = origin_subparsers.add_parser('add', help='添加模块源')
563
912
  add_origin_parser.add_argument('url', type=str, help='要添加的模块源URL')
913
+
564
914
  list_origin_parser = origin_subparsers.add_parser('list', help='列出所有模块源')
915
+
565
916
  del_origin_parser = origin_subparsers.add_parser('del', help='删除模块源')
566
917
  del_origin_parser.add_argument('url', type=str, help='要删除的模块源URL')
918
+
919
+ run_parser = subparsers.add_parser('run', help='运行指定主程序')
920
+ run_parser.add_argument('script', type=str, help='要运行的主程序路径')
921
+ run_parser.add_argument('--reload', action='store_true', help='启用热重载模式,自动检测代码变动并重启')
922
+
567
923
  args = parser.parse_args()
568
- source_manager = SourceManager()
924
+
569
925
  if hasattr(args, 'init') and args.init:
570
- print("正在初始化模块列表...")
926
+ print(f"{Shell_Printer.GREEN}正在初始化模块列表...{Shell_Printer.RESET}")
571
927
  from . import init as init_module
572
928
  init_module()
929
+ print(f"{Shell_Printer.GREEN}模块列表初始化完成{Shell_Printer.RESET}")
930
+
931
+ # 处理命令
573
932
  if args.command == 'enable':
574
933
  for module_name in args.module_names:
575
934
  module_name = module_name.strip()
576
935
  if not module_name:
577
936
  continue
937
+
578
938
  if '*' in module_name or '?' in module_name:
579
- print(f"正在匹配模块模式: {module_name}...")
939
+ shellprint.status(f"匹配模块模式: {module_name}")
580
940
  all_modules = mods.get_all_modules()
581
941
  if not all_modules:
582
- print_panel("未找到任何模块,请先更新源或检查配置", "错误")
942
+ shellprint.panel("未找到任何模块,请先更新源或检查配置", "错误", "error")
583
943
  continue
944
+
584
945
  matched_modules = [name for name in all_modules.keys() if fnmatch.fnmatch(name, module_name)]
585
946
  if not matched_modules:
586
- print_panel(f"未找到匹配模块模式 {module_name} 的模块", "错误")
947
+ shellprint.panel(f"未找到匹配模块模式 {module_name} 的模块", "错误", "error")
587
948
  continue
588
- print(f"找到 {len(matched_modules)} 个匹配模块:")
949
+
950
+ print(f"{Shell_Printer.GREEN}找到 {len(matched_modules)} 个匹配模块:{Shell_Printer.RESET}")
589
951
  for i, matched_module in enumerate(matched_modules, start=1):
590
- print(f" {i}. {matched_module}")
591
- if not confirm("是否启用所有匹配模块?", default=True):
592
- print("操作已取消")
952
+ print(f" {Shell_Printer.CYAN}{i}. {matched_module}{Shell_Printer.RESET}")
953
+
954
+ if not shellprint.confirm("是否启用所有匹配模块?", default=True):
955
+ print(f"{Shell_Printer.BLUE}操作已取消{Shell_Printer.RESET}")
593
956
  continue
957
+
594
958
  for matched_module in matched_modules:
595
959
  enable_module(matched_module)
596
960
  else:
597
961
  enable_module(module_name)
962
+
598
963
  elif args.command == 'disable':
599
964
  for module_name in args.module_names:
600
965
  module_name = module_name.strip()
601
966
  if not module_name:
602
967
  continue
968
+
603
969
  if '*' in module_name or '?' in module_name:
604
- print(f"正在匹配模块模式: {module_name}...")
970
+ shellprint.status(f"匹配模块模式: {module_name}")
605
971
  all_modules = mods.get_all_modules()
606
972
  if not all_modules:
607
- print_panel("未找到任何模块,请先更新源或检查配置", "错误")
973
+ shellprint.panel("未找到任何模块,请先更新源或检查配置", "错误", "error")
608
974
  continue
975
+
609
976
  matched_modules = [name for name in all_modules.keys() if fnmatch.fnmatch(name, module_name)]
610
977
  if not matched_modules:
611
- print_panel(f"未找到匹配模块模式 {module_name} 的模块", "错误")
978
+ shellprint.panel(f"未找到匹配模块模式 {module_name} 的模块", "错误", "error")
612
979
  continue
613
- print(f"找到 {len(matched_modules)} 个匹配模块:")
980
+
981
+ print(f"{Shell_Printer.GREEN}找到 {len(matched_modules)} 个匹配模块:{Shell_Printer.RESET}")
614
982
  for i, matched_module in enumerate(matched_modules, start=1):
615
- print(f" {i}. {matched_module}")
616
- if not confirm("是否禁用所有匹配模块?", default=True):
617
- print("操作已取消")
983
+ print(f" {Shell_Printer.CYAN}{i}. {matched_module}{Shell_Printer.RESET}")
984
+
985
+ if not shellprint.confirm("是否禁用所有匹配模块?", default=True):
986
+ print(f"{Shell_Printer.BLUE}操作已取消{Shell_Printer.RESET}")
618
987
  continue
988
+
619
989
  for matched_module in matched_modules:
620
990
  disable_module(matched_module)
621
991
  else:
622
992
  disable_module(module_name)
993
+
623
994
  elif args.command == 'list':
624
995
  list_modules(args.module)
996
+
625
997
  elif args.command == 'uninstall':
626
998
  for module_name in args.module_names:
627
999
  module_name = module_name.strip()
628
1000
  if not module_name:
629
1001
  continue
1002
+
630
1003
  if '*' in module_name or '?' in module_name:
631
- print(f"正在匹配模块模式: {module_name}...")
1004
+ shellprint.status(f"匹配模块模式: {module_name}")
632
1005
  all_modules = mods.get_all_modules()
633
1006
  if not all_modules:
634
- print_panel("未找到任何模块,请先更新源或检查配置", "错误")
1007
+ shellprint.panel("未找到任何模块,请先更新源或检查配置", "错误", "error")
635
1008
  continue
1009
+
636
1010
  matched_modules = [name for name in all_modules.keys() if fnmatch.fnmatch(name, module_name)]
637
1011
  if not matched_modules:
638
- print_panel(f"未找到匹配模块模式 {module_name} 的模块", "错误")
1012
+ shellprint.panel(f"未找到匹配模块模式 {module_name} 的模块", "错误", "error")
639
1013
  continue
640
- print(f"找到 {len(matched_modules)} 个匹配模块:")
1014
+
1015
+ print(f"{Shell_Printer.GREEN}找到 {len(matched_modules)} 个匹配模块:{Shell_Printer.RESET}")
641
1016
  for i, matched_module in enumerate(matched_modules, start=1):
642
- print(f" {i}. {matched_module}")
643
- if not confirm("是否卸载所有匹配模块?", default=True):
644
- print("操作已取消")
1017
+ print(f" {Shell_Printer.CYAN}{i}. {matched_module}{Shell_Printer.RESET}")
1018
+
1019
+ if not shellprint.confirm("是否卸载所有匹配模块?", default=True):
1020
+ print(f"{Shell_Printer.BLUE}操作已取消{Shell_Printer.RESET}")
645
1021
  continue
1022
+
646
1023
  for matched_module in matched_modules:
647
1024
  uninstall_module(matched_module)
648
1025
  else:
649
1026
  uninstall_module(module_name)
1027
+
650
1028
  elif args.command == 'install':
651
- for module_name in args.module_name:
1029
+ for module_name in args.module_names:
652
1030
  module_name = module_name.strip()
653
1031
  if not module_name:
654
1032
  continue
1033
+
655
1034
  if '*' in module_name or '?' in module_name:
656
- print(f"正在匹配模块模式: {module_name}...")
1035
+ shellprint.status(f"匹配模块模式: {module_name}")
657
1036
  all_modules = mods.get_all_modules()
658
1037
  if not all_modules:
659
- print_panel("未找到任何模块,请先更新源或检查配置", "错误")
1038
+ shellprint.panel("未找到任何模块,请先更新源或检查配置", "错误", "error")
660
1039
  continue
1040
+
661
1041
  matched_modules = [name for name in all_modules.keys() if fnmatch.fnmatch(name, module_name)]
662
1042
  if not matched_modules:
663
- print_panel(f"未找到匹配模块模式 {module_name} 的模块", "错误")
1043
+ shellprint.panel(f"未找到匹配模块模式 {module_name} 的模块", "错误", "error")
664
1044
  continue
665
- print(f"找到 {len(matched_modules)} 个匹配模块:")
1045
+
1046
+ print(f"{Shell_Printer.GREEN}找到 {len(matched_modules)} 个匹配模块:{Shell_Printer.RESET}")
666
1047
  for i, matched_module in enumerate(matched_modules, start=1):
667
- print(f" {i}. {matched_module}")
668
- if not confirm("是否安装所有匹配模块?", default=True):
669
- print("安装已取消")
1048
+ print(f" {Shell_Printer.CYAN}{i}. {matched_module}{Shell_Printer.RESET}")
1049
+
1050
+ if not shellprint.confirm("是否安装所有匹配模块?", default=True):
1051
+ print(f"{Shell_Printer.BLUE}安装已取消{Shell_Printer.RESET}")
670
1052
  continue
1053
+
671
1054
  for matched_module in matched_modules:
672
1055
  install_module(matched_module, args.force)
673
1056
  else:
674
1057
  install_module(module_name, args.force)
1058
+
675
1059
  elif args.command == 'update':
676
- SourceManager().update_sources()
1060
+ source_manager.update_sources()
1061
+
677
1062
  elif args.command == 'upgrade':
678
1063
  upgrade_all_modules(args.force)
1064
+
1065
+ elif args.command == 'run':
1066
+ script_path = args.script
1067
+ if not os.path.exists(script_path):
1068
+ shellprint.panel(f"找不到指定文件: {script_path}", "错误", "error")
1069
+ return
1070
+
1071
+ if args.reload:
1072
+ start_reloader(script_path)
1073
+ else:
1074
+ shellprint.panel(f"运行脚本: {Shell_Printer.BOLD}{script_path}{Shell_Printer.RESET}", "执行", "info")
1075
+ import runpy
1076
+ runpy.run_path(script_path, run_name="__main__")
1077
+
679
1078
  elif args.command == 'origin':
680
1079
  if args.origin_command == 'add':
681
1080
  success = source_manager.add_source(args.url)
682
- if success:
683
- if confirm("源已添加,是否立即更新源以获取最新模块信息?", default=True):
684
- source_manager.update_sources()
1081
+ if success and shellprint.confirm("源已添加,是否立即更新源以获取最新模块信息?", default=True):
1082
+ source_manager.update_sources()
1083
+
685
1084
  elif args.origin_command == 'list':
686
1085
  source_manager.list_sources()
1086
+
687
1087
  elif args.origin_command == 'del':
688
1088
  source_manager.del_source(args.url)
1089
+
689
1090
  else:
690
1091
  origin_parser.print_help()
691
1092
  else:
1093
+ # 如果没有提供命令,显示帮助信息
692
1094
  parser.print_help()
693
1095
 
694
1096
  if __name__ == "__main__":
695
- main()
1097
+ main()