diff --git a/naff/client/utils/__init__.py b/naff/client/utils/__init__.py index a3873878e..b28b4c02c 100644 --- a/naff/client/utils/__init__.py +++ b/naff/client/utils/__init__.py @@ -5,3 +5,4 @@ from .misc_utils import * from .serializer import * from .formatting import * +from .text_utils import * diff --git a/naff/client/utils/text_utils.py b/naff/client/utils/text_utils.py new file mode 100644 index 000000000..4d38adfcb --- /dev/null +++ b/naff/client/utils/text_utils.py @@ -0,0 +1,33 @@ +import re +import naff.models as models + +__all__ = ("mentions",) + + +def mentions( + text: str, + query: "str | re.Pattern[str] | models.BaseUser | models.BaseChannel | models.Role", + *, + tag_as_mention: bool = False, +) -> bool: + """Checks whether a query is present in a text. + + Args: + text: The text to search in + query: The query to search for + tag_as_mention: Should `BaseUser.tag` be checked *(only if query is an instance of BaseUser)* + + Returns: + Whether the query could be found in the text + """ + if isinstance(query, str): + return query in text + elif isinstance(query, re.Pattern): + return query.match(text) is not None + elif isinstance(query, models.BaseUser): + # mentions with <@!ID> aren't detected without the replacement + return (query.mention in text.replace("@!", "@")) or (query.tag in text if tag_as_mention else False) + elif isinstance(query, (models.BaseChannel, models.Role)): + return query.mention in text + else: + return False diff --git a/naff/models/discord/message.py b/naff/models/discord/message.py index 08f41fe55..5c1075d3c 100644 --- a/naff/models/discord/message.py +++ b/naff/models/discord/message.py @@ -12,6 +12,7 @@ from naff.client.utils.attr_converters import optional as optional_c from naff.client.utils.attr_converters import timestamp_converter from naff.client.utils.serializer import dict_filter_none +from naff.client.utils.text_utils import mentions from naff.models.discord.channel import BaseChannel from naff.models.discord.file import UPLOADABLE_TYPE from .base import DiscordObject @@ -380,6 +381,24 @@ def get_referenced_message(self) -> Optional["Message"]: return None return self._client.cache.get_message(self._channel_id, self._referenced_message_id) + def contains_mention( + self, + query: "str | re.Pattern[str] | models.BaseUser | models.BaseChannel | models.Role", + *, + tag_as_mention: bool = False, + ) -> bool: + """ + Check whether the message contains the query or not. + + Args: + query: The query to search for + tag_as_mention: Should `BaseUser.tag` be checked *(only if query is an instance of BaseUser)* + + Returns: + A boolean indicating whether the query could be found or not + """ + return mentions(text=self.content or self.system_content, query=query, tag_as_mention=tag_as_mention) + @classmethod def _process_dict(cls, data: dict, client: "Client") -> dict: if author_data := data.pop("author", None):