aboutsummaryrefslogtreecommitdiffstats
path: root/bot
diff options
context:
space:
mode:
Diffstat (limited to 'bot')
-rw-r--r--bot/exts/utilities/bookmark.py131
1 files changed, 77 insertions, 54 deletions
diff --git a/bot/exts/utilities/bookmark.py b/bot/exts/utilities/bookmark.py
index 2e3458d8..3c57aa09 100644
--- a/bot/exts/utilities/bookmark.py
+++ b/bot/exts/utilities/bookmark.py
@@ -1,7 +1,6 @@
-import asyncio
import logging
import random
-from typing import Optional
+from typing import Callable, Optional
import discord
from discord.ext import commands
@@ -15,7 +14,6 @@ log = logging.getLogger(__name__)
# Number of seconds to wait for other users to bookmark the same message
TIMEOUT = 120
-BOOKMARK_EMOJI = "📌"
MESSAGE_NOT_FOUND_ERROR = (
"You must either provide a reference to a valid message, or reply to one."
"\n\nThe lookup strategy for a message is as follows (in order):"
@@ -25,6 +23,54 @@ MESSAGE_NOT_FOUND_ERROR = (
)
+class LinkTargetMessage(discord.ui.View):
+ """The button that relays the user to the bookmarked message."""
+
+ def __init__(
+ self,
+ target_message: discord.Message,
+ ):
+ super().__init__()
+ self.add_item(discord.ui.Button(label="View Message", url=target_message.jump_url))
+
+
+class SendBookmark(discord.ui.View):
+ """The button that sends the bookmark to other users."""
+
+ def __init__(
+ self,
+ bookmark_function: Callable[
+ [discord.TextChannel, discord.Member, discord.Message, str], None
+ ],
+ author: discord.Member,
+ channel: discord.TextChannel,
+ target_message: discord.Message,
+ ):
+ super().__init__()
+
+ self.bookmark_function = bookmark_function # The function is the 'action_bookmark'
+ self.clicked: list[int] = [author.id]
+ self.channel = channel
+ self.target_message = target_message
+
+
+ @discord.ui.button(label="Receive Bookmark", style=discord.ButtonStyle.green)
+ async def button_callback(self, button: discord.Button, interaction: discord.Interaction) -> None:
+ """The button callback."""
+ if interaction.user.id in self.clicked:
+ return await interaction.response.send_message(
+ "You have already received a bookmark to that message.", ephemeral=True
+ )
+
+ await self.bookmark_function(
+ self.channel, interaction.user, self.target_message
+ )
+ await interaction.response.send_message(
+ "You have received a bookmark to that message.", ephemeral=True
+ )
+ self.clicked.append(interaction.user.id)
+
+
class Bookmark(commands.Cog):
"""Creates personal bookmarks by relaying a message link to the user's DMs."""
@@ -35,17 +81,13 @@ class Bookmark(commands.Cog):
def build_bookmark_dm(target_message: discord.Message, title: str) -> discord.Embed:
"""Build the embed to DM the bookmark requester."""
embed = discord.Embed(
- title=title,
- description=target_message.content,
- colour=Colours.soft_green
+ title=title, description=target_message.content, colour=Colours.soft_green
)
- embed.add_field(
- name="Wanna give it a visit?",
- value=f"[Visit original message]({target_message.jump_url})"
+ embed.set_author(
+ name=target_message.author,
+ icon_url=target_message.author.display_avatar.url,
)
- embed.set_author(name=target_message.author, icon_url=target_message.author.display_avatar.url)
embed.set_thumbnail(url=Icons.bookmark)
-
return embed
@staticmethod
@@ -57,6 +99,17 @@ class Bookmark(commands.Cog):
colour=Colours.soft_red
)
+ @staticmethod
+ def create_button_embed(target_message: discord.Message) -> discord.Embed:
+ """Generates the embed which is sent with the button, so other users can receive the bookmark too."""
+ return discord.Embed(
+ description=(
+ f"Click the button to be sent your very own bookmark to "
+ f"[this message]({target_message.jump_url})."
+ ),
+ colour=Colours.soft_green,
+ )
+
async def action_bookmark(
self,
channel: discord.TextChannel,
@@ -71,7 +124,7 @@ class Bookmark(commands.Cog):
"""
embed = self.build_bookmark_dm(target_message, title)
try:
- await member.send(embed=embed)
+ await member.send(embed=embed, view=LinkTargetMessage(target_message))
except discord.Forbidden:
error_embed = self.build_error_embed(f"{member.mention}, please enable your DMs to receive the bookmark.")
await channel.send(embed=error_embed)
@@ -102,53 +155,23 @@ class Bookmark(commands.Cog):
# Prevent users from bookmarking a message in a channel they don't have access to
permissions = target_message.channel.permissions_for(ctx.author)
if not permissions.read_messages:
- log.info(f"{ctx.author} tried to bookmark a message in #{target_message.channel} but has no permissions.")
- embed = self.build_error_embed(f"{ctx.author.mention} You don't have permission to view this channel.")
+ log.info(
+ f"{ctx.author} tried to bookmark a message in #{target_message.channel} but has no permissions."
+ )
+ embed = discord.Embed(
+ title=random.choice(ERROR_REPLIES),
+ color=Colours.soft_red,
+ description="You don't have permission to view this channel.",
+ )
await ctx.send(embed=embed)
return
await self.action_bookmark(ctx.channel, ctx.author, target_message, title)
- # Keep track of who has already bookmarked, so users can't spam reactions and cause loads of DMs
- bookmarked_users = [ctx.author.id]
-
- reaction_embed = discord.Embed(
- description=(
- f"React with {BOOKMARK_EMOJI} to be sent your very own bookmark to "
- f"[this message]({ctx.message.jump_url})."
- ),
- colour=Colours.soft_green
- )
- reaction_message = await ctx.send(embed=reaction_embed)
- await reaction_message.add_reaction(BOOKMARK_EMOJI)
-
- def event_check(reaction: discord.Reaction, user: discord.Member) -> bool:
- """Make sure that this reaction is what we want to operate on."""
- return (
- # Conditions for a successful pagination:
- all((
- # Reaction is on this message
- reaction.message.id == reaction_message.id,
- # User has not already bookmarked this message
- user.id not in bookmarked_users,
- # Reaction is the `BOOKMARK_EMOJI` emoji
- str(reaction.emoji) == BOOKMARK_EMOJI,
- # Reaction was not made by the Bot
- user.id != self.bot.user.id
- ))
- )
-
- while True:
- try:
- _, user = await self.bot.wait_for("reaction_add", timeout=TIMEOUT, check=event_check)
- except asyncio.TimeoutError:
- log.debug("Timed out waiting for a reaction")
- break
- log.trace(f"{user} has successfully bookmarked from a reaction, attempting to DM them.")
- await self.action_bookmark(ctx.channel, user, target_message, title)
- bookmarked_users.append(user.id)
-
- await reaction_message.delete()
+ view = SendBookmark(self.action_bookmark, ctx.author, ctx.channel, target_message)
+
+ embed = self.create_button_embed(target_message)
+ await ctx.send(embed=embed, view=view)
@bookmark.command(name="delete", aliases=("del", "rm"), root_aliases=("unbm", "unbookmark", "dmdelete", "dmdel"))
@whitelist_override(bypass_defaults=True, allow_dm=True)