Archived
1
0
Fork 0
This repository has been archived on 2024-04-26. You can view files and clone it, but cannot push or open issues or pull requests.
akari-bot/core/parser/command.py

86 lines
3.5 KiB
Python
Raw Normal View History

2022-08-15 09:54:24 +00:00
import copy
2022-08-30 12:49:01 +00:00
import re
2021-07-18 16:17:09 +00:00
import shlex
2021-10-24 10:55:45 +00:00
import traceback
2022-08-07 17:56:38 +00:00
from typing import Union, Dict
2021-08-07 07:56:48 +00:00
2022-08-10 09:10:35 +00:00
from core.exceptions import InvalidCommandFormatError
2023-03-04 08:51:56 +00:00
from core.types import MessageSession, Module
2023-03-01 09:10:45 +00:00
from core.utils.i18n import get_target_locale, Locale
2022-08-08 09:10:35 +00:00
from .args import parse_argv, Template, templates_to_str, DescPattern
from ..logger import Logger
2021-10-15 17:36:22 +00:00
2021-07-19 16:12:29 +00:00
2021-07-18 16:17:09 +00:00
class CommandParser:
2023-03-04 08:51:56 +00:00
def __init__(self, args: Module, command_prefixes: list,
bind_prefix=None,
2021-11-19 16:33:53 +00:00
msg: MessageSession = None):
2022-08-23 04:53:34 +00:00
args = copy.deepcopy(args)
self.command_prefixes = command_prefixes
self.bind_prefix = bind_prefix
2021-10-24 10:55:45 +00:00
self.origin_template = args
2021-11-19 16:33:53 +00:00
self.msg: Union[MessageSession, None] = msg
2022-01-27 13:16:53 +00:00
self.options_desc = []
2023-03-04 08:51:56 +00:00
lang = get_target_locale(self.msg) if self.msg is not None else Locale('zh_cn')
2022-08-07 17:56:38 +00:00
help_docs = {}
2023-03-04 08:51:56 +00:00
for match in (args.command_list.set if self.msg is None else args.command_list.get(self.msg.target.targetFrom)):
2022-08-07 17:56:38 +00:00
if match.help_doc:
for m in match.help_doc:
help_docs[m] = {'priority': match.priority, 'meta': match}
2021-10-15 17:36:22 +00:00
else:
2022-08-07 17:56:38 +00:00
help_docs[''] = {'priority': match.priority, 'meta': match}
if match.options_desc is not None:
for m in match.options_desc:
2023-03-04 08:51:56 +00:00
desc = match.options_desc[m]
if locale_str := re.findall(r'\{(.*)}', desc):
for l in locale_str:
desc = desc.replace(f'{{{l}}}', lang.t(l))
self.options_desc.append(f'{m} {desc}')
2022-08-23 04:53:34 +00:00
self.args: Dict[Union[Template, ''], dict] = help_docs
2021-07-19 16:12:29 +00:00
2021-07-26 12:43:51 +00:00
def return_formatted_help_doc(self) -> str:
2023-03-04 10:08:40 +00:00
lang = self.msg.locale if self.msg is not None else Locale('zh_cn')
2022-08-06 13:39:24 +00:00
if not self.args:
2023-03-04 08:51:56 +00:00
return ''
2022-08-07 17:56:38 +00:00
lst = []
format_args = templates_to_str([args for args in self.args if args != ''], with_desc=True)
for x in format_args:
2023-03-01 09:10:45 +00:00
if locale_str := re.findall(r'\{(.*)}', x):
for l in locale_str:
x = x.replace(f'{{{l}}}', lang.t(l))
2022-08-07 17:56:38 +00:00
x = f'{self.command_prefixes[0]}{self.bind_prefix} {x}'
lst.append(x)
args = '\n'.join(y for y in lst)
2022-01-27 13:16:53 +00:00
if self.options_desc:
2023-03-01 09:10:45 +00:00
args += f'\n{lang.t("core.help.options")}\n' + '\n'.join(self.options_desc)
2021-07-19 16:12:29 +00:00
return args
2021-07-18 16:17:09 +00:00
def parse(self, command):
2021-10-24 10:55:45 +00:00
if self.args is None:
2021-09-10 18:05:27 +00:00
return None
2021-10-24 10:55:45 +00:00
command = re.sub(r'[“”]', '"', command)
2021-09-04 13:27:23 +00:00
try:
split_command = shlex.split(command)
except ValueError:
split_command = command.split(' ')
Logger.debug(split_command)
2021-07-19 16:12:29 +00:00
try:
2023-03-04 08:51:56 +00:00
if not self.origin_template.command_list.set:
2021-10-24 10:55:45 +00:00
if len(split_command) == 1:
2022-08-06 13:39:24 +00:00
return None, None
2021-10-24 10:55:45 +00:00
else:
if len(split_command) == 1:
2022-08-06 13:39:24 +00:00
if '' in self.args:
return self.args['']['meta'], None
2022-08-08 09:10:35 +00:00
for arg in self.args:
if len(arg.args) == 1 and isinstance(arg.args[0], DescPattern):
return self.args[arg]['meta'], None
2021-10-24 10:55:45 +00:00
raise InvalidCommandFormatError
else:
2022-08-07 17:56:38 +00:00
base_match = parse_argv(split_command[1:], [args for args in self.args if args != ''])
2022-08-06 13:39:24 +00:00
return self.args[base_match.original_template]['meta'], base_match.args
2021-10-24 10:55:45 +00:00
except InvalidCommandFormatError:
2021-10-24 10:55:45 +00:00
traceback.print_exc()
2021-07-19 16:12:29 +00:00
raise InvalidCommandFormatError