aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Rohan Reddy Alleti <[email protected]>2022-06-13 09:46:35 +0530
committerGravatar GitHub <[email protected]>2022-06-12 21:16:35 -0700
commit61f25af93cf072ca1bb650bb68538ca0652ca177 (patch)
tree51848aeec1a15fa4d057cf11aee24c23512d411a
parentMerge pull request #2189 from python-discord/clean_improv (diff)
Add reroll command. (#1568)
Co-authored-by: Bluenix <[email protected]>
-rw-r--r--bot/exts/fun/off_topic_names.py177
1 files changed, 159 insertions, 18 deletions
diff --git a/bot/exts/fun/off_topic_names.py b/bot/exts/fun/off_topic_names.py
index b8206dab4..5c5fa1dd5 100644
--- a/bot/exts/fun/off_topic_names.py
+++ b/bot/exts/fun/off_topic_names.py
@@ -1,18 +1,30 @@
+import asyncio
import datetime
import difflib
+import json
+import random
+from functools import partial
+from typing import Optional
from botcore.site_api import ResponseCodeError
-from discord import Colour, Embed
+from discord import ButtonStyle, Colour, Embed, Interaction
from discord.ext import tasks
from discord.ext.commands import Cog, Context, group, has_any_role
+from discord.ui import Button, View
from bot.bot import Bot
-from bot.constants import Bot as BotConfig, Channels, MODERATION_ROLES
+from bot.constants import Bot as BotConfig, Channels, MODERATION_ROLES, NEGATIVE_REPLIES
from bot.converters import OffTopicName
from bot.log import get_logger
from bot.pagination import LinePaginator
CHANNELS = (Channels.off_topic_0, Channels.off_topic_1, Channels.off_topic_2)
+
+# In case, the off-topic channel name format is modified.
+OTN_FORMATTER = "ot{number}-{name}"
+OT_NUMBER_INDEX = 2
+NAME_START_INDEX = 4
+
log = get_logger(__name__)
@@ -45,19 +57,42 @@ class OffTopicNames(Cog):
'bot/off-topic-channel-names', params={'random_items': 3}
)
except ResponseCodeError as e:
- log.error(f"Failed to get new off topic channel names: code {e.response.status}")
+ log.error(f"Failed to get new off-topic channel names: code {e.response.status}")
raise
channel_0, channel_1, channel_2 = (self.bot.get_channel(channel_id) for channel_id in CHANNELS)
- await channel_0.edit(name=f'ot0-{channel_0_name}')
- await channel_1.edit(name=f'ot1-{channel_1_name}')
- await channel_2.edit(name=f'ot2-{channel_2_name}')
+ await channel_0.edit(name=OTN_FORMATTER.format(number=0, name=channel_0_name))
+ await channel_1.edit(name=OTN_FORMATTER.format(number=1, name=channel_1_name))
+ await channel_2.edit(name=OTN_FORMATTER.format(number=2, name=channel_2_name))
+
log.debug(
"Updated off-topic channel names to"
f" {channel_0_name}, {channel_1_name} and {channel_2_name}"
)
+ async def toggle_ot_name_activity(self, ctx: Context, name: str, active: bool) -> None:
+ """Toggle active attribute for an off-topic name."""
+ data = {
+ "active": active
+ }
+ await self.bot.api_client.patch(f"bot/off-topic-channel-names/{name}", data=data)
+ await ctx.send(f"Off-topic name `{name}` has been {'activated' if active else 'deactivated'}.")
+
+ async def list_ot_names(self, ctx: Context, active: bool = True) -> None:
+ """Send an embed containing active/deactivated off-topic channel names."""
+ result = await self.bot.api_client.get('bot/off-topic-channel-names', params={'active': json.dumps(active)})
+ lines = sorted(f"• {name}" for name in result)
+ embed = Embed(
+ title=f"{'Active' if active else 'Deactivated'} off-topic names (`{len(result)}` total)",
+ colour=Colour.blue()
+ )
+ if result:
+ await LinePaginator.paginate(lines, ctx, embed, max_size=400, empty=False)
+ else:
+ embed.description = "Hmmm, seems like there's nothing here yet."
+ await ctx.send(embed=embed)
+
@group(name='otname', aliases=('otnames', 'otn'), invoke_without_command=True)
@has_any_role(*MODERATION_ROLES)
async def otname_group(self, ctx: Context) -> None:
@@ -109,7 +144,111 @@ class OffTopicNames(Cog):
log.info(f"{ctx.author} deleted the off-topic channel name '{name}'")
await ctx.send(f":ok_hand: Removed `{name}` from the names list.")
- @otname_group.command(name='list', aliases=('l',))
+ @otname_group.command(name='activate', aliases=('whitelist',))
+ @has_any_role(*MODERATION_ROLES)
+ async def activate_ot_name(self, ctx: Context, name: OffTopicName) -> None:
+ """Activate an existing off-topic name."""
+ await self.toggle_ot_name_activity(ctx, name, True)
+
+ @otname_group.command(name='deactivate', aliases=('blacklist',))
+ @has_any_role(*MODERATION_ROLES)
+ async def de_activate_ot_name(self, ctx: Context, name: OffTopicName) -> None:
+ """Deactivate a specific off-topic name."""
+ await self.toggle_ot_name_activity(ctx, name, False)
+
+ @otname_group.command(name='reroll')
+ @has_any_role(*MODERATION_ROLES)
+ async def re_roll_command(self, ctx: Context, ot_channel_index: Optional[int] = None) -> None:
+ """
+ Re-roll an off-topic name for a specific off-topic channel and deactivate the current name.
+
+ ot_channel_index: [0, 1, 2, ...]
+ """
+ if ot_channel_index is not None:
+ try:
+ channel = self.bot.get_channel(CHANNELS[ot_channel_index])
+ except IndexError:
+ await ctx.send(f":x: No off-topic channel found with index {ot_channel_index}.")
+ return
+ elif ctx.channel.id in CHANNELS:
+ channel = ctx.channel
+
+ else:
+ await ctx.send("Please specify channel for which the off-topic name should be re-rolled.")
+ return
+
+ old_channel_name = channel.name
+ old_ot_name = old_channel_name[NAME_START_INDEX:] # ot1-name-of-ot -> name-of-ot
+
+ await self.de_activate_ot_name(ctx, old_ot_name)
+
+ response = await self.bot.api_client.get(
+ 'bot/off-topic-channel-names', params={'random_items': 1}
+ )
+ try:
+ new_channel_name = response[0]
+ except IndexError:
+ await ctx.send("Out of active off-topic names. Add new names to reroll.")
+ return
+
+ async def rename_channel() -> None:
+ """Rename off-topic channel and log events."""
+ await channel.edit(
+ name=OTN_FORMATTER.format(number=old_channel_name[OT_NUMBER_INDEX], name=new_channel_name)
+ )
+ log.info(
+ f"{ctx.author} Off-topic channel re-named from `{old_ot_name}` "
+ f"to `{new_channel_name}`."
+ )
+
+ await ctx.message.reply(
+ f":ok_hand: Off-topic channel re-named from `{old_ot_name}` "
+ f"to `{new_channel_name}`. "
+ )
+
+ try:
+ await asyncio.wait_for(rename_channel(), 3)
+ except asyncio.TimeoutError:
+ # Channel rename endpoint rate limited. The task was cancelled by asyncio.
+ btn_yes = Button(label="Yes", style=ButtonStyle.success)
+ btn_no = Button(label="No", style=ButtonStyle.danger)
+
+ embed = Embed(
+ title=random.choice(NEGATIVE_REPLIES),
+ description=(
+ "Re-naming the channel is being rate-limited. "
+ "Would you like to schedule an asyncio task to rename the channel within the current bot session ?"
+ ),
+ colour=Colour.blurple()
+ )
+
+ async def btn_call_back(schedule: bool, interaction: Interaction) -> None:
+ if ctx.author != interaction.user:
+ log.info("User is not author, skipping.")
+ return
+ message = interaction.message
+
+ embed.description = (
+ "Scheduled a channel re-name process within the current bot session."
+ if schedule
+ else
+ "Channel not re-named due to rate limit. Please try again later."
+ )
+ await message.edit(embed=embed, view=None)
+
+ if schedule:
+ await rename_channel()
+
+ btn_yes.callback = partial(btn_call_back, True)
+ btn_no.callback = partial(btn_call_back, False)
+
+ view = View()
+ view.add_item(btn_yes)
+ view.add_item(btn_no)
+
+ await ctx.message.reply(embed=embed, view=view)
+
+ @otname_group.group(name='list', aliases=('l',), invoke_without_command=True)
@has_any_role(*MODERATION_ROLES)
async def list_command(self, ctx: Context) -> None:
"""
@@ -117,17 +256,19 @@ class OffTopicNames(Cog):
Restricted to Moderator and above to not spoil the surprise.
"""
- result = await self.bot.api_client.get('bot/off-topic-channel-names')
- lines = sorted(f"• {name}" for name in result)
- embed = Embed(
- title=f"Known off-topic names (`{len(result)}` total)",
- colour=Colour.blue()
- )
- if result:
- await LinePaginator.paginate(lines, ctx, embed, max_size=400, empty=False)
- else:
- embed.description = "Hmmm, seems like there's nothing here yet."
- await ctx.send(embed=embed)
+ await self.active_otnames_command(ctx)
+
+ @list_command.command(name='active', aliases=('a',))
+ @has_any_role(*MODERATION_ROLES)
+ async def active_otnames_command(self, ctx: Context) -> None:
+ """List active off-topic channel names."""
+ await self.list_ot_names(ctx, True)
+
+ @list_command.command(name='deactivated', aliases=('d',))
+ @has_any_role(*MODERATION_ROLES)
+ async def deactivated_otnames_command(self, ctx: Context) -> None:
+ """List deactivated off-topic channel names."""
+ await self.list_ot_names(ctx, False)
@otname_group.command(name='search', aliases=('s',))
@has_any_role(*MODERATION_ROLES)