diff --git a/sopel/bot.py b/sopel/bot.py index fc98dd9ec7..7f7b61df70 100644 --- a/sopel/bot.py +++ b/sopel/bot.py @@ -22,6 +22,7 @@ from sopel.trigger import Trigger from sopel.module import NOLIMIT from sopel.logger import get_logger +from ast import literal_eval import sopel.loader @@ -466,6 +467,28 @@ def call(self, func, sopel, trigger): ) return + # if channel have own settings sections, we're checking for excluded modules/modules methods + if trigger.sender in self.config: + channel_config = self.config[trigger.sender] + + # disable listed modules completely on provided channel + if 'disable_modules' in channel_config: + disabled_modules = channel_config.disable_modules.split(',') + + # if "!" is used, we are disabling all modules on provided channel + if '!' in disabled_modules: + return + if func.__module__ in disabled_modules: + return + + # disable chosen methods from modules + if 'disable_commands' in channel_config: + disabled_commands = literal_eval(channel_config.disable_commands) + + if func.__module__ in disabled_commands: + if func.__name__ in disabled_commands[func.__module__]: + return + try: exit_code = func(sopel, trigger) except Exception: diff --git a/sopel/config/__init__.py b/sopel/config/__init__.py index f930365ce4..61e539d1ed 100644 --- a/sopel/config/__init__.py +++ b/sopel/config/__init__.py @@ -138,6 +138,9 @@ def __init__(self, name, items, parent): def __getattr__(self, name): return None + def __contains__(self, name): + return name in vars(self) + def __setattr__(self, name, value): object.__setattr__(self, name, value) if type(value) is list: @@ -164,6 +167,12 @@ def __getattr__(self, name): raise AttributeError("%r object has no attribute %r" % (type(self).__name__, name)) + def __getitem__(self, name): + return self.__getattr__(name) + + def __contains__(self, name): + return name in self.parser.sections() + def option(self, question, default=False): """Ask "y/n" and return the corresponding boolean answer.