from dataclasses import dataclass class Plugin: def __init__(self, bot): self.bot = bot self.name = self.__class__.__name__.lower()[:-6] # Remove "Plugin". self.config = self.get_config() @property def callbacks(self): """List of callback types available for this plugin.""" return { cb[3:]: getattr(self, cb) for cb in dir(self) if cb.startswith("on_") and callable(getattr(self, cb)) } def get_config(self): """Return the plugin section from the bot config.""" plugins_configs = self.bot.config["plugins"] return plugins_configs.get(self.name, {}) def get_runtime_value(self, key, plugin_name=None): """Get a value from the plugin runtime dict.""" if plugin_name is None: plugin_name = self.name return self.bot.values[self.name].get(key) def set_runtime_value(self, key, value): """Set a value in the plugin runtime dict.""" self.bot.values[self.name][key] = value def should_answer_question(self, message): """Store Question in object and return True if it should answer it.""" words = message.split() if words[0].lower() not in self.bot.names: return False question = message[len(words[0]):].strip() for q in self.QUESTIONS: if question.startswith(q): self.question = Question(q, question[len(q):].strip()) return True return False def should_handle_command(self, message): """Store Command in object and return True if it should handle it.""" command = self.parse_command(message) if command and any(c == command.ident for c in self.COMMANDS): self.command = command return True return False def parse_command(self, message): """Return a command ID if this message is a command.""" words = message.split() if words[0].lower() in self.bot.names and words[-1] == "please": ident = words[1] content = " ".join(words[2:-1]) return Command(ident, content) @dataclass class Question: preambule: str content: str @dataclass class Command: ident: str content: str