diff --git a/src/cogs/hypixel.py b/src/cogs/hypixel.py index c68d857..3ecdc68 100644 --- a/src/cogs/hypixel.py +++ b/src/cogs/hypixel.py @@ -1,6 +1,6 @@ import discord -from discord.ext import commands, bridge from discord.commands import option +from discord.ext import commands, bridge from src.func.General import General from src.func.String import String diff --git a/src/cogs/listeners.py b/src/cogs/listeners.py index c495f2d..341adcc 100644 --- a/src/cogs/listeners.py +++ b/src/cogs/listeners.py @@ -27,6 +27,9 @@ async def on_command_error(self, ctx, error): async def on_application_command_error(self, ctx, error): await Listener(obj=error).on_application_command_error(ctx) + @commands.Cog.listener() + async def on_message(self, message): + await Listener(obj=message).on_invitation_message() def setup(bot): bot.add_cog(Listeners(bot)) diff --git a/src/func/Listener.py b/src/func/Listener.py index f9aed16..b96fc3e 100644 --- a/src/func/Listener.py +++ b/src/func/Listener.py @@ -7,12 +7,14 @@ from discord.ext import commands from discord.ui import Button, Select, View +from src.utils.calculation_utils import extract_usernames from src.utils.consts import (error_channel_id, invalid_command_embed, member_not_found_embed, missing_permissions_embed, missing_role_embed, - neutral_color, not_owner_embed, pronoun_roles, + neutral_color, not_owner_embed, pronoun_roles, staff_bridge_channel, reaction_roles, registration_channel_id, registration_embed, err_404_embed, bot_missing_perms_embed, tickets_embed) from src.utils.discord_utils import create_ticket +from src.utils.referral_utils import validate_invites from src.utils.request_utils import get_jpg_file @@ -69,6 +71,7 @@ async def on_command_error(self, ctx): # All other errors get sent to the error channel else: + await ctx.respond(embed=err_404_embed) tb = "".join(traceback.format_exception( type(self.obj), self.obj, self.obj.__traceback__)) if len(tb) <= 1955: @@ -221,3 +224,30 @@ def __init__(self): style=discord.ButtonStyle.blurple, emoji="✉️")) return image, tickets_embed, TicketView() + + async def on_invitation_message(self): + if not self.obj.author.bot: + return + if self.obj.channel.id != staff_bridge_channel: + return + if not self.obj.embeds: + return + + embed = self.obj.embeds[0] + + if not embed.description: + return + + if "invited" not in embed.description.lower(): + return + + description = embed.description + + inviter, invitee = await extract_usernames(description) + + if not all((inviter, invitee)): + return + + return_message = await validate_invites(inviter, invitee) + + await self.obj.channel.send(return_message) diff --git a/src/func/String.py b/src/func/String.py index 613a76e..4a0a468 100644 --- a/src/func/String.py +++ b/src/func/String.py @@ -17,8 +17,8 @@ qotd_ans_channel_id, qotd_channel_id, ticket_categories, unknown_ign_embed, rainbow_separator, guild_handle, missing_permissions_embed) -from src.utils.db_utils import (delete_dnkl, insert_new_dnkl, select_one, - update_dnkl, get_invites) +from src.utils.db_utils import (delete_dnkl, select_one, + get_invites) from src.utils.request_utils import (get_hypixel_player, get_mojang_profile, get_player_guild, get_name_by_uuid) from src.utils.ticket_utils.dnkl import dnkl_application @@ -188,28 +188,9 @@ async def dnkladd(self, ctx): _, weekly_gexp = await get_player_gexp(uuid) if not ign: return unknown_ign_embed - + await ctx.respond("Please respond to the following prompts: ") # Ask DNKL application questions - embed = await dnkl_application(ign, uuid, ctx.channel, ctx.author, weekly_gexp) - dnkl_message = await bot.get_channel(dnkl_channel_id).send(embed=embed.set_author(name="Do-not-kick-list")) - - # Check if user is already on DNKL - current_message = await select_one("SELECT message_id FROM dnkl WHERE uuid = (?)", (uuid,)) - # User is not currently on DNKL - if not current_message: - await insert_new_dnkl(dnkl_message.id, uuid, ign) - return "This user has been added to the do-not-kick-list!" - - # User is already on DNKl - # Try to delete current message - try: - current_message = await bot.get_channel(dnkl_channel_id).fetch_message(current_message) - await current_message.delete() - except Exception: - pass - - await update_dnkl(dnkl_message.id, uuid) - return "Since this user was already on the do-not-kick-list, their entry has been updated." + dnkl_embed = await dnkl_application(ign, uuid, ctx.channel, ctx.author, weekly_gexp) async def dnklremove(self): ign, uuid = await get_mojang_profile(self.string) diff --git a/src/func/Union.py b/src/func/Union.py index a233b24..b5ba310 100644 --- a/src/func/Union.py +++ b/src/func/Union.py @@ -6,7 +6,6 @@ import discord -import src.utils.ui_utils as uiutils from src.utils.calculation_utils import check_tag from src.utils.consts import (active_req, allies, discord_not_linked_embed, guild_handle, neg_color, neutral_color, pos_color, registration_channel_id, @@ -14,7 +13,6 @@ unknown_ign_embed, join_request_embed) from src.utils.discord_utils import (create_ticket, has_tag_perms, is_linked_discord) -from src.utils.referral_utils import (validate_reference) from src.utils.request_utils import (get_gtag, get_hypixel_player, get_mojang_profile, get_player_guild) @@ -180,14 +178,6 @@ async def register(self, ctx, name): # User is a member if guild_name == guild_handle: - fields = [ - ["Who invited you to Miscellaneous on Hypixel?", "Enter NONE if you joined on your own.", - discord.InputTextStyle.short, - "Invited by:"] - ] - await ctx.response.send_modal( - modal=uiutils.ModalCreator(embed=embed, fields=fields, ign=ign, uuid=uuid, title="Player Reference", - function=validate_reference)) await ctx.author.add_roles(bot.member_role, reason="Registration - Member") guest_ticket = None diff --git a/src/utils/calculation_utils.py b/src/utils/calculation_utils.py index c14bd49..c8febae 100644 --- a/src/utils/calculation_utils.py +++ b/src/utils/calculation_utils.py @@ -196,3 +196,27 @@ async def is_valid_date(date: str): return True, parsed.day, parsed.month, parsed.year except ValueError: return False, None, None, None + + +async def extract_usernames(message: str): + # Define regular expressions for both formats + format1_pattern = r"🎉 \*\*(?:\[(.*?)\] )?(.*?)\*\* joined the guild! \*\*They weren't invited by anyone\." + format2_pattern = r"🎉 \*\*(?:\[(.*?)\] )?(.*?)\*\* invited(?: \*\*\[(.*?)\] )?(?:\*\*)? (?:\*\*)?(.*?)\*\* to the guild!" + + # Check if it matches format 1 + match_format1 = re.match(format1_pattern, message) + if match_format1: + username1 = match_format1.group(2) + return username1, None + + # Check if it matches format 2 + match_format2 = re.match(format2_pattern, message) + if match_format2: + username1 = match_format2.group(2) + username2 = match_format2.group(4) + if username2.startswith('['): # Check if the second username starts with '[' indicating a rank + username2 = username2.split('] ')[1] # Remove the rank from the second username + return username1, username2.strip('**') # Remove any leading or trailing '**' + + # If it doesn't match any format, return None for both usernames + return None, None diff --git a/src/utils/consts.py b/src/utils/consts.py index d5b7e77..423b195 100644 --- a/src/utils/consts.py +++ b/src/utils/consts.py @@ -36,6 +36,7 @@ weekly_lb_channel = config["weekly_gexp_lb"] daily_lb_channel = config["daily_gexp_lb"] rank_upgrade_channel = config["rank_upgrade_channel"] +staff_bridge_channel = config["staff_bridge_channel"] # Other variables guild_handle = config["guild_handle"] diff --git a/src/utils/referral_utils.py b/src/utils/referral_utils.py index 77d34df..f0f8746 100644 --- a/src/utils/referral_utils.py +++ b/src/utils/referral_utils.py @@ -9,7 +9,8 @@ from src.utils.request_utils import get_mojang_profile, get_player_guild, get_guild_by_name, get_name_by_uuid -async def validate_reference(invitee_uuid, inviter_ign): +async def validate_invites(inviter_ign, invitee_ign): + invitee_ign, invitee_uuid = await get_mojang_profile(invitee_ign) if invitee_ign else (None, None) inviter_ign, inviter_uuid = await get_mojang_profile(inviter_ign) if inviter_ign else (None, None) if not inviter_uuid: return f"{inviter_ign} is not a valid minecraft username.\nThis reference will not count." @@ -29,7 +30,7 @@ async def validate_reference(invitee_uuid, inviter_ign): count = await add_invitee(inviter_uuid, invitee_uuid) if not count: - return f"{inviter_ign} has already invited you in the past. No duplicate entries!" + return f"{inviter_ign} has already invited {invitee_ign} in the past. No duplicate entries!" return f"{inviter_ign} has invited {count} members to the guild this week!" diff --git a/src/utils/ui_utils.py b/src/utils/ui_utils.py index 4f337e2..dfe17c9 100644 --- a/src/utils/ui_utils.py +++ b/src/utils/ui_utils.py @@ -174,7 +174,7 @@ def __init__(self, author: discord.User, channel: discord.TextChannel, ign: str, self.weekly_gexp = weekly_gexp self.buttons = buttons - reasons = ["Exams", "Medical Issues", "Vacation", "Computer Problems", "Other"] + reasons = ["Exams", "Medical Issues", "Vacation", "Computer Problems", "Banned on Hypixel", "Other"] for reason in reasons: self.add_option(label=reason, value=reason) @@ -182,6 +182,15 @@ async def callback(self, interaction: discord.Interaction): reason = list(interaction.data.values())[0][0] other_reason = "" + + if reason == "Banned on Hypixel": + embed = discord.Embed(title="You cannot use the DNKL system if you are banned from the Hypixel!", + description="If you are banned, you will be removed from the guild.\n" + "You may rejoin once your ban is over.", + color=neg_color) + await interaction.response.send_message(embed=embed) + return + if reason == "Other": await interaction.response.send_message("Please elaborate on the reason for your inactivity.\n" \ "This information will only be visible to staff members.\n\n" \ @@ -197,11 +206,12 @@ async def callback(self, interaction: discord.Interaction): date = datetime.strptime(f"{self.day}/{self.month}/{self.year}", "%d/%B/%Y") + timedelta(weeks=int(self.length)) final_embed = discord.Embed(title=self.ign, url=f'https://plancke.io/hypixel/player/stats/{self.ign}', color=neutral_color) - final_embed.set_thumbnail(url=f'https://crafatar.com/renders/body/{self.uuid}') + final_embed.set_thumbnail(url=f"https://visage.surgeplay.com/full/{self.uuid}.png") final_embed.add_field(name="IGN:", value=self.ign, inline=False) final_embed.add_field(name="Start:", value=f"{self.day} {self.month} {self.year}", inline=False) final_embed.add_field(name="End:", value=f"{date.day} {date.strftime('%B')} {date.year}", inline=False) final_embed.add_field(name="Reason:", value=reason, inline=False) + final_embed.set_author(name="Do-not-kick-list") staff_approval_embed = final_embed.copy() staff_approval_embed.add_field(name="Guild Experience:",