mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-02 12:05:54 +00:00
refactor: 指令注册架构
This commit is contained in:
13
main.py
13
main.py
@@ -7,6 +7,7 @@ import time
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
try:
|
||||
import colorlog
|
||||
@@ -191,8 +192,14 @@ def start(first_time_init=False):
|
||||
import pkg.openai.session
|
||||
import pkg.qqbot.manager
|
||||
import pkg.openai.dprompt
|
||||
import pkg.qqbot.cmds.mgr
|
||||
|
||||
pkg.openai.dprompt.register_all()
|
||||
try:
|
||||
pkg.openai.dprompt.register_all()
|
||||
pkg.qqbot.cmds.mgr.register_all()
|
||||
except Exception as e:
|
||||
logging.error(e)
|
||||
traceback.print_exc()
|
||||
|
||||
# 配置openai api_base
|
||||
if "reverse_proxy" in config.openai_config and config.openai_config["reverse_proxy"] is not None:
|
||||
@@ -271,10 +278,6 @@ def start(first_time_init=False):
|
||||
threading.Thread(
|
||||
target=run_bot_wrapper
|
||||
).start()
|
||||
# 机器人暂时不能放在线程池中
|
||||
# pkg.utils.context.get_thread_ctl().submit_sys_task(
|
||||
# run_bot_wrapper
|
||||
# )
|
||||
finally:
|
||||
# 判断若是Windows,输出选择模式可能会暂停程序的警告
|
||||
if os.name == 'nt':
|
||||
|
||||
0
pkg/qqbot/cmds/__init__.py
Normal file
0
pkg/qqbot/cmds/__init__.py
Normal file
@@ -1,5 +1,10 @@
|
||||
import importlib
|
||||
import inspect
|
||||
import logging
|
||||
import copy
|
||||
import pkgutil
|
||||
import traceback
|
||||
import types
|
||||
|
||||
|
||||
__commands_tree__ = {}
|
||||
@@ -109,6 +114,9 @@ class Context:
|
||||
class AbstractCommand:
|
||||
"""指令抽象类"""
|
||||
|
||||
parent: type
|
||||
"""父指令类"""
|
||||
|
||||
name: str
|
||||
"""指令名"""
|
||||
|
||||
@@ -179,6 +187,12 @@ class AbstractCommand:
|
||||
# 更新索引
|
||||
__tree_index__[cls.__module__ + '.' + cls.__name__] = path + [name]
|
||||
|
||||
|
||||
class CommandPrivilegeError(Exception):
|
||||
"""指令权限不足或不存在异常"""
|
||||
pass
|
||||
|
||||
|
||||
# 传入Context对象,广搜命令树,返回执行结果
|
||||
# 若命令被处理,返回reply列表
|
||||
# 若命令未被处理,继续执行下一级指令
|
||||
@@ -198,12 +212,15 @@ def execute(context: Context) -> list:
|
||||
# 从树取出顶级指令
|
||||
node = __commands_tree__
|
||||
|
||||
path = ""
|
||||
|
||||
# 搜当前顶层,找不到则报错
|
||||
while True:
|
||||
path = path + ctx.crt_command + "."
|
||||
try:
|
||||
# 检查权限
|
||||
if ctx.privilege < node[ctx.crt_command]['privilege']:
|
||||
raise ValueError('权限不足')
|
||||
raise CommandPrivilegeError('权限不足: {}'.format(path[:-1]))
|
||||
# 执行
|
||||
execed, reply, ctx.crt_command = node[ctx.crt_command]['cls'].process(ctx)
|
||||
if execed:
|
||||
@@ -214,4 +231,36 @@ def execute(context: Context) -> list:
|
||||
# 删除crt_params第一个参数
|
||||
ctx.crt_params.pop(0)
|
||||
except KeyError:
|
||||
raise ValueError('找不到指令: {}'.format(ctx.command))
|
||||
raise CommandPrivilegeError('找不到指令: {}'.format(path[:-1]))
|
||||
|
||||
|
||||
def register_all():
|
||||
"""启动时调用此函数注册所有指令
|
||||
|
||||
递归处理pkg.qqbot.cmds包下及其子包下所有模块的所有继承于AbstractCommand的类
|
||||
"""
|
||||
# 模块:遍历其中的继承于AbstractCommand的类,进行注册
|
||||
# 包:递归处理包下的模块
|
||||
# 排除__开头的属性
|
||||
import pkg.qqbot.cmds
|
||||
|
||||
def walk(module, prefix, path_prefix):
|
||||
# 排除不处于pkg.qqbot.cmds中的包
|
||||
if not module.__name__.startswith('pkg.qqbot.cmds'):
|
||||
return
|
||||
for item in pkgutil.iter_modules(module.__path__):
|
||||
if item.name.startswith('__'):
|
||||
continue
|
||||
|
||||
if item.ispkg:
|
||||
walk(__import__(module.__name__ + '.' + item.name, fromlist=['']), prefix + item.name + '.', path_prefix + item.name + '/')
|
||||
else:
|
||||
m = __import__(module.__name__ + '.' + item.name, fromlist=[''])
|
||||
for name, cls in inspect.getmembers(m, inspect.isclass):
|
||||
# 检查是否为指令类
|
||||
if cls.__module__ == m.__name__ and issubclass(cls, AbstractCommand) and cls != AbstractCommand:
|
||||
cls.register(cls, cls.name, cls.parent)
|
||||
|
||||
walk(pkg.qqbot.cmds, '', '')
|
||||
logging.debug(__commands_tree__)
|
||||
|
||||
|
||||
0
pkg/qqbot/cmds/session/__init__.py
Normal file
0
pkg/qqbot/cmds/session/__init__.py
Normal file
@@ -4,6 +4,8 @@ import pkg.openai.session
|
||||
import pkg.utils.context
|
||||
|
||||
class ResetCommand(AbstractCommand):
|
||||
parent: type = None
|
||||
|
||||
name = 'reset'
|
||||
description = '重置当前会话'
|
||||
usage = 'reset'
|
||||
|
||||
@@ -13,7 +13,8 @@ import pkg.utils.updater
|
||||
import pkg.utils.context
|
||||
import pkg.qqbot.message
|
||||
import pkg.utils.credit as credit
|
||||
import pkg.qqbot.cmds.model as cmdmodel
|
||||
# import pkg.qqbot.cmds.model as cmdmodel
|
||||
import pkg.qqbot.cmds.mgr as cmdmgr
|
||||
|
||||
from mirai import Image
|
||||
|
||||
@@ -36,22 +37,24 @@ def process_command(session_name: str, text_message: str, mgr, config,
|
||||
params = [cmd[1:]] + params
|
||||
cmd = 'cfg'
|
||||
|
||||
# 选择指令处理函数
|
||||
cmd_obj = cmdmodel.search(cmd)
|
||||
if cmd_obj is not None and (cmd_obj['admin_only'] is False or is_admin):
|
||||
cmd_func = cmd_obj['func']
|
||||
reply = cmd_func(
|
||||
cmd=cmd,
|
||||
params=params,
|
||||
session_name=session_name,
|
||||
text_message=text_message,
|
||||
launcher_type=launcher_type,
|
||||
launcher_id=launcher_id,
|
||||
sender_id=sender_id,
|
||||
is_admin=is_admin,
|
||||
)
|
||||
else:
|
||||
reply = ["[bot]err:未知的指令或权限不足: " + cmd]
|
||||
# 包装参数
|
||||
context = cmdmgr.Context(
|
||||
command=cmd,
|
||||
crt_command=cmd,
|
||||
params=params,
|
||||
crt_params=params,
|
||||
session_name=session_name,
|
||||
text_message=text_message,
|
||||
launcher_type=launcher_type,
|
||||
launcher_id=launcher_id,
|
||||
sender_id=sender_id,
|
||||
is_admin=is_admin,
|
||||
privilege=2 if is_admin else 1, # 普通用户1,管理员2
|
||||
)
|
||||
try:
|
||||
reply = cmdmgr.execute(context)
|
||||
except cmdmgr.CommandPrivilegeError as e:
|
||||
reply = ["[bot]err:{}".format(e)]
|
||||
|
||||
return reply
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user