ErisPulse-HelpModule 2.0.0__tar.gz → 2.1.0__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.
@@ -2,13 +2,15 @@ from ErisPulse import sdk
2
2
  from ErisPulse.Core.Event import command
3
3
  from ErisPulse.Core import config
4
4
  from ErisPulse.Core.Bases import BaseModule
5
- from typing import Dict, List
5
+ from typing import Dict, List, Optional
6
+ from .templates import HelpTemplates
6
7
 
7
8
  class HelpModule(BaseModule):
8
9
  def __init__(self):
9
10
  self.sdk = sdk
10
11
  self.logger = sdk.logger.get_child("HelpModule")
11
12
  self.command_list = []
13
+ self.command_map = {}
12
14
 
13
15
  @staticmethod
14
16
  def should_eager_load():
@@ -100,114 +102,103 @@ class HelpModule(BaseModule):
100
102
  if event.get("detail_type") == "group":
101
103
  target_type = "group"
102
104
  target_id = event["group_id"]
103
- else:
105
+ elif event.get("detail_type") == "private" or event.get("detail_type") == "user":
104
106
  target_type = "user"
105
107
  target_id = event["user_id"]
108
+ else:
109
+ target_type = event.get("detail_type")
110
+ target_id = event.get("target_id")
106
111
 
107
112
  args = event.get("command", {}).get("args", [])
108
113
  adapter = getattr(sdk.adapter, platform)
109
114
 
110
115
  commands = self._build_command_list()
116
+ module_config = self._get_config()
111
117
 
112
118
  if args:
119
+ # 显示命令详情
113
120
  try:
114
- index = int(args[0]) - 1
115
- if 0 <= index < len(commands):
116
- help_text = self._format_command_detail(commands[index])
121
+ index = int(args[0])
122
+ if index in self.command_map:
123
+ # 使用模板构建命令详情
124
+ templates = HelpTemplates.build_command_detail(
125
+ self.command_map[index],
126
+ self._get_command_prefix()
127
+ )
128
+ help_content = self._select_best_format(platform, templates)
117
129
  else:
118
- help_text = f"错误: 序号超出范围,请输入 1-{len(commands)} 之间的序号"
130
+ # 使用错误模板
131
+ templates = HelpTemplates.build_error(
132
+ "序号超出范围",
133
+ f"请输入 1-{len(commands)} 之间的序号"
134
+ )
135
+ help_content = self._select_best_format(platform, templates)
119
136
  except ValueError:
120
- help_text = "错误: 请输入有效的序号"
137
+ templates = HelpTemplates.build_error(
138
+ "参数错误",
139
+ "请输入有效的序号"
140
+ )
141
+ help_content = self._select_best_format(platform, templates)
121
142
  else:
122
- help_text = self._format_command_list(commands)
143
+ # 显示命令列表
144
+ templates = HelpTemplates.build_help_list(
145
+ commands,
146
+ self.command_map,
147
+ self._get_command_prefix(),
148
+ module_config.get("group_commands", True)
149
+ )
150
+ help_content = self._select_best_format(platform, templates)
123
151
 
124
- await adapter.Send.To(target_type, target_id).Text(help_text)
152
+ # 发送消息
153
+ await self._send_with_format(adapter, target_type, target_id, help_content)
125
154
  except Exception as e:
126
- self.logger.error(f"处理帮助命令时出错: {e}")
127
-
128
- def _format_command_list(self, commands: List[Dict]) -> str:
129
- prefix = self._get_command_prefix()
130
- module_config = self._get_config()
131
-
132
- lines = [
133
- "命令帮助",
134
- "-" * 10,
135
- f"使用 '{prefix}help <序号>' 查看命令详情",
136
- ""
137
- ]
138
-
139
- if module_config.get("group_commands", True):
140
- grouped = self._group_commands_by_category(commands)
155
+ self.logger.error(f"处理帮助命令时出错: {e}", exc_info=True)
156
+
157
+ def _select_best_format(self, platform: str, templates: Dict[str, str]) -> tuple:
158
+ """
159
+ 根据平台支持的发送方法选择最佳格式
160
+ 优先使用 list_sends,不支持时使用 hasattr 兜底
161
+
162
+ 返回: (format_name, content)
163
+ """
164
+ # 首先尝试使用 list_sends(推荐方式)
165
+ try:
166
+ supported_methods = sdk.adapter.list_sends(platform)
141
167
 
142
- # 默认组
143
- if "default" in grouped:
144
- lines.append("[通用命令]")
145
- for idx, cmd in enumerate(grouped["default"], 1):
146
- name = cmd["name"]
147
- help_text = cmd["info"].get("help", "暂无描述")
148
- lines.append(f"{idx}. {prefix}{name} - {help_text}")
149
- lines.append("")
168
+ # 优先级: Html > Markdown > Text
169
+ if "Html" in supported_methods:
170
+ return ("Html", templates["html"])
171
+ elif "Markdown" in supported_methods:
172
+ return ("Markdown", templates["markdown"])
173
+ else:
174
+ return ("Text", templates["text"])
175
+ except Exception as e:
176
+ self.logger.warning(f"list_sends 检测失败: {e},尝试使用 hasattr 兜底")
150
177
 
151
- # 其他组
152
- for group, cmds in grouped.items():
153
- if group == "default":
154
- continue
155
- group_name = str(group) if group else "其他"
156
- lines.append(f"[{group_name}命令]")
157
- for idx, cmd in enumerate(cmds, 1):
158
- name = cmd["name"]
159
- help_text = cmd["info"].get("help", "暂无描述")
160
- lines.append(f"{idx}. {prefix}{name} - {help_text}")
161
- lines.append("")
162
- else:
163
- lines.append("[所有命令]")
164
- for idx, cmd in enumerate(commands, 1):
165
- name = cmd["name"]
166
- help_text = cmd["info"].get("help", "暂无描述")
167
- lines.append(f"{idx}. {prefix}{name} - {help_text}")
168
- lines.append("")
169
-
170
- lines.append("-" * 10)
171
- lines.append(f"共 {len(commands)} 个可用命令")
172
-
173
- return "\n".join(lines)
178
+ # 使用 hasattr 作为兜底方案
179
+ adapter = getattr(sdk.adapter, platform)
180
+ send_obj = adapter.Send if hasattr(adapter, "Send") else None
181
+
182
+ if send_obj is None:
183
+ self.logger.warning(f"平台 {platform} 不支持 Send 接口,使用纯文本格式")
184
+ return ("Text", templates["text"])
185
+
186
+ # 检查支持的方法
187
+ if hasattr(send_obj, "Html"):
188
+ return ("Html", templates["html"])
189
+ elif hasattr(send_obj, "Markdown"):
190
+ return ("Markdown", templates["markdown"])
191
+ else:
192
+ return ("Text", templates["text"])
174
193
 
175
- def _format_command_detail(self, cmd: Dict) -> str:
176
- prefix = self._get_command_prefix()
177
- name = cmd["name"]
178
- info = cmd["info"]
179
-
180
- lines = [
181
- f"命令详情: {prefix}{name}",
182
- "-" * 10,
183
- f"描述: {info.get('help', '暂无描述')}"
184
- ]
185
-
186
- # 别名
187
- aliases = []
188
- for alias, main_name in command.aliases.items():
189
- if main_name == info['main_name'] and alias != info['main_name']:
190
- aliases.append(alias)
191
-
192
- if aliases:
193
- lines.append(f"别名: {', '.join(f'{prefix}{a}' for a in aliases)}")
194
-
195
- # 用法
196
- if info.get("usage"):
197
- lines.append(f"用法: {info['usage'].replace('/', prefix)}")
198
-
199
- # 权限
200
- if info.get("permission"):
201
- lines.append("权限: 需要特殊权限")
202
-
203
- # 隐藏状态
204
- if info.get("hidden"):
205
- lines.append("状态: 隐藏命令")
206
-
207
- # 分组
208
- if info.get("group"):
209
- lines.append(f"分组: {info['group']}")
210
-
211
- lines.append("-" * 10)
212
-
213
- return "\n".join(lines)
194
+ async def _send_with_format(self, adapter, target_type: str, target_id: str,
195
+ format_content: tuple) -> None:
196
+ format_name, content = format_content
197
+
198
+ # 根据格式调用对应的发送方法
199
+ if format_name == "Html":
200
+ await adapter.Send.To(target_type, target_id).Html(content)
201
+ elif format_name == "Markdown":
202
+ await adapter.Send.To(target_type, target_id).Markdown(content)
203
+ else: # Text
204
+ await adapter.Send.To(target_type, target_id).Text(content)
@@ -0,0 +1,460 @@
1
+ """
2
+ 帮助模块模板系统
3
+ 提供多平台支持的消息模板
4
+ """
5
+ from typing import Dict, List, Optional
6
+ from ErisPulse.Core.Event import command
7
+
8
+
9
+ class HelpTemplates:
10
+ """帮助模块模板类"""
11
+
12
+ # 配色方案
13
+ PRIMARY_COLOR = "#1565c0" # 蓝色 - 主标题
14
+ SUCCESS_COLOR = "#2e7d32" # 绿色 - 成功信息
15
+ WARNING_COLOR = "#e65100" # 橙色 - 警告信息
16
+ ERROR_COLOR = "#b71c1c" # 红色 - 错误信息
17
+
18
+ # 半透明背景色
19
+ PRIMARY_BG = "rgba(21, 101, 192, 0.05)"
20
+ SUCCESS_BG = "rgba(76, 175, 80, 0.1)"
21
+ WARNING_BG = "rgba(255, 167, 38, 0.15)"
22
+ ERROR_BG = "rgba(183, 28, 28, 0.1)"
23
+
24
+ @classmethod
25
+ def _get_group_name(cls, group: str) -> str:
26
+ if group == "default":
27
+ return "通用命令"
28
+ return f"{group}命令" if group else "其他"
29
+
30
+ # ==================== 帮助列表模板 ====================
31
+
32
+ @classmethod
33
+ def build_help_list(cls, commands: List[Dict], command_map: Dict[int, Dict],
34
+ prefix: str, group_commands: bool = True) -> Dict[str, str]:
35
+ # 构建 HTML
36
+ html = cls._build_help_list_html(commands, command_map, prefix, group_commands)
37
+
38
+ # 构建 Markdown
39
+ markdown = cls._build_help_list_markdown(commands, command_map, prefix, group_commands)
40
+
41
+ # 构建 Text
42
+ text = cls._build_help_list_text(commands, command_map, prefix, group_commands)
43
+
44
+ return {"html": html, "markdown": markdown, "text": text}
45
+
46
+ @classmethod
47
+ def _build_help_list_html(cls, commands: List[Dict], command_map: Dict[int, Dict],
48
+ prefix: str, group_commands: bool) -> str:
49
+ # 重置命令映射
50
+ grouped = {}
51
+ if group_commands:
52
+ for cmd in commands:
53
+ group = cmd["info"].get("group") or "default"
54
+ if group not in grouped:
55
+ grouped[group] = []
56
+ grouped[group].append(cmd)
57
+ else:
58
+ grouped["default"] = commands
59
+
60
+ # 构建命令列表 HTML(带展开/折叠功能)
61
+ commands_html = ""
62
+ global_idx = 1
63
+
64
+ for group, cmds in grouped.items():
65
+ group_name = cls._get_group_name(group)
66
+
67
+ commands_html += f"""
68
+ <div style="font-size:13px; margin-bottom: 8px; font-weight: bold; color: {cls.PRIMARY_COLOR};">{group_name}</div>
69
+ """
70
+
71
+ for cmd in cmds:
72
+ name = cmd["name"]
73
+ info = cmd["info"]
74
+ help_text = info.get("help", "暂无描述")
75
+ command_map[global_idx] = cmd
76
+
77
+ # 构建命令详情内容
78
+ detail_content = cls._build_command_detail_inline(name, info, prefix)
79
+
80
+ commands_html += f"""<details style="margin-bottom: 8px;">
81
+ <summary style="cursor: pointer; font-size: 13px; padding: 4px; background: rgba(0, 0, 0, 0.02); border-radius: 4px; display: flex; align-items: center;">
82
+ <span style="font-weight: bold; margin-right: 8px;">{global_idx}.</span>
83
+ <code style="background: rgba(0, 0, 0, 0.05); padding: 2px 6px; border-radius: 3px; margin-right: 8px;">{prefix}{name}</code>
84
+ <span style="color: #666;">- {help_text}</span>
85
+ </summary>
86
+ <div style="padding: 8px; margin-top: 6px; border-left: 3px solid {cls.PRIMARY_BG}; background: rgba(0, 0, 0, 0.01); border-radius: 4px;">
87
+ {detail_content}
88
+ </div>
89
+ </details>"""
90
+ global_idx +=1
91
+
92
+ commands_html += "\n"
93
+
94
+ # 构建完整 HTML
95
+ html = f"""<div style="padding: 12px; border-radius: 8px;">
96
+ <div style="color: {cls.PRIMARY_COLOR}; font-size: 16px; font-weight: bold; margin-bottom: 12px;">
97
+ 命令帮助
98
+ </div>
99
+
100
+ <div style="padding: 8px; background: {cls.PRIMARY_BG}; border-radius: 6px; margin-bottom: 12px;">
101
+ <div style="font-size: 13px;">
102
+ 使用 '{prefix}help <序号>' 查看命令详情
103
+ </div>
104
+ </div>
105
+
106
+ {commands_html}
107
+
108
+ <div style="font-size: 12px; color: #666; margin-top: 8px;">
109
+ 共 {len(commands)} 个可用命令
110
+ </div>
111
+ </div>"""
112
+
113
+ return html
114
+
115
+ @classmethod
116
+ def _build_help_list_markdown(cls, commands: List[Dict], command_map: Dict[int, Dict],
117
+ prefix: str, group_commands: bool) -> str:
118
+ lines = [
119
+ "**命令帮助**",
120
+ "",
121
+ f"使用 `{prefix}help <序号>` 查看命令详情",
122
+ ""
123
+ ]
124
+
125
+ global_idx = 1
126
+
127
+ if group_commands:
128
+ grouped = {}
129
+ for cmd in commands:
130
+ group = cmd["info"].get("group") or "default"
131
+ if group not in grouped:
132
+ grouped[group] = []
133
+ grouped[group].append(cmd)
134
+
135
+ for group, cmds in grouped.items():
136
+ group_name = cls._get_group_name(group)
137
+ lines.append(f"**{group_name}**")
138
+ lines.append("")
139
+
140
+ for cmd in cmds:
141
+ name = cmd["name"]
142
+ help_text = cmd["info"].get("help", "暂无描述")
143
+ command_map[global_idx] = cmd
144
+ lines.append(f"{global_idx}. `{prefix}{name}` - {help_text}")
145
+ global_idx += 1
146
+
147
+ lines.append("")
148
+ else:
149
+ lines.append("**所有命令**")
150
+ lines.append("")
151
+ for cmd in commands:
152
+ name = cmd["name"]
153
+ help_text = cmd["info"].get("help", "暂无描述")
154
+ command_map[global_idx] = cmd
155
+ lines.append(f"{global_idx}. `{prefix}{name}` - {help_text}")
156
+ global_idx += 1
157
+ lines.append("")
158
+
159
+ lines.append("---")
160
+ lines.append(f"共 {len(commands)} 个可用命令")
161
+
162
+ return "\n".join(lines)
163
+
164
+ @classmethod
165
+ def _build_help_list_text(cls, commands: List[Dict], command_map: Dict[int, Dict],
166
+ prefix: str, group_commands: bool) -> str:
167
+ lines = [
168
+ "命令帮助",
169
+ "----------",
170
+ f"使用 '{prefix}help <序号>' 查看命令详情",
171
+ ""
172
+ ]
173
+
174
+ global_idx = 1
175
+
176
+ if group_commands:
177
+ grouped = {}
178
+ for cmd in commands:
179
+ group = cmd["info"].get("group") or "default"
180
+ if group not in grouped:
181
+ grouped[group] = []
182
+ grouped[group].append(cmd)
183
+
184
+ for group, cmds in grouped.items():
185
+ group_name = cls._get_group_name(group)
186
+ lines.append(f"[{group_name}]")
187
+ lines.append("")
188
+
189
+ for cmd in cmds:
190
+ name = cmd["name"]
191
+ help_text = cmd["info"].get("help", "暂无描述")
192
+ command_map[global_idx] = cmd
193
+ lines.append(f"{global_idx}. {prefix}{name} - {help_text}")
194
+ global_idx += 1
195
+
196
+ lines.append("")
197
+ else:
198
+ lines.append("[所有命令]")
199
+ lines.append("")
200
+ for cmd in commands:
201
+ name = cmd["name"]
202
+ help_text = cmd["info"].get("help", "暂无描述")
203
+ command_map[global_idx] = cmd
204
+ lines.append(f"{global_idx}. {prefix}{name} - {help_text}")
205
+ global_idx += 1
206
+ lines.append("")
207
+
208
+ lines.append("----------")
209
+ lines.append(f"共 {len(commands)} 个可用命令")
210
+
211
+ return "\n".join(lines)
212
+
213
+ @classmethod
214
+ def _build_command_detail_inline(cls, name: str, info: Dict, prefix: str) -> str:
215
+ """
216
+ 构建内联命令详情(用于展开区域)
217
+ """
218
+ parts = []
219
+
220
+ # 描述
221
+ parts.append(f"""<div style="margin-bottom: 8px;">
222
+ <strong style="font-size: 12px; color: {cls.PRIMARY_COLOR};">描述:</strong>
223
+ <span style="font-size: 12px; margin-left: 8px;">{info.get('help', '暂无描述')}</span>
224
+ </div>""")
225
+
226
+ # 别名 - 从全局 command.aliases 获取
227
+ main_name = info.get('main_name', name)
228
+ aliases = []
229
+ for alias, mapped_name in command.aliases.items():
230
+ if mapped_name == main_name and alias != main_name:
231
+ aliases.append(alias)
232
+
233
+ if aliases:
234
+ aliases_text = ", ".join(f"<code style='font-size: 11px;'>{prefix}{a}</code>" for a in aliases)
235
+ parts.append(f"""<div style="margin-bottom: 8px;">
236
+ <strong style="font-size: 12px; color: {cls.PRIMARY_COLOR};">别名:</strong>
237
+ <span style="font-size: 12px; margin-left: 8px;">{aliases_text}</span>
238
+ </div>""")
239
+
240
+ # 用法
241
+ if info.get("usage"):
242
+ parts.append(f"""<div style="margin-bottom: 8px;">
243
+ <strong style="font-size: 12px; color: {cls.PRIMARY_COLOR};">用法:</strong>
244
+ <span style="font-size: 12px; margin-left: 8px; font-family: monospace; background: rgba(0, 0, 0, 0.03); padding: 2px 6px; border-radius: 3px;">{info['usage'].replace('/', prefix)}</span>
245
+ </div>""")
246
+
247
+ # 权限
248
+ if info.get("permission"):
249
+ parts.append(f"""<div style="margin-bottom: 8px;">
250
+ <strong style="font-size: 12px; color: {cls.PRIMARY_COLOR};">权限:</strong>
251
+ <span style="font-size: 12px; margin-left: 8px; color: {cls.WARNING_COLOR};">需要特殊权限</span>
252
+ </div>""")
253
+
254
+ # 分组
255
+ if info.get("group"):
256
+ group_name = cls._get_group_name(info["group"])
257
+ parts.append(f"""<div style="margin-bottom: 8px;">
258
+ <strong style="font-size: 12px; color: {cls.PRIMARY_COLOR};">分组:</strong>
259
+ <span style="font-size: 12px; margin-left: 8px;">{group_name}</span>
260
+ </div>""")
261
+
262
+ return "\n".join(parts)
263
+
264
+ # ==================== 命令详情模板 ====================
265
+
266
+ @classmethod
267
+ def build_command_detail(cls, cmd: Dict, prefix: str) -> Dict[str, str]:
268
+ # 构建 HTML
269
+ html = cls._build_command_detail_html(cmd, prefix)
270
+
271
+ # 构建 Markdown
272
+ markdown = cls._build_command_detail_markdown(cmd, prefix)
273
+
274
+ # 构建 Text
275
+ text = cls._build_command_detail_text(cmd, prefix)
276
+
277
+ return {"html": html, "markdown": markdown, "text": text}
278
+
279
+ @classmethod
280
+ def _build_command_detail_html(cls, cmd: Dict, prefix: str) -> str:
281
+ name = cmd["name"]
282
+ info = cmd["info"]
283
+
284
+ html_parts = [
285
+ f"""<div style="padding: 12px; border-radius: 8px;">
286
+ <div style="color: {cls.PRIMARY_COLOR}; font-size: 16px; font-weight: bold; margin-bottom: 12px;">
287
+ 命令详情: {prefix}{name}
288
+ </div>"""
289
+ ]
290
+
291
+ # 描述
292
+ html_parts.append(f"""
293
+ <div style="margin-bottom: 12px; border: 1px solid #e0e0e0; padding: 12px; border-radius: 6px;">
294
+ <div style="margin-bottom: 8px;">
295
+ <strong style="font-size: 14px;">描述:</strong>
296
+ </div>
297
+ <div style="font-size: 13px;">
298
+ {info.get('help', '暂无描述')}
299
+ </div>
300
+ </div>""")
301
+
302
+ # 别名 - 从全局 command.aliases 获取
303
+ main_name = info.get('main_name', name)
304
+ aliases = []
305
+ for alias, mapped_name in command.aliases.items():
306
+ if mapped_name == main_name and alias != main_name:
307
+ aliases.append(alias)
308
+
309
+ if aliases:
310
+ aliases_text = ", ".join(f"{prefix}{a}" for a in aliases)
311
+ html_parts.append(f"""
312
+ <div style="margin-bottom: 8px;">
313
+ <div style="font-size: 13px; margin-bottom: 4px;">
314
+ <strong>别名:</strong>
315
+ </div>
316
+ <div style="font-size: 13px;">
317
+ {aliases_text}
318
+ </div>
319
+ </div>""")
320
+
321
+ # 用法
322
+ if info.get("usage"):
323
+ html_parts.append(f"""
324
+ <div style="margin-bottom: 8px;">
325
+ <div style="font-size: 13px; margin-bottom: 4px;">
326
+ <strong>用法:</strong>
327
+ </div>
328
+ <div style="font-size: 13px; font-family: monospace; background: rgba(0, 0, 0, 0.03); padding: 6px; border-radius: 4px;">
329
+ {info['usage'].replace('/', prefix)}
330
+ </div>
331
+ </div>""")
332
+
333
+ # 权限
334
+ if info.get("permission"):
335
+ html_parts.append(f"""
336
+ <div style="margin-bottom: 8px;">
337
+ <div style="font-size: 13px; margin-bottom: 4px;">
338
+ <strong>权限:</strong>
339
+ </div>
340
+ <div style="font-size: 13px; color: {cls.WARNING_COLOR};">
341
+ 需要特殊权限
342
+ </div>
343
+ </div>""")
344
+
345
+ # 分组
346
+ if info.get("group"):
347
+ group_name = cls._get_group_name(info["group"])
348
+ html_parts.append(f"""
349
+ <div style="margin-bottom: 8px;">
350
+ <div style="font-size: 13px; margin-bottom: 4px;">
351
+ <strong>分组:</strong>
352
+ </div>
353
+ <div style="font-size: 13px;">
354
+ {group_name}
355
+ </div>
356
+ </div>""")
357
+
358
+ html_parts.append("</div>")
359
+
360
+ return "\n".join(html_parts)
361
+
362
+ @classmethod
363
+ def _build_command_detail_markdown(cls, cmd: Dict, prefix: str) -> str:
364
+ name = cmd["name"]
365
+ info = cmd["info"]
366
+
367
+ lines = [
368
+ f"**命令详情:** `{prefix}{name}`",
369
+ "",
370
+ f"**描述:** {info.get('help', '暂无描述')}",
371
+ ""
372
+ ]
373
+
374
+ # 别名 - 从全局 command.aliases 获取
375
+ main_name = info.get('main_name', name)
376
+ aliases = []
377
+ for alias, mapped_name in command.aliases.items():
378
+ if mapped_name == main_name and alias != main_name:
379
+ aliases.append(alias)
380
+
381
+ if aliases:
382
+ aliases_text = ", ".join(f"`{prefix}{a}`" for a in aliases)
383
+ lines.append(f"**别名:** {aliases_text}")
384
+ lines.append("")
385
+
386
+ # 用法
387
+ if info.get("usage"):
388
+ lines.append(f"**用法:** `{info['usage'].replace('/', prefix)}`")
389
+ lines.append("")
390
+
391
+ # 权限
392
+ if info.get("permission"):
393
+ lines.append("**权限:** 需要特殊权限")
394
+ lines.append("")
395
+
396
+ # 分组
397
+ if info.get("group"):
398
+ group_name = cls._get_group_name(info["group"])
399
+ lines.append(f"**分组:** {group_name}")
400
+ lines.append("")
401
+
402
+ return "\n".join(lines)
403
+
404
+ @classmethod
405
+ def _build_command_detail_text(cls, cmd: Dict, prefix: str) -> str:
406
+ name = cmd["name"]
407
+ info = cmd["info"]
408
+
409
+ lines = [
410
+ f"命令详情: {prefix}{name}",
411
+ "----------",
412
+ f"描述: {info.get('help', '暂无描述')}",
413
+ ""
414
+ ]
415
+
416
+ # 别名 - 从全局 command.aliases 获取
417
+ main_name = info.get('main_name', name)
418
+ aliases = []
419
+ for alias, mapped_name in command.aliases.items():
420
+ if mapped_name == main_name and alias != main_name:
421
+ aliases.append(alias)
422
+
423
+ if aliases:
424
+ aliases_text = ", ".join(f"{prefix}{a}" for a in aliases)
425
+ lines.append(f"别名: {aliases_text}")
426
+ lines.append("")
427
+
428
+ # 用法
429
+ if info.get("usage"):
430
+ lines.append(f"用法: {info['usage'].replace('/', prefix)}")
431
+ lines.append("")
432
+
433
+ # 权限
434
+ if info.get("permission"):
435
+ lines.append("权限: 需要特殊权限")
436
+ lines.append("")
437
+
438
+ # 分组
439
+ if info.get("group"):
440
+ group_name = cls._get_group_name(info["group"])
441
+ lines.append(f"分组: {group_name}")
442
+ lines.append("")
443
+
444
+ return "\n".join(lines)
445
+
446
+ # ==================== 错误消息模板 ====================
447
+
448
+ @classmethod
449
+ def build_error(cls, title: str, message: str) -> Dict[str, str]:
450
+ html = f"""
451
+ <div style="padding: 12px; border-radius: 8px;">
452
+ <div style="color: {cls.ERROR_COLOR}; font-size: 14px; font-weight: bold; margin-bottom: 8px;">{title}</div>
453
+ <div style="font-size: 13px;">{message}</div>
454
+ </div>"""
455
+
456
+ markdown = f"**{title}**\n\n{message}"
457
+
458
+ text = f"{title}\n\n{message}"
459
+
460
+ return {"html": html, "markdown": markdown, "text": text}
@@ -1,15 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse-HelpModule
3
- Version: 2.0.0
3
+ Version: 2.1.0
4
4
  Summary: ErisPulse 帮助命令模块,提供自动化的命令帮助系统,支持查看所有可用命令及其用法说明
5
5
  Author-email: wsu2059q <wsu2059@qq.com>
6
- License: Copyright 2025 wsu2059q
7
-
8
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
9
-
10
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
11
-
12
- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6
+ License-Expression: MIT
13
7
  Project-URL: homepage, https://github.com/wsu2059q/ErisPulse-HelpModule
14
8
  Requires-Python: >=3.10
15
9
  Description-Content-Type: text/markdown
@@ -3,6 +3,7 @@ README.md
3
3
  pyproject.toml
4
4
  ErisPulse_HelpModule/Core.py
5
5
  ErisPulse_HelpModule/__init__.py
6
+ ErisPulse_HelpModule/templates.py
6
7
  ErisPulse_HelpModule.egg-info/PKG-INFO
7
8
  ErisPulse_HelpModule.egg-info/SOURCES.txt
8
9
  ErisPulse_HelpModule.egg-info/dependency_links.txt
@@ -1,15 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse-HelpModule
3
- Version: 2.0.0
3
+ Version: 2.1.0
4
4
  Summary: ErisPulse 帮助命令模块,提供自动化的命令帮助系统,支持查看所有可用命令及其用法说明
5
5
  Author-email: wsu2059q <wsu2059@qq.com>
6
- License: Copyright 2025 wsu2059q
7
-
8
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
9
-
10
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
11
-
12
- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6
+ License-Expression: MIT
13
7
  Project-URL: homepage, https://github.com/wsu2059q/ErisPulse-HelpModule
14
8
  Requires-Python: >=3.10
15
9
  Description-Content-Type: text/markdown
@@ -1,10 +1,11 @@
1
1
  [project]
2
2
  name = "ErisPulse-HelpModule"
3
- version = "2.0.0"
3
+ version = "2.1.0"
4
4
  description = "ErisPulse 帮助命令模块,提供自动化的命令帮助系统,支持查看所有可用命令及其用法说明"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
7
- license = { file = "LICENSE" }
7
+ license = "MIT"
8
+ license-files = ["LICENSE"]
8
9
  authors = [ { name = "wsu2059q", email = "wsu2059@qq.com" } ]
9
10
 
10
11
  dependencies = [
@@ -15,3 +16,6 @@ dependencies = [
15
16
 
16
17
  [project.entry-points."erispulse.module"]
17
18
  "HelpModule" = "ErisPulse_HelpModule:HelpModule"
19
+
20
+ [tool.setuptools.packages.find]
21
+ include = ["ErisPulse_HelpModule*"]