aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/__main__.py2
-rw-r--r--bot/cogs/superstarify.py195
-rw-r--r--bot/constants.py2
-rw-r--r--config-default.yml2
4 files changed, 198 insertions, 3 deletions
diff --git a/bot/__main__.py b/bot/__main__.py
index f74b3545c..ab66492bb 100644
--- a/bot/__main__.py
+++ b/bot/__main__.py
@@ -61,7 +61,7 @@ bot.load_extension("bot.cogs.deployment")
bot.load_extension("bot.cogs.defcon")
bot.load_extension("bot.cogs.eval")
bot.load_extension("bot.cogs.fun")
-bot.load_extension("bot.cogs.hiphopify")
+bot.load_extension("bot.cogs.superstarify")
bot.load_extension("bot.cogs.information")
bot.load_extension("bot.cogs.moderation")
bot.load_extension("bot.cogs.off_topic_names")
diff --git a/bot/cogs/superstarify.py b/bot/cogs/superstarify.py
new file mode 100644
index 000000000..e1cfcc184
--- /dev/null
+++ b/bot/cogs/superstarify.py
@@ -0,0 +1,195 @@
+import logging
+import random
+
+from discord import Colour, Embed, Member
+from discord.errors import Forbidden
+from discord.ext.commands import Bot, Context, command
+
+from bot.constants import (
+ Channels, Keys,
+ NEGATIVE_REPLIES, POSITIVE_REPLIES,
+ Roles, URLs
+)
+from bot.decorators import with_role
+
+
+log = logging.getLogger(__name__)
+
+
+class Superstarify:
+ """
+ A set of commands to moderate terrible nicknames.
+ """
+
+ def __init__(self, bot: Bot):
+ self.bot = bot
+ self.headers = {"X-API-KEY": Keys.site_api}
+
+ async def on_member_update(self, before, after):
+ """
+ This event will trigger when someone changes their name.
+ At this point we will look up the user in our database and check
+ whether they are allowed to change their names, or if they are in
+ superstar-prison. If they are not allowed, we will change it back.
+ :return:
+ """
+
+ if before.display_name == after.display_name:
+ return # User didn't change their nickname. Abort!
+
+ log.debug(
+ f"{before.display_name} is trying to change their nickname to {after.display_name}. "
+ "Checking if the user is in superstar-prison..."
+ )
+
+ response = await self.bot.http_session.get(
+ URLs.site_superstarify_api,
+ headers=self.headers,
+ params={"user_id": str(before.id)}
+ )
+
+ response = await response.json()
+
+ if response and response.get("end_timestamp") and not response.get("error_code"):
+ if after.display_name == response.get("forced_nick"):
+ return # Nick change was triggered by this event. Ignore.
+
+ log.debug(
+ f"{after.display_name} is currently in superstar-prison. "
+ f"Changing the nick back to {before.display_name}."
+ )
+ await after.edit(nick=response.get("forced_nick"))
+ try:
+ await after.send(
+ "You have tried to change your nickname on the **Python Discord** server "
+ f"from **{before.display_name}** to **{after.display_name}**, but as you "
+ "are currently in superstar-prison, you do not have permission to do so. "
+ "You will be allowed to change your nickname again at the following time:\n\n"
+ f"**{response.get('end_timestamp')}**."
+ )
+ except Forbidden:
+ log.warning(
+ "The user tried to change their nickname while in superstar-prison. "
+ "This led to the bot trying to DM the user to let them know they cannot do that, "
+ "but the user had either blocked the bot or disabled DMs, so it was not possible "
+ "to DM them, and a discord.errors.Forbidden error was incurred."
+ )
+
+ @command(name='superstarify', aliases=('force_nick', 'ss'))
+ @with_role(Roles.admin, Roles.owner, Roles.moderator)
+ async def superstarify(self, ctx: Context, member: Member, duration: str, *, forced_nick: str = None):
+ """
+ This command will force a random superstar name (like Taylor Swift) to be the user's
+ nickname for a specified duration. If a forced_nick is provided, it will use that instead.
+
+ :param ctx: Discord message context
+ :param ta:
+ If provided, this function shows data for that specific tag.
+ If not provided, this function shows the caller a list of all tags.
+ """
+
+ log.debug(
+ f"Attempting to superstarify {member.display_name} for {duration}. "
+ f"forced_nick is set to {forced_nick}."
+ )
+
+ embed = Embed()
+ embed.colour = Colour.blurple()
+
+ params = {
+ "user_id": str(member.id),
+ "duration": duration
+ }
+
+ if forced_nick:
+ params["forced_nick"] = forced_nick
+
+ response = await self.bot.http_session.post(
+ URLs.site_superstarify_api,
+ headers=self.headers,
+ json=params
+ )
+
+ response = await response.json()
+
+ if "error_message" in response:
+ log.warning(
+ "Encountered the following error when trying to superstarify the user:\n"
+ f"{response.get('error_message')}"
+ )
+ embed.colour = Colour.red()
+ embed.title = random.choice(NEGATIVE_REPLIES)
+ embed.description = response.get("error_message")
+ return await ctx.send(embed=embed)
+
+ else:
+ forced_nick = response.get('forced_nick')
+ end_time = response.get("end_timestamp")
+ image_url = response.get("image_url")
+
+ embed.title = "Congratulations!"
+ embed.description = (
+ f"Your previous nickname, **{member.display_name}**, was so bad that we have decided to change it. "
+ f"Your new nickname will be **{forced_nick}**.\n\n"
+ f"You will be unable to change your nickname until \n**{end_time}**.\n\n"
+ "If you're confused by this, please read our "
+ "[official nickname policy](https://pythondiscord.com/about/rules#nickname-policy)."
+ )
+ embed.set_image(url=image_url)
+
+ # Log to the mod_log channel
+ log.trace("Logging to the #mod-log channel. This could fail because of channel permissions.")
+ mod_log = self.bot.get_channel(Channels.modlog)
+ await mod_log.send(
+ f":middle_finger: {member.name}#{member.discriminator} (`{member.id}`) "
+ f"has been superstarified by **{ctx.author.name}**. Their new nickname is `{forced_nick}`. "
+ f"They will not be able to change their nickname again until **{end_time}**"
+ )
+
+ # Change the nick and return the embed
+ log.debug("Changing the users nickname and sending the embed.")
+ await member.edit(nick=forced_nick)
+ await ctx.send(embed=embed)
+
+ @command(name='unsuperstarify', aliases=('release_nick', 'uss'))
+ @with_role(Roles.admin, Roles.owner, Roles.moderator)
+ async def unsuperstarify(self, ctx: Context, member: Member):
+ """
+ This command will remove the entry from our database, allowing the user
+ to once again change their nickname.
+
+ :param ctx: Discord message context
+ :param member: The member to unsuperstarify
+ """
+
+ log.debug(f"Attempting to unsuperstarify the following user: {member.display_name}")
+
+ embed = Embed()
+ embed.colour = Colour.blurple()
+
+ response = await self.bot.http_session.delete(
+ URLs.site_superstarify_api,
+ headers=self.headers,
+ json={"user_id": str(member.id)}
+ )
+
+ response = await response.json()
+ embed.description = "User has been released from superstar-prison."
+ embed.title = random.choice(POSITIVE_REPLIES)
+
+ if "error_message" in response:
+ embed.colour = Colour.red()
+ embed.title = random.choice(NEGATIVE_REPLIES)
+ embed.description = response.get("error_message")
+ log.warning(
+ f"Error encountered when trying to unsuperstarify {member.display_name}:\n"
+ f"{response}"
+ )
+
+ log.debug(f"{member.display_name} was successfully released from superstar-prison.")
+ await ctx.send(embed=embed)
+
+
+def setup(bot):
+ bot.add_cog(Superstarify(bot))
+ log.info("Cog loaded: Superstarify")
diff --git a/bot/constants.py b/bot/constants.py
index 145dc4700..43f03d7bf 100644
--- a/bot/constants.py
+++ b/bot/constants.py
@@ -395,7 +395,7 @@ class URLs(metaclass=YAMLGetter):
site_api: str
site_facts_api: str
site_clean_api: str
- site_hiphopify_api: str
+ site_superstarify_api: str
site_idioms_api: str
site_logs_api: str
site_logs_view: str
diff --git a/config-default.yml b/config-default.yml
index 15f1a143a..046c1ea56 100644
--- a/config-default.yml
+++ b/config-default.yml
@@ -218,7 +218,7 @@ urls:
site_bigbrother_api: !JOIN [*SCHEMA, *API, "/bot/bigbrother"]
site_docs_api: !JOIN [*SCHEMA, *API, "/bot/docs"]
site_facts_api: !JOIN [*SCHEMA, *API, "/bot/snake_facts"]
- site_hiphopify_api: !JOIN [*SCHEMA, *API, "/bot/hiphopify"]
+ site_superstarify_api: !JOIN [*SCHEMA, *API, "/bot/superstarify"]
site_idioms_api: !JOIN [*SCHEMA, *API, "/bot/snake_idioms"]
site_infractions: !JOIN [*SCHEMA, *API, "/bot/infractions"]
site_infractions_user: !JOIN [*SCHEMA, *API, "/bot/infractions/user/{user_id}"]