Check nickname before parsing command, allowing users call commands with nickname instead of explicit "at"

This commit is contained in:
Richard Chien 2019-02-21 21:41:17 +08:00
parent fdc7327a0c
commit 838213d438
2 changed files with 61 additions and 48 deletions

View File

@ -29,7 +29,31 @@ async def handle_message(bot: NoneBot, ctx: Context_T) -> None:
if coros:
await asyncio.wait(coros)
if 'to_me' not in ctx:
raw_to_me = ctx.get('to_me', False)
_check_at_me(bot, ctx)
_check_calling_me_nickname(bot, ctx)
ctx['to_me'] = raw_to_me or ctx['to_me']
while True:
try:
handled = await handle_command(bot, ctx)
break
except SwitchException as e:
# we are sure that there is no session existing now
ctx['message'] = e.new_ctx_message
ctx['to_me'] = True
if handled:
logger.info(f'Message {ctx["message_id"]} is handled as a command')
return
handled = await handle_natural_language(bot, ctx)
if handled:
logger.info(f'Message {ctx["message_id"]} is handled '
f'as natural language')
return
def _check_at_me(bot: NoneBot, ctx: Context_T) -> None:
if ctx['message_type'] == 'private':
ctx['to_me'] = True
else:
@ -60,23 +84,29 @@ async def handle_message(bot: NoneBot, ctx: Context_T) -> None:
if not ctx['message']:
ctx['message'].append(MessageSegment.text(''))
while True:
try:
handled = await handle_command(bot, ctx)
break
except SwitchException as e:
# we are sure that there is no session existing now
ctx['message'] = e.new_ctx_message
ctx['to_me'] = True
if handled:
logger.info(f'Message {ctx["message_id"]} is handled as a command')
def _check_calling_me_nickname(bot: NoneBot, ctx: Context_T) -> None:
first_msg_seg = ctx['message'][0]
if first_msg_seg.type != 'text':
return
handled = await handle_natural_language(bot, ctx)
if handled:
logger.info(f'Message {ctx["message_id"]} is handled '
f'as natural language')
return
first_text = first_msg_seg.data['text']
if bot.config.NICKNAME:
# check if the user is calling me with my nickname
if isinstance(bot.config.NICKNAME, str) or \
not isinstance(bot.config.NICKNAME, Iterable):
nicknames = (bot.config.NICKNAME,)
else:
nicknames = filter(lambda n: n, bot.config.NICKNAME)
nickname_regex = '|'.join(nicknames)
m = re.search(rf'^({nickname_regex})([\s,]*|$)',
first_text, re.IGNORECASE)
if m:
nickname = m.group(1)
logger.debug(f'User is calling me {nickname}')
ctx['to_me'] = True
first_msg_seg.data['text'] = first_text[m.end():]
def _log_message(ctx: Context_T) -> None:

View File

@ -1,5 +1,4 @@
import asyncio
import re
from typing import Iterable, Optional, Callable, Union, NamedTuple
from . import NoneBot, permission as perm
@ -106,23 +105,7 @@ async def handle_natural_language(bot: NoneBot, ctx: Context_T) -> bool:
:param ctx: message context
:return: the message is handled as natural language
"""
msg = str(ctx['message'])
if bot.config.NICKNAME:
# check if the user is calling me with my nickname
if isinstance(bot.config.NICKNAME, str) or \
not isinstance(bot.config.NICKNAME, Iterable):
nicknames = (bot.config.NICKNAME,)
else:
nicknames = filter(lambda n: n, bot.config.NICKNAME)
nickname_regex = '|'.join(nicknames)
m = re.search(rf'^({nickname_regex})([\s,]*|$)', msg, re.IGNORECASE)
if m:
nickname = m.group(1)
logger.debug(f'User is calling me {nickname}')
ctx['to_me'] = True
msg = msg[m.end():]
session = NLPSession(bot, ctx, msg)
session = NLPSession(bot, ctx, str(ctx['message']))
# use msg_text here because CQ code "share" may be very long,
# at the same time some plugins may want to handle it