mirror of
https://github.com/nonebot/nonebot2.git
synced 2024-11-24 09:05:04 +08:00
Update
This commit is contained in:
parent
844ade5c31
commit
492fed9b50
@ -17,7 +17,7 @@ default_handler.setFormatter(logging.Formatter(
|
||||
logger.addHandler(default_handler)
|
||||
|
||||
from .plugin import handle_message, handle_notice, handle_request
|
||||
from .command import on_command
|
||||
from .command import on_command, call_command
|
||||
|
||||
|
||||
def create_bot(config_object: Any = None):
|
||||
|
@ -19,17 +19,33 @@ _aliases = {}
|
||||
_sessions = {}
|
||||
|
||||
|
||||
# TODO: session 保存为一个栈,命令可以调用命令,进入新的 session,命令执行完毕,
|
||||
# 中间没有抛出异常(标志进入交互模式的异常),则从栈中 pop
|
||||
|
||||
|
||||
class Command:
|
||||
__slots__ = ('name', 'func', 'permission')
|
||||
__slots__ = ('name', 'func', 'permission', 'args_parser')
|
||||
|
||||
def __init__(self, name: Tuple[str], func: Callable, permission: int):
|
||||
self.name = name
|
||||
self.func = func
|
||||
self.permission = permission
|
||||
self.args_parser = None
|
||||
|
||||
async def run(self, bot, session) -> bool:
|
||||
async def run(self, bot, session, *,
|
||||
permission: int = None) -> bool:
|
||||
if permission is None:
|
||||
permission = await calculate_permission(bot, session.ctx)
|
||||
if isinstance(self.func, Callable) and permission & self.permission:
|
||||
if isinstance(self.args_parser, Callable):
|
||||
self.args_parser(session)
|
||||
await self.func(bot, session)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
async def calculate_permission(bot: CQHttp, ctx: Dict[str, Any]) -> int:
|
||||
permission = 0
|
||||
ctx = session.ctx
|
||||
if ctx['user_id'] in bot.config.SUPERUSERS:
|
||||
permission |= perm.IS_SUPERUSER
|
||||
if ctx['message_type'] == 'private':
|
||||
@ -55,24 +71,22 @@ class Command:
|
||||
pass
|
||||
elif ctx['message_type'] == 'discuss':
|
||||
permission |= perm.IS_DISCUSS
|
||||
|
||||
if isinstance(self.func, Callable) and permission & self.permission:
|
||||
await self.func(bot, session)
|
||||
return True
|
||||
return False
|
||||
return permission
|
||||
|
||||
|
||||
def _find_command(name: Tuple[str]) -> Optional[Command]:
|
||||
if not name:
|
||||
def _find_command(name: Union[str, Tuple[str]]) -> Optional[Command]:
|
||||
cmd_name = name if isinstance(name, tuple) else (name,)
|
||||
|
||||
if not cmd_name:
|
||||
return None
|
||||
|
||||
cmd_tree = _registry
|
||||
for part in name[:-1]:
|
||||
for part in cmd_name[:-1]:
|
||||
if part not in cmd_tree:
|
||||
return None
|
||||
cmd_tree = cmd_tree[part]
|
||||
|
||||
return cmd_tree.get(name[-1])
|
||||
return cmd_tree.get(cmd_name[-1])
|
||||
|
||||
|
||||
class Session:
|
||||
@ -80,15 +94,16 @@ class Session:
|
||||
'current_key', 'current_arg', 'current_arg_text',
|
||||
'images', 'args', 'last_interaction')
|
||||
|
||||
def __init__(self, cmd: Command, ctx: Dict[str, Any],
|
||||
current_arg: str = ''):
|
||||
def __init__(self, cmd: Command, ctx: Dict[str, Any], *,
|
||||
current_arg: str = '', args: Dict[str, Any] = None):
|
||||
self.cmd = cmd
|
||||
self.ctx = ctx
|
||||
self.current_key = None
|
||||
self.current_arg = current_arg
|
||||
self.current_arg_text = Message(current_arg).extract_plain_text()
|
||||
self.images = []
|
||||
self.args = {}
|
||||
self.images = [s.data['url'] for s in ctx['message']
|
||||
if s.type == 'image' and 'url' in s.data]
|
||||
self.args = args or {}
|
||||
self.last_interaction = None
|
||||
|
||||
def require_arg(self, key: str, prompt: str = '', *,
|
||||
@ -137,9 +152,8 @@ async def handle_command(bot: CQHttp, ctx: Dict[str, Any]) -> bool:
|
||||
if not cmd:
|
||||
return False
|
||||
|
||||
session = Session(cmd=cmd, ctx=ctx, current_arg=''.join(cmd_remained))
|
||||
session.images = [s.data['url'] for s in ctx['message']
|
||||
if s.type == 'image' and 'url' in s.data]
|
||||
session = Session(cmd, ctx, current_arg=''.join(cmd_remained))
|
||||
# TODO: 插入 session
|
||||
return await cmd.run(bot, session)
|
||||
|
||||
|
||||
@ -156,13 +170,40 @@ def on_command(name: Union[str, Tuple[str]], aliases: Iterable = (),
|
||||
for parent_key in cmd_name[:-1]:
|
||||
current_parent[parent_key] = {}
|
||||
current_parent = current_parent[parent_key]
|
||||
current_parent[cmd_name[-1]] = Command(
|
||||
name=cmd_name, func=func, permission=permission)
|
||||
cmd = Command(name=cmd_name, func=func, permission=permission)
|
||||
current_parent[cmd_name[-1]] = cmd
|
||||
for alias in aliases:
|
||||
_aliases[alias] = cmd_name
|
||||
|
||||
# TODO: 给 func 添加一个 argparser 装饰器,用于注册它的参数解析器
|
||||
def args_parser(parser_func: Callable):
|
||||
cmd.args_parser = parser_func
|
||||
return parser_func
|
||||
|
||||
func.args_parser = args_parser
|
||||
return func
|
||||
|
||||
return deco
|
||||
|
||||
|
||||
async def call_command(name: Union[str, Tuple[str]],
|
||||
bot: CQHttp, ctx: Dict[str, Any], **kwargs) -> bool:
|
||||
"""
|
||||
Call a command internally.
|
||||
|
||||
There is no permission restriction on this function,
|
||||
which means any command can be called from any other command.
|
||||
Unexpected users should be handled by the caller command's permission
|
||||
option.
|
||||
|
||||
:param name: command name (str or tuple of str)
|
||||
:param bot: CQHttp instance
|
||||
:param ctx: event context
|
||||
:param kwargs: other keyword args that will be passed to Session()
|
||||
:return: the command is successfully called
|
||||
"""
|
||||
cmd = _find_command(name)
|
||||
if cmd:
|
||||
session = Session(cmd, ctx, **kwargs)
|
||||
# TODO: 插入 session
|
||||
return await cmd.run(bot, session, permission=perm.IS_SUPERUSER)
|
||||
return False
|
||||
|
@ -11,6 +11,7 @@ GROUP = 0x0F00
|
||||
SUPERUSER = 0xF000
|
||||
EVERYONE = 0xFFFF
|
||||
|
||||
IS_NOBODY = 0x0000
|
||||
IS_PRIVATE_FRIEND = PRIVATE_FRIEND
|
||||
IS_PRIVATE_GROUP = PRIVATE_GROUP
|
||||
IS_PRIVATE_DISCUSS = PRIVATE_DISCUSS
|
||||
|
15
plugins/weather.py
Normal file
15
plugins/weather.py
Normal file
@ -0,0 +1,15 @@
|
||||
import none
|
||||
from none.command import Session
|
||||
from none.helpers import send
|
||||
|
||||
|
||||
@none.on_command('weather', aliases=('天气',))
|
||||
async def weather(bot, session: Session):
|
||||
city = session.require_arg('city', prompt='你想知道哪个城市的天气呢?')
|
||||
await send(bot, session.ctx, f'你查询了{city}的天气')
|
||||
|
||||
|
||||
@weather.args_parser
|
||||
def _(session: Session):
|
||||
if session.current_key:
|
||||
session.args[session.current_key] = session.current_arg.strip()
|
Loading…
Reference in New Issue
Block a user