Unfinished changes
parent
32ab8538a4
commit
2a9323b5f5
|
@ -5,13 +5,14 @@ from __future__ import annotations
|
||||||
# Built-in imports
|
# Built-in imports
|
||||||
import re
|
import re
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import shlex
|
||||||
|
|
||||||
# Typing imports
|
# Typing imports
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
# Built-in imports
|
# Built-in imports
|
||||||
from typing import Union
|
from typing import Union, List, Tuple
|
||||||
|
|
||||||
|
|
||||||
class Simple:
|
class Simple:
|
||||||
|
@ -53,6 +54,14 @@ class Simple:
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@property
|
||||||
|
def client(self):
|
||||||
|
"""
|
||||||
|
Returns the Frank client instance.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._obj._client
|
||||||
|
|
||||||
|
|
||||||
class SimpleCommand(Simple):
|
class SimpleCommand(Simple):
|
||||||
"""
|
"""
|
||||||
|
@ -72,15 +81,48 @@ class SimpleCommand(Simple):
|
||||||
self.cmd = cmd
|
self.cmd = cmd
|
||||||
self.help_str = help_str
|
self.help_str = help_str
|
||||||
|
|
||||||
def match(self, message: str) -> bool:
|
def match(self, message: str) -> Tuple[bool, List[str]]:
|
||||||
"""
|
"""
|
||||||
Returns wether the command matches the given message.
|
Returns wether the command matches the given message. If the arguments
|
||||||
|
can't be parsed (e.g. unmatched quotes), it will return False as well.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
message: message to check
|
message: message to check
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self.cmd == message.split(" ")[0]
|
return self._match_full(message.split(" "))
|
||||||
|
|
||||||
|
def _match_full(self, parts: List[str]) -> Tuple[bool, List[str]]:
|
||||||
|
"""
|
||||||
|
Returns wether the message matches the full command.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
parts: parts of the message
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Can't match without 3 or more parts
|
||||||
|
if len(parts) < 3:
|
||||||
|
return False, None
|
||||||
|
|
||||||
|
# Return False if it doesn't match
|
||||||
|
if not all(
|
||||||
|
(
|
||||||
|
parts[0] == self.client.PREFIX,
|
||||||
|
parts[1] in self._obj.PREFIX,
|
||||||
|
parts[2] == self.cmd,
|
||||||
|
)
|
||||||
|
):
|
||||||
|
return False, None
|
||||||
|
|
||||||
|
# Parse the output, and return True with the parsed items if it works,
|
||||||
|
# otherwise return False
|
||||||
|
try:
|
||||||
|
parsed = shlex.split(" ".join(parts[3:]))
|
||||||
|
|
||||||
|
return True, parsed
|
||||||
|
|
||||||
|
except ValueError:
|
||||||
|
return False, None
|
||||||
|
|
||||||
|
|
||||||
class RegularCommand(SimpleCommand):
|
class RegularCommand(SimpleCommand):
|
||||||
|
@ -99,14 +141,43 @@ class RegularCommand(SimpleCommand):
|
||||||
super().__init__(self, func, cmd, help_str)
|
super().__init__(self, func, cmd, help_str)
|
||||||
|
|
||||||
self.alias = alias
|
self.alias = alias
|
||||||
|
|
||||||
|
# This only matters for aliases
|
||||||
self.requires_prefix = requires_prefix
|
self.requires_prefix = requires_prefix
|
||||||
|
|
||||||
def match(self, message: str) -> bool:
|
# TODO: make this return the right value
|
||||||
# This just makes it a bit easier to use in the function
|
def match(self, message: str) -> Tuple[bool, List[str]]:
|
||||||
module = self._obj
|
"""
|
||||||
client = module._client
|
Returns wether the message matches the current command.
|
||||||
|
"""
|
||||||
|
|
||||||
words = [word for word in message.split(" ") if word]
|
parts = message.split(" ")
|
||||||
|
|
||||||
|
# If the alias doesn't match, return the full match, otherwise return
|
||||||
|
# alias
|
||||||
|
matches, parts = self._match_alias(parts)
|
||||||
|
|
||||||
|
if matches:
|
||||||
|
return matches, parts
|
||||||
|
|
||||||
|
return self._match_full(parts)
|
||||||
|
|
||||||
|
# TODO: make this return the right value
|
||||||
|
def _match_alias(self, parts: List[str]) -> Tuple[bool, List[str]]:
|
||||||
|
"""
|
||||||
|
Returns wether the message matches an alias.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Return False if there's only one part but a prefix is required
|
||||||
|
if self.requires_prefix and len(parts) == 1:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Match with prefix
|
||||||
|
if self.requires_prefix:
|
||||||
|
return parts[0] == self.client.PREFIX and parts[1] in self.alias
|
||||||
|
|
||||||
|
# Match without prefix
|
||||||
|
return parts[0] in self.alias
|
||||||
|
|
||||||
|
|
||||||
class RegexCommand(SimpleCommand):
|
class RegexCommand(SimpleCommand):
|
||||||
|
@ -115,7 +186,7 @@ class RegexCommand(SimpleCommand):
|
||||||
prefix.
|
prefix.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def match(self, prefix: str) -> bool:
|
def match(self, message: str) -> Tuple[str, List[str]]:
|
||||||
"""
|
"""
|
||||||
Returns wether the regex pattern matches the given prefix.
|
Returns wether the regex pattern matches the given prefix.
|
||||||
|
|
||||||
|
@ -124,7 +195,20 @@ class RegexCommand(SimpleCommand):
|
||||||
prefix
|
prefix
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return bool(re.fullmatch(self.cmd, prefix))
|
parts = message.split(" ")
|
||||||
|
matches = bool(re.fullmatch(self.cmd, parts[0]))
|
||||||
|
|
||||||
|
# If it doesn't match, just return False, don't parse the rest
|
||||||
|
if not matches:
|
||||||
|
return False, None
|
||||||
|
|
||||||
|
try:
|
||||||
|
parsed = shlex.split(" ".join(parts))
|
||||||
|
|
||||||
|
return True, parsed
|
||||||
|
|
||||||
|
except ValueError:
|
||||||
|
return False, None
|
||||||
|
|
||||||
|
|
||||||
class Daemon(Simple):
|
class Daemon(Simple):
|
||||||
|
|
|
@ -49,5 +49,6 @@ class ModuleMeta:
|
||||||
@cached_property
|
@cached_property
|
||||||
def default(self) -> Default:
|
def default(self) -> Default:
|
||||||
return next(
|
return next(
|
||||||
iter(self._filter_attrs(lambda val: isinstance(val, Default))), None
|
iter(self._filter_attrs(lambda val: isinstance(val, Default))),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
|
|
|
@ -118,7 +118,9 @@ class Module(ModuleMeta):
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
await func(cmd=cmd[1:], author=author, channel=channel, mid=mid)
|
await func(
|
||||||
|
cmd=cmd[1:], author=author, channel=channel, mid=mid
|
||||||
|
)
|
||||||
|
|
||||||
elif self.default:
|
elif self.default:
|
||||||
await self.default(author=author, channel=channel, mid=mid)
|
await self.default(author=author, channel=channel, mid=mid)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[tool.black]
|
[tool.black]
|
||||||
line-length = 80
|
line-length = 79
|
||||||
target-version = ['py38']
|
target-version = ['py38']
|
||||||
include = '\.pyi?$'
|
include = '\.pyi?$'
|
||||||
exclude = '''
|
exclude = '''
|
||||||
|
|
Reference in New Issue