From cf5184334fb0d02d9110fcffc416006324629450 Mon Sep 17 00:00:00 2001 From: lenisko Date: Mon, 4 Dec 2017 18:10:54 +0100 Subject: [PATCH] Support disabling modules/commands per channel --- sopel/bot.py | 23 +++++++++++++++++++++++ sopel/config/__init__.py | 9 +++++++++ 2 files changed, 32 insertions(+) diff --git a/sopel/bot.py b/sopel/bot.py index fc98dd9ec7..2bc2b95fad 100644 --- a/sopel/bot.py +++ b/sopel/bot.py @@ -7,6 +7,7 @@ from __future__ import unicode_literals, absolute_import, print_function, division +from ast import literal_eval import collections import os import re @@ -466,6 +467,28 @@ def call(self, func, sopel, trigger): ) return + # if channel has its own config section, check 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.