Untitled

 avatar
unknown
plain_text
a year ago
16 kB
6
Indexable
import discord
from discord.ext import commands
from discord.ui import View
from jokeapi import Jokes  # Import the Jokes class
import asyncio
from PIL import Image, ImageDraw
from io import BytesIO
import requests

from bot_token import BOT_TOKEN

# Function to create a circular image with a specified size
def create_circular_image(image_url, size=(60, 60)):  # Specify the desired size (width, height)
    response = requests.get(image_url)
    img = Image.open(BytesIO(response.content)).convert("RGBA")
    
    # Resize the image to the specified size using LANCZOS resampling filter
    img = img.resize(size, Image.LANCZOS)
    
    bigsize = (img.size[0] * 3, img.size[1] * 3)
    mask = Image.new('L', bigsize, 0)
    draw = ImageDraw.Draw(mask)
    draw.ellipse((0, 0) + bigsize, fill=255)
    mask = mask.resize(img.size, Image.LANCZOS)
    img.putalpha(mask)

    output = BytesIO()
    img.save(output, format="PNG")
    output.seek(0)
    return output


class MyBot(commands.Bot):
    def __init__(self, command_prefix, intents):
        super().__init__(command_prefix=command_prefix, intents=intents)
        
    async def on_ready(self):
        # Function to execute when the bot successfully connects to Discord
        print(f"{self.user.name} has successfully connected to Discord.")
        
        # Sync the bot's commands when it's ready
        await self.sync_commands()
        
    async def on_command_error(self, ctx, error):
        if isinstance(error, commands.CommandNotFound):
            await ctx.send("That command does not exist.", ephemeral=True)
        else:
            # Handle other types of errors gracefully
            error_message = f"An error occurred: {type(error).__name__}: {error}"
            print(error_message)
            await ctx.send(error_message, ephemeral=True)
        
    @staticmethod
    def get_server_prefix(bot, message):
        # Static method to get the server prefix (e.g., "/")
        return "/"
    
    async def sync_commands(self):
        # Method to sync the bot's commands with Discord
        await self.tree.sync()
        print("Commands synced successfully")

# Create an instance of MyBot with custom command prefix and intents
bot = MyBot(command_prefix=MyBot.get_server_prefix, intents=discord.Intents.all())

class AnnouncementView(discord.ui.View):
    def __init__(self, bot, sender: discord.User, sender_id: int, target_channel_id: int):
        super().__init__()
        self.bot = bot  # Store the bot instance
        self.sender = sender  # Store the sender
        self.sender_id = sender_id
        self.target_channel_id = target_channel_id  # Store the target channel ID
        self.embed = discord.Embed(color=discord.Color.blue())  # Initialize the embed with a specified color
        self.embed.add_field(name="Title", value="Not provided", inline=False)
        self.embed.add_field(name="Description", value="Not provided", inline=False)
        self.embed.add_field(name="Date", value="Not provided", inline=False)
        self.embed.title = "Announcement! 📢"
        self.add_item(self.title_button)
        self.add_item(self.description_button)
        self.add_item(self.date_button)
        self.add_item(ConfirmButton(self))  # Add the ConfirmButton

    def add_items(self):
        title_button = title_button
        description_button = description_button
        date_button = date_button
        confirm_button = ConfirmButton(self)
        
        self.add_item(title_button)
        self.add_item(description_button)
        self.add_item(date_button)
        self.add_item(confirm_button)

    def set_thumbnail(self, image_url):
        # Set the thumbnail for the embed using the sender's circular avatar
        circular_image = create_circular_image(image_url)
        self.file = discord.File(circular_image, filename="circular_avatar.png")
        self.embed.set_thumbnail(url="attachment://circular_avatar.png")

    # Function to update the embed with new title, description, and date
    def update_embed(self, title=None, description=None, date=None):
        if title:
            self.embed.set_field_at(0, name="Title", value=title, inline=False)
        if description:
            self.embed.set_field_at(1, name="Description", value=description, inline=False)
        if date:
            self.embed.set_field_at(2, name="Date", value=date, inline=False)
            
    async def interaction_check(self, interaction: discord.Interaction) -> bool:
        if interaction.user.id != self.sender_id:
            await interaction.response.send_message("You are not allowed to interact with this embed.", ephemeral=True)
            return False
        return True



# Define a button for confirming the announcement
class ConfirmButton(discord.ui.Button):
    def __init__(self, parent_view):
        super().__init__(label="Confirm", style=discord.ButtonStyle.success)
        self.parent_view = parent_view

    # Callback function to handle button click
    async def callback(self, interaction: discord.Interaction):
        # Get the target channel to send the announcement
        target_channel = self.parent_view.bot.get_channel(self.parent_view.target_channel_id)
        if target_channel is None:
            # Notify if the channel is invalid
            await interaction.response.send_message("Invalid channel ID", ephemeral=True)
            return

        # Set the thumbnail before sending the embed
        self.parent_view.set_thumbnail(self.parent_view.sender.avatar.url)

        # Send the embed to the target channel
        await target_channel.send(embed=self.parent_view.embed, file=self.parent_view.file)
        await interaction.response.send_message("Announcement sent for review!", ephemeral=True)


# Define a command for creating an announcement
@bot.tree.command(name="announcement", description="📌 • Create an Announcement!")
async def announcement_command(interaction: discord.Interaction):
    try:
        await interaction.response.defer(ephemeral=True)  # Defer the initial response to allow interaction

        # Initialize an empty embed
        embed = discord.Embed(color=discord.Color.blue())
        embed.title = "Announcement! 📢"
        embed.add_field(name="Title", value="Not provided", inline=False)
        embed.add_field(name="Description", value="Not provided", inline=False)
        embed.add_field(name="Date", value="Not provided", inline=False)
        embed.set_footer(text=f"Sent by: @{interaction.user.name}")

        # Send the message with the initial embed and user's circular profile picture as thumbnail
        circular_image = create_circular_image(interaction.user.avatar.url)
        file = discord.File(circular_image, filename="circular_avatar.png")
        embed.set_thumbnail(url="attachment://circular_avatar.png")
        prompt_message = await interaction.followup.send(embed=embed, file=file, ephemeral=True)

        # Add buttons for title, description, date, and confirm
        title_button = discord.ui.Button(label="Enter Title", style=discord.ButtonStyle.secondary, custom_id="title_button")
        description_button = discord.ui.Button(label="Enter Description", style=discord.ButtonStyle.secondary, custom_id="description_button")
        date_button = discord.ui.Button(label="Enter Date", style=discord.ButtonStyle.secondary, custom_id="date_button")
        confirm_button = discord.ui.Button(label="Confirm", style=discord.ButtonStyle.success, custom_id="confirm_button")

        view = discord.ui.View()
        view.add_item(title_button)
        view.add_item(description_button)
        view.add_item(date_button)
        view.add_item(confirm_button)

        # Update the message with the view containing buttons
        await prompt_message.edit(view=view)

        while True:
            try:
                interaction = await bot.wait_for("button_click", timeout=60, check=lambda i: i.user == interaction.user)
            except asyncio.TimeoutError:
                await prompt_message.edit(content="Timed out. Please try again.", view=None)
                return

            # Handle button clicks to update the embed
            if interaction.component.custom_id == "title_button":
                title = await input_value(interaction, "Title")
                if title:
                    embed.set_field_at(0, name="Title", value=title, inline=False)
            elif interaction.component.custom_id == "description_button":
                description = await input_value(interaction, "Description")
                if description:
                    embed.set_field_at(1, name="Description", value=description, inline=False)
            elif interaction.component.custom_id == "date_button":
                date = await input_value(interaction, "Date (e.g., 05/19/2024)")
                if date:
                    embed.set_field_at(2, name="Date", value=date, inline=False)
            elif interaction.component.custom_id == "confirm_button":
                break  # Break the loop when the user confirms the announcement

            await interaction.response.edit_message(embed=embed, view=view)

        # Send the final announcement to the target channel
        target_channel_id = 1243960674015772772  # Specify the target channel ID
        message = await bot.get_channel(target_channel_id).send(embed=embed)

        # Add approve and decline buttons as components to the sent message
        approve_button = discord.ui.Button(label="Approve", style=discord.ButtonStyle.success, custom_id="approve_button")
        decline_button = discord.ui.Button(label="Decline", style=discord.ButtonStyle.danger, custom_id="decline_button")

        approve_view = discord.ui.View()
        approve_view.add_item(approve_button)
        approve_view.add_item(decline_button)

        await message.edit(view=approve_view)
    except Exception as e:
        error_message = f"An error occurred while creating the announcement: {e}"
        print(error_message)
        await interaction.response.send_message(error_message, ephemeral=True)


async def input_value(interaction, prompt):
    """Prompt the user to input a value."""
    await interaction.respond(
        content=f"Please enter the {prompt}:",
        ephemeral=True
    )

    try:
        response = await bot.wait_for("message", timeout=60, check=lambda m: m.author == interaction.user)
        return response.content
    except asyncio.TimeoutError:
        await interaction.followup.send("Timed out. Please try again.", ephemeral=True)
        return None


class ButtonView(View):
    def __init__(self, parent_view, embed):
        super().__init__()
        self.parent_view = parent_view
        self.embed = embed
     
    @discord.ui.button(label="Title", style=discord.ButtonStyle.secondary)
    async def title_button(self, interaction: discord.Interaction, button: discord.ui.Button):
        await interaction.response.send_message(TitleModal())
        
    @discord.ui.button(label="Description", style=discord.ButtonStyle.secondary)
    async def description_button(self, interaction: discord.Interaction, button: discord.ui.Button):
        await interaction.response.send_message(DescriptionModal())
        
    @discord.ui.button(label="Date", style=discord.ButtonStyle.secondary)
    async def date_button(self, interaction: discord.Interaction, button: discord.ui.Button):
        await interaction.response.send_message(DateModal())
     
     
    @discord.ui.button(label="Confirm", style=discord.ButtonStyle.success)
    async def confirm_button(self, interaction: discord.Interaction):
        await interaction.response.send_message("Confirmed!", ephemeral=True)

     
class TitleModal(discord.ui.Modal):
    def __init__(self, parent_view):
        self.parent_view = parent_view
        super().__init__(title="Enter a Title")
        self.title_input = discord.ui.TextInput(label="Title", placeholder="Enter title here...", required=True, max_length=50)
        self.add_item(self.title_input)

    async def on_submit(self, interaction: discord.Interaction):
        title = self.title_input.value
        self.parent_view.update_embed(title=title)
        await interaction.response.edit_message(embed=self.parent_view.embed, view=self.parent_view)
        
class DescriptionModal(discord.ui.Modal):
    def __init__(self, parent_view):
        self.parent_view = parent_view
        super().__init__(description="Enter a Description")
        self.description_input = discord.ui.TextInput(label="Description", placeholder="Enter description here...", required=True, max_length=500)
        self.add_item(self.description_input)

    async def on_submit(self, interaction: discord.Interaction):
        description = self.description_input.value
        self.parent_view.update_embed(description=description)
        await interaction.response.edit_message(embed=self.parent_view.embed, view=self.parent_view)
        
class DateModal(discord.ui.Modal):
    def __init__(self, parent_view):
        self.parent_view = parent_view
        super().__init__(date="Enter a Date")
        self.date_input = discord.ui.TextInput(label="Date", placeholder="Enter date here...", required=True, max_length=8)
        self.add_item(self.date_input)

    async def on_submit(self, interaction: discord.Interaction):
        date = self.date_input.value
        self.parent_view.update_embed(date=date)
        await interaction.response.edit_message(embed=self.parent_view.embed, view=self.parent_view)
    

# Define a button for approving the announcement
class ApproveButton(discord.ui.Button):
    async def callback(self, interaction: discord.Interaction):
        await interaction.response.send_message("Announcement approved!", ephemeral=True)


# Define a button for declining the announcement
class DeclineButton(discord.ui.Button):
    async def callback(self, interaction: discord.Interaction):
        await interaction.response.send_message("Announcement declined!", ephemeral=True)


# Define a command for fetching a joke
@bot.tree.command(name="joke", description="📌 • Use this command to brighten your day with a random joke.")
async def slash_command(interaction: discord.Interaction):
    try:
        j = await Jokes()  # Initialise the class
        joke = await j.get_joke(blacklist=['nsfw', 'racist'])  # Retrieve a random joke
        if joke["type"] == "single":
            await interaction.response.send_message(joke["joke"])
        else:
            await interaction.response.send_message(f"{joke['setup']}\n{joke['delivery']}")
    except Exception as e:
        error_message = f"An error occurred while fetching the joke: {e}"
        print(error_message)
        await interaction.response.send_message(error_message)
        
# Define a command for checking bot latency
@commands.command()
async def ping(ctx):
    try:
        # Get the bot's latency in milliseconds
        bot_latency = round(bot.latency * 1000)
        
        # Send the bot latency in the server's channel
        await ctx.send(f"Pong! {bot_latency}ms")
    except Exception as e:
        error_message = f"An error occurred while checking bot latency: {e}"
        print(error_message)
        await ctx.send(error_message)
        

# Run the bot
bot.run(BOT_TOKEN)
Editor is loading...
Leave a Comment