diff options
author | 2022-07-16 19:13:11 +0100 | |
---|---|---|
committer | 2022-07-16 19:15:37 +0100 | |
commit | c20c19c9cefb207586e9b51edf98948e1d710333 (patch) | |
tree | 248d671bbf42e2bf19e84e6002f5fe2909df587a | |
parent | Merge pull request #98 from python-discord/fix-stats-close (diff) |
Add a generic view and button
The view implements an interaction check for allowed_users and allowed_roles.
The button deleted the message attached the the parent view on click.
-rw-r--r-- | botcore/utils/__init__.py | 3 | ||||
-rw-r--r-- | botcore/utils/interactions.py | 86 | ||||
-rw-r--r-- | docs/changelog.rst | 5 | ||||
-rw-r--r-- | pyproject.toml | 2 |
4 files changed, 94 insertions, 2 deletions
diff --git a/botcore/utils/__init__.py b/botcore/utils/__init__.py index fa389743..dfdd6df5 100644 --- a/botcore/utils/__init__.py +++ b/botcore/utils/__init__.py @@ -1,6 +1,6 @@ """Useful utilities and tools for Discord bot development.""" -from botcore.utils import _monkey_patches, caching, channel, logging, members, regex, scheduling +from botcore.utils import _monkey_patches, caching, channel, interactions, logging, members, regex, scheduling from botcore.utils._extensions import unqualify @@ -24,6 +24,7 @@ __all__ = [ apply_monkey_patches, caching, channel, + interactions, logging, members, regex, diff --git a/botcore/utils/interactions.py b/botcore/utils/interactions.py new file mode 100644 index 00000000..6d632c53 --- /dev/null +++ b/botcore/utils/interactions.py @@ -0,0 +1,86 @@ +from typing import Optional, Sequence + +from discord import ButtonStyle, Interaction, ui + +from botcore.utils.logging import get_logger + +log = get_logger(__name__) + + +class ViewWithUserAndRoleCheck(ui.View): + """ + A view that allows the original invoker and moderators to interact with it. + + Args: + allowed_users: A sequence of user's ids who are allowed to interact with the view. + allowed_roles: A sequence of role ids that are allowed to interact with the view. + timeout: Timeout in seconds from last interaction with the UI before no longer accepting input. + If ``None`` then there is no timeout. + """ + + def __init__( + self, + *, + allowed_users: Sequence[int], + allowed_roles: Sequence[int], + timeout: Optional[float] = 180.0 + ) -> None: + super().__init__(timeout=timeout) + self.allowed_users = allowed_users + self.allowed_roles = allowed_roles + + async def interaction_check(self, interaction: Interaction) -> bool: + """ + Ensure the user clicking the button is the view invoker, or a moderator. + + Args: + interaction: The interaction that occurred. + """ + if interaction.user.id in self.allowed_users: + log.trace( + "Allowed interaction by %s (%d) on %d as they are an allowed user.", + interaction.user, + interaction.user.id, + interaction.message.id, + ) + return True + + if any(role.id in self.allowed_roles for role in getattr(interaction.user, "roles", [])): + log.trace( + "Allowed interaction by %s (%d)on %d as they have an allowed role.", + interaction.user, + interaction.user.id, + interaction.message.id, + ) + return True + + await interaction.response.send_message("This is not your button to click!", ephemeral=True) + return False + + +class DeleteMessageButton(ui.Button): + """ + A button that can be added to a view to delete the message containing the view on click. + + This button itself carries out no interaction checks, these should be done by the parent view. + + See :obj:`botcore.utils.interactions.ViewWithUserAndRoleCheck` for a view that implements basic checks. + + Args: + style (:literal-url:`ButtonStyle <https://discordpy.readthedocs.io/en/latest/interactions/api.html#discord.ButtonStyle>`): + The style of the button, set to ``ButtonStyle.secondary`` if not specified. + label: The label of the button, set to "Delete" if not specified. + """ # noqa: E501 + + def __init__( + self, + *, + style: ButtonStyle = ButtonStyle.secondary, + label: str = "Delete", + **kwargs + ): + super().__init__(style=style, label=label, **kwargs) + + async def callback(self, interaction: Interaction) -> None: + """Delete the original message on button click.""" + await interaction.delete_original_message() diff --git a/docs/changelog.rst b/docs/changelog.rst index 9d74eee8..cbe37062 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,6 +4,11 @@ Changelog ========= +- :release:`7.3.0 <16th July 2022>` +- :feature:`103` Add a generic view :obj:`botcore.utils.interactions.ViewWithUserAndRoleCheck` that only allows specified users and roles to interaction with it +- :feature:`103` Add a button :obj:`botcore.utils.interactions.DeleteMessageButton` that deletes the message attached to its parent view. + + - :release:`7.2.2 <9th July 2022>` - :bug:`98` Only close ``BotBase.stats._transport`` if ``BotBase.stats`` was created diff --git a/pyproject.toml b/pyproject.toml index ccb1a39d..cff654ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "bot-core" -version = "7.2.2" +version = "7.3.0" description = "Bot-Core provides the core functionality and utilities for the bots of the Python Discord community." authors = ["Python Discord <[email protected]>"] license = "MIT" |