225 lines
8.4 KiB
Python
Executable File
225 lines
8.4 KiB
Python
Executable File
import datetime
|
|
import time
|
|
import os
|
|
import discord
|
|
from discord.ext import commands
|
|
|
|
|
|
async def reload_all(client, ctx):
|
|
"""
|
|
Reloads all cogs (modules) in the 'cogs' folder and syncs the command tree.
|
|
|
|
Args:
|
|
client (discord.Client): The bot's main client object.
|
|
ctx (commands.Context): The context in which the command was invoked.
|
|
"""
|
|
cogs_folder = os.path.abspath(os.path.dirname(__file__)) # Get the cogs folder path
|
|
for filename in os.listdir(cogs_folder):
|
|
if filename.endswith(".py"):
|
|
try:
|
|
await client.reload_extension(f"cogs.{filename[:-3]}")
|
|
except Exception as e:
|
|
print(f"Error reloading {filename}: {e}")
|
|
await client.load_extension(f"cogs.{filename[:-3]}")
|
|
await client.tree.sync() # Synchronize command tree
|
|
await ctx.reply("Reloaded all cogs.")
|
|
|
|
|
|
class Admin(commands.Cog):
|
|
"""Cog that provides administrative commands for bot control and information."""
|
|
|
|
def __init__(self, client):
|
|
self.client = client
|
|
|
|
@commands.command(
|
|
name="ping",
|
|
brief="Bot Latency",
|
|
description="Displays the bot's latency in milliseconds.",
|
|
)
|
|
async def _ping(self, ctx):
|
|
"""
|
|
Responds with the bot's latency (ping time).
|
|
|
|
Args:
|
|
ctx (commands.Context): The context in which the command was invoked.
|
|
"""
|
|
latency = round(self.client.latency * 1000, 2) # Convert to ms
|
|
await ctx.reply(f"Pong! 🏓\nLatency: {latency}ms")
|
|
|
|
@commands.command(
|
|
name="info",
|
|
brief="Bot Info",
|
|
description="Provides information about the bot's owner and team (if applicable).",
|
|
)
|
|
async def _info(self, ctx):
|
|
"""
|
|
Displays information about the bot's owner or team members.
|
|
|
|
Args:
|
|
ctx (commands.Context): The context in which the command was invoked.
|
|
"""
|
|
app_info = await self.client.application_info()
|
|
if app_info.team:
|
|
team_members = "\n".join(
|
|
f"{member.name}#{member.discriminator} ({'Owner' if member.id == app_info.team.owner_id else 'Member'})"
|
|
for member in app_info.team.members
|
|
)
|
|
await ctx.reply(
|
|
f"Bot is part of the team: {app_info.team.name}\nMembers:\n{team_members}"
|
|
)
|
|
else:
|
|
await ctx.reply(
|
|
f"Bot is owned by {app_info.owner} and is not part of a team."
|
|
)
|
|
|
|
@commands.command(
|
|
name="uptime",
|
|
brief="Bot Runtime",
|
|
description="Displays how long the bot has been running since its last restart.",
|
|
)
|
|
async def _uptime(self, ctx):
|
|
"""
|
|
Calculates and sends the bot's uptime based on a start timestamp.
|
|
|
|
Args:
|
|
ctx (commands.Context): The context in which the command was invoked.
|
|
"""
|
|
with open("time.txt", "r") as file:
|
|
start_time = float(file.read())
|
|
uptime = str(
|
|
datetime.timedelta(seconds=int(time.time() - start_time))
|
|
) # Calculate uptime
|
|
await ctx.send(f"Uptime: {uptime}")
|
|
|
|
@commands.hybrid_command(
|
|
name="reload",
|
|
brief="Reload Cog",
|
|
description="Reloads a specific cog or all cogs.",
|
|
aliases=["rl"],
|
|
)
|
|
@commands.is_owner()
|
|
async def _reload(self, ctx, extension: str):
|
|
"""
|
|
Reloads a specified cog/module or all modules if 'all' is passed.
|
|
|
|
Args:
|
|
ctx (commands.Context): The context in which the command was invoked.
|
|
extension (str): Name of the cog to reload, or 'all' to reload all cogs.
|
|
"""
|
|
if extension.lower() == "all":
|
|
await reload_all(self.client, ctx)
|
|
return
|
|
try:
|
|
await self.client.unload_extension(f"cogs.{extension}")
|
|
await self.client.load_extension(f"cogs.{extension}")
|
|
await ctx.send(f"Successfully reloaded {extension}.")
|
|
except commands.ExtensionNotLoaded:
|
|
await ctx.send(f"Extension {extension} was not loaded, loading it now.")
|
|
try:
|
|
await self.client.load_extension(f"cogs.{extension}")
|
|
await ctx.send(f"Successfully loaded {extension}.")
|
|
except Exception as e:
|
|
await ctx.send(f"Failed to load {extension}: {e}")
|
|
except commands.ExtensionNotFound:
|
|
await ctx.send(f"Extension {extension} was not found.")
|
|
except Exception as e:
|
|
await ctx.send(f"Failed to reload {extension}: {e}")
|
|
|
|
@commands.hybrid_command(
|
|
name="purge",
|
|
brief="Delete messages",
|
|
description="Deletes a specified number of messages from the current channel (default: 100).",
|
|
)
|
|
@commands.has_permissions(manage_channels=True)
|
|
@commands.cooldown(1, 10, commands.BucketType.user)
|
|
async def _purge(self, ctx, n: int = 100):
|
|
"""
|
|
Deletes a specified number of messages from the current channel.
|
|
|
|
Args:
|
|
ctx (commands.Context): The context in which the command was invoked.
|
|
n (int, optional): The number of messages to delete. Defaults to 100.
|
|
"""
|
|
n += 1
|
|
if n <= 0:
|
|
return
|
|
if n < 100:
|
|
await ctx.channel.purge(limit=n)
|
|
await ctx.channel.send(
|
|
f"Successfully purged last {n-1} messages", delete_after=2
|
|
)
|
|
elif n == 100:
|
|
await ctx.channel.purge()
|
|
await ctx.channel.send(
|
|
"Successfully purged last 100 messages", delete_after=2
|
|
)
|
|
else: # n > 100
|
|
for i in range(n // 100):
|
|
await ctx.channel.purge()
|
|
await ctx.channel.purge(limit=n % 100)
|
|
await ctx.channel.send(
|
|
f"Successfully purged last {n-1} messages", delete_after=2
|
|
)
|
|
|
|
@commands.hybrid_command(
|
|
name="nuke",
|
|
brief="Clear channel",
|
|
description="Deletes all messages by duplicating and deleting the channel.",
|
|
)
|
|
@commands.has_permissions(manage_channels=True)
|
|
@commands.cooldown(1, 30, commands.BucketType.user)
|
|
async def _nuke(self, ctx, channel_name: str = "Current"):
|
|
"""
|
|
Duplicates and deletes a specified channel (or the current channel) to clear messages.
|
|
|
|
Args:
|
|
ctx (commands.Context): The context in which the command was invoked.
|
|
channel_name (str, optional): Name of the channel to nuke. Defaults to 'Current' (the invoking channel).
|
|
"""
|
|
# Determine the channel ID based on the channel_name parameter
|
|
if channel_name.lower() == "current":
|
|
channel_id = ctx.channel.id
|
|
else:
|
|
channel_id = discord.utils.get(ctx.guild.channels, name=channel_name)
|
|
if channel_id is None:
|
|
return await ctx.send(f"Channel **{channel_name}** was not found.")
|
|
|
|
existing_channel = self.client.get_channel(channel_id)
|
|
if existing_channel:
|
|
await existing_channel.clone(reason="Channel has been nuked")
|
|
await existing_channel.delete()
|
|
await self._send_embed(
|
|
ctx,
|
|
f"Channel **{existing_channel.name}** has been nuked.",
|
|
discord.Color.red(),
|
|
)
|
|
else:
|
|
await ctx.send(f"No channel with ID {channel_id} was found.")
|
|
|
|
@commands.command(
|
|
name="guildids",
|
|
brief="List all guild IDs",
|
|
description="Lists all guild IDs the bot is currently in. Owner only.",
|
|
)
|
|
@commands.is_owner()
|
|
async def _guildids(self, ctx):
|
|
"""
|
|
Sends a list of all guild IDs the bot is in to the owner.
|
|
|
|
Args:
|
|
ctx (commands.Context): The context in which the command was invoked.
|
|
"""
|
|
guild_ids = [str(guild.id) for guild in self.client.guilds]
|
|
guilds_str = "\n".join(guild_ids)
|
|
await ctx.author.send(f"Guild IDs:\n{guilds_str}")
|
|
await ctx.reply("Sent you a DM with all guild IDs.")
|
|
|
|
async def _send_embed(self, ctx, description, color=discord.Color.blurple()):
|
|
embed = discord.Embed(description=description, color=color)
|
|
await ctx.send(embed=embed)
|
|
|
|
|
|
async def setup(client):
|
|
"""Sets up the Admin cog for the bot."""
|
|
await client.add_cog(Admin(client))
|