diff --git a/bot.py b/bot.py index 693d690..3f1495b 100755 --- a/bot.py +++ b/bot.py @@ -12,6 +12,22 @@ from corpus import corpus import markovify import textwrap +from html import escape +from html2image import Html2Image + +# Directory to save screenshots +SCREENSHOTS_DIR = "screenshots" +os.makedirs(SCREENSHOTS_DIR, exist_ok=True) + +# Initialize the Html2Image object with the specified output path +hti = Html2Image( + output_path=SCREENSHOTS_DIR, + custom_flags=["--disable-gpu", "--disable-software-rasterizer", "--no-sandbox"] +) + +# Set a constant file name for the screenshot +SCREENSHOT_FILE_NAME = "message_screenshot.png" +SCREENSHOT_FILE_PATH = os.path.join(SCREENSHOTS_DIR, SCREENSHOT_FILE_NAME) # Load environment variables from .env file load_dotenv() @@ -454,6 +470,50 @@ async def asciiart(self, interaction: discord.Interaction, message: str = None): llm_answer = ensure_code_blocks_closed(llm_answer) await interaction.followup.send(llm_answer+"...*bzzzzzt...bzzzzzt*...") + @app_commands.command(name="hate_calc", description="Calculates the level of hatred between two users. How lovely.") + async def hate_calc(self, interaction: discord.Interaction, user1: discord.Member, user2: discord.Member): + # Extract the user IDs + user1_id = user1.id + user2_id = user2.id + + # Calculate the hate percentage based on the sum of the user IDs + hate_value = (user1_id + user2_id) % 101 # Modulus to keep the result between 0 and 100 + + # Determine the relationship level + if hate_value <= 33: + statement = "You two merely tolerate each other. How quaint." + emoji = "😐" # Mild dislike + elif 33 < hate_value <= 66: + statement = "There’s some genuine despise between you two. Things get interesting." + emoji = "πŸ‘Ώ" # Despise + elif 66 < hate_value < 100: + statement = "You two are clearly enemies. oh, how delightful!" + emoji = "😑" # Enemies + else: + statement = "Arch-enemies. Perfect. Just perfect. I love it." + emoji = "πŸ’€" # Arch-enemy + + # Fetch the profile pictures + user1_avatar = user1.display_avatar.url + user2_avatar = user2.display_avatar.url + + # Create an embed message for the result in a GLaDOS style + embed = discord.Embed( + title="Hate Calculation", + description=f"{statement}\n\n**Hate Level:** {hate_value}% {emoji}", + color=discord.Color.dark_gray() + ) + + # Add the profile pictures to the embed + embed.set_thumbnail(url=user1_avatar) + embed.set_author(name=f"{user1.display_name} vs {user2.display_name}", icon_url=user1_avatar) + embed.add_field(name="User 1", value=f"{user1.mention}", inline=True) + embed.add_field(name="User 2", value=f"{user2.mention}", inline=True) + embed.set_image(url=user2_avatar) # Display user2's avatar below user1's + + # Sending the result + await interaction.response.send_message(embed=embed) + @app_commands.command(name="help", description="List all available commands.") async def list_bot_commands(self, interaction: discord.Interaction): # Define potential command descriptions @@ -1188,7 +1248,7 @@ async def on_reaction_add(reaction, user): # Unrestrict user permissions in other channels while the quiz is ongoing await unrestrict_user_permissions(guild, user) - # Part 2: Handle general knife emoji reactions + # Part 3: Handle general knife emoji reactions knife_reaction = None for react in message.reactions: if str(react.emoji) == 'πŸ”ͺ': @@ -1196,16 +1256,172 @@ async def on_reaction_add(reaction, user): break if knife_reaction and knife_reaction.count >= 1: - # Look for a channel that contains the word "stab" in its name - stab_channel = discord.utils.find(lambda c: "stab" in c.name.lower(), message.guild.text_channels) - if stab_channel: - message_link = message.jump_url - await stab_channel.send( - f"Hey {message.author.mention}, knife emoji reaction for {message_link}. " - f"Looks like someone is ready to stab you! " - f"This time it isn't me!" - ) - print(message.author.display_name, message.content) + try: + # Process the message content + processed_content = message.content or "" + + # Escape text content, but handle emoji separately + processed_content = escape(processed_content) # Escape the entire message first + + # Now process custom emojis and insert them back as HTML tags with a fallback + if message.guild and message.guild.emojis: + for emoji in message.guild.emojis: # Iterate through all custom emojis in the server + # Replace custom emoji text with the corresponding tag and add a fallback + custom_emoji_code = f"<:{emoji.name}:{emoji.id}>" # Use HTML escaped version to find the match + emoji_url = f"https://cdn.discordapp.com/emojis/{emoji.id}.png" + fallback_emoji = "πŸ€”" # You can change this to any other emoji you prefer as the fallback + processed_content = processed_content.replace( + custom_emoji_code, + f'emoji' + ) + + # Process stickers if any are present + sticker_html = "" + if message.stickers: + for sticker in message.stickers: + if sticker.url: # Ensure sticker URL exists + # Add a humorous fallback message or image if the sticker doesn't load + sticker_html += f'
sticker' + # Add a humorous caption below the sticker + sticker_html += f'
The sticker cannot escape...
' + else: + # If no URL is available, add a humorous message + sticker_html += f'
Oops! The sticker ran away! πŸƒπŸ’¨
' + + # Process attachments if any are present + attachments_html = "" + if message.attachments: + for attachment in message.attachments: + # Check for image attachments + if attachment.url.endswith(('.png', '.jpg', '.jpeg', '.gif', '.webp')): + # Add the image with a fallback using onerror + attachments_html += f'
image' + # Add a humorous caption below the image + attachments_html += f'
Oops! The image took a break! πŸ’€
' + + # For other attachments, add a downloadable link + else: + file_extension = attachment.url.split('.')[-1].upper() # Get the file extension in uppercase + attachments_html += f'
' + attachments_html += f'πŸ“Ž Attached file: {attachment.filename} ({file_extension})
' + # Add a fun comment about the attachment type + attachments_html += f'
This file is just hanging around... 🧳
' + + # Construct the complete HTML content + content = f""" + + + + + +
+
+ Message by @{message.author.display_name} +
+
+ {processed_content} {sticker_html} {attachments_html} +
+
+ + + """ + + # Create the screenshot with dynamic size capturing only the necessary area + hti.screenshot(html_str=content, save_as=SCREENSHOT_FILE_NAME, size=(1300, 1000)) + + # Find a channel that contains "stab" in its name + stab_channel = discord.utils.find(lambda c: "stab" in c.name.lower(), message.guild.text_channels) + + if stab_channel: + # Send the screenshot directly to the stab channel + await stab_channel.send( + f"Hey {message.author.mention}, a knife emoji reaction has been added to your message: {message.jump_url}. " + f"Looks like someone is ready to stab you! Here's a screenshot of the message:", + ) + await stab_channel.send(file=discord.File(SCREENSHOT_FILE_PATH)) + else: + print("No channel with 'stab' in the name was found.") + + except Exception as e: + # Log the error message to the console + print(f"An error occurred while taking or sending the screenshot: {e}") # Regular bot command implementation @bot.command(name="start", help="Start chat mode to send messages manually.")