Add empty message support for natural language processors

This commit is contained in:
Richard Chien 2018-12-15 23:41:03 +08:00
parent c4147e47cc
commit bc8cdf6131
2 changed files with 21 additions and 6 deletions

View File

@ -4,6 +4,10 @@ sidebar: auto
# 更新日志 # 更新日志
## next
- 自然语言处理器支持响应只有机器人昵称而没有实际内容的消息,通过 `on_natural_language``allow_empty_message` 参数开启(默认关闭)
## v0.4.2 ## v0.4.2
- 修复命令处理器中抛出异常导致运行超时 `SESSION_RUN_TIMEOUT` 不生效的问题 - 修复命令处理器中抛出异常导致运行超时 `SESSION_RUN_TIMEOUT` 不生效的问题

View File

@ -14,35 +14,41 @@ _nl_processors = set()
class NLProcessor: class NLProcessor:
__slots__ = ('func', 'keywords', 'permission', __slots__ = ('func', 'keywords', 'permission',
'only_to_me', 'only_short_message') 'only_to_me', 'only_short_message',
'allow_empty_message')
def __init__(self, *, func: Callable, keywords: Optional[Iterable], def __init__(self, *, func: Callable, keywords: Optional[Iterable],
permission: int, only_to_me: bool, only_short_message: bool): permission: int, only_to_me: bool, only_short_message: bool,
allow_empty_message: bool):
self.func = func self.func = func
self.keywords = keywords self.keywords = keywords
self.permission = permission self.permission = permission
self.only_to_me = only_to_me self.only_to_me = only_to_me
self.only_short_message = only_short_message self.only_short_message = only_short_message
self.allow_empty_message = allow_empty_message
def on_natural_language(keywords: Union[Optional[Iterable], Callable] = None, def on_natural_language(keywords: Union[Optional[Iterable], Callable] = None,
*, permission: int = perm.EVERYBODY, *, permission: int = perm.EVERYBODY,
only_to_me: bool = True, only_to_me: bool = True,
only_short_message: bool = True) -> Callable: only_short_message: bool = True,
allow_empty_message: bool = False) -> Callable:
""" """
Decorator to register a function as a natural language processor. Decorator to register a function as a natural language processor.
:param keywords: keywords to respond, if None, respond to all messages :param keywords: keywords to respond, if None, respond to all messages
:param permission: permission required by the processor :param permission: permission required by the processor
:param only_to_me: only handle messages to me :param only_to_me: only handle messages to me
:param only_short_message: only handle short message :param only_short_message: only handle short messages
:param allow_empty_message: handle empty messages
""" """
def deco(func: Callable) -> Callable: def deco(func: Callable) -> Callable:
nl_processor = NLProcessor(func=func, keywords=keywords, nl_processor = NLProcessor(func=func, keywords=keywords,
permission=permission, permission=permission,
only_to_me=only_to_me, only_to_me=only_to_me,
only_short_message=only_short_message) only_short_message=only_short_message,
allow_empty_message=allow_empty_message)
_nl_processors.add(nl_processor) _nl_processors.add(nl_processor)
return func return func
@ -89,7 +95,8 @@ async def handle_natural_language(bot: NoneBot, ctx: Context_T) -> bool:
nicknames = (bot.config.NICKNAME,) nicknames = (bot.config.NICKNAME,)
else: else:
nicknames = filter(lambda n: n, bot.config.NICKNAME) nicknames = filter(lambda n: n, bot.config.NICKNAME)
m = re.search(rf'^({"|".join(nicknames)})[\s,]+', msg, re.IGNORECASE) m = re.search(rf'^{"|".join(nicknames)}([\s,]|$)',
msg, re.IGNORECASE)
if m: if m:
logger.debug(f'User is calling me {m.group(1)}') logger.debug(f'User is calling me {m.group(1)}')
ctx['to_me'] = True ctx['to_me'] = True
@ -103,6 +110,10 @@ async def handle_natural_language(bot: NoneBot, ctx: Context_T) -> bool:
coros = [] coros = []
for p in _nl_processors: for p in _nl_processors:
if not p.allow_empty_message and not session.msg:
# don't allow empty msg, but it is one, so skip to next
continue
if p.only_short_message and \ if p.only_short_message and \
msg_text_length > bot.config.SHORT_MESSAGE_MAX_LENGTH: msg_text_length > bot.config.SHORT_MESSAGE_MAX_LENGTH:
continue continue