Skip to content

Commit eacbad4

Browse files
committed
更新 SayaManager,支持不可重载/卸载的metadata
1 parent 2c829e5 commit eacbad4

File tree

11 files changed

+96
-50
lines changed

11 files changed

+96
-50
lines changed

sagiri_bot/config.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from pathlib import Path
66
from pydantic import BaseModel
77
from typing_extensions import TypedDict
8-
from typing import Type, List, Dict, Union
8+
from typing import Type, List, Dict, Union, Any
99

1010
from creart import add_creator
1111
from creart import exists_module
@@ -23,6 +23,7 @@ class PluginMeta(BaseModel):
2323
icon: str = ""
2424
prefix: List[str] = []
2525
triggers: List[str] = []
26+
metadata: Dict[str, Any] = {}
2627

2728

2829
def load_plugin_meta(path: Union[Path, str]) -> PluginMeta:

sagiri_bot/handler/required_module/bot_management/metadata.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,9 @@
99
"usage": "发送 setting -set key1=value1 key2=value2 ... 改变群内设置\n发送 user -grant @target [1-3] 改变成员权限等级\n发送 blacklist -add @target 添加群内黑名单\n发送 blacklist -remove @target 移除群内黑名单",
1010
"icon": "",
1111
"prefix": [],
12-
"triggers": []
12+
"triggers": [],
13+
"metadata": {
14+
"uninstallable": false,
15+
"reloadable": false
16+
}
1317
}

sagiri_bot/handler/required_module/chat_recorder_handler/metadata.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,9 @@
99
"usage": "自动触发",
1010
"icon": "",
1111
"prefix": [],
12-
"triggers": []
12+
"triggers": [],
13+
"metadata": {
14+
"uninstallable": false,
15+
"reloadable": false
16+
}
1317
}

sagiri_bot/handler/required_module/exception_catcher/metadata.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,9 @@
99
"usage": "后台发生错误时自动触发",
1010
"icon": "",
1111
"prefix": [],
12-
"triggers": []
12+
"triggers": [],
13+
"metadata": {
14+
"uninstallable": false,
15+
"reloadable": true
16+
}
1317
}

sagiri_bot/handler/required_module/helper/metadata.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,9 @@
99
"usage": "发送 `/help` 即可查看所有插件",
1010
"icon": "",
1111
"prefix": ["/", ".", "#", ""],
12-
"triggers": ["help", "帮助", "菜单", "功能", "纱雾帮助"]
12+
"triggers": ["help", "帮助", "菜单", "功能", "纱雾帮助"],
13+
"metadata": {
14+
"uninstallable": false,
15+
"reloadable": true
16+
}
1317
}

sagiri_bot/handler/required_module/message_statistics/metadata.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,9 @@
99
"usage": "在群中发送 `消息量统计` 即可\n发送 `消息量统计 -group` 可查看本群统计",
1010
"icon": "",
1111
"prefix": ["", "/"],
12-
"triggers": ["消息量统计"]
12+
"triggers": ["消息量统计"],
13+
"metadata": {
14+
"uninstallable": false,
15+
"reloadable": true
16+
}
1317
}

sagiri_bot/handler/required_module/mirai_event/metadata.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,9 @@
99
"usage": "自动触发",
1010
"icon": "",
1111
"prefix": [],
12-
"triggers": []
12+
"triggers": [],
13+
"metadata": {
14+
"uninstallable": false,
15+
"reloadable": true
16+
}
1317
}

sagiri_bot/handler/required_module/saya_manager/__init__.py

+40-40
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import os
22
import re
3-
from typing import List, Dict, Optional, Union
3+
from typing import List, Dict, Union
44

5+
from creart import create
56
from graia.saya import Saya, Channel
67
from graia.ariadne.app import Ariadne
78
from graia.broadcast.interrupt.waiter import Waiter
@@ -11,11 +12,11 @@
1112
from graia.saya.builtins.broadcast.schema import ListenerSchema
1213
from graia.ariadne.event.message import Group, Member, GroupMessage
1314

14-
from .utils import saya_data
15+
from .utils import saya_data, uninstallable, reloadable
1516
from sagiri_bot.internal_utils import MessageChainUtils
1617
from sagiri_bot.internal_utils import user_permission_require
1718

18-
saya = Saya.current()
19+
saya = create(Saya)
1920
channel = Channel.current()
2021

2122
channel.name("SayaManager")
@@ -30,10 +31,6 @@
3031
inc = InterruptControl(saya.broadcast)
3132

3233

33-
def get_loaded_channels() -> Dict[str, Channel]:
34-
return saya.channels
35-
36-
3734
def get_all_channels() -> List[str]:
3835
ignore = ["__init__.py", "__pycache__"]
3936
dirs = [
@@ -54,13 +51,9 @@ def get_all_channels() -> List[str]:
5451

5552

5653
def get_unloaded_channels() -> List[str]:
57-
loaded_channels = get_loaded_channels()
54+
loaded_channels = saya.channels
5855
all_channels = get_all_channels()
59-
return [channel for channel in all_channels if channel not in loaded_channels]
60-
61-
62-
def get_channel(name: str) -> Optional[Channel]:
63-
return get_loaded_channels().get(name)
56+
return [c for c in all_channels if c not in loaded_channels]
6457

6558

6659
def load_channel(modules: Union[str, List[str]]) -> Dict[str, Exception]:
@@ -83,37 +76,37 @@ def unload_channel(modules: Union[str, List[str]]) -> Dict[str, Exception]:
8376
exceptions = {}
8477
if isinstance(modules, str):
8578
modules = [modules]
86-
loaded_channels = get_loaded_channels()
79+
loaded_channels = saya.channels
8780
channels_to_unload = {
8881
module: loaded_channels[module]
8982
for module in modules
9083
if module in loaded_channels
9184
}
9285
with saya.module_context():
93-
for channel, value in channels_to_unload.items():
86+
for c, value in channels_to_unload.items():
9487
try:
9588
saya.uninstall_channel(value)
9689
except Exception as e:
97-
exceptions[channel] = e
90+
exceptions[c] = e
9891
return exceptions
9992

10093

10194
def reload_channel(modules: Union[str, List[str]]) -> Dict[str, Exception]:
10295
exceptions = {}
10396
if isinstance(modules, str):
10497
modules = [modules]
105-
loaded_channels = get_loaded_channels()
98+
loaded_channels = saya.channels
10699
channels_to_reload = {
107100
module: loaded_channels[module]
108101
for module in modules
109102
if module in loaded_channels
110103
}
111104
with saya.module_context():
112-
for channel, value in channels_to_reload.items():
105+
for c, value in channels_to_reload.items():
113106
try:
114107
saya.reload_channel(value)
115108
except Exception as e:
116-
exceptions[channel] = e
109+
exceptions[c] = e
117110
return exceptions
118111

119112

@@ -122,7 +115,7 @@ async def saya_manager(
122115
app: Ariadne, message: MessageChain, group: Group, member: Member, source: Source
123116
):
124117
if message.display.strip() == "已加载插件":
125-
loaded_channels = get_loaded_channels()
118+
loaded_channels = saya.channels
126119
keys = list(loaded_channels.keys())
127120
keys.sort()
128121
return await app.send_group_message(
@@ -143,20 +136,20 @@ async def saya_manager(
143136
)
144137
elif re.match(r"插件详情 .+", message.display):
145138
target = message.display[5:].strip()
146-
loaded_channels = get_loaded_channels()
139+
loaded_channels = saya.channels
147140
keys = list(loaded_channels.keys())
148141
if target.isdigit():
149142
keys.sort()
150143
if not 0 <= int(target) - 1 < len(keys):
151144
return await app.send_group_message(
152145
group, MessageChain("错误的编号!请检查后再发送!"), quote=source
153146
)
154-
channel = loaded_channels[keys[int(target) - 1]]
147+
c = loaded_channels[keys[int(target) - 1]]
155148
channel_path = keys[int(target) - 1]
156149
else:
157150
for lchannel in loaded_channels.keys():
158-
if loaded_channels[lchannel]._name == target:
159-
channel = loaded_channels[lchannel]
151+
if loaded_channels[lchannel].meta["name"] == target:
152+
c = loaded_channels[lchannel]
160153
channel_path = lchannel
161154
break
162155
else:
@@ -167,9 +160,9 @@ async def saya_manager(
167160
group,
168161
MessageChain(
169162
[
170-
Plain(text=f"插件名称:{channel._name}\n"),
171-
Plain(text=f"插件作者:{'、'.join(channel._author)}\n"),
172-
Plain(text=f"插件描述:{channel._description}\n"),
163+
Plain(text=f"插件名称:{c.meta['name']}\n"),
164+
Plain(text=f"插件作者:{'、'.join(c.meta['author'])}\n"),
165+
Plain(text=f"插件描述:{c.meta['description']}\n"),
173166
Plain(text=f"插件包名:{channel_path}"),
174167
]
175168
),
@@ -207,18 +200,18 @@ async def saya_manager(
207200
return await app.send_group_message(
208201
group, MessageChain("错误的编号!请检查后再发送!"), quote=source
209202
)
210-
channel = unloaded_channels[int(target) - 1]
203+
c = unloaded_channels[int(target) - 1]
211204
else:
212205
for ulchannel in unloaded_channels:
213206
if ulchannel == target:
214-
channel = ulchannel
207+
c = ulchannel
215208
break
216209
else:
217210
return await app.send_group_message(
218211
group, MessageChain("错误的名称!请检查后再发送!"), quote=source
219212
)
220213

221-
await app.send_message(group, MessageChain(f"你确定要加载插件 `{channel}` 吗?(是/否)"))
214+
await app.send_message(group, MessageChain(f"你确定要加载插件 `{c}` 吗?(是/否)"))
222215

223216
@Waiter.create_using_function([GroupMessage])
224217
def confirm_waiter(
@@ -236,10 +229,10 @@ def confirm_waiter(
236229
group, MessageChain("非预期回复,进程退出"), quote=source
237230
)
238231
elif result == "是":
239-
result = load_channel(channel)
232+
result = load_channel(c)
240233
if result:
241234
return await app.send_group_message(
242-
group, MessageChain(f"发生错误:{result[channel]}"), quote=source
235+
group, MessageChain(f"发生错误:{result[c]}"), quote=source
243236
)
244237
else:
245238
return await app.send_group_message(
@@ -256,30 +249,37 @@ def confirm_waiter(
256249
)
257250
load_type = "reload" if message.display[0] == "重" else "unload"
258251
target = message.display[5:].strip()
259-
loaded_channels = get_loaded_channels()
252+
loaded_channels = saya.channels
260253
keys = list(loaded_channels.keys())
261254
keys.sort()
262255
if target.isdigit():
263256
if not 0 <= int(target) - 1 < len(keys):
264257
return await app.send_group_message(
265258
group, MessageChain("错误的编号!请检查后再发送!"), quote=source
266259
)
267-
channel = loaded_channels[keys[int(target) - 1]]
260+
c = loaded_channels[keys[int(target) - 1]]
268261
channel_path = keys[int(target) - 1]
269262
else:
270263
for lchannel in loaded_channels.keys():
271-
if loaded_channels[lchannel]._name == target:
272-
channel = loaded_channels[lchannel]
264+
if loaded_channels[lchannel].meta["name"] == target:
265+
c = loaded_channels[lchannel]
273266
channel_path = lchannel
274267
break
275268
else:
276269
return await app.send_group_message(
277270
group, MessageChain("错误的名称!请检查后再发送!"), quote=source
278271
)
279-
272+
if load_type == "reload" and not reloadable(c.module):
273+
return await app.send_group_message(
274+
group, MessageChain(f"插件 `{c.meta['name']}` 不可重载!"), quote=source
275+
)
276+
if load_type == "unload" and not uninstallable(c.module):
277+
return await app.send_group_message(
278+
group, MessageChain(f"插件 `{c.meta['name']}` 不可卸载!"), quote=source
279+
)
280280
await app.send_message(
281281
group,
282-
MessageChain(f"你确定要{message.display[0]}载插件 `{channel._name}` 吗?(是/否)"),
282+
MessageChain(f"你确定要{message.display[0]}载插件 `{c.meta['name']}` 吗?(是/否)"),
283283
)
284284

285285
@Waiter.create_using_function([GroupMessage])
@@ -322,7 +322,7 @@ def confirm_waiter(
322322
)
323323
switch_type = "on" if message.display[:2] == "打开" else "off"
324324
target = message.display[5:].strip()
325-
loaded_channels = get_loaded_channels()
325+
loaded_channels = saya.channels
326326
keys = list(loaded_channels.keys())
327327
keys.sort()
328328
channel_path = ""
@@ -334,7 +334,7 @@ def confirm_waiter(
334334
channel_path = keys[int(target) - 1]
335335
else:
336336
for lchannel in loaded_channels.keys():
337-
if loaded_channels[lchannel]._name == target:
337+
if loaded_channels[lchannel].meta["name"] == target:
338338
channel_path = lchannel
339339
break
340340
saya_data.switch_on(

sagiri_bot/handler/required_module/saya_manager/metadata.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,9 @@
99
"usage": "发送 `已加载插件` 查看已加载插件\n发送 `插件详情 [编号|名称]` 可查看插件详情\n发送 `[加载|重载|卸载|打开|关闭]插件 [编号|名称]` 可加载/重载/卸载/打开/关闭插件",
1010
"icon": "",
1111
"prefix": [],
12-
"triggers": []
12+
"triggers": [],
13+
"metadata": {
14+
"uninstallable": false,
15+
"reloadable": false
16+
}
1317
}

sagiri_bot/handler/required_module/saya_manager/utils.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
from graia.ariadne.event.mirai import MiraiEvent, GroupEvent
1616
from graia.saya.builtins.broadcast.schema import ListenerSchema
1717

18+
from sagiri_bot.config import load_plugin_meta_by_module
19+
1820
DEFAULT_SWITCH = True
1921
DEFAULT_NOTICE = False
2022

@@ -70,7 +72,8 @@ def saya_init():
7072
if isinstance(cube.metaclass, ListenerSchema):
7173
bcc.removeListener(bcc.getListener(cube.content))
7274
if all(
73-
[issubclass(i, GroupEvent) for i in cube.metaclass.listening_events]
75+
issubclass(i, GroupEvent)
76+
for i in cube.metaclass.listening_events
7477
):
7578
cube.metaclass.decorators.append(manageable(channel.module))
7679
else:
@@ -241,4 +244,14 @@ def load(
241244
return self
242245

243246

247+
def reloadable(module: str) -> bool:
248+
plugin_meta = load_plugin_meta_by_module(module)
249+
return plugin_meta.metadata.get("reloadable", True)
250+
251+
252+
def uninstallable(module: str) -> bool:
253+
plugin_meta = load_plugin_meta_by_module(module)
254+
return plugin_meta.metadata.get("uninstallable", True)
255+
256+
244257
saya_data = SayaData().load()

sagiri_bot/handler/required_module/system_status/metadata.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,9 @@
99
"usage": "发送 /sys 或 '/sys -a' 或 '/sys -all' 查看CPU、内存以及图库占用信息\n发送 /sys -i 或 '/sys -info' 查看CPU、内存信息\n发送 /sys -s 或 '/sys -storage' 查看图库占用信息",
1010
"icon": "",
1111
"prefix": ["/"],
12-
"triggers": ["sys", "system"]
12+
"triggers": ["sys", "system"],
13+
"metadata": {
14+
"uninstallable": false,
15+
"reloadable": true
16+
}
1317
}

0 commit comments

Comments
 (0)