diff options
author | Arjun Satarkar <me@arjunsatarkar.net> | 2024-03-11 05:44:12 +0000 |
---|---|---|
committer | Arjun Satarkar <me@arjunsatarkar.net> | 2024-03-11 05:44:12 +0000 |
commit | afb14f53f4dc43163fe5d8528d94eadaf54fb34d (patch) | |
tree | 4e630d03ad07323aa492062bf1f7c6668eceb70d | |
parent | 8cdeb0a316628f2e581e66e0c72442ac23c56a74 (diff) | |
download | aps-cogs-afb14f53f4dc43163fe5d8528d94eadaf54fb34d.tar aps-cogs-afb14f53f4dc43163fe5d8528d94eadaf54fb34d.tar.gz aps-cogs-afb14f53f4dc43163fe5d8528d94eadaf54fb34d.zip |
Add skeleton of starboard cog; improve menu handling
We were previously not escaping mentions right in `qotd list` and
`qotd suggest`. I think everyone and here could have maybe got
through? Not sure about the defaults there.
Also improved the handling in Markov where previously we'd been
1. allowing mentions but 2. editing the message from a dummy one so
they didn't ping, which I think was out of some idea of preserving the
exact text of an exclusion but it seems inelegant.
-rw-r--r-- | README.adoc | 2 | ||||
-rw-r--r-- | markov/markov.py | 11 | ||||
-rw-r--r-- | question_of_the_day/question_of_the_day.py | 5 | ||||
-rw-r--r-- | starboard/__init__.py | 5 | ||||
-rw-r--r-- | starboard/info.json | 5 | ||||
-rw-r--r-- | starboard/starboard.py | 145 |
6 files changed, 165 insertions, 8 deletions
diff --git a/README.adoc b/README.adoc index 15d98d9..dc9842b 100644 --- a/README.adoc +++ b/README.adoc @@ -1 +1,3 @@ = aps-cogs + +My cogs for the https://docs.discord.red/en/stable/[Red] self-hosted https://discord.com/[Discord] bot. diff --git a/markov/markov.py b/markov/markov.py index 8081b07..3399581 100644 --- a/markov/markov.py +++ b/markov/markov.py @@ -284,13 +284,14 @@ class Markov(commands.Cog): text = "" for i, string in enumerate(await config_value): text += f"{i + 1}. {repr(string)}\n" - pages = list(redbot.core.utils.chat_formatting.pagify(text)) + pages = list( + redbot.core.utils.chat_formatting.pagify( + discord.utils.escape_mentions(text) + ) + ) if pages: - message = await ctx.reply( - ".", allowed_mentions=discord.AllowedMentions.none() - ) - await redbot.core.utils.menus.menu(ctx, pages, message=message) + await redbot.core.utils.menus.menu(ctx, pages) else: await ctx.reply("No results.") diff --git a/question_of_the_day/question_of_the_day.py b/question_of_the_day/question_of_the_day.py index a307552..f6d7086 100644 --- a/question_of_the_day/question_of_the_day.py +++ b/question_of_the_day/question_of_the_day.py @@ -412,9 +412,8 @@ class QuestionOfTheDay(commands.Cog): async def paginate_questions(self, ctx, questions: list): return [ - x - for x in redbot.core.utils.chat_formatting.pagify( - redbot.core.utils.common_filters.filter_various_mentions( + *redbot.core.utils.chat_formatting.pagify( + discord.utils.escape_mentions( "\n".join( [ f"{i + 1}. {redbot.core.utils.chat_formatting.bold(question['question'])} by " diff --git a/starboard/__init__.py b/starboard/__init__.py new file mode 100644 index 0000000..eeb3d75 --- /dev/null +++ b/starboard/__init__.py @@ -0,0 +1,5 @@ +from .starboard import Starboard + + +async def setup(bot): + await bot.add_cog(Starboard(bot)) diff --git a/starboard/info.json b/starboard/info.json new file mode 100644 index 0000000..af11ade --- /dev/null +++ b/starboard/info.json @@ -0,0 +1,5 @@ +{ + "author": ["Arjun Satarkar"], + "description": "Create starboards in your server.", + "short": "Create starboards in your server." +} diff --git a/starboard/starboard.py b/starboard/starboard.py new file mode 100644 index 0000000..609257c --- /dev/null +++ b/starboard/starboard.py @@ -0,0 +1,145 @@ +import asyncio +import discord +import redbot.core +from redbot.core import Config +from redbot.core import commands + + +class Starboard(commands.Cog): + def __init__(self, bot): + self.bot = bot + self.config = Config.get_conf( + self, identifier="551742410770612234|31374c1f-a5e9-470a-8fed-1137e980f27a" + ) + self.config.register_guild(starboards={}) + + def emoji_as_sendable_text(self, emoji: discord.Emoji | discord.PartialEmoji | str): + if isinstance(emoji, str): + return emoji + if emoji.animated: + return f"<a:{emoji.name}:{emoji.id}>" + else: + return f"<:{emoji.name}:{emoji.id}>" + + @commands.group() + async def starboard(self, _ctx): + pass + + @starboard.command() + @commands.admin_or_permissions(manage_guild=True) + async def add(self, ctx, name: str, channel: discord.TextChannel, threshold: int): + if threshold < 1: + await ctx.reply("Error: threshold must be 1 or higher.") + return + async with self.config.guild(ctx.guild).starboards() as starboards: + if name in starboards: + await ctx.reply( + "Error: a starboard with that name already exists (see `starboard list`)." + ) + return + starboards[name] = { + "channel_id": channel.id, + "threshold": threshold, + "allow_all_reactions": False, + "reactions": { + "unicode": {}, + "custom": {}, + }, + } + + wait_message_id = await ctx.reply( + f"Creating starboard ``{name}`` posting to {channel.mention} requiring {threshold} reactions." + "\nReact to this message with all reactions you want the bot to consider for this starboard," + " then send DONE, or else type ANY to check for all reactions. If you don't react, ⭐ will" + " be chosen by default.", + allowed_mentions=discord.AllowedMentions.none(), + ) + + try: + done_message = await self.bot.wait_for( + "message", + check=lambda m: m.content.lower() in ["done", "any"], + timeout=120, + ) + except asyncio.TimeoutError: + await ctx.send( + f"Error: timed out; cancelling creation of starboard ``{name}``.", + allowed_mentions=discord.AllowedMentions.none(), + ) + del starboards[name] + return + + # Accumulated to easily post the confirmation message + emoji_text_list = [] + match done_message.content.lower(): + case "done": + reactions = ( + await ctx.channel.fetch_message(wait_message_id) + ).reactions + if not reactions: + starboards[name]["reactions"]["unicode"]["⭐"] = 1 + else: + for reaction in reactions: + emoji = reaction.emoji + if isinstance(emoji, str): + starboards[name]["reactions"]["unicode"][emoji] = 1 + else: + starboards[name]["reactions"]["custom"][emoji.id] = 1 + emoji_text_list.append(self.emoji_as_sendable_text(emoji)) + case "any": + starboards[name]["allow_all_reactions"] = True + + confirmation_text = f"Created starboard ``{name}`` posting to {channel} and requiring {threshold}" + if not emoji_text_list: + confirmation_text += " of any emoji." + else: + confirmation_text += f" reactions of {redbot.core.utils.chat_formatting.humanize_list(emoji_text_list, style='or')}." + await ctx.send( + confirmation_text, allowed_mentions=discord.AllowedMentions.none() + ) + + @starboard.command() + @commands.admin_or_permissions(manage_guild=True) + async def remove(self, ctx, name: str): + async with self.config.guild(ctx.guild).starboards() as starboards: + try: + del starboards[name] + except KeyError: + await ctx.reply( + "Error: no starboard found with that name (see `starboard list`)." + ) + else: + await ctx.reply("Removed that starboard.") + + @starboard.command() + async def list(self, ctx): + starboards = await self.config.guild(ctx.guild).starboards() + list_text = "Name, Channel, Threshold, Reactions" + for name in starboards: + starboard = starboards[name] + list_text.append( + f"\n* ``{name}``, {ctx.guild.get_channel(starboard['channel_id'])}," + f" {starboard['threshold']}, " + ) + if starboard["allow_all_reactions"]: + list_text.append("*any*") + else: + emoji_list = [] + for emoji in ( + starboard["reactions"]["custom"] + starboard["reactions"]["unicode"] + ): + emoji_list.append( + self.emoji_as_sendable_text(self.bot.get_emoji(emoji)) + ) + list_text.append( + redbot.core.utils.chat_formatting.humanize_list(emoji_list) + ) + pages = [ + *redbot.core.utils.chat_formatting.pagify( + discord.utils.escape_mentions(list_text) + ) + ] + if pages: + await redbot.core.utils.menus.menu(ctx, pages) + else: + await ctx.reply("No starboards.") |