diff options
author | 2022-02-22 22:15:19 +0200 | |
---|---|---|
committer | 2022-07-16 02:07:25 +0300 | |
commit | d1ae7ce9235e4d63ee1dde282ca890ac5509f950 (patch) | |
tree | 236cc81b3f6574c3a75e737c4bc9b3926c91a55e | |
parent | Add listing commands (diff) |
Accept strings in channel scope and change role string interpretation
The channel scope settings were changed to accomodate strings. That means that if a string is specified, the bot will look whether the context channel's name matches. If it's a number, it will match the ID.
Accordingly the same changed was applied to the bypass roles and pings settings: if it's a non-numeric string, it will look for a role with that name.
-rw-r--r-- | bot/exts/filtering/_settings_types/bypass_roles.py | 13 | ||||
-rw-r--r-- | bot/exts/filtering/_settings_types/channel_scope.py | 27 | ||||
-rw-r--r-- | bot/exts/filtering/_settings_types/ping.py | 26 | ||||
-rw-r--r-- | bot/exts/filtering/_utils.py | 8 | ||||
-rw-r--r-- | bot/exts/filtering/filtering.py | 2 | ||||
-rw-r--r-- | tests/bot/exts/filtering/test_settings_entries.py | 8 | ||||
-rw-r--r-- | tests/helpers.py | 2 |
7 files changed, 48 insertions, 38 deletions
diff --git a/bot/exts/filtering/_settings_types/bypass_roles.py b/bot/exts/filtering/_settings_types/bypass_roles.py index 9665283ff..bfc4a30fd 100644 --- a/bot/exts/filtering/_settings_types/bypass_roles.py +++ b/bot/exts/filtering/_settings_types/bypass_roles.py @@ -4,7 +4,6 @@ from discord import Member from bot.exts.filtering._filter_context import FilterContext from bot.exts.filtering._settings_types.settings_entry import ValidationEntry -from bot.exts.filtering._utils import ROLE_LITERALS class RoleBypass(ValidationEntry): @@ -16,14 +15,16 @@ class RoleBypass(ValidationEntry): super().__init__(entry_data) self.roles = set() for role in entry_data: - if role in ROLE_LITERALS: - self.roles.add(ROLE_LITERALS[role]) - elif role.isdigit(): + if role.isdigit(): self.roles.add(int(role)) - # Ignore entries that can't be resolved. + else: + self.roles.add(role) def triggers_on(self, ctx: FilterContext) -> bool: """Return whether the filter should be triggered on this user given their roles.""" if not isinstance(ctx.author, Member): return True - return all(member_role.id not in self.roles for member_role in ctx.author.roles) + return all( + member_role.id not in self.roles and member_role.name not in self.roles + for member_role in ctx.author.roles + ) diff --git a/bot/exts/filtering/_settings_types/channel_scope.py b/bot/exts/filtering/_settings_types/channel_scope.py index b17914f2f..63da6c7e5 100644 --- a/bot/exts/filtering/_settings_types/channel_scope.py +++ b/bot/exts/filtering/_settings_types/channel_scope.py @@ -1,9 +1,16 @@ -from typing import Any +from typing import Any, Union from bot.exts.filtering._filter_context import FilterContext from bot.exts.filtering._settings_types.settings_entry import ValidationEntry +def maybe_cast_to_int(item: str) -> Union[str, int]: + """Cast the item to int if it consists of only digit, or leave as is otherwise.""" + if item.isdigit(): + return int(item) + return item + + class ChannelScope(ValidationEntry): """A setting entry which tells whether the filter was invoked in a whitelisted channel or category.""" @@ -12,17 +19,17 @@ class ChannelScope(ValidationEntry): def __init__(self, entry_data: Any): super().__init__(entry_data) if entry_data["disabled_channels"]: - self.disabled_channels = set(entry_data["disabled_channels"]) + self.disabled_channels = set(map(maybe_cast_to_int, entry_data["disabled_channels"])) else: self.disabled_channels = set() if entry_data["disabled_categories"]: - self.disabled_categories = set(entry_data["disabled_categories"]) + self.disabled_categories = set(map(maybe_cast_to_int, entry_data["disabled_categories"])) else: self.disabled_categories = set() if entry_data["enabled_channels"]: - self.enabled_channels = set(entry_data["enabled_channels"]) + self.enabled_channels = set(map(maybe_cast_to_int, entry_data["enabled_channels"])) else: self.enabled_channels = set() @@ -34,12 +41,18 @@ class ChannelScope(ValidationEntry): If the channel is explicitly enabled, it bypasses the set disabled channels and categories. """ channel = ctx.channel - if hasattr(channel, "parent"): - channel = channel.parent - return ( + enabled_id = ( channel.id in self.enabled_channels or ( channel.id not in self.disabled_channels and (not channel.category or channel.category.id not in self.disabled_categories) ) ) + enabled_name = ( + channel.name in self.enabled_channels + or ( + channel.name not in self.disabled_channels + and (not channel.category or channel.category.name not in self.disabled_categories) + ) + ) + return enabled_id and enabled_name diff --git a/bot/exts/filtering/_settings_types/ping.py b/bot/exts/filtering/_settings_types/ping.py index 857e4a7e8..0f9a014c4 100644 --- a/bot/exts/filtering/_settings_types/ping.py +++ b/bot/exts/filtering/_settings_types/ping.py @@ -5,7 +5,6 @@ from discord import Guild from bot.exts.filtering._filter_context import FilterContext from bot.exts.filtering._settings_types.settings_entry import ActionEntry -from bot.exts.filtering._utils import ROLE_LITERALS class Ping(ActionEntry): @@ -40,13 +39,18 @@ class Ping(ActionEntry): """Return the appropriate formatting for the formatting, be it a literal, a user ID, or a role ID.""" if mention in ("here", "everyone"): return f"@{mention}" - if mention in ROLE_LITERALS: - return f"<@&{ROLE_LITERALS[mention]}>" - if not mention.isdigit(): - return mention - - mention = int(mention) - if any(mention == role.id for role in guild.roles): - return f"<@&{mention}>" - else: - return f"<@{mention}>" + if mention.isdigit(): # It's an ID. + mention = int(mention) + if any(mention == role.id for role in guild.roles): + return f"<@&{mention}>" + else: + return f"<@{mention}>" + + # It's a name + for role in guild.roles: + if role.name == mention: + return role.mention + for member in guild.members: + if str(member) == mention: + return member.mention + return mention diff --git a/bot/exts/filtering/_utils.py b/bot/exts/filtering/_utils.py index 790f70ee5..d09262193 100644 --- a/bot/exts/filtering/_utils.py +++ b/bot/exts/filtering/_utils.py @@ -8,14 +8,6 @@ from typing import Set import regex -from bot.constants import Roles - -ROLE_LITERALS = { - "admins": Roles.admins, - "onduty": Roles.moderators, - "staff": Roles.helpers -} - VARIATION_SELECTORS = r"\uFE00-\uFE0F\U000E0100-\U000E01EF" INVISIBLE_RE = regex.compile(rf"[{VARIATION_SELECTORS}\p{{UNASSIGNED}}\p{{FORMAT}}\p{{CONTROL}}--\s]", regex.V1) ZALGO_RE = regex.compile(rf"[\p{{NONSPACING MARK}}\p{{ENCLOSING MARK}}--[{VARIATION_SELECTORS}]]", regex.V1) diff --git a/bot/exts/filtering/filtering.py b/bot/exts/filtering/filtering.py index 58e16043a..d34b4928a 100644 --- a/bot/exts/filtering/filtering.py +++ b/bot/exts/filtering/filtering.py @@ -89,7 +89,7 @@ class Filtering(Cog): @Cog.listener() async def on_message(self, msg: Message) -> None: """Filter the contents of a sent message.""" - if msg.author.bot: + if msg.author.bot or msg.webhook_id: return ctx = FilterContext(Event.MESSAGE, msg.author, msg.channel, msg.content, msg, msg.embeds) diff --git a/tests/bot/exts/filtering/test_settings_entries.py b/tests/bot/exts/filtering/test_settings_entries.py index 4db6438ab..d18861bd6 100644 --- a/tests/bot/exts/filtering/test_settings_entries.py +++ b/tests/bot/exts/filtering/test_settings_entries.py @@ -62,7 +62,7 @@ class FilterTests(unittest.TestCase): def test_context_doesnt_trigger_for_disabled_channel(self): """A filter shouldn't trigger if it's been disabled in the channel.""" channel = MockTextChannel(id=123) - scope = ChannelScope({"disabled_channels": [123], "disabled_categories": None, "enabled_channels": None}) + scope = ChannelScope({"disabled_channels": ["123"], "disabled_categories": None, "enabled_channels": None}) self.ctx.channel = channel result = scope.triggers_on(self.ctx) @@ -71,9 +71,9 @@ class FilterTests(unittest.TestCase): def test_context_doesnt_trigger_in_disabled_category(self): """A filter shouldn't trigger if it's been disabled in the category.""" - channel = MockTextChannel() + channel = MockTextChannel(category=MockCategoryChannel(id=456)) scope = ChannelScope({ - "disabled_channels": None, "disabled_categories": [channel.category.id], "enabled_channels": None + "disabled_channels": None, "disabled_categories": ["456"], "enabled_channels": None }) self.ctx.channel = channel @@ -84,7 +84,7 @@ class FilterTests(unittest.TestCase): def test_context_triggers_in_enabled_channel_in_disabled_category(self): """A filter should trigger in an enabled channel even if it's been disabled in the category.""" channel = MockTextChannel(id=123, category=MockCategoryChannel(id=234)) - scope = ChannelScope({"disabled_channels": None, "disabled_categories": [234], "enabled_channels": [123]}) + scope = ChannelScope({"disabled_channels": None, "disabled_categories": ["234"], "enabled_channels": ["123"]}) self.ctx.channel = channel result = scope.triggers_on(self.ctx) diff --git a/tests/helpers.py b/tests/helpers.py index 17214553c..e74306d23 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -423,7 +423,7 @@ category_channel_instance = discord.CategoryChannel( class MockCategoryChannel(CustomMockMixin, unittest.mock.Mock, HashableMixin): def __init__(self, **kwargs) -> None: default_kwargs = {'id': next(self.discord_id)} - super().__init__(**collections.ChainMap(default_kwargs, kwargs)) + super().__init__(**collections.ChainMap(kwargs, default_kwargs)) # Create a Message instance to get a realistic MagicMock of `discord.Message` |