aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar mbaruh <[email protected]>2022-02-22 22:15:19 +0200
committerGravatar mbaruh <[email protected]>2022-07-16 02:07:25 +0300
commitd1ae7ce9235e4d63ee1dde282ca890ac5509f950 (patch)
tree236cc81b3f6574c3a75e737c4bc9b3926c91a55e
parentAdd 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.py13
-rw-r--r--bot/exts/filtering/_settings_types/channel_scope.py27
-rw-r--r--bot/exts/filtering/_settings_types/ping.py26
-rw-r--r--bot/exts/filtering/_utils.py8
-rw-r--r--bot/exts/filtering/filtering.py2
-rw-r--r--tests/bot/exts/filtering/test_settings_entries.py8
-rw-r--r--tests/helpers.py2
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`