From 539451aba55201b25637d0f452010cd878e71292 Mon Sep 17 00:00:00 2001 From: Johannes Christ Date: Sun, 20 Jan 2019 09:28:54 +0100 Subject: Move superstarify cog to Django API. --- bot/cogs/superstarify.py | 285 -------------------------------------- bot/cogs/superstarify/__init__.py | 281 +++++++++++++++++++++++++++++++++++++ bot/cogs/superstarify/stars.py | 86 ++++++++++++ 3 files changed, 367 insertions(+), 285 deletions(-) delete mode 100644 bot/cogs/superstarify.py create mode 100644 bot/cogs/superstarify/__init__.py create mode 100644 bot/cogs/superstarify/stars.py diff --git a/bot/cogs/superstarify.py b/bot/cogs/superstarify.py deleted file mode 100644 index 84467bd8c..000000000 --- a/bot/cogs/superstarify.py +++ /dev/null @@ -1,285 +0,0 @@ -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.cogs.moderation import Moderation -from bot.cogs.modlog import ModLog -from bot.constants import ( - Icons, Keys, - NEGATIVE_REPLIES, POSITIVE_REPLIES, - Roles, URLs -) -from bot.decorators import with_role - -log = logging.getLogger(__name__) -NICKNAME_POLICY_URL = "https://pythondiscord.com/about/rules#nickname-policy" - - -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} - - @property - def moderation(self) -> Moderation: - return self.bot.get_cog("Moderation") - - @property - def modlog(self) -> ModLog: - return self.bot.get_cog("ModLog") - - async def on_member_update(self, before: Member, after: Member): - """ - 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. - """ - - 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." - ) - - async def on_member_join(self, member: Member): - """ - This event will trigger when someone (re)joins the server. - At this point we will look up the user in our database and check - whether they are in superstar-prison. If so, we will change their name - back to the forced nickname. - """ - - response = await self.bot.http_session.get( - URLs.site_superstarify_api, - headers=self.headers, - params={"user_id": str(member.id)} - ) - - response = await response.json() - - if response and response.get("end_timestamp") and not response.get("error_code"): - forced_nick = response.get("forced_nick") - end_timestamp = response.get("end_timestamp") - log.debug( - f"{member.name} rejoined but is currently in superstar-prison. " - f"Changing the nick back to {forced_nick}." - ) - - await member.edit(nick=forced_nick) - try: - await member.send( - "You have left and rejoined the **Python Discord** server, effectively resetting " - f"your nickname from **{forced_nick}** to **{member.name}**, " - "but as you are currently in superstar-prison, you do not have permission to do so. " - "Therefore your nickname was automatically changed back. You will be allowed to " - "change your nickname again at the following time:\n\n" - f"**{end_timestamp}**." - ) - except Forbidden: - log.warning( - "The user left and rejoined the server while in superstar-prison. " - "This led to the bot trying to DM the user to let them know their name was restored, " - "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." - ) - - # Log to the mod_log channel - log.trace("Logging to the #mod-log channel. This could fail because of channel permissions.") - mod_log_message = ( - f"**{member.name}#{member.discriminator}** (`{member.id}`)\n\n" - f"Superstarified member potentially tried to escape the prison.\n" - f"Restored enforced nickname: `{forced_nick}`\n" - f"Superstardom ends: **{end_timestamp}**" - ) - await self.modlog.send_log_message( - icon_url=Icons.user_update, - colour=Colour.gold(), - title="Superstar member rejoined server", - text=mod_log_message, - thumbnail=member.avatar_url_as(static_format="png") - ) - - @command(name='superstarify', aliases=('force_nick', 'star')) - @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") - old_nick = member.display_name - - embed.title = "Congratulations!" - embed.description = ( - f"Your previous nickname, **{old_nick}**, 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 " - f"[official nickname policy]({NICKNAME_POLICY_URL})." - ) - 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_message = ( - f"**{member.name}#{member.discriminator}** (`{member.id}`)\n\n" - f"Superstarified by **{ctx.author.name}**\n" - f"Old nickname: `{old_nick}`\n" - f"New nickname: `{forced_nick}`\n" - f"Superstardom ends: **{end_time}**" - ) - await self.modlog.send_log_message( - icon_url=Icons.user_update, - colour=Colour.gold(), - title="Member Achieved Superstardom", - text=mod_log_message, - thumbnail=member.avatar_url_as(static_format="png") - ) - - await self.moderation.notify_infraction( - user=member, - infr_type="Superstarify", - duration=duration, - reason=f"Your nickname didn't comply with our [nickname policy]({NICKNAME_POLICY_URL})." - ) - - # 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', 'unstar')) - @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}" - ) - - else: - await self.moderation.notify_pardon( - user=member, - title="You are no longer superstarified.", - content="You may now change your nickname on the server." - ) - - 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/cogs/superstarify/__init__.py b/bot/cogs/superstarify/__init__.py new file mode 100644 index 000000000..7f5b0d487 --- /dev/null +++ b/bot/cogs/superstarify/__init__.py @@ -0,0 +1,281 @@ +import logging +import random +from datetime import datetime + +from discord import Colour, Embed, Member +from discord.errors import Forbidden +from discord.ext.commands import Bot, Context, command + +from bot.cogs.moderation import Moderation +from bot.cogs.modlog import ModLog +from bot.constants import ( + Icons, Keys, + NEGATIVE_REPLIES, POSITIVE_REPLIES, + Roles, URLs +) +from bot.converters import ExpirationDate +from bot.decorators import with_role +from bot.cogs.superstarify.stars import get_nick +from bot.utils.moderation import post_infraction + +log = logging.getLogger(__name__) +NICKNAME_POLICY_URL = "https://pythondiscord.com/about/rules#nickname-policy" + + +class Superstarify: + """ + A set of commands to moderate terrible nicknames. + """ + + def __init__(self, bot: Bot): + self.bot = bot + + @property + def moderation(self) -> Moderation: + return self.bot.get_cog("Moderation") + + @property + def modlog(self) -> ModLog: + return self.bot.get_cog("ModLog") + + async def on_member_update(self, before: Member, after: Member): + """ + 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. + """ + + if before.display_name == after.display_name: + return # User didn't change their nickname. Abort! + + log.trace( + f"{before.display_name} is trying to change their nickname to {after.display_name}. " + "Checking if the user is in superstar-prison..." + ) + + active_superstarifies = await self.bot.api_client.get( + 'bot/infractions', + params={ + 'active': 'true', + 'type': 'superstar', + 'user__id': str(before.id) + } + ) + + if active_superstarifies: + [infraction] = active_superstarifies + forced_nick = get_nick(infraction['id'], before.id) + if after.display_name == forced_nick: + return # Nick change was triggered by this event. Ignore. + + log.info( + f"{after.display_name} is currently in superstar-prison. " + f"Changing the nick back to {before.display_name}." + ) + await after.edit(nick=forced_nick) + end_timestamp_human = ( + datetime.fromisoformat(infraction['expires_at'][:-1]) + .strftime('%c') + ) + + 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"**{end_timestamp_human}**." + ) + 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." + ) + + async def on_member_join(self, member: Member): + """ + This event will trigger when someone (re)joins the server. + At this point we will look up the user in our database and check + whether they are in superstar-prison. If so, we will change their name + back to the forced nickname. + """ + + active_superstarifies = await self.bot.api_client.get( + 'bot/infractions', + params={ + 'active': 'true', + 'type': 'superstarify', + 'user__id': before.id + } + ) + + if active_superstarifies: + [infraction] = active_superstarifies + forced_nick = get_nick(infraction['id'], member.id) + await member.edit(nick=forced_nick) + end_timestamp_human = ( + datetime.fromisoformat(response['expires_at'][:-1]) + .strftime('%c') + ) + + try: + await member.send( + "You have left and rejoined the **Python Discord** server, effectively resetting " + f"your nickname from **{forced_nick}** to **{member.name}**, " + "but as you are currently in superstar-prison, you do not have permission to do so. " + "Therefore your nickname was automatically changed back. You will be allowed to " + "change your nickname again at the following time:\n\n" + f"**{end_timestamp_human}**." + ) + except Forbidden: + log.warning( + "The user left and rejoined the server while in superstar-prison. " + "This led to the bot trying to DM the user to let them know their name was restored, " + "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." + ) + + # Log to the mod_log channel + log.trace("Logging to the #mod-log channel. This could fail because of channel permissions.") + mod_log_message = ( + f"**{member.name}#{member.discriminator}** (`{member.id}`)\n\n" + f"Superstarified member potentially tried to escape the prison.\n" + f"Restored enforced nickname: `{forced_nick}`\n" + f"Superstardom ends: **{end_timestamp_human}**" + ) + await self.modlog.send_log_message( + icon_url=Icons.user_update, + colour=Colour.gold(), + title="Superstar member rejoined server", + text=mod_log_message, + thumbnail=member.avatar_url_as(static_format="png") + ) + + @command(name='superstarify', aliases=('force_nick', 'star')) + @with_role(Roles.admin, Roles.owner, Roles.moderator) + async def superstarify( + self, ctx: Context, member: Member, + expiration: ExpirationDate, reason: str = None + ): + """ + This command will force a random superstar name (like Taylor Swift) to be the user's + nickname for a specified duration. An optional reason can be provided. + If no reason is given, the original name will be shown in a generated reason. + """ + + active_superstarifies = await self.bot.api_client.get( + 'bot/infractions', + params={ + 'active': 'true', + 'type': 'superstar', + 'user__id': str(member.id) + } + ) + if active_superstarifies: + return await ctx.send( + ":x: According to my records, this user is already superstarified. " + f"See infraction **#{active_superstarifies[0]['id']}**." + ) + + + infraction = await post_infraction( + ctx, member, + type='superstar', reason=reason or ('old nick: ' + member.display_name), + expires_at=expiration + ) + forced_nick = get_nick(infraction['id'], member.id) + + embed = Embed() + 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**{expiration}**.\n\n" + "If you're confused by this, please read our " + f"[official nickname policy]({NICKNAME_POLICY_URL})." + ) + + # Log to the mod_log channel + log.trace("Logging to the #mod-log channel. This could fail because of channel permissions.") + mod_log_message = ( + f"**{member.name}#{member.discriminator}** (`{member.id}`)\n\n" + f"Superstarified by **{ctx.author.name}**\n" + f"Old nickname: `{member.display_name}`\n" + f"New nickname: `{forced_nick}`\n" + f"Superstardom ends: **{expiration}**" + ) + await self.modlog.send_log_message( + icon_url=Icons.user_update, + colour=Colour.gold(), + title="Member Achieved Superstardom", + text=mod_log_message, + thumbnail=member.avatar_url_as(static_format="png") + ) + + await self.moderation.notify_infraction( + user=member, + infr_type="Superstarify", + expires_at=expiration, + reason=f"Your nickname didn't comply with our [nickname policy]({NICKNAME_POLICY_URL})." + ) + + # Change the nick and return the embed + log.trace("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', 'unstar')) + @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() + + active_superstarifies = await self.bot.api_client.get( + 'bot/infractions', + params={ + 'active': 'true', + 'type': 'superstar', + 'user__id': str(member.id) + } + ) + if not active_superstarifies: + return await ctx.send( + ":x: There is no active superstarify infraction for this user." + ) + + + [infraction] = active_superstarifies + await self.bot.api_client.patch( + 'bot/infractions/' + str(infraction['id']), + json={'active': False} + ) + + embed = Embed() + embed.description = "User has been released from superstar-prison." + embed.title = random.choice(POSITIVE_REPLIES) + + await self.moderation.notify_pardon( + user=member, + title="You are no longer superstarified.", + content="You may now change your nickname on the server." + ) + log.trace(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/cogs/superstarify/stars.py b/bot/cogs/superstarify/stars.py new file mode 100644 index 000000000..9b49d7175 --- /dev/null +++ b/bot/cogs/superstarify/stars.py @@ -0,0 +1,86 @@ +import random + + +STAR_NAMES = ( + "Adele", + "Aerosmith", + "Aretha Franklin", + "Ayumi Hamasaki", + "B'z", + "Barbra Streisand", + "Barry Manilow", + "Barry White", + "Beyonce", + "Billy Joel", + "Bob Dylan", + "Bob Marley", + "Bob Seger", + "Bon Jovi", + "Britney Spears", + "Bruce Springsteen", + "Bruno Mars", + "Bryan Adams", + "Celine Dion", + "Cher", + "Christina Aguilera", + "David Bowie", + "Donna Summer", + "Drake", + "Ed Sheeran", + "Elton John", + "Elvis Presley", + "Eminem", + "Enya", + "Flo Rida", + "Frank Sinatra", + "Garth Brooks", + "George Michael", + "George Strait", + "James Taylor", + "Janet Jackson", + "Jay-Z", + "Johnny Cash", + "Johnny Hallyday", + "Julio Iglesias", + "Justin Bieber", + "Justin Timberlake", + "Kanye West", + "Katy Perry", + "Kenny G", + "Kenny Rogers", + "Lady Gaga", + "Lil Wayne", + "Linda Ronstadt", + "Lionel Richie", + "Madonna", + "Mariah Carey", + "Meat Loaf", + "Michael Jackson", + "Neil Diamond", + "Nicki Minaj", + "Olivia Newton-John", + "Paul McCartney", + "Phil Collins", + "Pink", + "Prince", + "Reba McEntire", + "Rihanna", + "Robbie Williams", + "Rod Stewart", + "Santana", + "Shania Twain", + "Stevie Wonder", + "Taylor Swift", + "Tim McGraw", + "Tina Turner", + "Tom Petty", + "Tupac Shakur", + "Usher", + "Van Halen", + "Whitney Houston", +) + + +def get_nick(infraction_id, member_id): + rng = random.Random(str(infraction_id) + str(member_id)) + return rng.choice(STAR_NAMES) -- cgit v1.2.3