"""The command processor.
Contains methods to process the Commands in command.py.
"""
import discord
from mehlbot.command import Command
from mehlbot.logger import setup_logger
logger = setup_logger(__name__)
[docs]async def process_command(client: discord.Client, commands: dict[str, Command], message: discord.Message) -> bool:
"""Processes the message with the given commands. For usage see the.
/example directory.
:param client: discord.Client
:param commands: bot_commands, unless using custom commands storage.
:param message: received message.
:return: True if message is command
"""
message_content = message.content.strip()
command_name: str
# Check if command name matches with one of the given commands and argument amount.
# (special case for var args, only needs matching message begin)
for command_name, command in commands.items():
entered_command_keys = message_content.split(" ")
command_keys = command_name.split(" ")
if not await method_name(command, command_keys, entered_command_keys):
continue
provided_argument_amount = len(entered_command_keys) - len(command_keys)
allowed_args_matches = False
num_args = [command.allowed_num_args[0]]
# Check if any possible variation of the args amount match
# See complex example.
for allowed_args in command.allowed_num_args:
if len(allowed_args) == provided_argument_amount:
allowed_args_matches = True
num_args.append(allowed_args)
# If the command args amount don't match (and not var args)
# then print incorrect usage of the given command.
if not allowed_args_matches and not command.var_args:
if len(command.allowed_num_args[0]) > 0:
output = "\n"
for allowed_args in command.allowed_num_args:
output += f"> `{command.command_name} <"
output += ">, <".join(allowed_args) + ">`\n"
else:
output = f"{command.command_name}"
channel_msg = f"Incorrect command usage: {output}"
logger.info(channel_msg)
await message.channel.send(channel_msg)
continue
args = entered_command_keys[len(command_keys) :]
# Extract var args from message
if command.var_args:
if len(num_args) > 1:
channel_msg = f"Command {command_name} is ambiguous because of var args and multiple command args."
logger.error(channel_msg)
await message.channel.send(channel_msg)
return False
var_args_pos = len(command_keys) + len(num_args[0])
args = entered_command_keys[len(command_keys) : var_args_pos] + [
" ".join(entered_command_keys[var_args_pos:]),
]
await command.callback(message, client, args)
return True
return False
[docs]async def method_name(command: Command, command_keys: list[str], entered_command_keys: list[str]):
"""Check if the command matches any.
:param command:
:param command_keys:
:param entered_command_keys:
:return:
"""
matches = True
for idx, _command_key in enumerate(command_keys):
if idx >= len(entered_command_keys) and not command.var_args:
break
if command_keys[idx] != entered_command_keys[idx]:
matches = False
break
return matches