import os
import discord
from discord import app_commands
from discord.ext import commands, tasks
import asyncio
import json
import random
from datetime import datetime, timedelta
from discord import Embed
import string


import requests

try:
    # Try to load config file
    with open("config.json", "r") as f:
        config = json.load(f)
except FileNotFoundError:
    # If config file doesn't exist, create one and prompt user for bot token
    bot_token = input("Enter your bot token: ")
    invite_link = input("Enter your bot invite link: ")

    config = {
        "bot_token": bot_token,
        "invite_link": invite_link
    }
    
    with open("config.json", "w") as f:
        json.dump(config, f, indent=4)

# Access settings securely
bot_token = config.get("bot_token")
invite_link = config.get('invite_link')






intents = discord.Intents.default()
intents.members = True
intents.messages = True

client = discord.Client(intents=intents)
tree = app_commands.CommandTree(client)

server_invites = {}
invite_data = {}
invites = {}
dm_invites = {}  


# Path to the JSON file
command_counts_file = 'command_counts.json'

# Dictionary to store command usage counts
command_counts = {}

# Load existing data from JSON file if available
if os.path.exists(command_counts_file):
    with open(command_counts_file, 'r') as file:
        command_counts = json.load(file)


# Function to update command count
def update_command_count(command_name):
    if command_name in command_counts:
        command_counts[command_name] += 1
    else:
        command_counts[command_name] = 1
    save_command_counts()

# Function to save command counts to JSON file
def save_command_counts():
    with open(command_counts_file, 'w') as file:
        json.dump(command_counts, file)


# Get all commands sorted by usage count
def get_all_used_commands():
    if not command_counts:
        return None
    sorted_commands = sorted(command_counts.items(), key=lambda x: x[1], reverse=True)
    return sorted_commands




### Database ###
import sqlite3

# Connect to the SQLite database
conn = sqlite3.connect('Tamoza_Bot_DB.db')
cursor = conn.cursor()

# Create a table to store log channels if it doesn't exist
cursor.execute('''CREATE TABLE IF NOT EXISTS Tamoza_Bot_DB (
                server_name TEXT,
                guild_id INTEGER PRIMARY KEY,
                log_message_name INTEGER,
                log_message_id INTEGER,
                user_name INTEGER,
                user_id INTEGER,
                inv_log_channel INTEGER,
                inv_log_channel_name INTEGER
                )''')
conn.commit()

# Define your bot instance
@client.event
async def on_ready():
    await client.wait_until_ready()

    for guild in client.guilds:
        invites[guild.id] = await guild.invites()
        

    try:
        await tree.sync()
        print("Commands synced on startup.")
    except discord.HTTPException as e:
        print(f"Syncing failed: {e}")
        
    print(f"We have logged in as {client.user}.")
    await server_count()


async def server_count():
    guild_count = len(client.guilds)
    print(f"I am in {guild_count} servers.")


def get_log_channel_id(guild_id):
    """Retrieve log channel ID from the database for the guild ID of the given context."""
    
    try:
        cursor.execute('''SELECT log_message_id FROM Tamoza_Bot_DB WHERE guild_id = ?''', (guild_id,))
        result = cursor.fetchone()
        if result:
            return result[0]
        else:
            #raise ValueError("Log channel not set up for this guild.")
            pass
    except sqlite3.Error as e:
        print("SQLite error:", e)
        raise
    except Exception as e:
        print("Error:", e)
        raise

def get_inv_channel_id(guild_id):
    
    
    try:
        cursor.execute('''SELECT inv_log_channel FROM Tamoza_Bot_DB WHERE guild_id = ?''', (guild_id,))
        result = cursor.fetchone()
        if result:
            return result[0]
        else:
            #raise ValueError("Invite Log channel not set up for this guild.")
            pass
    except sqlite3.Error as e:
        print("SQLite error:", e)
        raise
    except Exception as e:
        print("Error:", e)
        raise


"""""
@client.event
async def on_message_delete(message: discord.Message):

    if message.author == client.user:  # Ignore messages deleted by the bot itself
        return

    log_channel_id = get_log_channel_id(message.guild.id)  # Remove await here
    log_channel = client.get_channel(log_channel_id)

    if log_channel:
        embed = discord.Embed(title = f"> {message.author}'s Message was Deleted", description = f"Deleted Message: {message.content}\nAuthor: {message.author.mention}\nChannel: {message.channel.mention}", timestamp = datetime.now(), color = discord.Colour.red())
        #embed.set_author(name = message.author.name, icon_url = message.author.display_avatar)
        try:
            embed.add_field(name="Deleted by:", value=message.guild.get_member(message.author.id).mention, inline=False)
        except AttributeError:  # Handle cases where the deleter is not found
            embed.add_field(name="Deleted by:", value="(Unknown)", inline=False)
        await log_channel.send(embed=embed)
    
@client.event
async def on_message_edit(before, after):

    log_channel_id = get_log_channel_id(after.guild.id) 
    log_channel = client.get_channel(log_channel_id)

    if log_channel:

        embed = discord.Embed(title = f"> {before.author} Edited Their Message", description = f"Before: {before.content}\nAfter: {after.content}\nAuthor: {before.author.mention}\nLocation: {before.channel.mention}", timestamp = datetime.now(), color = discord.Colour.blue())
        #embed.set_author(name = after.author.name, icon_url = after.author.display_avatar)
        await log_channel.send(embed=embed)

"""

@client.event
async def on_member_update(before, after):
    try:
        log_channel_id = get_log_channel_id(after.guild.id)
        log_channel = client.get_channel(log_channel_id)
        
        # Check if a role was added
        if len(before.roles) < len(after.roles):
            added_role = next(role for role in after.roles if role not in before.roles)
            embed = discord.Embed(
                title="> Role Added",
                description=f"{after.mention} has been given {added_role.mention} role.",
                color=discord.Color.green()
            )
            
            await log_channel.send(embed=embed)

        # Check if a role was removed
        elif len(before.roles) > len(after.roles):
            removed_role = next(role for role in before.roles if role not in after.roles)
            embed = discord.Embed(
                title="> Role Removed",
                description=f"{after.mention} was removed from the {removed_role.mention} role.",
                color=discord.Color.red()
            )
            
            await log_channel.send(embed=embed)
    except:
        pass

    
@client.event
async def on_guild_join(guild):
    for channel in guild.text_channels:
        if channel.permissions_for(guild.me).send_messages:
            x_link = "https://x.com/Tamoza04"
            embed = discord.Embed(title="> Thank you for inviting me!", description="TamozaBot is a Discord bot created by Tamoza. It provides various features and functionalities to enhance your Discord server experience. To see all command use `/help`", color=0x00ff00)
            embed.add_field(name="Beta Status", value="TamozaBot is currently in beta.", inline=False)
            embed.add_field(name="Contact", value=f"If you need any help, you can contact me on [x]({x_link}).", inline=False)

            await channel.send(embed=embed)
            break


@client.event
async def on_voice_state_update(member, before, after):
    if before.channel != after.channel:
        if before.channel is None:
            await log_embed(f"{member.mention} joined voice channel {after.channel.mention}.", member)
        elif after.channel is None:
            await log_embed(f"{member.mention} left voice channel {before.channel.mention}.", member)
        else:
            mover = None
            # Check if any users have the "move members" permission in the voice channels involved
            mover_before = any(perm[0] == 'move_members' and perm[1] for perm in before.channel.permissions_for(member))
            mover_after = any(perm[0] == 'move_members' and perm[1] for perm in after.channel.permissions_for(member))
            
            if mover_before and not mover_after:
                mover = member
            elif mover_after and not mover_before:
                mover = member

            if mover:
                await log_embed(f"{member.mention} has been moved from {before.channel.mention} to {after.channel.mention} by {mover.mention}.", member)
            else:
                await log_embed(f"{member.mention} has moved from {before.channel.mention} to {after.channel.mention}.", member)

    if before.channel == after.channel:
        # Check for mute state change only if deafen state remains the same
        if before.self_deaf == after.self_deaf and before.self_mute != after.self_mute:
            action = "muted" if after.self_mute else "unmuted"
            await log_embed(f"{member.mention} has {action} themselves in {after.channel.mention}.", member)

        if before.self_deaf != after.self_deaf:
        # Check only for deafen state change
            action = "deafened" if after.self_deaf else "undeafened"
            await log_embed(f"{member.mention} has {action} themselves in {after.channel.mention}.", member)

# Dictionary to store user timezones (example: {user_id: "timezone"})
user_timezones = {}
async def log_embed(message, member=None):
    try:
        guild_id = member.guild.id  
        log_channel_id = get_log_channel_id(guild_id)  # Continue with your logic using log_channel_id
        channel = client.get_channel(log_channel_id)
        
        # Check if the log channel is set
        if channel is None:
            raise ValueError("Log channel not set")
        
        current_time = datetime.now()
        if member:
            member_timezone_offset = user_timezones.get(member.id, 0)  # Default to UTC if timezone not set
            user_offset = timedelta(hours=int(member_timezone_offset))
            current_time += user_offset
        current_time_str = current_time.strftime('%Y-%m-%d %H:%M:%S %Z')
        
        embed = Embed(description=message, color=0x00ff00)
        embed.set_footer(text=f"User ID: {member.id}")
        embed.timestamp = datetime.now()

        """""
        if member:
            if member.guild:
                guild = member.guild
                member = guild.get_member(member.id)  # Fetch member from guild
                # Check if the member has a custom avatar
                if member.avatar:
                    avatar_url = member.avatar.url
                else:
                    # Use the default avatar URL
                    avatar_url = member.default_avatar_url
                embed.set_author(name=member.display_name, icon_url=avatar_url)
            else:
                # Handle the case where the member object doesn't have a guild associated with it
                embed.set_author(name=member.display_name)
        """""
        await channel.send(embed=embed)
    except ValueError:
        # Log channel not set, handle this situation (e.g., print an error message)
        #print("Log channel not set")
        pass
    except Exception as e:
        # Handle other exceptions
        #print(f"An error occurred: {e}")
        pass


def find_invite_by_code(invite_list, code):
    for inv in invite_list:     
        if inv.code == code:      
            return inv

@client.event
async def on_invite_create(invite):
    guild_id = invite.guild.id if invite.guild else None
    try:
        inv_log_channel_id = get_inv_channel_id(guild_id)
        log_channel = None
        
        if inv_log_channel_id:
            log_channel = discord.utils.get(invite.guild.text_channels, id=inv_log_channel_id)

        inviter_mention = invite.inviter.mention if invite.inviter else "Unknown"

        embed = discord.Embed(title="> Invite Created")
        embed.add_field(name="**Invite Code**", value=invite.code)
        embed.add_field(name="**Invite Created by**", value=inviter_mention)

        if log_channel:
            await log_channel.send(embed=embed)
        else:
            # Handle the case where the log channel is not found or not set up
            print("Log channel not found or not set up.")

        # Store invite information (code, inviter, etc.) in persistent storage
        invite_data[invite.code] = {
            "inviter": invite.inviter.id if invite.inviter else None
        }
        # ... (Implement the storage mechanism to save invite_data)

    except ValueError as e:
        print(e)  # Log the error message
        # print("Log channel not set up for this guild.")

@client.event
async def on_member_join(member):
    

    await log_embed(f"{member.mention} has joined the server.", member)

    guild = member.guild

    # Fetch invites before the member joins
    invites_before_join = invites.get(guild.id, [])
    invites_after_join = await guild.invites()

    for invite_before in invites_before_join:
        invite_after = next((i for i in invites_after_join if i.code == invite_before.code), None)

        if invite_after and invite_before.uses < invite_after.uses:
            try:
                log_channel_id = get_inv_channel_id(guild.id)
                log_channel = client.get_channel(log_channel_id)

                if not log_channel:
                    print(f"Log channel not found for guild ID: {guild.id}")
                    return  # Prevent sending message to a non-existent channel

                embed = discord.Embed(title="> Member Joined")
                embed.add_field(name="Member", value=member.mention, inline=False)
                embed.add_field(name="Invite Code", value=invite_after.code, inline=False)

                # Handle cases where the inviter might not be available
                if invite_after.inviter:
                    embed.add_field(name="Invited by", value=invite_after.inviter.mention, inline=False)
                else:
                    embed.add_field(name="Invited by", value="Server (direct join or vanity URL)", inline=False)

                await log_channel.send(embed=embed)
            except Exception as e:
                print(f"An error occurred while sending log message: {e}")

    # Update invites dictionary even if there was an error
    invites[guild.id] = invites_after_join


@client.event
async def on_member_remove(member):
    # Check if the guild ID exists in invites dictionary
    if member.guild.id in invites:
        # Log the member's departure
        await log_embed(f"{member.mention} has left the server.", member)
        # Update invites dictionary with the latest invite list
        invites[member.guild.id] = await member.guild.invites()
    else:
        print("Guild ID not found in invites dictionary")
    



### Slash Commands ###
import typing  # Add this line at the top of your script

@tree.command(name="setlogchannel", description="Setup log channel for the bot")
async def setlogchannel(interaction: discord.Interaction, log_channel: typing.Optional[discord.TextChannel] = None, inviter_channel: typing.Optional[discord.TextChannel] = None):
    # Check if user has permissions to manage channels
    if interaction.user.guild_permissions.manage_channels:
        try:
            # Function to update command count
            command_name = "setlogchannel"
            update_command_count(command_name)
        except:
            print("cannot update setlogchannel Command count")

        # Fetch the user ID who initiated the command
        user_name = interaction.user.name
        user_id = interaction.user.id
        conn = sqlite3.connect('Tamoza_Bot_DB.db')
        cursor = conn.cursor()
        # Update the log channel for the server in the database
        cursor.execute('''INSERT OR REPLACE INTO Tamoza_Bot_DB (server_name, guild_id, log_message_name, log_message_id, user_name, user_id, inv_log_channel, inv_log_channel_name) 
                        VALUES (?, ?, ?, ?, ?, ?, ?, ?)''', (interaction.guild.name, interaction.guild.id, log_channel.name if log_channel else None, log_channel.id if log_channel else None, user_name, user_id, inviter_channel.id if inviter_channel else None, inviter_channel.name if inviter_channel else None))
        conn.commit()
        
        #await interaction.response.send_message(f' Log channel set to {log_channel.mention if log_channel else "not set"}')
        # Send an embed with additional information
        embed = discord.Embed(title="> Log Channel Setup", description=":ballot_box_with_check: The log channel has been successfully set.")
        await interaction.response.send_message(embed=embed)
    else:
        await interaction.response.send_message("You don't have permissions to manage channels.")


@tree.command(name="help", description="Get help for the TamozaBot")
async def help(interaction: discord.Interaction):
    await interaction.response.defer()

    try:
        # Function to update command count
        command_name = "help"
        update_command_count(command_name)
    except:
        print("cannot update help Command count")
    
    commands = [
        ("**/setlogchannel**",  "Setup log channel and Inviter log." ),
        ("**/kick**",  "Kick a member from the server with a reason." ),
        ("**/ban**",  "Ban a member from the server with a reason." ),
        ("**/roles**",  "Show all roles and the number of users in each role." ),
        ("**/temproles**",  "Temporarily removes all roles from a member and restores them after a specified duration." ),
        ("**/clean**",  "Clears a specified number of messages in a channel (1-100)." ),
        ("**/cleanuser**",  "Clear all user messages in channel (1-100)." ),
        ("**/clearresponses**",  "Clear 100 response messages from the bot." ),
        ("**/mention**",  "Mention a member in a specific channel with a message." ),
        ("**/mentionall**",  "Mention everyone in a specified channel with a message." ),
        ("**/randomteams**",  "Randomly generate teams from members in your voice channel." ),
        ("**/teamup**",  "Randomly generate teams with mentioned users." ),
        ("**/serverstatus**",  "Displays how many roles, channels, members, users, and bots." ),
        ("**/userstatus**",  "Displays the status and information of a user." ),
        ("**/avatar**",  "Displays user avatar." ),
        ("**/warn**",  "Warn a user." ),
        ("**/checkwarnings**",  "Check warnings for a user." ),
        ("**/customcommand**",  "Create a custom command." ),
        ("**/runcustom**",  "Run a custom command." ),
        ("**/removecommand**",  "Remove a custom command." ),
        ("**/giveaway**",  "Start a giveaway." ),
        ("**/poll**",  "Create a poll with the given question and options." ),
        ("**/privatemsg**",  "Send private message." ),
        ("**/addevent**",  "Add a new event to the calendar." ),
        ("**/removeevent**",  "Remove an event from the calendar." ),
        ("**/viewevents**",  "View all your calendar events." ),
        ("**/stickymsg**",  "Send sticky message." ),
        ("**/stopstickymsg**",  "Stop sticky message in a channel." ),
        ("**/addsocial**",  "Add social account." ),
        ("**/social**",  "Show user social accounts." ),
        ("**/passgen**",  "Generate a strong password." ),
        ("**/shorturl**",  "Create a short URL." ),
        ("**/invite**",  "Invite link for TamozaBot." ),
        ("**/about**",  "About TamozaBot." ),

            # Add other commands here...
            
    ]

    embed = discord.Embed(title="> Commands", description="These are the available commands:", color=0x00ff00)

    for name, value in commands[:23]:  # Limit to 25 fields per embed
        embed.add_field(name=name, value=f"```{value}```", inline=False)
        embed.set_footer(text="TamozaBot - © 2024 | For more info, visit: https://x.com/Tamoza04")  # Add footer text with link
    await interaction.followup.send(embed=embed)

    if len(commands) > 23:
        for chunk in [commands[i:i+25] for i in range(23, len(commands), 23)]:
            embed = discord.Embed(title="Commands", description="Continued...", color=0x00ff00)
            for name, value in chunk:
                embed.add_field(name=name, value=f"```{value}```", inline=False)
                embed.set_footer(text="TamozaBot - © 2024 | For more info, visit: https://x.com/Tamoza04")  # Add footer text with link
                embed.timestamp = datetime.now()
            await interaction.followup.send(embed=embed)


@tree.command(name="highestcommands", description="Shows the count of the top 10 most used commands.")
async def highest_commands(interaction):
    # Replace 'YOUR_USER_ID' with your actual user ID
    if interaction.user.id != 549538566666190848:
        await interaction.response.send_message("Sorry, only the owner of the bot can use this command.", ephemeral=True)
        return

    all_commands = get_all_used_commands()
    if all_commands is not None:
        chunk_size = 25  # Number of commands to display in each embed
        for i in range(0, len(all_commands), chunk_size):
            embed = discord.Embed(title="All Used Commands", color=discord.Color.blue())
            chunk = all_commands[i:i+chunk_size]
            for command, count in chunk:
                embed.add_field(name=f"Command: {command}", value=f"Usage Count: {count}", inline=False)
            
            # Send the embed as a response
            if i == 0:
                await interaction.response.send_message(embed=embed, ephemeral=True)
            else:
                await interaction.followup.send(embed=embed, ephemeral=True)
    else:
        await interaction.response.send_message("No commands have been used yet.")


@tree.command(name="kick", description="Kick a member from the server with a reason.")
async def kick(interaction: discord.Interaction, member: discord.Member, *, reason: str):
    if not interaction.user.guild_permissions.kick_members:  # Check visibility permission
        await interaction.response.send_message("You don't have permission to see this command.", ephemeral=True)
        return

    # Check user permissions
    if not interaction.user.guild_permissions.kick_members:
        await interaction.response.send_message("You must have the 'Kick Members' permission to use this command.", ephemeral=True)
        return

    try:
        # Function to update command count
        command_name = "kick"
        update_command_count(command_name)
    except:
        print("cannot update kick Command count")

    try:
        
        await member.kick(reason=reason)
        await interaction.response.send_message(f"{member.mention} has been kicked from the server. Reason: {reason}", ephemeral=True)

        try:
            guild_id = interaction.guild.id  
            log_channel_id = get_log_channel_id(guild_id) # Continue with your logic using log_channel_id
            log_channel = discord.utils.get(interaction.guild.text_channels, id=get_log_channel_id(guild_id))
            #await log_channel.send(f"{member.mention} has been kicked from the server by {interaction.user.mention}. Reason: {reason}")

            # Create an embed object
            embed = discord.Embed(title="> Member has been Kicked", color=discord.Color.red())

            # Add fields to the embed
            embed.add_field(name="**Member**", value=member.mention, inline=False)
            embed.add_field(name="**By**", value=interaction.user.mention, inline=False)
            embed.add_field(name="**Reason**", value=reason, inline=False)
            embed.timestamp = datetime.now()
            # Send the embed to the log channel
            await log_channel.send(embed=embed)
            
        except ValueError:
            pass

    except discord.Forbidden:
        await interaction.response.send_message(f"Failed to kick {member.mention}. Please check my permissions or the member's roles.", ephemeral=True)
 

@tree.command(name="ban", description="Ban a member from the server with a reason.")
async def ban(interaction: discord.Interaction, member: discord.Member, *, reason: str):
    """Bans the specified member from the server with the provided reason."""

    if not interaction.guild.me.guild_permissions.ban_members:
        await interaction.response.send_message(f"I don't need permission to ban members.", ephemeral=True)
        return


    try:
        # Function to update command count
        command_name = "ban"
        update_command_count(command_name)
    except:
        print("cannot update ban Command count")
    try:
        
        await member.ban(reason=reason)
        await interaction.response.send_message(f"{member.mention} has been banned from the server Reason: {reason}", ephemeral=True)

        try:
            guild_id = interaction.guild.id  
            log_channel_id = get_log_channel_id(guild_id) # Continue with your logic using log_channel_id
            log_channel = discord.utils.get(interaction.guild.text_channels, id=get_log_channel_id(guild_id))
            #await log_channel.send(f"{member.mention} has been banned from the server by {interaction.user.mention} Reason: {reason}")
            # Create an embed object
            embed = discord.Embed(title="> Member has been Banned", color=discord.Color.dark_red())

            # Add fields to the embed
            embed.add_field(name="**Member**", value=member.mention, inline=False)
            embed.add_field(name="**Moderator**", value=interaction.user.mention, inline=False)
            embed.add_field(name="**Reason**", value=reason, inline=False)
            embed.timestamp = datetime.now()

            await log_channel.send(embed=embed)

        except ValueError:
            pass
        
    except discord.Forbidden:
        await interaction.response.send_message(f"Failed to ban {member.mention}. Please check my permissions.", ephemeral=True)


@tree.command(name="temproles", description="Temporarily removes all roles from a member and restores them after a specified duration.")
async def temproles(interaction: discord.Interaction, member: discord.Member, duration: int):


    # Permission check moved to interaction.user context
    if not interaction.user.guild_permissions.manage_roles:
        await interaction.response.send_message("You don't have permission to use this command.", ephemeral=True)
        return

    # Check if the bot's role is higher than all of the user's roles
    bot_role = interaction.guild.get_role(interaction.guild.me.top_role.id)
    if bot_role.position <= max(role.position for role in member.roles):
        await interaction.response.send_message("You have to put the Bot role above all user roles in the role hierarchy.", ephemeral=True)
        return
    
    
    
    # Check if duration is within reasonable limits
    if duration < 0 or duration > 60:
        await interaction.response.send_message("Please enter a valid duration between 0 and 60 seconds.", ephemeral=True)
        return

    # Get member's current roles (excluding @everyone)
    member_roles = [role for role in member.roles if role != interaction.guild.default_role]

    try:
        # Function to update command count
        command_name = "temproles"
        update_command_count(command_name)
    except:
        print("cannot update temproles Command count")

    # Check if the member has any assignable roles
    if not member_roles:
        await interaction.response.send_message("The member already has no assignable roles.", ephemeral=True)
        return

    # Store removed roles before removing them
    removed_roles = member_roles
    try:
        await member.remove_roles(*removed_roles)
        await interaction.response.send_message(f"Removed {member.mention}'s roles for {duration} seconds.", ephemeral=True)
            # Get the log channel by its ID (replace log_channel_id with the actual ID)
        try:
            guild_id = interaction.guild.id  
            log_channel_id = get_log_channel_id(guild_id) # Continue with your logic using log_channel_id
            log_channel = discord.utils.get(interaction.guild.text_channels, id=log_channel_id)
            if log_channel:
                try:
                    # Create an embed object
                    embed = discord.Embed(title=f"> Roles have been Removed", color=discord.Color.red())

                    # Add fields to the embed
                    embed.add_field(name="**Member**", value=member.mention, inline=False)
                    embed.add_field(name="**By**", value=interaction.user.mention, inline=False)
                    embed.add_field(name="**Duration**", value=f"{duration} seconds", inline=False)
                    embed.timestamp = datetime.now()
                    # Send the embed to the log channel
                    await log_channel.send(embed=embed)
                except discord.errors.HTTPException as e:
                    print(f"Failed to send message to log channel: {e}")
            
        except ValueError:
            pass

    except discord.errors.InteractionResponded:
        pass

    # Schedule role restoration after the specified duration
    await asyncio.sleep(duration)

    # Re-add the removed roles in a loop, handling potential rate limits
    for role in removed_roles:
        try:
            await member.add_roles(role)
        except discord.HTTPException as e:
            # Wait for a minute before retrying due to rate limits
            try:
                await interaction.response.send_message(f"Rate limit encountered while adding role {role.name}. Retrying in 1 minute.", ephemeral=True)
                await asyncio.sleep(60)
                await member.add_roles(role)
            except discord.errors.InteractionResponded:
                pass
            except discord.HTTPException:
                try:
                    await interaction.response.send_message(f"Failed to add role {role.name} due to rate limits. Skipping.", ephemeral=True)
                except discord.errors.InteractionResponded:
                    pass

    try:
        await interaction.response.send_message(f"Restored {member.mention}'s roles by {interaction.user.mention}.")
    except discord.errors.InteractionResponded:
        pass
    try:
        # Get the log channel by its ID (replace log_channel_id with the actual ID)
        log_channel = discord.utils.get(interaction.guild.text_channels, id=log_channel_id)
        if log_channel:
            try:
                # Create an embed object
                embed = discord.Embed(title="> Roles Temporarily Removed and Restored", color=discord.Color.green())

                # Add fields to the embed
                embed.add_field(name="**Member**", value=member.mention, inline=False)
                embed.add_field(name="**By**", value=interaction.user.mention, inline=False)
                embed.add_field(name="**Duration**", value=f"{duration} seconds", inline=False)

                # Send the embed to the log channel
                await log_channel.send(embed=embed)
            except discord.errors.HTTPException as e:
                print(f"Failed to send message to log channel: {e}")
    except ValueError:
            pass


@tree.command(name="clean", description="Clears a specified number of messages in the same channel (1-100).")
async def clean(interaction: discord.Interaction, count: int):
    try:
        # Check user permissions
        if not interaction.guild.me.guild_permissions.manage_messages:
            await interaction.response.send_message("I don't have permission to delete messages in this channel.", ephemeral=True)
            return

        await interaction.response.defer()

        # Validate the count within the allowed range
        if not 1 <= count <= 100:
            raise ValueError("Invalid message count. Please specify a number between 1 and 100.")

        
        try:
            # Function to update command count
            command_name = "clean"
            update_command_count(command_name)
        except:
            print("cannot update clean Command count")
    

        # Get the channel where the command was used
        channel = interaction.channel

        # Delete the messages, ensuring count doesn't exceed available messages
        deleted_messages = await channel.purge(limit=count + 1)  # Adjust for command message

        # Get the count of actually deleted messages
        deleted_count = len(deleted_messages)

        #await interaction.followup.send(f"Deleted {deleted_count} messages in {channel.mention}.")

        # Attempt to log the deletion
        try:
            guild_id = interaction.guild.id  
            log_channel_id = get_log_channel_id(guild_id)  # Assuming you have a function to get log channel ID
            log_channel = interaction.guild.get_channel(log_channel_id)
            if log_channel:
                embed = discord.Embed(title="> Message Deletion", color=discord.Color.blue())
                embed.add_field(name="Deleted messages", value=deleted_count, inline=False)
                embed.add_field(name="Channel", value=channel.mention, inline=False)
                embed.set_footer(text=f"Requested by {interaction.user.display_name}")
                embed.timestamp = datetime.now()

                await log_channel.send(embed=embed)
        except discord.errors.NotFound:
            print("Message not found when trying to log deletion.")
        except Exception as e:
            print(f"Failed to log message deletion: {e}")

    except discord.Forbidden:
        await interaction.response.send_message("I don't have permission to delete messages in this channel.", ephemeral=True)
    except ValueError as e:
        await interaction.response.send_message(str(e), ephemeral=True)
    except Exception as e:
        print(f"An error occurred: {e}")


@tree.command(name="clearuser", description="Clear all user messages in channel (1-100).")
async def clear_user_messages(ctx, user: discord.Member, msg_number: int):
    if msg_number > 100:
        response_message = await ctx.response.send_message("Invalid message count. Please specify a number between 1 and 100.", ephemeral=True)
        return
    
    if ctx.user.guild_permissions.administrator:  # Check if the author has admin permissions
        
        
        try:
            # Function to update command count
            command_name = "clearuser"
            update_command_count(command_name)
        except:
            print("cannot update clearuser Command count")
    
        
        # Acknowledge the interaction
        response_message = await ctx.response.send_message("Clearing messages...", ephemeral=True)

        def is_user(message):
            return message.author == user

        deleted = await ctx.channel.purge(limit=msg_number, check=is_user)  # Delete up to msg_number + 1 messages from the user
        
        try:
            guild_id = ctx.guild.id  
            log_channel_id = get_log_channel_id(guild_id) # Continue with your logic using log_channel_id
            log_channel = discord.utils.get(ctx.guild.text_channels, id=log_channel_id)
            if log_channel:
                try:
                    embed = discord.Embed(description="> **Deleted User Message**", color=discord.Color.green())
                    embed.add_field(name="**User**", value=user.mention, inline=False)
                    embed.add_field(name="**By**", value=ctx.user.mention, inline=False)
                    embed.add_field(name="**Deleted Message**", value=str(len(deleted)) + " Messages", inline=False)
                    embed.timestamp = datetime.now()
                    await log_channel.send(embed=embed)
                except discord.errors.HTTPException as e:
                    print(f"Failed to send message to log channel: {e}")
        except ValueError:
            pass
        
        
        
        
        # Send a confirmation message
        confirmation_message = await ctx.channel.send(f"Deleted {len(deleted)} messages from {user.mention}.", delete_after=5)


    else:
        await ctx.channel.send("You don't have permission to use this command.")


@tree.command(name="clearresponses", description="Clear 20 response messages from the bot.")
async def clear_bot_responses(ctx):
    if ctx.user.guild_permissions.administrator:  # Check if the author has admin permissions
        
        try:
            # Function to update command count
            command_name = "clearresponses"
            update_command_count(command_name)
        except:
            print("cannot update clearresponses Command count")
    
        # Send a response to acknowledge the command
        await ctx.response.send_message("Clearing messages...", ephemeral=True)

        deleted_count = 0
        async for message in ctx.channel.history(limit=20):  # Limiting to the last 100 messages for performance
            if message.author == ctx.guild.me:  # Check if the author of the message is the bot member
                await message.delete()
                deleted_count += 1

        # Send a confirmation message with the number of messages deleted
        await ctx.channel.send(f"Deleted {deleted_count} response messages from the bot.", delete_after=5)
    else:
        await ctx.channel.send("You don't have permission to use this command.", ephemeral=True)


@tree.command(name="mention", description="Mention a member in a specific channel with a message.")
async def mention(interaction: discord.Interaction, member: discord.Member, channel: discord.TextChannel, message: str):
    """Mentions the given member in the specified channel with the provided message."""
    if not channel.permissions_for(interaction.guild.me).send_messages:
        await interaction.response.send_message(f"I don't have permission to send messages to {member.mention} in {channel.mention}", ephemeral=True)
        return
    
    try:
        # Function to update command count
        command_name = "mention"
        update_command_count(command_name)
    except:
        print("cannot update mention Command count")

    try:
        
        
        
        await channel.send(f"{member.mention} {message}")
        await interaction.response.send_message(f"Message sent to {member.mention} in {channel.mention}!", ephemeral=True)

        try:
            guild_id = interaction.guild.id  
            log_channel_id = get_log_channel_id(guild_id)
            
            if log_channel_id:
                log_channel = discord.utils.get(interaction.guild.text_channels, id=log_channel_id)
                if log_channel:
                    # Create an embed object
                    embed = discord.Embed(title="> Message Sent", color=discord.Color.blue())

                    # Add fields to the embed
                    embed.add_field(name="**Member**", value=member.mention, inline=False)
                    embed.add_field(name="**Channel**", value=channel.mention, inline=False)
                    embed.add_field(name="**By**", value=interaction.user.mention, inline=False)
                    embed.add_field(name="**Message**", value=f"```{message}```", inline=False)

                    # Send the embed to the log channel
                    await log_channel.send(embed=embed)
                else:
                    print("Log channel not found")
            else:
                print("Log channel ID not found")
                
        except ValueError:
            pass
        
    except discord.Forbidden:
        await interaction.response.send_message(f"Failed to send message to {member.mention} in {channel.mention}. Please check my permissions.", ephemeral=True)


@tree.command(name="mentionall", description="Mention everyone in a specified channel with a message.")
async def mention_everyone(interaction: discord.Interaction, channel: discord.TextChannel, message: str):
    """Mentions everyone in the given channel with the provided message.
    **This command is restricted to users with the 'Manage Messages' permission.**"""

    # Check if the user has the required permission
    if not interaction.user.guild_permissions.manage_messages:
        await interaction.response.send_message("You don't have permission to use this command.", ephemeral=True)
        return

    # Ensure bot has send_messages permission in the channel
    if not channel.permissions_for(interaction.guild.me).send_messages:
        await interaction.response.send_message(f"I don't have permission to send messages in {channel.mention}.", ephemeral=True)
        return

    
    try:
        # Function to update command count
        command_name = "mentionall"
        update_command_count(command_name)
    except:
        print("cannot update mentionall Command count")
    try:
        # Mention everyone using the @everyone mention
        await channel.send(f"@everyone {message}")
        await interaction.response.send_message(f"Message sent to everyone in {channel.mention}!", ephemeral=True)

        try:
            guild_id = interaction.guild.id  
            log_channel_id = get_log_channel_id(guild_id) # Continue with your logic using log_channel_id
            # Log the message if a logging channel is set
            log_channel = discord.utils.get(interaction.guild.text_channels, id=log_channel_id)
            if log_channel:
                #await log_channel.send(f"Everyone mentioned in {channel.mention} by {interaction.user.mention}: {message}")
                embed = discord.Embed(title="> **Everyone mention**", color=0x00ff00)  # Set color to green (hex value)
                embed.add_field(name="**Message**", value=f"```{message}```", inline=False)
                embed.add_field(name="**Channel:**", value=f"{channel.mention}", inline=False)
                embed.add_field(name="**By**", value=interaction.user.mention, inline=False)
                embed.timestamp = datetime.now()
            #user = interaction.user
            #embed.set_footer(text=f"Requested by {user.display_name}", icon_url=user.avatar.url)
            await log_channel.send(embed=embed)
        
        except ValueError:
            pass

    except discord.Forbidden:
        await interaction.response.send_message(f"Failed to mention everyone in {channel.mention}. Please check my permissions.", ephemeral=True)


@tree.command(name="randomteams",description="Randomly generate teams from members in your voice channel. Defualt team is 2",)
async def random_teams(interaction: discord.Interaction, channel: discord.VoiceChannel, num_teams: int = 2):
    """
    Creates `num_teams` random teams from members in the caller's voice channel.

    Args:
        interaction (discord.Interaction): The interaction object for slash commands.
        channel (discord.VoiceChannel): The voice channel to create teams from.
        num_teams (int, optional): The number of teams to generate. Defaults to 2.
    """

    if interaction.user.voice is None or interaction.user.voice.channel is None:  # Check if user is in a voice channel
        await interaction.response.send_message("You must be in a voice channel to use this command.", ephemeral=True)
        return

    members = list(channel.members)  # Convert members to a list

    if len(members) < num_teams:
        await interaction.response.send_message("Not enough members in the voice channel for that many teams.", ephemeral=True)
        return

    
    try:
        # Function to update command count
        command_name = "randomteams"
        update_command_count(command_name)
    except:
        print("cannot update Command count")
    # Shuffle members randomly
    random.shuffle(members)

    # Divide members into teams manually
    teams = []
    members_per_team = len(members) // num_teams
    leftover = len(members) % num_teams

    for i in range(num_teams):
        team = members[:members_per_team]
        teams.append(team)
        del members[:members_per_team]

    # Distribute leftover members evenly
    for i in range(leftover):
        teams[i % num_teams].append(members[0])
        del members[0]

    # Format and send announcement
    await interaction.response.defer()  # Acknowledge command

    # Create embed for table representation
    embed = discord.Embed(title="Generated Teams", description=f"{num_teams} teams created:")

    # Loop through teams and add rows to embed
    for i, team in enumerate(teams):
        team_names = [f"{member.mention}" for member in team]
        embed.add_field(name=f"Team {i+1}", value=", ".join(team_names), inline=False)
        embed.timestamp = datetime.now()
    # Send the embed message
    await interaction.followup.send(embed=embed)


@tree.command(name="teamup", description="Randomly generate teams with mentioned users.")
async def random_team_users(interaction: discord.Interaction, num_teams: int, user_mentions: str):
    """
    Randomly generate teams with manually mentioned users.

    Args:
        interaction (discord.Interaction): The interaction object for slash commands.
        num_teams (int): The number of teams to generate.
        user_mentions (str): Mention strings of users separated by spaces.
    """
    try:
        # Function to update command count
        command_name = "teamup"
        update_command_count(command_name)
    except:
        print("cannot update teamup Command count")

    # Split the user mentions string into individual mentions
    user_mention_list = user_mentions.split()

    # Check if there are enough mentions for the specified number of teams
    if len(user_mention_list) < num_teams:
        await interaction.response.send_message("There must be at least as many mentioned users as there are teams.", ephemeral=True)
        return

    # Convert mention strings to User objects
    users = []
    for mention in user_mention_list:
        user_id = int(mention.replace("<@", "").replace(">", "").replace("!", ""))
        user = interaction.guild.get_member(user_id)
        if user:
            users.append(user)
        else:
            await interaction.response.send_message(f"User {mention} not found.", ephemeral=True)
            return

    random.shuffle(users)  # Shuffle the list of users

    teams = [[] for _ in range(num_teams)]  # Initialize empty teams list

    # Distribute users among teams
    for i, user in enumerate(users):
        teams[i % num_teams].append(user)

    # Create and send the message
    await interaction.response.defer()  # Acknowledge command

    # Create embed for team representation
    embed = discord.Embed(title=f"Randomly Generated Teams ({num_teams} teams):", color=discord.Color.blue())

    # Add fields for each team
    for i, team in enumerate(teams):
        team_mentions = ", ".join([member.mention for member in team])
        embed.add_field(name=f"Team {i+1}", value=team_mentions, inline=False)

    # Send the embed message
    await interaction.followup.send(embed=embed)


@tree.command(name="serverstatus", description="Displays how many roles, channels, members, users, and bots.")
async def server_status_command(interaction: discord.Interaction):
    guild = interaction.guild

    try:
        # Function to update command count
        command_name = "serverstatus"
        update_command_count(command_name)
    except:
        print("cannot update serverstatus Command count")


    # Count roles, text channels, voice channels, and members
    role_count = len(guild.roles)
    text_channel_count = sum(1 for channel in guild.channels if isinstance(channel, discord.TextChannel))
    voice_channel_count = sum(1 for channel in guild.channels if isinstance(channel, discord.VoiceChannel))
    member_count = len(guild.members)

    # Calculate user and bot counts
    user_count = sum(1 for member in guild.members if not member.bot)
    bot_count = member_count - user_count

    # Create an instance of discord.Embed()
    embed = discord.Embed()

    # Define the status values
    status_values = [
        ("Total Members", member_count),
        ("Users", user_count),
        ("Bots", bot_count),
        ("Total Roles", role_count),
        ("Text Channels", text_channel_count),
        ("Voice Channels", voice_channel_count)
    ]

    # Create the table string
    table = "```css\n"
    for name, value in status_values:
        table += f"{name.ljust(15)}: {value}\n"
    table += "```"

    # Add the table to the embed
    embed.add_field(name="Server Status", value=table, inline=False)

    # Get the number of members in each voice channel
    voice_channel_members = {}
    for voice_channel in guild.voice_channels:
        if voice_channel.members:  # Check if there are members in the voice channel
            voice_channel_members[voice_channel.name] = len(voice_channel.members)

    # Add the voice channel members information to the embed
    if voice_channel_members:
        voice_channels_info = "\n".join([f"{name}: {count}" for name, count in voice_channel_members.items()])
        embed.add_field(name="Voice Channel Members", value=voice_channels_info, inline=False)
    else:
        embed.add_field(name="Voice Channel Members", value="No members in voice channels", inline=False)

    # Access the user who initiated the interaction
    user = interaction.user
    embed.set_footer(text=f"Requested by {user.display_name}")
    embed.timestamp = datetime.now()

    await interaction.response.send_message(embed=embed)


@tree.command(name="userstatus", description="Displays the status and information of a user.")
async def userstatus(interaction: discord.Interaction, member: typing.Optional[discord.Member] = None):
    try:
        # Function to update command count
        command_name = "userstatus"
        update_command_count(command_name)
    except:
        print("cannot update userstatus Command count")


    # If no member is mentioned or selected, use the interaction's user
    member = member or interaction.user

    # Retrieve basic user information
    joined_discord = member.created_at.strftime("%B %d, %Y")
    joined_server = member.joined_at.strftime("%B %d, %Y")
    roles = ", ".join([role.name for role in member.roles])
    activity = member.activity.name if member.activity else "Not playing"

    # Calculate time difference for join dates
    today = datetime.today().date()

    # Time since joined Discord
    time_since_joined_discord = today - member.created_at.date()
    years_discord = time_since_joined_discord.days // 365
    months_discord = (time_since_joined_discord.days % 365) // 30
    days_discord = (time_since_joined_discord.days % 365) % 30
    elapsed_time_discord_str = f"{years_discord} years, {months_discord} months, {days_discord} days ago"

    # Time since joined Server
    time_since_joined_server = today - member.joined_at.date()
    years_server = time_since_joined_server.days // 365
    months_server = (time_since_joined_server.days % 365) // 30
    days_server = (time_since_joined_server.days % 365) % 30
    elapsed_time_server_str = f"{years_server} years, {months_server} months, {days_server} days ago"

    # Construct embed message
    embed = discord.Embed(title=f"> User Information: {member.display_name}", color=member.color)
    embed.add_field(name="**Username**", value=member.name, inline=True)
    
    # Add Discriminator field only if it exists and is non-zero
    if member.discriminator and int(member.discriminator) != 0:
        embed.add_field(name="**Discriminator**", value=member.discriminator, inline=True)
    
    embed.add_field(name="**Joined Discord**", value=f"{joined_discord}\n\t({elapsed_time_discord_str})", inline=False)
    embed.add_field(name="**Joined Server**", value=f"{joined_server}\n\t({elapsed_time_server_str})", inline=False)
    embed.add_field(name="**Roles**", value=roles, inline=False)
    # embed.add_field(name="Activity", value=activity)
    embed.set_thumbnail(url=member.avatar.url)
    embed.timestamp = datetime.now()

    # Send the embed 
    await interaction.response.send_message(embed=embed)


@tree.command(name="avatar", description="Displays user avatar.")
async def user_avatar(interaction: discord.Interaction, user: typing.Optional[discord.Member] = None):
    # If no user is mentioned or selected, use the interaction's user
    
    try:
        # Function to update command count
        command_name = "avatar"
        update_command_count(command_name)
    except:
        print("cannot update avatar Command count")
    
    if not user:
        user = interaction.user

    embed = discord.Embed(title=f"{user.name}'s Avatar")
    
    if user.avatar:
        embed.set_image(url=user.avatar.url)
        embed.timestamp = datetime.now()
        await interaction.response.send_message(embed=embed)
    else:
        embed.description = f"{user.name} doesn't have an avatar set."
        await interaction.response.send_message(embed=embed)


@tree.command(name="roles", description="Show all roles and the number of users in each role.")
async def show_roles(interaction: discord.Interaction):
    guild = interaction.guild
    roles = guild.roles
    try:
        # Function to update command count
        command_name = "roles"
        update_command_count(command_name)
    except:
        print("cannot update roles Command count")

    role_counts = {}
    for member in guild.members:
        for role in member.roles:
            if role.id not in role_counts:
                role_counts[role.id] = 0
            role_counts[role.id] += 1

    role_info = []
    for role in roles:
        if role.id in role_counts:
            role_info.append(f"{role.name}: {role_counts[role.id]}")
        else:
            role_info.append(f"{role.name}: 0")  # Add roles with zero members

    if role_info:
        embed = discord.Embed(title="Roles and User Counts", color=discord.Color.blue())
        embed.description = "\n".join(role_info)
        embed.timestamp = datetime.now()
        await interaction.response.send_message(embed=embed)
    else:
        await interaction.response.send_message("No roles found in the server.")


### Warnings ###
            
# Function to create the warnings table
def create_warnings_table():
    conn = sqlite3.connect('warnings.db')
    cursor = conn.cursor()
    cursor.execute('''CREATE TABLE IF NOT EXISTS warnings (
                        guild_id INTEGER,
                        user_id INTEGER,
                        moderator_id INTEGER,
                        reason TEXT
                    )''')
    conn.commit()
    conn.close()

# Function to add a warning to the database
def add_warning(guild_id, user_id, moderator_id, reason):
    conn = sqlite3.connect('warnings.db')
    cursor = conn.cursor()
    cursor.execute('INSERT INTO warnings VALUES (?, ?, ?, ?)', (guild_id, user_id, moderator_id, reason))
    conn.commit()
    conn.close()

# Function to get warnings for a user from the database
def get_warnings(guild_id, user_id):
    conn = sqlite3.connect('warnings.db')
    cursor = conn.cursor()
    cursor.execute('SELECT moderator_id, reason FROM warnings WHERE guild_id = ? AND user_id = ?', (guild_id, user_id))
    warnings = cursor.fetchall()
    conn.close()
    return warnings

@tree.command(name="warn", description="Warn a user.")
async def warn_user(interaction: discord.Interaction, member: discord.Member, *, reason: str):
    create_warnings_table()  # Create the table if it doesn't exist
    if interaction.user.guild_permissions.kick_members:
        try:
            # Function to update command count
            command_name = "warn"
            update_command_count(command_name)
        except:
            print("cannot update warn Command count")


        add_warning(interaction.guild_id, member.id, interaction.user.id, reason)  # Pass interaction.user.id as moderator_id
        embed = discord.Embed(title="User Warned", description=f"{member.mention} has been warned by {interaction.user.mention}.", color=0xFF0000)
        embed.add_field(name="Reason", value=reason, inline=False)
        await interaction.response.send_message(embed=embed)
    else:
        await interaction.response.send_message("You don't have permission to warn users.")

@tree.command(name="checkwarnings", description="Check warnings for a user.")
async def check_warnings(interaction: discord.Interaction, member: discord.Member):
    create_warnings_table()  # Create the table if it doesn't exist
    if interaction.user.guild_permissions.kick_members:
        try:
            # Function to update command count
            command_name = "checkwarnings"
            update_command_count(command_name)
        except:
            print("cannot update checkwarnings Command count")

        warnings = get_warnings(interaction.guild_id, member.id)
        if warnings:
            warning_list = "\n".join([f"{i+1}- Warned by <@{warning[0]}>: ```{warning[1]}```" for i, warning in enumerate(warnings)])
            embed = discord.Embed(title="User Warnings", description=f"{member.display_name} has the following warnings:", color=0xFF0000)
            embed.add_field(name="Warnings", value=warning_list, inline=False)
            await interaction.response.send_message(embed=embed)
        else:
            await interaction.response.send_message(f"{member.display_name} has no warnings.")
    else:
        await interaction.response.send_message("You don't have kick permission to check warnings.")


### Custom Command ###
        
# Connect to SQLite database
conn = sqlite3.connect('custom_commands.db')
c = conn.cursor()

# Create table for custom commands if not exists
c.execute('''CREATE TABLE IF NOT EXISTS custom_commands (
             guild_id INTEGER,
             command_name TEXT,
             action TEXT,
             PRIMARY KEY (guild_id, command_name))''')
conn.commit()

@tree.command(name="customcommand", description="Create a custom command.")
async def create_custom_command(interaction: discord.Interaction, command_name: str, *, action: str):
    # Check if the user has the necessary permissions
    if not interaction.user.guild_permissions.manage_guild:
        await interaction.response.send_message("You don't have permission to create custom commands.")
        return
    # Check if the command name already exists for the guild
    try:
        # Function to update command count
        command_name1 = "customcommand"
        update_command_count(command_name1)
    except:
        print("cannot update customcommand Command count")

    conn = sqlite3.connect('custom_commands.db')
    c = conn.cursor()
    c.execute('SELECT * FROM custom_commands WHERE guild_id = ? AND command_name = ?', (interaction.guild_id, command_name))
    if c.fetchone():
        await interaction.response.send_message(f"The command '{command_name}' already exists.", ephemeral=True)
    else:
        c.execute('INSERT INTO custom_commands VALUES (?, ?, ?)', (interaction.guild_id, command_name, action))
        conn.commit()
        await interaction.response.send_message(f"Custom command '{command_name}' has been created." , ephemeral=True)
        
        try:
            guild_id = interaction.guild.id  
            log_channel_id = get_log_channel_id(guild_id) # Continue with your logic using log_channel_id
            log_channel = discord.utils.get(interaction.guild.text_channels, id=log_channel_id)
            if log_channel:
                try:
                    # Create an embed object
                    embed = discord.Embed(title="Custom Command Created", description=f"Custom command '{command_name}' has been created.", color=discord.Color.green())

                    # Send the embed to the log channel
                    await log_channel.send(embed=embed)
                except discord.errors.HTTPException as e:
                    print(f"Failed to send message to log channel: {e}")
        except:
            pass

        
@tree.command(name="runcustom", description="Run a custom command.")
async def run_custom_command(interaction: discord.Interaction, command_name: str):
    try:
        # Function to update command count
        command_name1 = "runcustom"
        update_command_count(command_name1)
    except:
        print("cannot update runcustom Command count")

    # Check if the command exists for the guild
    conn = sqlite3.connect('custom_commands.db')
    c = conn.cursor()
    c.execute('SELECT action FROM custom_commands WHERE guild_id = ? AND command_name = ?', (interaction.guild_id, command_name))
    command = c.fetchone()
    if command:
        await interaction.response.send_message(command[0])
    else:
        await interaction.response.send_message(f"Custom command '{command_name}' does not exist.", ephemeral=True)


@tree.command(name="removecommand", description="Remove a custom command.")
async def remove_custom_command(interaction: discord.Interaction, command_name: str):
    # Check if the user has the necessary permissions
    if not interaction.user.guild_permissions.manage_guild:
        await interaction.response.send_message("You don't have permission to remove custom commands.", ephemeral=True)
        return
    try:
        # Function to update command count
        command_name1 = "removecommand"
        update_command_count(command_name1)
    except:
        print("cannot update removecommand Command count")

    # Check if the command exists for the guild
    conn = sqlite3.connect('custom_commands.db')
    c = conn.cursor()
    c.execute('SELECT * FROM custom_commands WHERE guild_id = ? AND command_name = ?', (interaction.guild_id, command_name))
    if not c.fetchone():
        await interaction.response.send_message(f"The command '{command_name}' does not exist.", ephemeral=True)
    else:
        c.execute('DELETE FROM custom_commands WHERE guild_id = ? AND command_name = ?', (interaction.guild_id, command_name))
        conn.commit()
        await interaction.response.send_message(f"Custom command '{command_name}' has been removed.", ephemeral=True)


@tree.command(name="giveaway", description="Start a giveaway.")
async def start_giveaway(interaction: discord.Interaction, duration: int, *, prize: str):
    await interaction.response.defer()
    # Check if the user has the required permissions
    if interaction.user.guild_permissions.administrator:
        # Inform users about the giveaway
        #await interaction.response.send_message(f" **Giveaway Time!** \n\nReact with 🎉 to enter!\nPrize: {prize}\nDuration: {duration} seconds")
        try:
            # Function to update command count
            command_name = "giveaway"
            update_command_count(command_name)
        except:
            print("cannot update giveaway Command count")

        # Start the giveaway
        message = await interaction.channel.send(f"🎉 **Giveaway Time!** 🎉\n\nReact with 🎉 to enter!\nPrize: {prize}\nDuration: {duration} seconds")
        await message.add_reaction("🎉")
        try:

            await interaction.followup.send(f"The giveaway for {prize} has started!")

        except Exception as e:
        # Handle any errors that occur during command execution
            await interaction.followup.send(f"An error occurred: {e}")
        # Wait for the duration of the giveaway
        await asyncio.sleep(duration)

        # Fetch the message to get the updated reactions
        message = await interaction.channel.fetch_message(message.id)
        reactions = message.reactions
        users = []
        async for user in reactions[0].users():
            if user != client.user:
                users.append(user)

        # Check if there are participants
        if len(users) > 0:
            # Pick a winner
            winner = random.choice(users)

            # Announce the winner
            await interaction.channel.send(f"🎉 Congratulations {winner.mention}! You won the {prize}! 🎉")
        else:
            await interaction.channel.send("Unfortunately, no one participated in the giveaway. Better luck next time!")
    else:
        await interaction.response.send_message("You don't have permission to start a giveaway.")


@tree.command(name="poll", description="Create a poll with the given question and options.")
async def create_poll(interaction: discord.Interaction, question: str, options: str, time_sec: int):
    
    try:
        # Function to update command count
        command_name = "poll"
        update_command_count(command_name)
    except:
        print("cannot update poll Command count")

    options = options.split(',')  # Split the options string into a list
    option_emojis = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟']  # Emoji options for voting
    option_buttons = {}  # Dictionary to store option buttons
    
    # Create buttons for each option
    for i, option in enumerate(options):
        option_buttons[option_emojis[i]] = option
    
    # Create and send initial poll embed
    embed = discord.Embed(title="> Question: " + question, color=0x00ff00)
    embed.description = "\n".join([f"{emoji} {option}" for emoji, option in option_buttons.items()])
    
    try:
        msg_embed = await interaction.channel.send(embed=embed)
        await interaction.response.send_message("Poll Started", ephemeral=True)
    except discord.Forbidden:
        return await interaction.response.send_message("I don't have permission to send messages in this channel.", ephemeral=True)

    # Add reaction buttons for each option
    for emoji in option_buttons.keys():
        await msg_embed.add_reaction(emoji)
        
    
    # Poll duration (in seconds)
    poll_duration = time_sec  # 10 seconds

    # Wait for reactions
    await asyncio.sleep(poll_duration)

    # Fetch the updated message to get the latest reaction counts
    msg_embed = await interaction.channel.fetch_message(msg_embed.id)
    
    final_description = []
    total_votes = sum(reaction.count - 1 for reaction in msg_embed.reactions)  # Total number of votes
    max_votes = 0
    winners = []  # List to store tied winners

    for line in embed.description.split('\n'):
        emoji, option = line.split(' ', 1)
        reaction = discord.utils.get(msg_embed.reactions, emoji=emoji)
        if reaction:
            vote_count = reaction.count - 1
            vote_percentage = (vote_count / total_votes) * 100 if total_votes > 0 else 0
            final_description.append(f"{emoji} {option} - {vote_count} votes ({vote_percentage:.2f}%)")

            # Track tied winners
            if vote_count >= max_votes:
                if vote_count > max_votes:  # Clear previous winners if a higher vote count is found
                    winners.clear()
                max_votes = vote_count
                winners.append(option)
        else:
            final_description.append(line)

    embed.description = "\n".join(final_description)

    # Declare tied winners or no winner
    if len(winners) > 1:
        embed.add_field(name="> The Poll Ends", value="It's a tie! ", inline=False)
        embed.add_field(name=" Tied Winners:", value=", ".join(winners), inline=False)
    elif winners:
        winner_option = winners[0]
        embed.add_field(name="> The Poll Ends", value=":3g_winner: The Winner: " + "**" + winner_option + "**", inline=False)
    else:
        embed.add_field(name="> The Poll Ends", value="No winner", inline=False)

    await msg_embed.edit(embed=embed)
    
# Add error handling for the command
@create_poll.error
async def create_poll_error(interaction, error):
    if isinstance(error, commands.MissingRequiredArgument):
        await interaction.response.send_message("Please provide a question and options for the poll.")
    else:
        await interaction.response.send_message("An error occurred while creating the poll.")


@tree.command(name="privatemsg", description="Send private message.")
async def send_dm(interaction, member: discord.Member, *, message: str):

    if not interaction.user.guild_permissions.administrator:  # Check administrator permission
        await interaction.response.send_message("You don't have administrator permission to see this command.", ephemeral=True)
        return
    
    await member.send(message)
    await interaction.response.send_message(f" private message sent to {member.mention} ```{message}```", ephemeral=True)
    
    try:
        # Function to update command count
        command_name = "privatemsg"
        update_command_count(command_name)
    except:
        print("cannot update privatemsg Command count")
        
    try:
        guild_id = interaction.guild.id  
        log_channel_id = get_log_channel_id(guild_id) # Continue with your logic using log_channel_id
        log_channel = discord.utils.get(interaction.guild.text_channels, id=log_channel_id)
        if log_channel:
            try:
                embed = discord.Embed(title="> Private Message Sent", color=discord.Color.green())
                embed.add_field(name="**Recipient**", value=member.mention, inline=False)
                embed.add_field(name="**By**", value=interaction.user.mention, inline=False)  # Changed ctx.user to ctx.author
                embed.add_field(name="**Message**", value=f"```{message}```", inline=False)
                embed.timestamp = datetime.now()
                await log_channel.send(embed=embed)
            except discord.errors.HTTPException as e:
                print(f"Failed to send message to log channel: {e}")
    except ValueError:
        pass
    
    

# Connect to SQLite database
con = sqlite3.connect("sticky_messages.db")
cur = con.cursor()
try:
    cur.execute("CREATE TABLE sticky(guild_id, channel_id, message_id, message)")
    print("Created new sticky table for sticky_messages")
except sqlite3.OperationalError:
    print("Found existing table for sticky")

# Command to set up sticky messages
@tree.command(name="stickymsg", description="Send sticky message.")
async def set_up_sticky_messages(ctx, msg_content: str, channel: discord.TextChannel):
    ref = cur.execute(f"""SELECT * FROM sticky WHERE channel_id=?""", (channel.id,))
    ref_fetch = ref.fetchall()

    if ref_fetch:
        return await ctx.response.send_message("You already have a sticky message setup, You have to delete the old sticky message to add new one using `/stopstickymsg`.", ephemeral=True)  # Corrected method

    try:
        msg = await channel.send(msg_content)
    except discord.HTTPException:
        return await ctx.response.send_message("Failed to send sticky message. Please check permissions.", ephemeral=True)  # Corrected method
    
    try:
        # Function to update command count
        command_name = "stickymsg"
        update_command_count(command_name)
    except:
        print("cannot update stickymsg Command count")


    cur.execute(f"""INSERT INTO sticky 
    VALUES (?, ?, ?, ?);""", (ctx.guild.id, channel.id, msg.id, msg_content))
    con.commit()
    await ctx.response.send_message("Created Sticky Message", ephemeral=True)  # Corrected method

    try:
        guild_id = ctx.guild.id  
        log_channel_id = get_log_channel_id(guild_id) # Continue with your logic using log_channel_id
        log_channel = discord.utils.get(ctx.guild.text_channels, id=log_channel_id)
        if log_channel:
            try:
                embed = discord.Embed(description="> **Created Sticky Message**", color=discord.Color.green())
                embed.add_field(name="**By**", value=ctx.user.mention, inline=False)
                embed.add_field(name="**Message**", value=msg_content, inline=False)
                embed.timestamp = datetime.now()
                await log_channel.send(embed=embed)
            except discord.errors.HTTPException as e:
                print(f"Failed to send message to log channel: {e}")
    except ValueError:
        pass
    
    

# Command to stop sticky messages in a channel
@tree.command(name="stopstickymsg", description="Stop sticky message in a channel.")
async def remove_sticky_message(ctx, channel: discord.TextChannel):
    # Fetch the message ID associated with the channel
    cur.execute("SELECT message_id FROM sticky WHERE channel_id=?", (channel.id,))
    result = cur.fetchone()
    try:
        # Function to update command count
        command_name = "stopstickymsg"
        update_command_count(command_name)
    except:
        print("cannot update stopstickymsg Command count")

    if result:
        message_id = result[0]
        try:
            # Fetch the channel and delete the message
            channel_obj = await client.fetch_channel(channel.id)
            message = await channel_obj.fetch_message(message_id)
            await message.delete()
        except discord.NotFound:
            pass  # Message already deleted or not found
        
        # Remove the record from the database
        cur.execute("DELETE FROM sticky WHERE channel_id=?", (channel.id,))
        con.commit()
        
        await ctx.response.send_message("Sticky message removed from the channel", ephemeral=True)
        
        try:
            guild_id = ctx.guild.id  
            log_channel_id = get_log_channel_id(guild_id) # Continue with your logic using log_channel_id
            log_channel = discord.utils.get(ctx.guild.text_channels, id=log_channel_id)
            if log_channel:
                try:
                    embed = discord.Embed(description="> **Sticky message removed**", color=discord.Color.green())
                    embed.add_field(name="**By**", value=ctx.user.mention, inline=False)
                    embed.add_field(name="**channel**", value=channel, inline=False)
                    embed.timestamp = datetime.now()
                    await log_channel.send(embed=embed)
                except discord.errors.HTTPException as e:
                    print(f"Failed to send message to log channel: {e}")
        except ValueError:
            pass
        
        
    else:
        await ctx.response.send_message("No sticky message found for the channel")

# Event handler for message events
@client.event
async def on_message(msg):
    ref = cur.execute(f"""SELECT * FROM sticky WHERE channel_id=?""", (msg.channel.id,))
    ref_fetch = ref.fetchall()

    if not ref_fetch:
        return

    channel_id = ref_fetch[0][1]
    message_id = ref_fetch[0][2]
    message_content = ref_fetch[0][3]

    try:
        channel = await client.fetch_channel(channel_id)
        message = await channel.fetch_message(message_id)
    except discord.errors.NotFound:
        #print("Message not found. It might have been deleted.")
        # Handle the error here, such as updating the database or logging the event.
        return

    await message.delete()
    try:
        new_msg = await channel.send(message_content)
    except discord.HTTPException:
        print("Failed to send new sticky message. Please check permissions.")
        return

    cur.execute("UPDATE sticky SET message_id = ? WHERE channel_id= ?", (new_msg.id, channel_id))
    con.commit()


# Event data structure (could be a class for richer features)
events = {}  # {user_id: [event1, event2, ...]}

@tasks.loop(minutes=1)  # Check for reminders every minute
async def check_reminders():
    for user_id, user_events in events.items():
        for event in user_events:
            if event['datetime'] <= datetime.utcnow() + timedelta(minutes=15):
                user = client.get_user(user_id)
                if user:
                    await user.send(f"Reminder: Event '{event['title']}' starts in 15 minutes!")
                # Remove reminded event if desired
                # user_events.remove(event)

# Event data structure (could be a class for richer features)
events = {}  # {user_id: [event1, event2, ...]}

@tasks.loop(minutes=1)  # Check for reminders every minute
async def check_reminders():
    """
    Checks for upcoming events and sends reminders 15 minutes before.

    Handles potential errors and logs them for debugging.
    """

    for user_id, user_events in events.items():
        for event in user_events:
            if event['datetime'] <= datetime.utcnow() + timedelta(minutes=15):
                try:
                    user = client.get_user(user_id)
                    if user:
                        await user.send(f"Reminder: Event '{event['title']}' starts in 15 minutes!")
                        # Remove reminded event if desired (e.g., user_events.remove(event))
                except discord.HTTPException as e:
                    print(f"Error sending reminder to user {user_id}: {e}")



# Connect to SQLite database
conn = sqlite3.connect('events.db')
c = conn.cursor()

# Create events table if not exists
c.execute('''CREATE TABLE IF NOT EXISTS events
             (server_name TEXT, user_id INTEGER, title TEXT, year INTEGER, month INTEGER, day INTEGER, hour INTEGER, minute INTEGER)''')
conn.commit()


@tree.command(name="addevent", description="Add a new event to the calendar.")
async def add_event(context, title: str, year: int, month: int, day: int, hour: int = None , minute: int = None):
    try:
        # Check if any of the required arguments are None
        if None in (year, month, day):
            if isinstance(context, discord.Interaction):
                await context.response.send_message("Please provide a valid date.", ephemeral=True)
            else:
                await context.send("Please provide a valid date.", ephemeral=True)
            return
        try:
            # Function to update command count
            command_name = "addevent"
            update_command_count(command_name)
        except:
            print("cannot update addevent Command count")

        # Check if hour and minute are provided, if not set them to 0
        hour = hour or 0
        minute = minute or 0

        conn = sqlite3.connect('events.db')
        c = conn.cursor()
        # Insert the event into the database
        c.execute("INSERT INTO events (user_id, title, year, month, day, hour, minute) VALUES (?, ?, ?, ?, ?, ?, ?)",
                  (context.user.id, title, year, month, day, hour, minute))
        conn.commit()
        
        if isinstance(context, discord.Interaction):
            await context.response.send_message(f"Event '{title}' added successfully!", ephemeral=True)
        else:
            await context.send(f"Event '{title}' added successfully!", ephemeral=True)
        
        # Retrieve the event from the database
        c.execute("SELECT * FROM events WHERE user_id = ? AND title = ?", (context.user.id, title))
        event = c.fetchone()
        
       
    except (ValueError, IndexError):
        if isinstance(context, discord.Interaction):
            await context.response.send_message("Invalid add command format. Use '!addevent <title> <year> <month> <day> [<hour> <minute>]'.", ephemeral=True)
        else:
            await context.send("Invalid add command format. Use '!addevent <title> <year> <month> <day> [<hour> <minute>]'.", ephemeral=True)


# Command to remove an event
@tree.command(name="removeevent", description="Remove an event from the calendar.")
async def remove_event(context, title: str):
    try:
        # Function to update command count
        command_name = "removeevent"
        update_command_count(command_name)
    except:
        print("cannot update removeevent Command count")

    # Check if the context is an Interaction
    if isinstance(context, discord.Interaction):
        # Retrieve the user ID from the interaction
        user_id = context.user.id
    else:
        # For backward compatibility with Message context
        user_id = context.author.id

    # Delete event from SQLite database
    conn = sqlite3.connect('events.db')
    c = conn.cursor()
    c.execute("DELETE FROM events WHERE user_id = ? AND title = ?", (user_id, title))
    conn.commit()

    # Send a response based on the context
    if isinstance(context, discord.Interaction):
        await context.response.send_message(f"Event '{title}' removed successfully!", ephemeral=True)
    else:
        await context.channel.send(f"Event '{title}' removed successfully!", ephemeral=True)


# Command to view events
@tree.command(name="viewevents", description="View all your events.")
async def view_events(context):
    try:
        # Function to update command count
        command_name = "viewevents"
        update_command_count(command_name)
    except:
        print("cannot update viewevents Command count")

    # Check if the context is an Interaction
    if isinstance(context, discord.Interaction):
        # Retrieve the user ID from the interaction
        user_id = context.user.id
    else:
        # For backward compatibility with Message context
        user_id = context.author.id

    # Retrieve events from SQLite database
    conn = sqlite3.connect('events.db')
    c = conn.cursor()
    c.execute("SELECT * FROM events WHERE user_id = ? ORDER BY year, month, day, hour, minute", (user_id,))
    user_events = c.fetchall()
    
    if not user_events:
        if isinstance(context, discord.Interaction):
            # Send a message using interaction's response
            await context.response.send_message("You don't have any events in your calendar.", ephemeral=True)
        else:
            # Send a message using context
            await context.send("You don't have any events in your calendar.", ephemeral=True)
        return
    
    # Create an embed object
    embed = discord.Embed(title="Your Upcoming Events ", color=0xffd700)  # Set the color to gold
    
    # Create a dictionary to store events grouped by date
    events_by_date = {}

    # Group events by date
    for event in user_events:
        # Extract event details
        title, year, month, day, hour, minute = event[1:7]
        event_date = (year, month, day)

        # Combine event details into one string
        event_info = f" ```{title}```"

        # Add event to the dictionary based on its date
        if event_date in events_by_date:
            events_by_date[event_date].append((hour, minute, event_info))
        else:
            events_by_date[event_date] = [(hour, minute, event_info)]

    # Create fields for each date group
    for event_date, event_infos in events_by_date.items():
        datetime_str = datetime(*event_date).strftime("%Y-%m-%d")
        event_info_str = "\n".join([f"`{hour:02d}:{minute:02d}` {event_info}" for hour, minute, event_info in event_infos])
        embed.add_field(name=f"> :calendar_spiral: {datetime_str}", value=event_info_str + "\n\u200b", inline=False)

    # Send the embed
    if isinstance(context, discord.Interaction):
        await context.response.send_message(embed=embed)
    else:
        await context.send(embed=embed)



# Connect to SQLite database
conn = sqlite3.connect('social_accounts.db')
c = conn.cursor()

# Create table if it doesn't exist
# Update the SQLite table creation query to include user_id and user_name
c.execute('''CREATE TABLE IF NOT EXISTS social_accounts
             (user_id INTEGER PRIMARY KEY,
             user_name TEXT,
             twitter TEXT, 
             insta TEXT, 
             twitch TEXT, 
             snapchat TEXT, 
             tiktok TEXT, 
             youtube TEXT,
             facebook TEXT, 
             telegram TEXT, 
             linkedin TEXT, 
             kick TEXT)''')
conn.commit()

# Update the commands to include user_id and user_name
@tree.command(name="addsocial", description="Add social account.")
async def social(interaction: discord.Interaction,
                 twitter: typing.Optional[str] = None,
                 insta: typing.Optional[str] = None,
                 twitch: typing.Optional[str] = None,
                 snapchat: typing.Optional[str] = None,
                 tiktok: typing.Optional[str] = None,
                 youtube: typing.Optional[str] = None,
                 facebook: typing.Optional[str] = None,
                 telegram: typing.Optional[str] = None,
                 linkedin: typing.Optional[str] = None,
                 kick: typing.Optional[str] = None):
    
    try:
        # Function to update command count
        command_name = "addsocial"
        update_command_count(command_name)
    except:
        print("cannot update addsocial Command count")

    user_id = interaction.user.id
    user_name = interaction.user.name
    conn = sqlite3.connect('social_accounts.db')
    c = conn.cursor()
    # Update or insert social account data into the database
    c.execute('''INSERT OR REPLACE INTO social_accounts 
                 (user_id, user_name, twitter, insta, twitch, 
                 snapchat, tiktok, youtube, facebook, telegram, linkedin, kick)
                 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''',
              (user_id,
               user_name,
               twitter if twitter else None,
               insta if insta else None,
               twitch if twitch else None,
               snapchat if snapchat else None,
               tiktok if tiktok else None,
               youtube if youtube else None,
               facebook if facebook else None,
               telegram if telegram else None,
               linkedin if linkedin else None,
               kick if kick else None))
    conn.commit()

    await interaction.response.send_message("Social account data saved successfully.", ephemeral=True)


@tree.command(name="social", description="Show social accounts.")
async def show_social(interaction: discord.Interaction, user: typing.Optional[discord.User] = None):
    
    try:
        # Function to update command count
        command_name = "social"
        update_command_count(command_name)
    except:
        print("cannot update social Command count")


    if not user:
        user = interaction.user

    user_id = user.id
    conn = sqlite3.connect('social_accounts.db')
    c = conn.cursor()

    # Retrieve social account data from the database for the specified user
    c.execute('''SELECT user_name, twitter, insta, twitch, snapchat, tiktok, youtube, facebook, telegram, linkedin, kick
                 FROM social_accounts WHERE user_id = ?''', (user_id,))
    row = c.fetchone()

    if row:
        user_name, twitter, insta, twitch, snapchat, tiktok, youtube, facebook, telegram, linkedin, kick = row

        # Initialize an empty list to store fields for the embed
        fields = []

        # Add fields for social accounts with values
        if twitter:
            fields.append(("> **Twitter**", twitter))
        if insta:
            fields.append(("> **Instagram**", insta))
        if snapchat:
            fields.append(("> **Snapchat**", snapchat))
        if tiktok:
            fields.append(("> **TikTok**", tiktok))
        if facebook:
            fields.append(("> **Facebook**", facebook))
        if telegram:
            fields.append(("> **Telegram**", telegram))
        if linkedin:
            fields.append(("> **LinkedIn**", linkedin))
        if youtube:
            fields.append(("> **YouTube**", youtube))
        if twitch:
            fields.append(("> **Twitch**", twitch))
        if kick:
            fields.append(("> **Kick**", kick))

        # Check if any fields were added
        if fields:
            # Create an embed message
            embed = discord.Embed(title=f"Social Accounts for {user_name}", color=discord.Color.blue())

            # Add fields to the embed
            for name, value in fields:
                embed.add_field(name=name, value=value, inline=False)

            await interaction.response.send_message(embed=embed)
        else:
            embed = discord.Embed(title=f"No social account data found for {user_name}.", color=discord.Color.blue())
            await interaction.response.send_message(embed=embed)
    else:
        embed = discord.Embed(title=f"No social account data found for this user.", color=discord.Color.blue())
        await interaction.response.send_message(embed=embed)


@tree.command(name="passgen", description="Generate a strong password.")
async def generate_password(interaction: discord.Interaction, length: int = 12, count: int = 1, lowercase: bool = True, uppercase: bool = True, symbols: bool = True, numbers: bool = True):

    if count > 5:
        await interaction.response.send_message("Please request 5 passwords or fewer at a time.", ephemeral=True)
        return
    try:
        # Function to update command count
        command_name = "passgen"
        update_command_count(command_name)
    except:
        print("cannot update passgen Command count")

    # Define character sets based on options
    charset = ''
    if lowercase:
        charset += string.ascii_lowercase
    if uppercase:
        charset += string.ascii_uppercase
    if symbols:
        charset += string.punctuation
    if numbers:
        charset += string.digits

    if not charset:
        await interaction.response.send_message("Please enable at least one character set option.", ephemeral=True)
        return

    passwords = []
    for _ in range(count):
        password = ''.join(random.choices(charset, k=length))
        passwords.append(password)

    response = '\n'.join(passwords)
    await interaction.user.send(f'Here are {count} passwords with {length} characters each:\n```{response}```')
    await interaction.response.send_message("Password Sent to DM.", ephemeral=True)


@tree.command(name="shorturl", description="Create a short URL.")
async def shorten_url(ctx: commands.Context, url: str):
    """Shorten a URL using tinyurl.com."""
    try:
        # Function to update command count
        command_name = "shorturl"
        update_command_count(command_name)
    except:
        print("cannot update shorturl Command count")

    try:
        response = requests.get(f'http://tinyurl.com/api-create.php?url={url}')
        short_url = response.text
        await ctx.response.send_message(f'Shortened URL: {short_url}')
    except Exception as e:
        await ctx.response.send_message(f'Error: {e}')


@tree.command(name="about", description="About TamozaBot.")
async def about(interaction):
    try:
        # Function to update command count
        command_name = "about"
        update_command_count(command_name)
    except:
        print("cannot update about Command count")

    x_link = "https://x.com/Tamoza04"
    guild_count = len(client.guilds)

    embed = discord.Embed(title="> About TamozaBot", description="TamozaBot is a Discord bot created by Tamoza using Python. It provides various features and functionalities to enhance your Discord server experience.", color=0x00ff00)
    embed.add_field(name="Current Guilds", value=f"TamozaBot is currently in {guild_count} servers.", inline=False)
    embed.add_field(name="Beta Status", value="TamozaBot is currently in beta.", inline=False)
    embed.add_field(name="Contact", value=f"If you need any help, you can contact me on [X]({x_link}).", inline=False)

    await interaction.response.send_message(embed=embed)


@tree.command(name="invite", description="Invite link for TamozaBot.")
async def invite(interaction):
    try:
        # Function to update command count
        command_name = "invite"
        update_command_count(command_name)
    except:
        print("cannot update invite Command count")

    
    embed = discord.Embed(title="Invite TamozaBot", description="Click the button below to add TamozaBot to your server!", color=0x00ff00)
    embed.add_field(name="Invite Link", value=f"[Click here to invite TamozaBot]({invite_link})", inline=False)

    await interaction.response.send_message(embed=embed)




@client.event
async def on_shutdown():
    conn.close()



client.run(bot_token)