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

239 lines
14 KiB
Python
Raw Normal View History

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
2021-11-09 13:48:41 +00:00
from core.elements import MessageSession, Command, command_prefix, ExecutionLockList, RegexCommand
2021-10-24 10:55:45 +00:00
from core.exceptions import AbuseWarning
2021-10-14 15:18:47 +00:00
from core.loader import ModulesManager
2021-07-07 16:00:24 +00:00
from core.logger import Logger
2021-07-19 16:12:29 +00:00
from core.parser.command import CommandParser, InvalidCommandFormatError, InvalidHelpDocTypeError
2021-10-20 14:04:30 +00:00
from core.tos import warn_target
2021-10-24 10:55:45 +00:00
from core.utils import remove_ineffective_text, RemoveDuplicateSpace
from database import BotDBUtil
2021-02-01 15:13:11 +00:00
2021-10-14 15:18:47 +00:00
Modules = ModulesManager.return_modules_list_as_dict()
ModulesAliases = ModulesManager.return_modules_alias_map()
2021-11-09 13:48:41 +00:00
ModulesRegex = ModulesManager.return_specified_type_modules(RegexCommand)
2021-10-14 15:18:47 +00:00
2021-10-20 14:04:30 +00:00
counter_same = {} # 命令使用次数计数(重复使用单一命令)
counter_all = {} # 命令使用次数计数(使用所有命令)
temp_ban_counter = {} # 临时封禁计数
async def msg_counter(msg: MessageSession, command: str):
same = counter_same.get(msg.target.senderId)
if same is None or datetime.now().timestamp() - same['ts'] > 300 or same[
2021-11-12 14:25:53 +00:00
'command'] != command: # 检查是否滥用(重复使用同一命令)
2021-10-20 14:04:30 +00:00
counter_same[msg.target.senderId] = {'command': command, 'count': 1,
'ts': datetime.now().timestamp()}
else:
same['count'] += 1
if same['count'] > 10:
raise AbuseWarning('一段时间内使用相同命令的次数过多')
all_ = counter_all.get(msg.target.senderId)
if all_ is None or datetime.now().timestamp() - all_['ts'] > 300: # 检查是否滥用(重复使用同一命令)
counter_all[msg.target.senderId] = {'count': 1,
'ts': datetime.now().timestamp()}
else:
all_['count'] += 1
if all_['count'] > 30:
raise AbuseWarning('一段时间内使用命令的次数过多')
2021-10-14 15:18:47 +00:00
2021-07-24 08:59:15 +00:00
async def parser(msg: MessageSession):
2021-02-03 07:40:17 +00:00
"""
接收消息必经的预处理器
2021-07-24 08:59:15 +00:00
:param msg: 从监听器接收到的dict该dict将会经过此预处理器传入下游
2021-02-03 07:40:17 +00:00
:return: 无返回
"""
2021-10-14 15:18:47 +00:00
global Modules
global ModulesAliases
global ModulesRegex
if Modules == {}:
Modules = ModulesManager.return_modules_list_as_dict()
2021-10-24 10:55:45 +00:00
if ModulesAliases == {}:
2021-10-14 15:18:47 +00:00
ModulesAliases = ModulesManager.return_modules_alias_map()
2021-10-24 10:55:45 +00:00
if ModulesRegex == {}:
2021-11-09 13:48:41 +00:00
ModulesRegex = ModulesManager.return_specified_type_modules(RegexCommand)
2021-07-26 12:43:51 +00:00
display = RemoveDuplicateSpace(msg.asDisplay()) # 将消息转换为一般显示形式
2021-08-25 16:30:50 +00:00
msg.trigger_msg = display
2021-07-24 08:59:15 +00:00
msg.target.senderInfo = senderInfo = BotDBUtil.SenderInfo(msg.target.senderId)
2021-08-25 11:45:03 +00:00
enabled_modules_list = BotDBUtil.Module(msg).check_target_enabled_module_list()
if senderInfo.query.isInBlockList and not senderInfo.query.isInAllowList or len(display) == 0:
2021-06-04 13:53:24 +00:00
return
if display[0] in command_prefix: # 检查消息前缀
2021-11-21 13:20:07 +00:00
if len(display) <= 1 or (display[0] == '~' and display[1] == '~'):
2021-10-20 14:04:30 +00:00
return
Logger.info(
f'[{msg.target.senderId}{f" ({msg.target.targetId})" if msg.target.targetFrom != msg.target.senderFrom else ""}] -> [Bot]: {display}')
2021-10-20 14:04:30 +00:00
command = display[1:]
2021-06-07 13:49:39 +00:00
command_list = remove_ineffective_text(command_prefix, command.split('&&')) # 并行命令处理
2021-07-15 14:59:32 +00:00
if len(command_list) > 5 and not senderInfo.query.isSuperUser:
2021-07-26 12:43:51 +00:00
await msg.sendMessage('你不是本机器人的超级管理员最多只能并排执行5个命令。')
2021-07-12 13:31:11 +00:00
return
2021-10-24 10:55:45 +00:00
if not ExecutionLockList.check(msg):
ExecutionLockList.add(msg)
else:
return await msg.sendMessage('您有命令正在执行,请稍后再试。')
2021-06-04 13:53:24 +00:00
for command in command_list:
command_spilt = command.split(' ') # 切割消息
2021-10-20 14:04:30 +00:00
msg.trigger_msg = command # 触发该命令的消息,去除消息前缀
command_first_word = command_spilt[0].lower()
2021-12-22 13:06:40 +00:00
sudo = False
if command_first_word == 'sudo':
if not msg.checkSuperUser():
return await msg.sendMessage('你不是本机器人的超级管理员无法使用sudo命令。')
sudo = True
del command_spilt[0]
command_first_word = command_spilt[0].lower()
msg.trigger_msg = ' '.join(command_spilt)
2021-10-20 14:04:30 +00:00
if command_first_word in ModulesAliases:
command_spilt[0] = ModulesAliases[command_first_word]
command = ' '.join(command_spilt)
command_spilt = command.split(' ')
command_first_word = command_spilt[0]
2021-10-20 14:04:30 +00:00
msg.trigger_msg = command
if command_first_word in Modules: # 检查触发命令是否在模块列表中
try:
is_temp_banned = temp_ban_counter.get(msg.target.senderId)
if is_temp_banned is not None:
ban_time = datetime.now().timestamp() - is_temp_banned['ts']
if ban_time < 300:
if is_temp_banned['count'] < 2:
is_temp_banned['count'] += 1
return await msg.sendMessage('提示:\n'
'由于你的行为触发了警告,我们已对你进行临时封禁。\n'
f'距离解封时间还有{str(int(300 - ban_time))}秒。')
elif is_temp_banned['count'] <= 5:
is_temp_banned['count'] += 1
return await msg.sendMessage('即使是触发了临时封禁,继续使用命令还是可能会导致你被再次警告。\n'
f'距离解封时间还有{str(int(300 - ban_time))}秒。')
else:
return await warn_target(msg)
2021-11-19 04:55:05 +00:00
if msg.target.targetFrom != 'QQ|Guild' or command_first_word != 'module':
await msg_counter(msg, command)
2021-07-09 09:36:38 +00:00
module = Modules[command_first_word]
2021-10-24 10:55:45 +00:00
if not isinstance(module, Command):
if module.desc is not None:
2021-10-24 10:55:45 +00:00
await msg.sendMessage(f'介绍:\n{module.desc}')
2021-10-22 13:24:09 +00:00
continue
2021-10-24 10:55:45 +00:00
if module.required_superuser:
if not msg.checkSuperUser():
await msg.sendMessage('你没有使用该命令的权限。')
continue
elif not module.base:
2021-12-22 13:09:37 +00:00
if command_first_word not in enabled_modules_list and not sudo: # 若未开启
2021-10-24 10:55:45 +00:00
await msg.sendMessage(f'{command_first_word}模块未启用,请发送~enable {command_first_word}启用本模块。')
continue
elif module.required_admin:
if not await msg.checkPermission():
await msg.sendMessage(f'{command_first_word}命令仅能被该群组的管理员所使用,请联系管理员执行此命令。')
continue
2021-10-24 11:02:26 +00:00
if not module.match_list.set:
2021-12-22 13:06:40 +00:00
await msg.sendMessage(f'发生错误:{command_first_word}未绑定任何命令,请联系开发者处理。'
2021-11-21 13:20:07 +00:00
f'\n错误汇报地址https://github.com/Teahouse-Studios/bot/issues/new?assignees=OasisAkari&labels=bug&template=report_bug.yaml&title=%5BBUG%5D%3A+。')
2021-10-24 10:55:45 +00:00
continue
none_doc = True
2021-11-19 16:33:53 +00:00
for func in module.match_list.get(msg.target.targetFrom):
2021-10-24 10:55:45 +00:00
if func.help_doc is not None:
none_doc = False
if not none_doc:
try:
2021-11-19 16:33:53 +00:00
command_parser = CommandParser(module, msg=msg)
2021-07-19 16:12:29 +00:00
try:
2021-12-22 13:13:12 +00:00
parsed_msg = command_parser.parse(msg.trigger_msg)
2021-10-24 10:55:45 +00:00
submodule = parsed_msg[0]
msg.parsed_msg = parsed_msg[1]
if submodule.required_superuser:
if not msg.checkSuperUser():
await msg.sendMessage('你没有使用该命令的权限。')
continue
elif submodule.required_admin:
if not await msg.checkPermission():
await msg.sendMessage(
f'此命令仅能被该群组的管理员所使用,请联系管理员执行此命令。')
2021-10-22 13:24:09 +00:00
continue
2021-11-14 09:57:53 +00:00
if not senderInfo.query.disable_typing:
async with msg.Typing(msg):
await parsed_msg[0].function(msg) # 将msg传入下游模块
else:
await parsed_msg[0].function(msg)
2021-10-24 10:55:45 +00:00
except InvalidCommandFormatError:
await msg.sendMessage('语法错误。\n' + command_parser.return_formatted_help_doc())
2021-10-22 13:24:09 +00:00
continue
2021-10-24 10:55:45 +00:00
except InvalidHelpDocTypeError:
traceback.print_exc()
await msg.sendMessage(
f'{command_first_word}模块的帮助信息有误,请联系开发者处理。'
2021-11-21 13:20:07 +00:00
f'\n错误汇报地址https://github.com/Teahouse-Studios/bot/issues/new?assignees=OasisAkari&labels=bug&template=report_bug.yaml&title=%5BBUG%5D%3A+')
2021-10-24 10:55:45 +00:00
continue
else:
msg.parsed_msg = None
for func in module.match_list.set:
if func.help_doc is None:
2021-11-14 09:57:53 +00:00
if not senderInfo.query.disable_typing:
async with msg.Typing(msg):
await func.function(msg) # 将msg传入下游模块
else:
await func.function(msg)
2021-10-20 14:04:30 +00:00
except AbuseWarning as e:
await warn_target(msg, str(e))
temp_ban_counter[msg.target.senderId] = {'count': 1,
'ts': datetime.now().timestamp()}
return
except Exception as e:
Logger.error(traceback.format_exc())
2021-11-25 15:40:30 +00:00
ExecutionLockList.remove(msg)
2021-10-20 14:04:30 +00:00
await msg.sendMessage('执行命令时发生错误,请报告机器人开发者:\n' + str(
2021-11-21 13:20:07 +00:00
e) + '\n错误汇报地址https://github.com/Teahouse-Studios/bot/issues/new?assignees=OasisAkari&labels=bug&template=report_bug.yaml&title=%5BBUG%5D%3A+')
2021-10-22 13:24:09 +00:00
continue
2021-10-24 10:55:45 +00:00
ExecutionLockList.remove(msg)
2021-07-26 14:33:49 +00:00
for regex in ModulesRegex: # 遍历正则模块列表
2021-10-20 14:04:30 +00:00
try:
if regex in enabled_modules_list:
regex_module = ModulesRegex[regex]
2021-12-03 11:50:52 +00:00
if regex_module.required_superuser:
if not msg.checkSuperUser():
continue
elif regex_module.required_admin:
if not await msg.checkPermission():
continue
2021-10-24 10:55:45 +00:00
for rfunc in regex_module.match_list.set:
msg.matched_msg = False
matched = False
2021-10-24 10:55:45 +00:00
if rfunc.mode.upper() in ['M', 'MATCH']:
msg.matched_msg = re.match(rfunc.pattern, display, flags=rfunc.flags)
if msg.matched_msg is not None:
matched = True
2021-10-24 10:55:45 +00:00
elif rfunc.mode.upper() in ['A', 'FINDALL']:
msg.matched_msg = re.findall(rfunc.pattern, display, flags=rfunc.flags)
if msg.matched_msg:
matched = True
if matched:
if regex_module.required_superuser:
if not msg.checkSuperUser():
continue
elif regex_module.required_admin:
if not await msg.checkPermission():
continue
if not ExecutionLockList.check(msg):
ExecutionLockList.add(msg)
else:
return await msg.sendMessage('您有命令正在执行,请稍后再试。')
2021-11-14 09:57:53 +00:00
if rfunc.show_typing and not senderInfo.query.disable_typing:
2021-10-24 10:55:45 +00:00
async with msg.Typing(msg):
await rfunc.function(msg) # 将msg传入下游模块
else:
await rfunc.function(msg) # 将msg传入下游模块
2021-10-31 15:59:18 +00:00
ExecutionLockList.remove(msg)
2021-10-20 14:04:30 +00:00
except AbuseWarning as e:
await warn_target(msg, str(e))
temp_ban_counter[msg.target.senderId] = {'count': 1,
'ts': datetime.now().timestamp()}
2021-10-24 10:55:45 +00:00
return
2021-10-20 14:04:30 +00:00
except Exception:
Logger.error(traceback.format_exc())
2021-10-22 13:24:09 +00:00
ExecutionLockList.remove(msg)