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/message.py

612 lines
35 KiB
Python
Raw Normal View History

2023-06-29 11:12:50 +00:00
import asyncio
import inspect
2021-02-01 15:13:11 +00:00
import re
import traceback
2021-10-20 14:04:30 +00:00
from datetime import datetime
2021-02-01 15:13:11 +00:00
2022-06-16 11:49:41 +00:00
from config import Config
2023-09-03 08:50:12 +00:00
from core.builtins import command_prefix, ExecutionLockList, ErrorMessage, MessageTaskManager, Url, Bot, \
base_superuser_list
2022-06-28 08:47:00 +00:00
from core.exceptions import AbuseWarning, FinishedException, InvalidCommandFormatError, InvalidHelpDocTypeError, \
2023-06-10 03:59:24 +00:00
WaitCancelException, NoReportException, SendMessageFailed
2023-07-07 08:07:13 +00:00
from core.loader import ModulesManager, current_unloaded_modules, err_modules
2021-07-07 16:00:24 +00:00
from core.logger import Logger
2022-05-22 15:05:06 +00:00
from core.parser.command import CommandParser
2021-10-20 14:04:30 +00:00
from core.tos import warn_target
2023-03-04 08:51:56 +00:00
from core.types import Module
2023-09-01 14:38:32 +00:00
from core.utils.message import remove_duplicate_space
from database import BotDBUtil
2021-02-01 15:13:11 +00:00
2022-06-16 11:49:41 +00:00
enable_tos = Config('enable_tos')
2022-07-14 13:23:15 +00:00
enable_analytics = Config('enable_analytics')
2023-07-20 13:30:07 +00:00
bug_report_targets = Config('bug_report_targets')
2022-06-16 11:49:41 +00:00
2023-11-19 07:53:35 +00:00
TOS_TEMPBAN_TIME = Config('tos_temp_ban_time', 300)
2021-10-20 14:04:30 +00:00
counter_same = {} # 命令使用次数计数(重复使用单一命令)
counter_all = {} # 命令使用次数计数(使用所有命令)
2022-08-03 15:35:38 +00:00
temp_ban_counter = {} # 临时限制计数
2021-10-20 14:04:30 +00:00
2022-01-20 12:13:03 +00:00
async def remove_temp_ban(msg: Bot.MessageSession):
2023-09-01 14:38:32 +00:00
is_temp_banned = temp_ban_counter.get(msg.target.sender_id)
2023-12-19 08:50:45 +00:00
if is_temp_banned:
2023-09-01 14:38:32 +00:00
del temp_ban_counter[msg.target.sender_id]
2021-10-20 14:04:30 +00:00
2022-01-20 12:13:03 +00:00
2023-07-08 15:09:21 +00:00
async def tos_msg_counter(msg: Bot.MessageSession, command: str):
2023-09-01 14:38:32 +00:00
same = counter_same.get(msg.target.sender_id)
2023-12-19 06:35:50 +00:00
if not same or datetime.now().timestamp() - same['ts'] > 300 or same['command'] != command:
2023-10-25 16:27:43 +00:00
# 检查是否滥用5分钟内重复使用同一命令10条
2023-09-01 14:38:32 +00:00
counter_same[msg.target.sender_id] = {'command': command, 'count': 1,
'ts': datetime.now().timestamp()}
2021-10-20 14:04:30 +00:00
else:
same['count'] += 1
if same['count'] > 10:
2023-04-08 07:23:08 +00:00
raise AbuseWarning(msg.locale.t("tos.reason.cooldown"))
2023-09-01 14:38:32 +00:00
all_ = counter_all.get(msg.target.sender_id)
2023-12-19 06:35:50 +00:00
if not all_ or datetime.now().timestamp() - all_['ts'] > 300: # 检查是否滥用5分钟内使用20条命令
2023-09-01 14:38:32 +00:00
counter_all[msg.target.sender_id] = {'count': 1,
'ts': datetime.now().timestamp()}
2021-10-20 14:04:30 +00:00
else:
all_['count'] += 1
if all_['count'] > 20:
2023-04-08 07:23:08 +00:00
raise AbuseWarning(msg.locale.t("tos.reason.abuse"))
2021-10-20 14:04:30 +00:00
2021-10-14 15:18:47 +00:00
async def temp_ban_check(msg: Bot.MessageSession):
2023-09-01 14:38:32 +00:00
is_temp_banned = temp_ban_counter.get(msg.target.sender_id)
2023-11-19 07:53:35 +00:00
is_superuser = msg.check_super_user()
2023-12-19 08:50:45 +00:00
if is_temp_banned and not is_superuser:
2022-05-22 14:42:54 +00:00
ban_time = datetime.now().timestamp() - is_temp_banned['ts']
2023-11-19 07:53:35 +00:00
if ban_time < TOS_TEMPBAN_TIME:
2022-05-22 14:42:54 +00:00
if is_temp_banned['count'] < 2:
is_temp_banned['count'] += 1
2023-11-19 07:53:35 +00:00
return await msg.finish(msg.locale.t("tos.tempbanned", ban_time=str(int(TOS_TEMPBAN_TIME - ban_time))))
2022-05-22 14:42:54 +00:00
elif is_temp_banned['count'] <= 5:
is_temp_banned['count'] += 1
2023-11-19 07:53:35 +00:00
return await msg.finish(msg.locale.t("tos.tempbanned.warning", ban_time=str(int(TOS_TEMPBAN_TIME - ban_time))))
2022-05-22 14:42:54 +00:00
else:
2023-04-08 07:23:08 +00:00
raise AbuseWarning(msg.locale.t("tos.reason.bypass"))
2022-05-22 14:42:54 +00:00
async def parser(msg: Bot.MessageSession, require_enable_modules: bool = True, prefix: list = None,
2022-06-19 02:16:04 +00:00
running_mention: bool = False):
2021-02-03 07:40:17 +00:00
"""
接收消息必经的预处理器
2021-07-24 08:59:15 +00:00
:param msg: 从监听器接收到的dict该dict将会经过此预处理器传入下游
2022-01-26 09:52:17 +00:00
:param require_enable_modules: 是否需要检查模块是否已启用
:param prefix: 使用的命令前缀如果为None则使用默认的命令前缀存在''值的情况下则代表无需命令前缀
2022-03-16 11:20:30 +00:00
:param running_mention: 消息内若包含机器人名称则检查是否有命令正在运行
2021-02-03 07:40:17 +00:00
:return: 无返回
"""
2023-09-01 14:38:32 +00:00
identify_str = f'[{msg.target.sender_id}{f" ({msg.target.target_id})" if msg.target.target_from != msg.target.sender_from else ""}]'
# Logger.info(f'{identify_str} -> [Bot]: {display}')
2022-05-22 14:36:37 +00:00
try:
2023-06-29 11:12:50 +00:00
asyncio.create_task(MessageTaskManager.check(msg))
2023-09-01 14:38:32 +00:00
modules = ModulesManager.return_modules_list(msg.target.target_from)
2023-09-01 14:38:32 +00:00
msg.trigger_msg = remove_duplicate_space(msg.as_display()) # 将消息转换为一般显示形式
2023-06-09 11:03:01 +00:00
if len(msg.trigger_msg) == 0:
2021-07-12 13:31:11 +00:00
return
2023-09-01 14:38:32 +00:00
msg.target.sender_info = BotDBUtil.SenderInfo(msg.target.sender_id)
if msg.target.sender_info.query.isInBlockList and not msg.target.sender_info.query.isInAllowList and not msg.target.sender_info.query.isSuperUser \
or msg.target.sender_id in msg.options.get('ban', []):
2023-03-04 08:51:56 +00:00
return
msg.prefixes = command_prefix.copy() # 复制一份作为基础命令前缀
get_custom_alias = msg.options.get('command_alias')
2023-12-19 08:50:45 +00:00
if get_custom_alias:
get_display_alias = get_custom_alias.get(msg.trigger_msg)
2023-12-19 08:50:45 +00:00
if get_display_alias:
2023-06-09 11:03:01 +00:00
msg.trigger_msg = get_display_alias
get_custom_prefix = msg.options.get('command_prefix') # 获取自定义命令前缀
2023-12-19 08:50:45 +00:00
if get_custom_prefix:
msg.prefixes = get_custom_prefix + msg.prefixes # 混合
2022-05-22 14:36:37 +00:00
disable_prefix = False
2023-12-19 08:50:45 +00:00
if prefix: # 如果上游指定了命令前缀,则使用指定的命令前缀
2022-05-22 14:36:37 +00:00
if '' in prefix:
disable_prefix = True
msg.prefixes.clear()
msg.prefixes.extend(prefix)
display_prefix = ''
in_prefix_list = False
for cp in msg.prefixes: # 判断是否在命令前缀列表中
2023-06-09 11:03:01 +00:00
if msg.trigger_msg.startswith(cp):
display_prefix = cp
in_prefix_list = True
break
if in_prefix_list or disable_prefix: # 检查消息前缀
2023-06-09 11:03:01 +00:00
if len(msg.trigger_msg) <= 1 or msg.trigger_msg[:2] == '~~': # 排除 ~~xxx~~ 的情况
2022-01-08 11:05:17 +00:00
return
2023-05-15 14:26:53 +00:00
if in_prefix_list: # 如果在命令前缀列表中,则将此命令前缀移动到列表首位
msg.prefixes.remove(display_prefix)
msg.prefixes.insert(0, display_prefix)
2022-05-22 14:36:37 +00:00
Logger.info(
2023-06-09 11:03:01 +00:00
f'{identify_str} -> [Bot]: {msg.trigger_msg}')
if disable_prefix and not in_prefix_list:
2023-06-09 11:03:01 +00:00
command = msg.trigger_msg
2022-05-22 14:36:37 +00:00
else:
2023-06-09 11:03:01 +00:00
command = msg.trigger_msg[len(display_prefix):]
if not ExecutionLockList.check(msg): # 加锁
2022-05-22 14:36:37 +00:00
ExecutionLockList.add(msg)
else:
2023-09-01 14:38:32 +00:00
return await msg.send_message(msg.locale.t("parser.command.running.prompt"))
2023-03-04 08:51:56 +00:00
no_alias = False
for moduleName in modules:
if command.startswith(moduleName): # 判断此命令是否匹配一个实际的模块
no_alias = True
2023-07-09 05:06:28 +00:00
if not no_alias:
for um in current_unloaded_modules:
if command.startswith(um):
no_alias = True
if not no_alias:
for em in err_modules:
if command.startswith(em):
no_alias = True
2023-03-04 08:51:56 +00:00
if not no_alias: # 如果没有匹配到模块,则判断是否匹配命令别名
alias_list = []
2023-04-19 08:29:46 +00:00
for alias in ModulesManager.modules_aliases:
if command.startswith(alias) and not command.startswith(ModulesManager.modules_aliases[alias]):
2023-03-04 08:51:56 +00:00
alias_list.append(alias)
if alias_list:
max_ = max(alias_list, key=len)
2023-04-19 08:29:46 +00:00
command = command.replace(max_, ModulesManager.modules_aliases[max_], 1)
2023-03-04 08:51:56 +00:00
command_split: list = command.split(' ') # 切割消息
msg.trigger_msg = command # 触发该命令的消息,去除消息前缀
command_first_word = command_split[0].lower()
sudo = False
mute = False
if command_first_word == 'mute':
mute = True
if command_first_word == 'sudo':
2023-09-01 14:38:32 +00:00
if not msg.check_super_user():
2023-10-25 16:57:26 +00:00
return await msg.send_message(msg.locale.t("parser.superuser.permission.denied"))
2023-03-04 08:51:56 +00:00
sudo = True
del command_split[0]
command_first_word = command_split[0].lower()
2023-03-04 08:51:56 +00:00
msg.trigger_msg = ' '.join(command_split)
2023-03-04 08:51:56 +00:00
in_mute = msg.muted
if in_mute and not mute:
return
2023-03-04 08:51:56 +00:00
if command_first_word in modules: # 检查触发命令是否在模块列表中
time_start = datetime.now()
try:
if enable_tos:
await temp_ban_check(msg)
module: Module = modules[command_first_word]
if not module.command_list.set: # 如果没有可用的命令,则展示模块简介
2023-12-19 08:50:45 +00:00
if module.desc:
2023-08-12 06:18:43 +00:00
desc = msg.locale.t("parser.module.desc", desc=msg.locale.tl_str(module.desc))
2023-04-08 17:51:57 +00:00
2023-03-04 08:51:56 +00:00
if command_first_word not in msg.enabled_modules:
2023-03-05 11:15:44 +00:00
desc += '\n' + msg.locale.t("parser.module.disabled.prompt", module=command_first_word,
prefix=msg.prefixes[0])
2023-09-01 14:38:32 +00:00
await msg.send_message(desc)
2023-03-04 08:51:56 +00:00
else:
2023-09-01 14:38:32 +00:00
await msg.send_message(ErrorMessage(msg.locale.t("error.module.unbound",
module=command_first_word)))
2023-03-04 08:51:56 +00:00
return
if module.required_base_superuser:
2023-09-01 14:38:32 +00:00
if msg.target.sender_id not in base_superuser_list:
await msg.send_message(msg.locale.t("parser.superuser.permission.denied"))
return
elif module.required_superuser:
2023-09-01 14:38:32 +00:00
if not msg.check_super_user():
await msg.send_message(msg.locale.t("parser.superuser.permission.denied"))
2023-03-04 08:51:56 +00:00
return
elif not module.base:
if command_first_word not in msg.enabled_modules and not sudo and require_enable_modules: # 若未开启
2023-09-01 14:38:32 +00:00
await msg.send_message(
2023-03-05 11:15:44 +00:00
msg.locale.t("parser.module.disabled.prompt", module=command_first_word,
prefix=msg.prefixes[0]))
2023-03-04 08:51:56 +00:00
return
elif module.required_admin:
2023-09-01 14:38:32 +00:00
if not await msg.check_permission():
await msg.send_message(msg.locale.t("parser.admin.module.permission.denied",
module=command_first_word))
2023-03-04 08:51:56 +00:00
return
none_doc = True # 检查模块绑定的命令是否有文档
2023-09-01 14:38:32 +00:00
for func in module.command_list.get(msg.target.target_from):
2023-03-04 08:51:56 +00:00
if func.help_doc:
none_doc = False
if not none_doc: # 如果有,送入命令解析
async def execute_submodule(msg: Bot.MessageSession, command_first_word, command_split):
2023-03-04 08:51:56 +00:00
try:
command_parser = CommandParser(module, msg=msg, bind_prefix=command_first_word,
command_prefixes=msg.prefixes)
2022-05-22 14:36:37 +00:00
try:
2023-03-04 08:51:56 +00:00
parsed_msg = command_parser.parse(msg.trigger_msg) # 解析命令对应的子模块
submodule = parsed_msg[0]
msg.parsed_msg = parsed_msg[1] # 使用命令模板解析后的消息
Logger.debug(msg.parsed_msg)
if submodule.required_base_superuser:
2023-09-01 14:38:32 +00:00
if msg.target.sender_id not in base_superuser_list:
await msg.send_message(msg.locale.t("parser.superuser.permission.denied"))
return
elif submodule.required_superuser:
2023-09-01 14:38:32 +00:00
if not msg.check_super_user():
await msg.send_message(msg.locale.t("parser.superuser.permission.denied"))
2023-03-04 08:51:56 +00:00
return
elif submodule.required_admin:
2023-09-01 14:38:32 +00:00
if not await msg.check_permission():
await msg.send_message(
2023-03-05 11:15:44 +00:00
msg.locale.t("parser.admin.submodule.permission.denied"))
2023-03-04 08:51:56 +00:00
return
2023-09-01 14:38:32 +00:00
if msg.target.target_from in submodule.exclude_from or \
2023-03-04 08:51:56 +00:00
('*' not in submodule.available_for and
2023-09-01 14:38:32 +00:00
msg.target.target_from not in submodule.available_for):
2023-03-04 08:51:56 +00:00
raise InvalidCommandFormatError
2022-07-21 17:50:28 +00:00
kwargs = {}
func_params = inspect.signature(submodule.function).parameters
2023-12-19 08:50:45 +00:00
if len(func_params) > 1 and msg.parsed_msg:
2023-05-22 17:03:25 +00:00
parsed_msg_ = msg.parsed_msg.copy()
for param_name, param_obj in func_params.items():
2023-05-28 09:21:33 +00:00
if param_obj.annotation == Bot.MessageSession:
kwargs[param_name] = msg
param_name_ = param_name
2023-05-22 17:03:25 +00:00
if (param_name__ := f'<{param_name}>') in parsed_msg_:
param_name_ = param_name__
2023-05-22 17:03:25 +00:00
if param_name_ in parsed_msg_:
kwargs[param_name] = parsed_msg_[param_name_]
try:
if param_obj.annotation == int:
2023-05-22 17:03:25 +00:00
kwargs[param_name] = int(parsed_msg_[param_name_])
elif param_obj.annotation == float:
2023-05-22 17:03:25 +00:00
kwargs[param_name] = float(parsed_msg_[param_name_])
elif param_obj.annotation == bool:
2023-05-22 17:03:25 +00:00
kwargs[param_name] = bool(parsed_msg_[param_name_])
del parsed_msg_[param_name_]
except (KeyError, ValueError):
raise InvalidCommandFormatError
else:
if param_name_ not in kwargs:
2023-05-22 17:03:25 +00:00
if param_obj.default is not inspect.Parameter.empty:
kwargs[param_name_] = param_obj.default
else:
kwargs[param_name_] = None
else:
kwargs[func_params[list(func_params.keys())[0]].name] = msg
2023-09-01 14:38:32 +00:00
if not msg.target.sender_info.query.disable_typing:
2022-05-22 14:36:37 +00:00
async with msg.Typing(msg):
await parsed_msg[0].function(**kwargs) # 将msg传入下游模块
2022-05-22 14:36:37 +00:00
else:
await parsed_msg[0].function(**kwargs)
2022-07-14 13:23:15 +00:00
raise FinishedException(msg.sent) # if not using msg.finish
2023-03-04 08:51:56 +00:00
except InvalidCommandFormatError:
2023-09-01 14:38:32 +00:00
await msg.send_message(msg.locale.t("parser.command.format.invalid",
module=command_first_word,
prefix=msg.prefixes[0]))
2023-03-04 08:51:56 +00:00
"""if msg.options.get('typo_check', True): # 判断是否开启错字检查
nmsg, command_first_word, command_split = await typo_check(msg,
display_prefix,
modules,
command_first_word,
command_split)
if nmsg is None:
return ExecutionLockList.remove(msg)
msg = nmsg
await execute_submodule(msg, command_first_word, command_split)"""
return
except InvalidHelpDocTypeError:
Logger.error(traceback.format_exc())
2023-09-01 14:38:32 +00:00
await msg.send_message(
2023-03-05 11:15:44 +00:00
ErrorMessage(msg.locale.t("error.module.helpdoc.invalid",
module=command_first_word)))
2023-03-04 08:51:56 +00:00
return
await execute_submodule(msg, command_first_word, command_split)
else: # 如果没有,直接传入下游模块
msg.parsed_msg = None
for func in module.command_list.set:
if not func.help_doc:
2023-09-01 14:38:32 +00:00
if not msg.target.sender_info.query.disable_typing:
2023-03-04 08:51:56 +00:00
async with msg.Typing(msg):
await func.function(msg) # 将msg传入下游模块
else:
await func.function(msg)
raise FinishedException(msg.sent) # if not using msg.finish
2023-06-10 03:59:24 +00:00
except SendMessageFailed:
2023-09-01 14:38:32 +00:00
if msg.target.target_from == 'QQ|Group':
2023-05-12 14:13:04 +00:00
await msg.call_api('send_group_msg', group_id=msg.session.target,
message=f'[CQ:poke,qq={Config("qq_account")}]')
2023-09-01 14:38:32 +00:00
await msg.send_message(msg.locale.t("error.message.limited"))
2023-03-04 08:51:56 +00:00
except FinishedException as e:
time_used = datetime.now() - time_start
Logger.info(f'Successfully finished session from {identify_str}, returns: {str(e)}. '
f'Times take up: {str(time_used)}')
2023-09-01 14:38:32 +00:00
if (msg.target.target_from != 'QQ|Guild' or command_first_word != 'module') and enable_tos:
2023-07-08 15:09:21 +00:00
await tos_msg_counter(msg, msg.trigger_msg)
2023-03-04 08:51:56 +00:00
else:
2023-06-02 11:28:40 +00:00
Logger.debug(f'Tos is disabled, check the configuration if it is not work as expected.')
2023-03-04 08:51:56 +00:00
if enable_analytics:
BotDBUtil.Analytics(msg).add(msg.trigger_msg, command_first_word, 'normal')
2023-04-08 11:31:25 +00:00
except AbuseWarning as e:
2023-11-19 08:41:33 +00:00
if enable_tos and Config('tos_warning_counts', 5) >= 1:
2023-04-08 11:31:25 +00:00
await warn_target(msg, str(e))
2023-09-01 14:38:32 +00:00
temp_ban_counter[msg.target.sender_id] = {'count': 1,
'ts': datetime.now().timestamp()}
2023-04-26 03:08:52 +00:00
else:
2023-09-01 14:38:32 +00:00
await msg.send_message(msg.locale.t("error.prompt.noreport", err_msg=e))
2023-04-08 11:31:25 +00:00
2023-03-04 08:51:56 +00:00
except NoReportException as e:
Logger.error(traceback.format_exc())
2023-08-12 06:18:43 +00:00
err_msg = msg.locale.tl_str(str(e))
2023-09-01 14:38:32 +00:00
await msg.send_message(msg.locale.t("error.prompt.noreport", err_msg=err_msg))
2023-03-04 08:51:56 +00:00
except Exception as e:
2023-07-20 13:30:07 +00:00
tb = traceback.format_exc()
Logger.error(tb)
2024-01-12 16:22:23 +00:00
errmsg = msg.locale.t('error.prompt', err_msg=str(e))
2024-01-12 16:27:30 +00:00
if Config('bug_report_url'):
errmsg += '\n' + msg.locale.t('error.prompt.address', url=str(Url(Config('bug_report_url'))))
2024-01-12 16:22:23 +00:00
await msg.send_message(errmsg)
2023-07-20 13:30:07 +00:00
if bug_report_targets:
for target in bug_report_targets:
if f := await Bot.FetchTarget.fetch_target(target):
2023-09-03 08:50:12 +00:00
await f.send_direct_message(
2023-12-11 04:48:20 +00:00
msg.locale.t('error.message.report', module=msg.trigger_msg) + tb)
2023-09-01 14:38:32 +00:00
if command_first_word in current_unloaded_modules and msg.check_super_user():
2023-09-03 08:50:12 +00:00
await msg.send_message(
msg.locale.t('parser.module.unloaded', module=command_first_word, prefix=msg.prefixes[0]))
2023-07-07 08:07:13 +00:00
elif command_first_word in err_modules:
2023-09-01 14:38:32 +00:00
await msg.send_message(msg.locale.t('error.module.unloaded', module=command_first_word))
2023-07-07 06:34:00 +00:00
2022-06-26 06:06:26 +00:00
return msg
2023-11-18 14:29:48 +00:00
if msg.muted:
return
if running_mention:
2023-06-09 11:03:01 +00:00
if msg.trigger_msg.find('小可') != -1:
if ExecutionLockList.check(msg):
2023-09-01 14:38:32 +00:00
return await msg.send_message(msg.locale.t('parser.command.running.prompt2'))
2023-03-04 08:51:56 +00:00
for m in modules: # 遍历模块
try:
2023-03-04 08:51:56 +00:00
if m in msg.enabled_modules and modules[m].regex_list.set: # 如果模块已启用
regex_module = modules[m]
if regex_module.required_base_superuser:
2023-09-01 14:38:32 +00:00
if msg.target.sender_id not in base_superuser_list:
continue
elif regex_module.required_superuser:
2023-09-01 14:38:32 +00:00
if not msg.check_super_user():
continue
elif regex_module.required_admin:
2023-09-01 14:38:32 +00:00
if not await msg.check_permission():
continue
2023-09-01 14:38:32 +00:00
if msg.target.target_from in regex_module.exclude_from or \
2023-03-04 08:51:56 +00:00
('*' not in regex_module.available_for and
2023-09-01 14:38:32 +00:00
msg.target.target_from not in regex_module.available_for):
2023-03-04 08:51:56 +00:00
continue
for rfunc in regex_module.regex_list.set: # 遍历正则模块的表达式
2022-08-27 16:30:34 +00:00
time_start = datetime.now()
2022-08-04 07:00:40 +00:00
try:
msg.matched_msg = False
matched = False
if rfunc.mode.upper() in ['M', 'MATCH']:
2023-06-09 11:03:01 +00:00
msg.matched_msg = re.match(rfunc.pattern, msg.trigger_msg, flags=rfunc.flags)
2023-12-19 08:50:45 +00:00
if msg.matched_msg:
2022-08-04 07:00:40 +00:00
matched = True
elif rfunc.mode.upper() in ['A', 'FINDALL']:
2023-06-09 11:03:01 +00:00
msg.matched_msg = re.findall(rfunc.pattern, msg.trigger_msg, flags=rfunc.flags)
2023-12-19 08:50:45 +00:00
if msg.matched_msg:
2022-08-04 07:00:40 +00:00
matched = True
2023-09-01 14:38:32 +00:00
if matched and not (msg.target.target_from in regex_module.exclude_from or
2023-03-04 08:51:56 +00:00
('*' not in regex_module.available_for and
2023-09-01 14:38:32 +00:00
msg.target.target_from not in regex_module.available_for)): # 如果匹配成功
if rfunc.logging:
Logger.info(
2023-06-09 11:03:01 +00:00
f'{identify_str} -> [Bot]: {msg.trigger_msg}')
2022-08-31 15:30:09 +00:00
if enable_tos and rfunc.show_typing:
2022-08-04 07:00:40 +00:00
await temp_ban_check(msg)
2023-03-04 08:51:56 +00:00
if rfunc.required_superuser:
2023-09-01 14:38:32 +00:00
if not msg.check_super_user():
2022-08-04 07:00:40 +00:00
continue
2023-03-04 08:51:56 +00:00
elif rfunc.required_admin:
2023-09-01 14:38:32 +00:00
if not await msg.check_permission():
2022-08-04 07:00:40 +00:00
continue
if not ExecutionLockList.check(msg):
ExecutionLockList.add(msg)
else:
2023-09-01 14:38:32 +00:00
return await msg.send_message(msg.locale.t("parser.command.running.prompt"))
if rfunc.show_typing and not msg.target.sender_info.query.disable_typing:
2022-08-04 07:00:40 +00:00
async with msg.Typing(msg):
await rfunc.function(msg) # 将msg传入下游模块
else:
await rfunc.function(msg) # 将msg传入下游模块
raise FinishedException(msg.sent) # if not using msg.finish
except FinishedException as e:
2022-08-27 16:30:34 +00:00
time_used = datetime.now() - time_start
2022-12-08 09:16:53 +00:00
if rfunc.logging:
Logger.info(
f'Successfully finished session from {identify_str}, returns: {str(e)}. '
f'Times take up: {time_used}')
2022-08-04 07:00:40 +00:00
2022-09-01 15:40:03 +00:00
if enable_analytics and rfunc.show_typing:
2023-03-04 08:51:56 +00:00
BotDBUtil.Analytics(msg).add(msg.trigger_msg, m, 'regex')
2022-08-04 07:00:40 +00:00
2022-08-31 15:05:42 +00:00
if enable_tos and rfunc.show_typing:
2023-07-08 15:09:21 +00:00
await tos_msg_counter(msg, msg.trigger_msg)
2022-08-09 16:38:03 +00:00
else:
2023-06-03 07:02:12 +00:00
Logger.debug(f'Tos is disabled, check the configuration if it is not work as expected.')
2022-08-04 07:00:40 +00:00
continue
2023-04-04 16:36:07 +00:00
except NoReportException as e:
Logger.error(traceback.format_exc())
2023-08-12 06:18:43 +00:00
err_msg = msg.locale.tl_str(str(e))
2023-09-01 14:38:32 +00:00
await msg.send_message(msg.locale.t("error.prompt.noreport", err_msg=err_msg))
2023-04-08 09:31:53 +00:00
2023-04-08 11:31:25 +00:00
except AbuseWarning as e:
2023-11-19 08:49:03 +00:00
if enable_tos and Config('tos_warning_counts', 5) >= 1:
2023-04-08 11:31:25 +00:00
await warn_target(msg, str(e))
2023-09-01 14:38:32 +00:00
temp_ban_counter[msg.target.sender_id] = {'count': 1,
'ts': datetime.now().timestamp()}
2023-04-26 03:08:52 +00:00
else:
2023-09-01 14:38:32 +00:00
await msg.send_message(msg.locale.t("error.prompt.noreport", err_msg=e))
2023-04-08 11:31:25 +00:00
2023-04-08 09:31:53 +00:00
except Exception as e:
2023-07-20 13:35:31 +00:00
tb = traceback.format_exc()
Logger.error(tb)
2024-01-12 16:22:23 +00:00
errmsg = msg.locale.t('error.prompt', err_msg=str(e))
if Config('bug_report_url'):
2024-02-01 12:21:54 +00:00
errmsg += '\n' + msg.locale.t('error.prompt.address',
url=str(Url(Config('bug_report_url'))))
2024-01-12 16:22:23 +00:00
await msg.send_message(errmsg)
2023-07-20 13:35:31 +00:00
if bug_report_targets:
for target in bug_report_targets:
if f := await Bot.FetchTarget.fetch_target(target):
2023-09-03 08:50:12 +00:00
await f.send_direct_message(
msg.locale.t('error.message.report', module=msg.trigger_msg) + tb)
2023-03-04 08:51:56 +00:00
finally:
ExecutionLockList.remove(msg)
2023-06-10 03:59:24 +00:00
except SendMessageFailed:
2023-09-01 14:38:32 +00:00
if msg.target.target_from == 'QQ|Group':
2023-05-12 14:13:04 +00:00
await msg.call_api('send_group_msg', group_id=msg.session.target,
message=f'[CQ:poke,qq={Config("qq_account")}]')
2023-09-01 14:38:32 +00:00
await msg.send_message((msg.locale.t("error.message.limited")))
continue
return msg
except WaitCancelException: # 出现于等待被取消的情况
2022-08-04 07:52:42 +00:00
Logger.warn('Waiting task cancelled by user.')
2022-05-22 14:36:37 +00:00
except Exception:
Logger.error(traceback.format_exc())
2023-03-04 08:51:56 +00:00
finally:
ExecutionLockList.remove(msg)
2022-08-08 17:02:25 +00:00
2023-03-04 08:51:56 +00:00
"""async def typo_check(msg: MessageSession, display_prefix, modules, command_first_word, command_split):
2022-08-08 17:02:25 +00:00
enabled_modules = []
for m in msg.enabled_modules:
2022-08-09 17:02:50 +00:00
if m in modules and isinstance(modules[m], Command):
2022-08-08 17:02:25 +00:00
enabled_modules.append(m)
match_close_module: list = difflib.get_close_matches(command_first_word, enabled_modules, 1, 0.6)
if match_close_module:
module = modules[match_close_module[0]]
none_doc = True # 检查模块绑定的命令是否有文档
for func in module.match_list.get(msg.target.targetFrom):
if func.help_doc is not None:
none_doc = False
len_command_split = len(command_split)
if not none_doc and len_command_split > 1:
get_submodules: List[CommandMeta] = module.match_list.get(msg.target.targetFrom)
docs = {} # 根据命令模板的空格数排序命令
for func in get_submodules:
2022-08-23 07:36:07 +00:00
help_doc: List[Template] = copy.deepcopy(func.help_doc)
2022-08-08 17:02:25 +00:00
if not help_doc:
... # todo: ...此处应该有一个处理例外情况的逻辑
for h_ in help_doc:
2022-08-23 07:36:07 +00:00
h_.args_ = [a for a in h_.args if isinstance(a, ArgumentPattern)]
2022-08-08 17:02:25 +00:00
if (len_args := len(h_.args)) not in docs:
docs[len_args] = [h_]
else:
docs[len_args].append(h_)
if len_command_split - 1 > len(docs): # 如果空格数远大于命令模板的空格数
select_docs = docs[max(docs)]
else:
select_docs = docs[len_command_split - 1] # 选择匹配的命令组
2023-01-28 05:53:11 +00:00
match_close_command: list = difflib.get_close_matches(' '.join(command_split[1:]),
templates_to_str(select_docs),
2022-08-08 17:02:25 +00:00
1, 0.3) # 进一步匹配命令
if match_close_command:
match_split = match_close_command[0]
2023-04-30 03:30:59 +00:00
m_split_options = filter(None, re.split(r'(\\[.*?])', match_split)) # 切割可选参数
2022-08-08 17:02:25 +00:00
old_command_split = command_split.copy()
del old_command_split[0]
new_command_split = [match_close_module[0]]
for m_ in m_split_options:
if m_.startswith('['): # 如果是可选参数
m_split = m_.split(' ') # 切割可选参数中的空格(说明存在多个子必须参数)
if len(m_split) > 1:
match_close_options = difflib.get_close_matches(m_split[0][1:], old_command_split, 1,
0.3) # 进一步匹配可选参数
if match_close_options:
position = old_command_split.index(match_close_options[0]) # 定位可选参数的位置
new_command_split.append(m_split[0][1:]) # 将可选参数插入到新命令列表中
new_command_split += old_command_split[position + 1: position + len(m_split)]
del old_command_split[position: position + len(m_split)] # 删除原命令列表中的可选参数
else:
if m_split[0][1] == '<':
new_command_split.append(old_command_split[0])
del old_command_split[0]
else:
new_command_split.append(m_split[0][1:-1])
else:
m__ = filter(None, m_.split(' ')) # 必须参数
for mm in m__:
if len(old_command_split) > 0:
if mm.startswith('<'):
new_command_split.append(old_command_split[0])
del old_command_split[0]
else:
match_close_args = difflib.get_close_matches(old_command_split[0], [mm], 1,
0.5) # 进一步匹配参数
if match_close_args:
new_command_split.append(mm)
del old_command_split[0]
else:
new_command_split.append(old_command_split[0])
del old_command_split[0]
else:
new_command_split.append(mm)
new_command_display = " ".join(new_command_split)
if new_command_display != msg.trigger_msg:
wait_confirm = await msg.waitConfirm(
2024-01-28 10:03:05 +00:00
f'你是否想要输入{display_prefix}{new_command_display}')
2022-08-08 17:02:25 +00:00
if wait_confirm:
command_split = new_command_split
command_first_word = new_command_split[0]
msg.trigger_msg = ' '.join(new_command_split)
return msg, command_first_word, command_split
else:
if len_command_split - 1 == 1:
new_command_display = f'{match_close_module[0]} {" ".join(command_split[1:])}'
if new_command_display != msg.trigger_msg:
wait_confirm = await msg.waitConfirm(
2024-01-28 10:03:05 +00:00
f'你是否想要输入{display_prefix}{new_command_display}')
2022-08-08 17:02:25 +00:00
if wait_confirm:
command_split = [match_close_module[0]] + command_split[1:]
command_first_word = match_close_module[0]
msg.trigger_msg = ' '.join(command_split)
return msg, command_first_word, command_split
else:
new_command_display = f'{match_close_module[0] + (" " + " ".join(command_split[1:]) if len(command_split) > 1 else "")}'
if new_command_display != msg.trigger_msg:
wait_confirm = await msg.waitConfirm(
2024-01-28 10:03:05 +00:00
f'你是否想要输入{display_prefix}{new_command_display}')
2022-08-08 17:02:25 +00:00
if wait_confirm:
command_split = [match_close_module[0]]
command_first_word = match_close_module[0]
msg.trigger_msg = ' '.join(command_split)
return msg, command_first_word, command_split
return None, None, None
2023-03-04 08:51:56 +00:00
"""