Allow commands that handle messages not to me

This commit is contained in:
Richard Chien 2018-06-30 17:26:36 +08:00
parent 0c74fbadca
commit 4a50850d11
3 changed files with 26 additions and 25 deletions

View File

@ -27,12 +27,14 @@ _sessions = {}
class Command: class Command:
__slots__ = ('name', 'func', 'permission', 'args_parser_func') __slots__ = ('name', 'func', 'permission', 'only_to_me', 'args_parser_func')
def __init__(self, name: Tuple[str], func: Callable, permission: int): def __init__(self, name: Tuple[str], func: Callable, permission: int, *,
only_to_me: bool):
self.name = name self.name = name
self.func = func self.func = func
self.permission = permission self.permission = permission
self.only_to_me = only_to_me
self.args_parser_func = None self.args_parser_func = None
async def run(self, session, *, permission: Optional[int] = None) -> bool: async def run(self, session, *, permission: Optional[int] = None) -> bool:
@ -97,7 +99,8 @@ async def _calculate_permission(bot: CQHttp, ctx: Dict[str, Any]) -> int:
def on_command(name: Union[str, Tuple[str]], *, def on_command(name: Union[str, Tuple[str]], *,
aliases: Iterable = (), aliases: Iterable = (),
permission: int = perm.EVERYBODY) -> Callable: permission: int = perm.EVERYBODY,
only_to_me: bool = True) -> Callable:
def deco(func: Callable) -> Callable: def deco(func: Callable) -> Callable:
if not isinstance(name, (str, tuple)): if not isinstance(name, (str, tuple)):
raise TypeError('the name of a command must be a str or tuple') raise TypeError('the name of a command must be a str or tuple')
@ -109,7 +112,8 @@ def on_command(name: Union[str, Tuple[str]], *,
for parent_key in cmd_name[:-1]: for parent_key in cmd_name[:-1]:
current_parent[parent_key] = current_parent.get(parent_key) or {} current_parent[parent_key] = current_parent.get(parent_key) or {}
current_parent = current_parent[parent_key] current_parent = current_parent[parent_key]
cmd = Command(name=cmd_name, func=func, permission=permission) cmd = Command(name=cmd_name, func=func, permission=permission,
only_to_me=only_to_me)
current_parent[cmd_name[-1]] = cmd current_parent[cmd_name[-1]] = cmd
for alias in aliases: for alias in aliases:
_aliases[alias] = cmd_name _aliases[alias] = cmd_name
@ -129,20 +133,19 @@ class CommandGroup:
Group a set of commands with same name prefix. Group a set of commands with same name prefix.
""" """
__slots__ = ('basename', 'permission') __slots__ = ('basename', 'permission', 'only_to_me')
def __init__(self, name: Union[str, Tuple[str]], def __init__(self, name: Union[str, Tuple[str]],
permission: Optional[int] = None): permission: Optional[int] = None, *,
""" only_to_me: Optional[bool] = None):
:param name: name prefix of commands in this group
:param permission: default permission
"""
self.basename = (name,) if isinstance(name, str) else name self.basename = (name,) if isinstance(name, str) else name
self.permission = permission self.permission = permission
self.only_to_me = only_to_me
def command(self, name: Union[str, Tuple[str]], *, def command(self, name: Union[str, Tuple[str]], *,
aliases: Optional[Iterable] = None, aliases: Optional[Iterable] = None,
permission: Optional[int] = None) -> Callable: permission: Optional[int] = None,
only_to_me: Optional[bool] = None) -> Callable:
sub_name = (name,) if isinstance(name, str) else name sub_name = (name,) if isinstance(name, str) else name
name = self.basename + sub_name name = self.basename + sub_name
@ -153,6 +156,10 @@ class CommandGroup:
kwargs['permission'] = permission kwargs['permission'] = permission
elif self.permission is not None: elif self.permission is not None:
kwargs['permission'] = self.permission kwargs['permission'] = self.permission
if only_to_me is not None:
kwargs['only_to_me'] = only_to_me
elif self.only_to_me is not None:
kwargs['only_to_me'] = self.only_to_me
return on_command(name, **kwargs) return on_command(name, **kwargs)
@ -263,10 +270,6 @@ def _new_command_session(bot: CQHttp,
:param ctx: message context :param ctx: message context
:return: CommandSession object or None :return: CommandSession object or None
""" """
if not ctx['to_me']:
# TODO: 支持不需要 at 的命令
return None
msg_text = str(ctx['message']).lstrip() msg_text = str(ctx['message']).lstrip()
for start in bot.config.COMMAND_START: for start in bot.config.COMMAND_START:
@ -304,6 +307,8 @@ def _new_command_session(bot: CQHttp,
cmd = _find_command(cmd_name) cmd = _find_command(cmd_name)
if not cmd: if not cmd:
return None return None
if cmd.only_to_me and not ctx['to_me']:
return None
return CommandSession(bot, ctx, cmd, current_arg=''.join(cmd_remained)) return CommandSession(bot, ctx, cmd, current_arg=''.join(cmd_remained))

View File

@ -9,17 +9,13 @@ from .helpers import send
async def handle_message(bot: CQHttp, ctx: Dict[str, Any]) -> None: async def handle_message(bot: CQHttp, ctx: Dict[str, Any]) -> None:
# TODO: 支持让插件自己选择是否响应没有 at 的消息
if ctx['message_type'] != 'private': if ctx['message_type'] != 'private':
# group or discuss # group or discuss
ctx['to_me'] = False ctx['to_me'] = False
indexes_to_remove = [] first_message_seg = ctx['message'][0]
for i, seg in enumerate(ctx['message']): if first_message_seg == MessageSegment.at(ctx['self_id']):
if seg == MessageSegment.at(ctx['self_id']):
ctx['to_me'] = True ctx['to_me'] = True
indexes_to_remove.append(i) del ctx['message'][0]
for i in reversed(indexes_to_remove):
del ctx['message'][i]
if not ctx['message']: if not ctx['message']:
ctx['message'].append(MessageSegment.text('')) ctx['message'].append(MessageSegment.text(''))
else: else:

View File

@ -4,11 +4,11 @@ from none import on_command, CommandSession
from none.command import permissions as perm from none.command import permissions as perm
@on_command('echo') @on_command('echo', only_to_me=False)
async def echo(session: CommandSession): async def echo(session: CommandSession):
await session.send(session.current_arg) await session.send(session.current_arg)
@on_command('say', permission=perm.SUPERUSER) @on_command('say', permission=perm.SUPERUSER, only_to_me=False)
async def _(session: CommandSession): async def _(session: CommandSession):
await session.send(unescape(session.current_arg)) await session.send(unescape(session.current_arg))