mirror of
https://github.com/nonebot/nonebot2.git
synced 2024-11-27 18:45:05 +08:00
Add lots of comments and logs
This commit is contained in:
parent
1c78eb1b80
commit
21db23168f
@ -16,9 +16,11 @@ class NoneBot(CQHttp):
|
||||
if config_object is None:
|
||||
from . import default_config as config_object
|
||||
|
||||
super_kwargs = {k.lower(): v for k, v in config_object.__dict__.items()
|
||||
if k.isupper() and not k.startswith('_')}
|
||||
super().__init__(message_class=Message, **super_kwargs)
|
||||
config_dict = {k: v for k, v in config_object.__dict__.items()
|
||||
if k.isupper() and not k.startswith('_')}
|
||||
logger.debug(f'Loaded configurations: {config_dict}')
|
||||
super().__init__(message_class=Message,
|
||||
**{k.lower(): v for k, v in config_dict.items()})
|
||||
|
||||
self.config = config_object
|
||||
self.asgi.debug = self.config.DEBUG
|
||||
@ -39,29 +41,10 @@ class NoneBot(CQHttp):
|
||||
asyncio.ensure_future(handle_notice_or_request(self, ctx))
|
||||
|
||||
def run(self, host=None, port=None, *args, **kwargs):
|
||||
logger.info(f'Running on {host}:{port}')
|
||||
super().run(host=host, port=port, loop=asyncio.get_event_loop(),
|
||||
*args, **kwargs)
|
||||
|
||||
def get_data_folder(self,
|
||||
*sub_folder: str) -> Optional[str]:
|
||||
folder = self.config.DATA_FOLDER
|
||||
if not folder:
|
||||
return None
|
||||
|
||||
if sub_folder:
|
||||
folder = os.path.join(folder, *sub_folder)
|
||||
|
||||
if not os.path.isdir(folder):
|
||||
os.makedirs(folder, 0o755, exist_ok=True)
|
||||
return folder
|
||||
|
||||
def get_data_file(self, path: str, *others: str) -> Optional[str]:
|
||||
rel_path = os.path.join(path, *others)
|
||||
parent = self.get_data_folder(os.path.dirname(rel_path))
|
||||
if not parent:
|
||||
return None
|
||||
return os.path.join(parent, os.path.basename(rel_path))
|
||||
|
||||
|
||||
_bot: Optional[NoneBot] = None
|
||||
|
||||
@ -103,11 +86,14 @@ def run(host: str = None, port: int = None, *args, **kwargs) -> None:
|
||||
_plugins = set()
|
||||
|
||||
|
||||
def clear_plugins() -> None:
|
||||
_plugins.clear()
|
||||
|
||||
|
||||
def load_plugins(plugin_dir: str, module_prefix: str) -> None:
|
||||
"""
|
||||
Find all non-hidden modules or packages in a given directory,
|
||||
and import them with the given module prefix.
|
||||
|
||||
:param plugin_dir: plugin directory to search
|
||||
:param module_prefix: module prefix used while importing
|
||||
"""
|
||||
for name in os.listdir(plugin_dir):
|
||||
path = os.path.join(plugin_dir, name)
|
||||
if os.path.isfile(path) and \
|
||||
@ -125,12 +111,15 @@ def load_plugins(plugin_dir: str, module_prefix: str) -> None:
|
||||
mod_name = f'{module_prefix}.{m.group(1)}'
|
||||
try:
|
||||
_plugins.add(importlib.import_module(mod_name))
|
||||
logger.info('Succeeded to import "{}"'.format(mod_name))
|
||||
logger.info(f'Succeeded to import "{mod_name}"')
|
||||
except ImportError:
|
||||
logger.warning('Failed to import "{}"'.format(mod_name))
|
||||
logger.warning(f'Failed to import "{mod_name}"')
|
||||
|
||||
|
||||
def load_builtin_plugins() -> None:
|
||||
"""
|
||||
Load built-in plugins distributed along with "none" package.
|
||||
"""
|
||||
plugin_dir = os.path.join(os.path.dirname(__file__), 'plugins')
|
||||
load_plugins(plugin_dir, 'none.plugins')
|
||||
|
||||
|
@ -8,6 +8,11 @@ class ParserExit(RuntimeError):
|
||||
|
||||
|
||||
class ArgumentParser(ArgumentParser):
|
||||
"""
|
||||
An ArgumentParser wrapper that avoid printing messages to
|
||||
standard I/O.
|
||||
"""
|
||||
|
||||
def _print_message(self, *args, **kwargs):
|
||||
# do nothing
|
||||
pass
|
||||
|
@ -8,6 +8,7 @@ from typing import (
|
||||
from aiocqhttp.message import Message
|
||||
|
||||
from . import NoneBot, permission as perm
|
||||
from .log import logger
|
||||
from .expression import render
|
||||
from .helpers import context_id
|
||||
from .session import BaseSession
|
||||
@ -26,8 +27,8 @@ _sessions = {}
|
||||
|
||||
|
||||
class Command:
|
||||
__slots__ = (
|
||||
'name', 'func', 'permission', 'only_to_me', 'args_parser_func')
|
||||
__slots__ = ('name', 'func', 'permission',
|
||||
'only_to_me', 'args_parser_func')
|
||||
|
||||
def __init__(self, *, name: Tuple[str], func: Callable, permission: int,
|
||||
only_to_me: bool):
|
||||
@ -266,6 +267,8 @@ def parse_command(bot: NoneBot,
|
||||
:param cmd_string: command string
|
||||
:return: (Command object, current arg string)
|
||||
"""
|
||||
logger.debug(f'Parsing command: {cmd_string}')
|
||||
|
||||
matched_start = None
|
||||
for start in bot.config.COMMAND_START:
|
||||
# loop through COMMAND_START to find the longest matched start
|
||||
@ -286,8 +289,11 @@ def parse_command(bot: NoneBot,
|
||||
|
||||
if matched_start is None:
|
||||
# it's not a command
|
||||
logger.debug('It\'s not a command')
|
||||
return None, None
|
||||
|
||||
logger.debug(f'Matched command start: '
|
||||
f'{matched_start}{"(space)" if not matched_start else ""}')
|
||||
full_command = cmd_string[len(matched_start):].lstrip()
|
||||
|
||||
if not full_command:
|
||||
@ -314,10 +320,13 @@ def parse_command(bot: NoneBot,
|
||||
if not cmd_name:
|
||||
cmd_name = (cmd_name_text,)
|
||||
|
||||
logger.debug(f'Split command name: {cmd_name}')
|
||||
cmd = _find_command(cmd_name)
|
||||
if not cmd:
|
||||
logger.debug(f'Command {cmd_name} not found')
|
||||
return None, None
|
||||
|
||||
logger.debug(f'Command {cmd.name} found, function: {cmd.func}')
|
||||
return cmd, ''.join(cmd_remained)
|
||||
|
||||
|
||||
@ -337,11 +346,13 @@ async def handle_command(bot: NoneBot, ctx: Dict[str, Any]) -> bool:
|
||||
if _sessions.get(ctx_id):
|
||||
session = _sessions[ctx_id]
|
||||
if session and session.is_valid:
|
||||
logger.debug(f'Session of command {session.cmd.name} exists')
|
||||
session.refresh(ctx, current_arg=str(ctx['message']))
|
||||
# there is no need to check permission for existing session
|
||||
check_perm = False
|
||||
else:
|
||||
# the session is expired, remove it
|
||||
logger.debug(f'Session of command {session.cmd.name} is expired')
|
||||
del _sessions[ctx_id]
|
||||
session = None
|
||||
if not session:
|
||||
@ -349,6 +360,7 @@ async def handle_command(bot: NoneBot, ctx: Dict[str, Any]) -> bool:
|
||||
if not cmd or cmd.only_to_me and not ctx['to_me']:
|
||||
return False
|
||||
session = CommandSession(bot, ctx, cmd, current_arg=current_arg)
|
||||
logger.debug(f'New session of command {session.cmd.name} created')
|
||||
return await _real_run_command(session, ctx_id, check_perm=check_perm)
|
||||
|
||||
|
||||
@ -395,6 +407,7 @@ async def _real_run_command(session: CommandSession,
|
||||
# override session only when not disabling interaction
|
||||
_sessions[ctx_id] = session
|
||||
try:
|
||||
logger.debug(f'Running command {session.cmd.name}')
|
||||
res = await session.cmd.run(session, **kwargs)
|
||||
if not disable_interaction:
|
||||
# the command is finished, remove the session
|
||||
@ -404,8 +417,11 @@ async def _real_run_command(session: CommandSession,
|
||||
if disable_interaction:
|
||||
# if the command needs further interaction, we view it as failed
|
||||
return False
|
||||
logger.debug(f'Further interaction needed for '
|
||||
f'command {session.cmd.name}')
|
||||
session.last_interaction = datetime.now()
|
||||
# return True because this step of the session is successful
|
||||
return True
|
||||
except _FinishException:
|
||||
logger.debug(f'Session of command {session.cmd.name} finished')
|
||||
return True
|
||||
|
@ -1,3 +1,19 @@
|
||||
"""
|
||||
Default configurations.
|
||||
|
||||
Any derived configurations must import everything from this module
|
||||
at the very beginning of their code, and then set their own value
|
||||
to override the default one.
|
||||
|
||||
For example:
|
||||
|
||||
>>> from none.default_config import *
|
||||
>>> PORT = 9090
|
||||
>>> DEBUG = False
|
||||
>>> SUPERUSERS.add(123456)
|
||||
>>> NICKNAME = '小明'
|
||||
"""
|
||||
|
||||
import os
|
||||
from datetime import timedelta
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
"""
|
||||
Provide logger object.
|
||||
|
||||
Any other modules in "none" should use "logger" from this module
|
||||
to log messages.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import sys
|
||||
|
||||
|
@ -9,6 +9,8 @@ from .natural_language import handle_natural_language
|
||||
|
||||
|
||||
async def handle_message(bot: NoneBot, ctx: Dict[str, Any]) -> None:
|
||||
_log_message(ctx)
|
||||
|
||||
if ctx['message_type'] != 'private':
|
||||
# group or discuss
|
||||
ctx['to_me'] = False
|
||||
@ -23,10 +25,21 @@ async def handle_message(bot: NoneBot, ctx: Dict[str, Any]) -> None:
|
||||
|
||||
handled = await handle_command(bot, ctx)
|
||||
if handled:
|
||||
logger.debug('Message is handled as a command')
|
||||
logger.info(f'Message {ctx["message_id"]} is handled as a command')
|
||||
return
|
||||
|
||||
handled = await handle_natural_language(bot, ctx)
|
||||
if handled:
|
||||
logger.debug('Message is handled as natural language')
|
||||
logger.info(f'Message {ctx["message_id"]} is handled '
|
||||
f'as natural language')
|
||||
return
|
||||
|
||||
|
||||
def _log_message(ctx: Dict[str, Any]) -> None:
|
||||
msg_from = f'{ctx["user_id"]}'
|
||||
if ctx['message_type'] == 'group':
|
||||
msg_from += f'@[群:{ctx["group_id"]}]'
|
||||
elif ctx['message_type'] == 'discuss':
|
||||
msg_from += f'@[讨论组:{ctx["discuss_id"]}]'
|
||||
logger.info(f'Message {ctx["message_id"]} from {msg_from}: '
|
||||
f'{ctx["message"]}')
|
||||
|
@ -89,6 +89,7 @@ async def handle_natural_language(bot: NoneBot, ctx: Dict[str, Any]) -> bool:
|
||||
nicknames = filter(lambda n: n, bot.config.NICKNAME)
|
||||
m = re.search(rf'^({"|".join(nicknames)})[\s,,]+', msg)
|
||||
if m:
|
||||
logger.debug(f'User is calling me {m.group(1)}')
|
||||
ctx['to_me'] = True
|
||||
msg = msg[m.end():]
|
||||
|
||||
@ -114,10 +115,13 @@ async def handle_natural_language(bot: NoneBot, ctx: Dict[str, Any]) -> bool:
|
||||
# wait for possible results, and sort them by confidence
|
||||
results = sorted(filter(lambda r: r, await asyncio.gather(*coros)),
|
||||
key=lambda r: r.confidence, reverse=True)
|
||||
logger.debug(results)
|
||||
logger.debug(f'NLP results: {results}')
|
||||
if results and results[0].confidence >= 60.0:
|
||||
# choose the result with highest confidence
|
||||
logger.debug(f'NLP result with highest confidence: {results[0]}')
|
||||
return await call_command(bot, ctx, results[0].cmd_name,
|
||||
args=results[0].cmd_args,
|
||||
check_perm=False)
|
||||
else:
|
||||
logger.debug('No NLP result having enough confidence')
|
||||
return False
|
||||
|
@ -76,9 +76,19 @@ async def handle_notice_or_request(bot: NoneBot, ctx: Dict[str, Any]) -> None:
|
||||
event += f'.{ctx["sub_type"]}'
|
||||
|
||||
if post_type == 'notice':
|
||||
_log_notice(ctx)
|
||||
session = NoticeSession(bot, ctx)
|
||||
else: # must be 'request'
|
||||
_log_request(ctx)
|
||||
session = RequestSession(bot, ctx)
|
||||
|
||||
logger.debug(f'Emitting event: {event}')
|
||||
await _bus.emit(event, session)
|
||||
|
||||
|
||||
def _log_notice(ctx: Dict[str, Any]) -> None:
|
||||
logger.info(f'Notice: {ctx}')
|
||||
|
||||
|
||||
def _log_request(ctx: Dict[str, Any]) -> None:
|
||||
logger.info(f'Request: {ctx}')
|
||||
|
Loading…
Reference in New Issue
Block a user