plugin: handle aliases for commands
This commit is contained in:
parent
d85d5e054f
commit
3748312c41
|
@ -41,7 +41,7 @@ Missing features
|
||||||
- [x] Wikipedia: find definition, get random page
|
- [x] Wikipedia: find definition, get random page
|
||||||
- [ ] Wolframalpha
|
- [ ] Wolframalpha
|
||||||
- [ ] Youtube: parsing for title, requests for channel or video
|
- [ ] Youtube: parsing for title, requests for channel or video
|
||||||
- [ ] Command aliases
|
- [x] Command aliases
|
||||||
- [ ] Question aliases
|
- [ ] Question aliases
|
||||||
- [x] Sleep
|
- [x] Sleep
|
||||||
- [ ] Various macros:
|
- [ ] Various macros:
|
||||||
|
|
|
@ -129,33 +129,59 @@ class Plugin:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Is it a valid command?
|
# Is it a valid command?
|
||||||
command = self.parse_command(message, no_content=no_content)
|
parsed_command = self.__parse_command(message, no_content=no_content)
|
||||||
if not command:
|
if not parsed_command:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Is it a command I can handle?
|
# Is it a command I can handle?
|
||||||
commands = self.config.get("commands", [])
|
available_commands = self.config.get("commands", [])
|
||||||
if (
|
aliases = self.config.get("aliases", {})
|
||||||
any(command.ident == c for c in commands) or
|
for ident in available_commands:
|
||||||
(no_content and any(command.ident.startswith(c) for c in commands))
|
# Match commands differently according to no_content. If no_content
|
||||||
):
|
# is True, check the parsed command (pc) raw data as a string that
|
||||||
self.command = command
|
# may contain the available identifier (ai) at its beginning.
|
||||||
self.bot.log_d(f"Processing command from plugin {self.name}.")
|
# If no_content is False (default), simply compare the parsed
|
||||||
|
# identifier with available identifiers.
|
||||||
|
if no_content:
|
||||||
|
match = lambda pc, ai: (
|
||||||
|
pc.raw == ai or pc.raw.startswith(ai + " ")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
match = lambda pc, ai: pc.ident == ai
|
||||||
|
# First case: the command identifier has been used.
|
||||||
|
if match(parsed_command, ident):
|
||||||
|
parsed_command.ident = ident
|
||||||
|
parsed_command.match = ident
|
||||||
|
self.__save_command(parsed_command)
|
||||||
|
return True
|
||||||
|
# Second case: an alias of the identifier has been used.
|
||||||
|
ident_aliases = aliases.get(ident, [])
|
||||||
|
for alias in ident_aliases:
|
||||||
|
if match(parsed_command, alias):
|
||||||
|
parsed_command.ident = ident
|
||||||
|
parsed_command.match = alias
|
||||||
|
self.__save_command(parsed_command)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def parse_command(self, message, no_content=False):
|
def __parse_command(self, message, no_content=False):
|
||||||
"""Return a command ID if this message is a command."""
|
"""Return a command ID if this message is a command.
|
||||||
|
|
||||||
|
The command raw field is always set. The ident and content fields are
|
||||||
|
not set when no_content is True. The match field is never set by this
|
||||||
|
method.
|
||||||
|
"""
|
||||||
words = message.split()
|
words = message.split()
|
||||||
command_suffix = self.config["command_suffix"]
|
command_suffix = self.config["command_suffix"]
|
||||||
if words[0].lower() in self.bot.names and words[-1] == command_suffix:
|
if words[0].lower() in self.bot.names and words[-1] == command_suffix:
|
||||||
|
raw = " ".join(words[1:-1])
|
||||||
if no_content:
|
if no_content:
|
||||||
ident = " ".join(words[1:-1])
|
ident = ""
|
||||||
content = ""
|
content = ""
|
||||||
else:
|
else:
|
||||||
ident = words[1]
|
ident = words[1]
|
||||||
content = " ".join(words[2:-1])
|
content = " ".join(words[2:-1])
|
||||||
return Command(ident, content)
|
return Command(ident, content, raw)
|
||||||
|
|
||||||
def __respects_handling_conditions(self, exclude_conditions=None):
|
def __respects_handling_conditions(self, exclude_conditions=None):
|
||||||
"""Check if question conditions are valid."""
|
"""Check if question conditions are valid."""
|
||||||
|
@ -172,6 +198,11 @@ class Plugin:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def __save_command(self, command):
|
||||||
|
"""Save command in instance for further processing by the plugin."""
|
||||||
|
self.command = command
|
||||||
|
self.bot.log_d(f"Processing command from plugin {self.name}: {command}")
|
||||||
|
|
||||||
def signal_failure(self, target):
|
def signal_failure(self, target):
|
||||||
"""Signal a plugin failure to target."""
|
"""Signal a plugin failure to target."""
|
||||||
self.bot.say(target, self.bot.config["error_message"])
|
self.bot.say(target, self.bot.config["error_message"])
|
||||||
|
@ -185,5 +216,11 @@ class Question:
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Command:
|
class Command:
|
||||||
|
# Identifier as set in config. Set even when an alias has been used.
|
||||||
ident: str
|
ident: str
|
||||||
|
# Content of the command when it has been parsed, empty str otherwise.
|
||||||
content: str
|
content: str
|
||||||
|
# Raw command content (minus name and suffix), always set.
|
||||||
|
raw: str
|
||||||
|
# Identifier matched, possibly an alias. Set only when matched.
|
||||||
|
match: str = ""
|
||||||
|
|
|
@ -44,9 +44,11 @@ class MoodPlugin(Plugin):
|
||||||
self.bot.say(event.target, random.choice(greetings))
|
self.bot.say(event.target, random.choice(greetings))
|
||||||
|
|
||||||
def on_pubmsg(self, event):
|
def on_pubmsg(self, event):
|
||||||
|
# Only one command: calm down.
|
||||||
if self.should_handle_command(event.arguments[0], no_content=True):
|
if self.should_handle_command(event.arguments[0], no_content=True):
|
||||||
self.calm_down(event.target)
|
self.calm_down(event.target)
|
||||||
return True
|
return True
|
||||||
|
# Only one question: what's your mood?
|
||||||
if self.should_answer_question(event.arguments[0]):
|
if self.should_answer_question(event.arguments[0]):
|
||||||
self.say_mood(event.target)
|
self.say_mood(event.target)
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -31,9 +31,8 @@ class NotesPlugin(Plugin):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# "note down" command.
|
# "note down" command.
|
||||||
command0 = self.config["commands"][0]
|
if self.command.ident == self.config["commands"][0]:
|
||||||
if self.command.ident.startswith(command0):
|
content = self.command.raw[len(self.command.match):].strip()
|
||||||
content = self.command.ident[len(command0):].strip()
|
|
||||||
match = self.content_re.match(content)
|
match = self.content_re.match(content)
|
||||||
if not match:
|
if not match:
|
||||||
return False
|
return False
|
||||||
|
@ -59,8 +58,7 @@ class NotesPlugin(Plugin):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# "deliver notes for me" command.
|
# "deliver notes for me" command.
|
||||||
command1 = self.config["commands"][1]
|
if self.command.ident == self.config["commands"][1]:
|
||||||
if self.command.ident == command1:
|
|
||||||
self.deliver_notes(event.target, event.source.nick)
|
self.deliver_notes(event.target, event.source.nick)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
|
@ -42,14 +42,12 @@ class SleepPlugin(Plugin):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# "sleep" command.
|
# "sleep" command.
|
||||||
command0 = self.config["commands"][0]
|
if self.command.ident == self.config["commands"][0]:
|
||||||
if self.command.ident.startswith(command0):
|
|
||||||
self.fall_asleep()
|
self.fall_asleep()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# "wake up" command.
|
# "wake up" command.
|
||||||
command1 = self.config["commands"][1]
|
if self.command.ident == self.config["commands"][1]:
|
||||||
if self.command.ident.startswith(command1):
|
|
||||||
self.wake_up()
|
self.wake_up()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue