Compare commits

...

2 Commits

52 changed files with 386 additions and 157 deletions

View File

@@ -19,6 +19,11 @@ LAVALINK_PORT=13592
EMOJI_SYNC=false
JISHAKU_ENABLED=false
# Slash (/) command sync — guild sync makes commands appear immediately
SLASH_SYNC_GLOBAL=true
SLASH_SYNC_ALL_GUILDS=true
# SLASH_GUILD_IDS=
# Traefik (optional override — default in compose: letsencrypt)
# TRAEFIK_CERT_RESOLVER=letsencrypt

View File

@@ -27,8 +27,11 @@ LAVALINK_PASSWORD="youshallnotpass"
LAVALINK_SECURE="false"
LAVALINK_PORT="13592"
# ── Emoji Sync ────────────────────────────────────────────────────────────────
EMOJI_SYNC="false"
SLASH_SYNC_GLOBAL=true
# Instant / commands in every connected server (set false if you have many guilds and hit rate limits)
SLASH_SYNC_ALL_GUILDS=true
# Or limit instant sync to specific guild IDs (comma-separated). Overrides ALL_GUILDS when set.
# SLASH_GUILD_IDS=
# ── API / Dashboard Backend ───────────────────────────────────────────────────
API_ENABLED="false"

View File

@@ -33,6 +33,7 @@ from utils.Tools import *
from utils.config import *
from utils.emoji import SUCCESS, ERROR, TICK, CROSS, REACTION_TEST_EMOJIS
from utils.sync_emojis import run_sync
from utils.slash_sync import sync_slash_commands
import cogs
@@ -99,21 +100,28 @@ async def on_ready():
# Sync application emojis on startup
await run_sync(TOKEN)
async def sync_commands():
# Register / slash commands (guild sync = instant; global can take up to ~1h)
if not getattr(client, "_slash_synced", False):
client._slash_synced = True
try:
synced = await client.tree.sync()
all_commands = list(client.commands)
print(f"Synced Total {len(all_commands)} Client Commands and {len(synced)} Slash Commands")
await sync_slash_commands(client)
except Exception as e:
print(f"Error syncing command tree: {e}")
print(f"\033[31mError syncing command tree: {e}\033[0m")
client.loop.create_task(sync_commands())
if SERVER_COUNT_CHANNEL_ID or USER_COUNT_CHANNEL_ID:
client.loop.create_task(update_stats())
@client.event
async def on_guild_join(guild: discord.Guild):
# Instant slash commands in the new server
try:
from utils.slash_sync import sync_guild
synced = await sync_guild(client, guild, copy_global=True)
print(f"◈ Slash sync for new guild {guild.id}: {len(synced)} command(s)")
except Exception as e:
print(f"Slash sync on guild join failed: {e}")
if not LOG_CHANNEL_ID:
return
log_channel = client.get_channel(LOG_CHANNEL_ID)
@@ -155,7 +163,7 @@ async def on_command_completion(context: commands.Context) -> None:
# --- Utility Commands ---
@client.command(name='spotify')
@client.hybrid_command(name='spotify')
async def spotify(ctx: Context, user: discord.Member = None):
"""Shows what a user is listening to on Spotify."""
user = user or ctx.author
@@ -176,7 +184,7 @@ async def spotify(ctx: Context, user: discord.Member = None):
await ctx.send(embed=embed)
@client.command(name='makeinvite', aliases=['createinvite', 'makeinv'])
@client.hybrid_command(name='makeinvite', aliases=['createinvite', 'makeinv'])
@commands.is_owner()
async def make_invite(ctx: Context, guild_id: int = None):
"""Creates an invite for a specified server (owner only)."""
@@ -206,7 +214,7 @@ async def make_invite(ctx: Context, guild_id: int = None):
# --- Webhook Management Commands ---
@client.command(name='create_hook', aliases=['makehook'])
@client.hybrid_command(name='create_hook', aliases=['makehook'])
@commands.has_permissions(administrator=True)
async def create_hook(ctx: Context, *, name: str = None):
"""Creates a webhook in the current channel."""
@@ -228,7 +236,7 @@ async def create_hook(ctx: Context, *, name: str = None):
await ctx.send(f"Webhook created: **{webhook.name}**\n||{webhook.url}||\n(I could not DM you the URL.)")
@client.command(name='delete_hook', aliases=['delhook'])
@client.hybrid_command(name='delete_hook', aliases=['delhook'])
@commands.has_permissions(administrator=True)
async def delete_hook(ctx: Context, webhook_url: str = None):
"""Deletes a webhook using its URL."""
@@ -244,7 +252,7 @@ async def delete_hook(ctx: Context, webhook_url: str = None):
await ctx.send(f"{ERROR} Webhook not found or URL is invalid.")
@client.command(name='list_hooks', aliases=['hooks'])
@client.hybrid_command(name='list_hooks', aliases=['hooks'])
@commands.has_permissions(administrator=True)
async def list_hooks(ctx: Context):
"""Lists all webhooks in the current channel."""
@@ -262,7 +270,7 @@ async def list_hooks(ctx: Context):
# --- Game Command ---
@client.command()
@client.hybrid_command()
async def reaction(ctx: Context):
"""See how fast you can react to the correct emoji."""
emojis = ["🍪", "🎉", "🧋", "🍒", "🍑", "💸", "🌙", "💕"]

View File

@@ -50,7 +50,7 @@ class Birthdays(commands.Cog):
self.client = client
self.check_birthdays.start()
@commands.command(
@commands.hybrid_command(
name="birthdaysetup",
help="Set up the birthday log channel and role.")
@commands.has_permissions(administrator=True)
@@ -69,7 +69,7 @@ class Birthdays(commands.Cog):
await ctx.send(view=CV2("Birthday Setup", f"Birthday log channel set to {channel.mention} and birthday role set to {role.mention}."))
@commands.command(
@commands.hybrid_command(
name="setbirthday",
help="Set your birthday.")
@commands.guild_only()
@@ -112,7 +112,7 @@ class Birthdays(commands.Cog):
except asyncio.TimeoutError:
await ctx.send(view=CV2("Error", "You took too long to respond. Please try again."))
@commands.command(
@commands.hybrid_command(
name="removebirthday",
help="Remove your birthday.")
@commands.guild_only()
@@ -126,7 +126,7 @@ class Birthdays(commands.Cog):
else:
await ctx.send(view=CV2("Error", "You have no birthday set."))
@commands.command(
@commands.hybrid_command(
name="listbirthdays",
help="List all members who have their birthday today.")
@commands.guild_only()
@@ -143,7 +143,7 @@ class Birthdays(commands.Cog):
else:
await ctx.send(view=CV2("Birthdays", "No birthdays today."))
@commands.command(
@commands.hybrid_command(
name="birthday",
help="Check your birthday.")
@commands.guild_only()

View File

@@ -144,7 +144,7 @@ class Games(Cog):
game = btn.BetaBattleShip(player1=ctx.author, player2=player)
await game.start(ctx)
@commands.group(name="country-guesser",
@commands.hybrid_group(name="country-guesser",
help="Guess name of the country by flag.",
aliases=["guess", "guesser", "countryguesser"],
usage="country-guesser")

View File

@@ -36,7 +36,7 @@ class Invcrole(commands.Cog):
''')
await db.commit()
@commands.group(name='vcrole', help="Vcrole Setup commands", invoke_without_command=True)
@commands.hybrid_group(name='vcrole', help="Vcrole Setup commands", invoke_without_command=True)
@blacklist_check()
@ignore_check()
@commands.has_permissions(administrator=True)

View File

@@ -52,7 +52,7 @@ class AutoReaction(commands.Cog):
cursor = await db.execute("SELECT 1 FROM autoreact WHERE guild_id = ? AND trigger = ?", (guild_id, trigger))
return await cursor.fetchone()
@commands.group(name="react", aliases=["autoreact"], help="Lists all subcommands of autoreact group.", invoke_without_command=True)
@commands.hybrid_group(name="react", aliases=["autoreact"], help="Lists all subcommands of autoreact group.", invoke_without_command=True)
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 4, commands.BucketType.user)

View File

@@ -46,7 +46,7 @@ class AutoResponder(commands.Cog):
''')
await db.commit()
@commands.group(name="autoresponder", invoke_without_command=True, aliases=['ar'], help="Manage autoresponders in the server.")
@commands.hybrid_group(name="autoresponder", invoke_without_command=True, aliases=['ar'], help="Manage autoresponders in the server.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 5, commands.BucketType.user)

View File

@@ -92,7 +92,7 @@ class AutoRole(commands.Cog):
@commands.group(name="autorole", invoke_without_command=True)
@commands.hybrid_group(name="autorole", invoke_without_command=True)
@commands.cooldown(1, 5, commands.BucketType.user)
@commands.max_concurrency(1, per=commands.BucketType.default, wait=False)
@commands.guild_only()

View File

@@ -123,7 +123,7 @@ class Blackjack(commands.Cog):
total_sum += 1
return total_sum
@commands.command(aliases=['bj', 'blackjacks'], help="Play a simple game of blackjack.", usage="blackjack")
@commands.hybrid_command(aliases=['bj', 'blackjacks'], help="Play a simple game of blackjack.", usage="blackjack")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)

View File

@@ -207,7 +207,7 @@ class Blacklist(commands.Cog):
await warning_message.delete(delay=3)
break
@commands.group(name="blacklistword", aliases=["blword"], invoke_without_command=True)
@commands.hybrid_group(name="blacklistword", aliases=["blword"], invoke_without_command=True)
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)

View File

@@ -54,7 +54,7 @@ class Block(commands.Cog):
@commands.group(name="blacklist", aliases=["bl"], invoke_without_command=True)
@commands.hybrid_group(name="blacklist", aliases=["bl"], invoke_without_command=True)
@commands.is_owner()
async def blacklist(self, ctx):
if ctx.subcommand_passed is None:

View File

@@ -122,7 +122,7 @@ class calculator(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.command(name='calculator', help='Starts a calculator session', aliases=['calc', 'calculate', 'math'])
@commands.hybrid_command(name='calculator', help='Starts a calculator session', aliases=['calc', 'calculate', 'math'])
async def calculator(self, ctx):
"""Starts a new calculator session."""
# Ensure we pass the author to the view so it knows who triggered it

View File

@@ -74,7 +74,7 @@ class Counting(commands.Cog):
"**counting stats** — View current counting stats"
))
@commands.group(name="counting", invoke_without_command=True)
@commands.hybrid_group(name="counting", invoke_without_command=True)
async def counting(self, ctx):
if not self.is_enabled(ctx.guild.id):
await self.not_enabled_embed(ctx)

View File

@@ -81,7 +81,7 @@ class StaffDMCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.command(name="dmstaff")
@commands.hybrid_command(name="dmstaff")
async def dm_staff(self, ctx, member: discord.Member, *, message: str):
if ctx.author.id not in STAFF_IDS:
view = PermissionErrorView()

View File

@@ -406,7 +406,7 @@ class Emergency(commands.Cog):
) as cursor:
return await cursor.fetchone() is not None
@commands.group(name="emergency", aliases=["emg"], invoke_without_command=True)
@commands.hybrid_group(name="emergency", aliases=["emg"], invoke_without_command=True)
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 4, commands.BucketType.user)
@@ -614,7 +614,7 @@ class Emergency(commands.Cog):
roles = await cursor.fetchall()
await ctx.reply(view=RoleListView(roles, is_auth))
@commands.command(name="emergencysituation", aliases=["emgs"])
@commands.hybrid_command(name="emergencysituation", aliases=["emgs"])
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 40, commands.BucketType.user)
@@ -736,7 +736,7 @@ class Emergency(commands.Cog):
await anti.commit()
await proc_msg.delete()
@commands.command(name="emergencyrestore", aliases=["emgrestore"])
@commands.hybrid_command(name="emergencyrestore", aliases=["emgrestore"])
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 30, commands.BucketType.user)

View File

@@ -88,12 +88,12 @@ class encryption(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.group(invoke_without_command=True)
@commands.hybrid_group(invoke_without_command=True)
async def encode(self, ctx):
"""All encode methods"""
await ctx.send_help(ctx.command)
@commands.group(invoke_without_command=True)
@commands.hybrid_group(invoke_without_command=True)
async def decode(self, ctx):
"""All decode methods"""
await ctx.send_help(ctx.command)
@@ -204,7 +204,7 @@ class encryption(commands.Cog):
except Exception:
await ctx.send(view=DecodeErrorView("ASCII85"))
@commands.command(name="password")
@commands.hybrid_command(name="password")
async def password(self, ctx):
"""Generates a random secure password for you"""
if hasattr(ctx, "guild") and ctx.guild is not None:

View File

@@ -197,7 +197,7 @@ class Extra(commands.Cog):
@commands.command(name="uptime", description="Shows the Bot's Uptime.")
@commands.hybrid_command(name="uptime", description="Shows the Bot's Uptime.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -447,7 +447,7 @@ class Extra(commands.Cog):
@commands.command(name="boostcount",
@commands.hybrid_command(name="boostcount",
help="Shows boosts count",
usage="boosts",
aliases=["bco"],
@@ -788,7 +788,7 @@ class Extra(commands.Cog):
@commands.command(name="joined-at",
@commands.hybrid_command(name="joined-at",
help="Shows when a user joined",
usage="joined-at [user]",
with_app_command=True)
@@ -799,7 +799,7 @@ class Extra(commands.Cog):
joined = ctx.author.joined_at.strftime("%a, %d %b %Y %I:%M %p")
await ctx.send(view=CV2("joined-at", f"**`{joined}`**"))
@commands.command(name="github", usage="github [search]")
@commands.hybrid_command(name="github", usage="github [search]")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -906,7 +906,7 @@ class Extra(commands.Cog):
@commands.command(name="permissions", aliases= ["perms"],
@commands.hybrid_command(name="permissions", aliases= ["perms"],
help="Check and list the key permissions of a specific user",
usage="perms <user>",
with_app_command=True)

View File

@@ -35,7 +35,7 @@ class FastGreet(commands.Cog):
)
""")
@commands.command(name="fastgreet_add")
@commands.hybrid_command(name="fastgreet_add")
@commands.has_permissions(administrator=True)
async def add_greet_channel(self, ctx, channel: discord.TextChannel):
with sqlite3.connect(DB_PATH) as conn:
@@ -45,7 +45,7 @@ class FastGreet(commands.Cog):
""", (ctx.guild.id, channel.id))
await ctx.send(f"{channel.mention} added as a greet channel.")
@commands.command(name="fastgreet_remove")
@commands.hybrid_command(name="fastgreet_remove")
@commands.has_permissions(administrator=True)
async def remove_greet_channel(self, ctx, channel: discord.TextChannel):
with sqlite3.connect(DB_PATH) as conn:
@@ -54,7 +54,7 @@ class FastGreet(commands.Cog):
""", (ctx.guild.id, channel.id))
await ctx.send(f"{channel.mention} removed from greet channels.")
@commands.command(name="fastgreet_list")
@commands.hybrid_command(name="fastgreet_list")
async def list_greet_channels(self, ctx):
with sqlite3.connect(DB_PATH) as conn:
cursor = conn.execute("""

View File

@@ -56,58 +56,58 @@ class Fun(commands.Cog):
async def meter_command(self, ctx, title, user, text):
await ctx.send(view=CV2(title, text))
@commands.command(name="shipp")
@commands.hybrid_command(name="shipp")
@blacklist_check()
@ignore_check()
async def shipp(self, ctx, user1: discord.Member, user2: discord.Member):
percentage = random.randint(0, 100)
await ctx.send(view=CV2(f"{self.random_emoji()} Ship Result", f"**{user1.mention} x {user2.mention} = {percentage}% Love**"))
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def hug(self, ctx, user: discord.Member):
await self.action_command(ctx, user, "hug")
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def kiss(self, ctx, user: discord.Member):
await self.action_command(ctx, user, "kiss")
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def pat(self, ctx, user: discord.Member):
await self.action_command(ctx, user, "pat")
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def slap(self, ctx, user: discord.Member):
await self.action_command(ctx, user, "slap")
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def tickle(self, ctx, user: discord.Member):
await self.action_command(ctx, user, "tickle")
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def coinflip(self, ctx):
result = random.choice(["Heads", "Tails"])
await ctx.send(view=CV2("🪙 Coin Flip", f"**Result: {result}**"))
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def dice(self, ctx):
result = random.randint(1, 6)
await ctx.send(view=CV2("🎲 Dice Roll", f"**You rolled a {result}!**"))
@commands.command(name="8ball")
@commands.hybrid_command(name="8ball")
@blacklist_check()
@ignore_check()
async def eight_ball(self, ctx, *, question: str):
@@ -116,7 +116,7 @@ class Fun(commands.Cog):
"Don't count on it.", "My sources say no.", "Very doubtful."]
await ctx.send(view=CV2("🎱 Magic 8Ball", f"**Q:** {question}\n**A:** {random.choice(responses)}"))
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def roast(self, ctx, user: discord.Member):
@@ -127,56 +127,56 @@ class Fun(commands.Cog):
]
await ctx.send(view=CV2("🔥 Roast Time", random.choice(roasts)))
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def iq(self, ctx, user: discord.Member = None):
user = user or ctx.author
await ctx.send(view=CV2("🧠 IQ Test", f"**{user.mention} has an IQ of {random.randint(50, 200)}!**"))
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def dumb(self, ctx, user: discord.Member = None):
user = user or ctx.author
await ctx.send(view=CV2("🤪 Dumbness Test", f"**{user.mention} is {random.randint(0, 100)}% dumb!**"))
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def simprate(self, ctx, user: discord.Member = None):
user = user or ctx.author
await ctx.send(view=CV2("😳 Simp Rate", f"**{user.mention} is {random.randint(0, 100)}% simp!**"))
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def toxic(self, ctx, user: discord.Member = None):
user = user or ctx.author
await ctx.send(view=CV2("☠️ Toxic Meter", f"**{user.mention} is {random.randint(0, 100)}% toxic!**"))
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def intelligence(self, ctx, user: discord.Member = None):
user = user or ctx.author
await ctx.send(view=CV2("🧠 Intelligence Meter", f"**{user.mention} has {random.randint(0, 200)} IQ Points!**"))
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def genius(self, ctx, user: discord.Member = None):
user = user or ctx.author
await ctx.send(view=CV2("🤓 Genius Rate", f"**{user.mention} is {random.randint(0, 100)}% genius!**"))
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def brainrate(self, ctx, user: discord.Member = None):
user = user or ctx.author
await ctx.send(view=CV2("🧠 Brain Power", f"**{user.mention} is using {random.randint(0, 100)}% of their brain!**"))
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
async def howhot(self, ctx, user: discord.Member = None):

View File

@@ -86,7 +86,7 @@ class AvatarView(View):
await interaction.response.edit_message(embed=embed)
from utils.config import BotName
from utils.config import BotName, DISCORD_CLIENT_ID
class General(commands.Cog):
@@ -208,7 +208,7 @@ class General(commands.Cog):
await msg.add_reaction(CROSS)
@commands.command(name="users", help=f"checks total users of {BotName}.")
@commands.hybrid_command(name="users", help=f"checks total users of {BotName}.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -251,7 +251,7 @@ class General(commands.Cog):
except:
pass
@commands.command(name="rickroll",
@commands.hybrid_command(name="rickroll",
help="Detects if provided url is a rick-roll",
usage="Rickroll <url>")
@blacklist_check()
@@ -271,7 +271,7 @@ class General(commands.Cog):
title = "Rick Roll {} in webpage".format("was found" if rickRoll else "was not found")
await ctx.reply(view=CV2(title, "🎵 Never gonna give you up..." if rickRoll else "✅ Safe to click!"), mention_author=True)
@commands.command(name="hash",
@commands.hybrid_command(name="hash",
help="Hashes provided text with provided algorithm")
@blacklist_check()
@ignore_check()
@@ -297,7 +297,7 @@ class General(commands.Cog):
hash_lines = f"**{algorithm}:** `{algos[algorithm.lower()]}`"
await ctx.reply(view=CV2(f"Hashed \"{message}\"", hash_lines), mention_author=True)
@commands.command(
@commands.hybrid_command(
name="invite",
aliases=['invite-bot'],
description="Get Support & Bot invite link!"
@@ -309,7 +309,7 @@ class General(commands.Cog):
invite_text = (
"```Empower your server with blazing-fast features and 24/7 support!```\n"
f"{AXIOM_LINKS} **Quick Actions**\n"
f">>> **[Invite {BotName}](https://discord.com/oauth2/authorize?client_id=1396114795102470196&permissions=8&integration_type=0&scope=bot+applications.commands)**\n"
f">>> **[Invite {BotName}](https://discord.com/oauth2/authorize?client_id={DISCORD_CLIENT_ID or (ctx.bot.user.id if ctx.bot.user else '')}&permissions=8&integration_type=0&scope=bot%20applications.commands)**\n"
"**[Support Server](https://discord.gg/hexahost)**"
)
await ctx.send(view=CV2(f"{AXIOM_CONNECTION} {BotName} Integration Hub!", invite_text))

View File

@@ -118,7 +118,7 @@ class Ignore(commands.Cog):
)
await db.commit()
@commands.group(
@commands.hybrid_group(
name="ignore",
help="Manage ignored commands, channels, users, and bypassed users.",
invoke_without_command=True,

View File

@@ -53,22 +53,22 @@ class ImageCommands(commands.Cog):
else:
await ctx.send(view=CV2("❌ Error", f"No image found for {title.lower()}."))
@commands.command(name="boy")
@commands.hybrid_command(name="boy")
async def boy_image(self, ctx):
url = await self.fetch_pexels_image("handsome boy")
await self.send_image_view(ctx, "👦 Boy Pic", url)
# @commands.command(name="girl")
# @commands.hybrid_command(name="girl")
# async def girl_image(self, ctx):
# url = await self.fetch_pexels_image("beautiful girl")
# await self.send_image_view(ctx, "👧 Girl Pic", url)
@commands.command(name="couple")
@commands.hybrid_command(name="couple")
async def couple_image(self, ctx):
url = await self.fetch_pexels_image("romantic couple")
await self.send_image_view(ctx, "💑 Couple Pic", url)
@commands.command(name="anime")
@commands.hybrid_command(name="anime")
async def anime_image(self, ctx):
url = await self.fetch_waifu_image("waifu")
await self.send_image_view(ctx, "🧚 Anime Waifu", url)

View File

@@ -190,7 +190,7 @@ class JoinToCreate(commands.Cog):
print(f"Error in J2C on_ready: {e}")
continue
@commands.command(name='j2csetup')
@commands.hybrid_command(name='j2csetup')
@commands.has_permissions(administrator=True)
async def setup_private_channels(self, ctx):
if ctx.guild.id in self.setup_data:
@@ -225,7 +225,7 @@ class JoinToCreate(commands.Cog):
await ctx.send(view=CV2("✅ Success", f"J2C system setup complete! Join {join_channel.mention} to create a private VC."))
@commands.command(name='j2creset')
@commands.hybrid_command(name='j2creset')
@commands.has_permissions(administrator=True)
async def reset_private_channels(self, ctx):
if ctx.guild.id not in self.setup_data:

View File

@@ -129,7 +129,7 @@ class Jail(commands.Cog):
)
await log_channel.send(view=CV2("🔓 Member Unjailed", desc))
@commands.command(name="jail")
@commands.hybrid_command(name="jail")
@commands.has_permissions(manage_roles=True)
async def jail(self, ctx, member: discord.Member, duration: str = None, *, reason="No reason provided"):
jail_role_id = self.get_setting(ctx.guild.id, "jail_role")
@@ -182,13 +182,13 @@ class Jail(commands.Cog):
)
await log_channel.send(view=CV2("🔒 Member Jailed", desc))
@commands.command(name="unjail")
@commands.hybrid_command(name="unjail")
@commands.has_permissions(manage_roles=True)
async def unjail(self, ctx, member: discord.Member):
await self.unjail_member(ctx.guild, member)
await ctx.send(view=CV2("✅ Success", f"{member.mention} has been unjailed."))
@commands.command(name="jailhistory")
@commands.hybrid_command(name="jailhistory")
async def jailhistory(self, ctx, member: discord.Member):
cursor = self.conn.execute("""
SELECT reason, jailed_at, duration, mod_id FROM jailed

View File

@@ -37,7 +37,7 @@ class joindm(commands.Cog):
with open(jsondb_path('joindm_messages.json'), 'w') as f:
json.dump(self.joindm_messages, f)
@commands.group(invoke_without_command=True)
@commands.hybrid_group(invoke_without_command=True)
@commands.has_permissions(administrator=True)
async def joindm(self, ctx):
# Display the current join DM message

View File

@@ -293,7 +293,7 @@ class Leveling (commands .Cog ):
self .last_level_cache ={}
self .db_path =db_path("leveling.db")
@commands.group (name ="level",invoke_without_command =True ,description ="Leveling system")
@commands.hybrid_group (name ="level",invoke_without_command =True ,description ="Leveling system")
async def level (self ,ctx ):
"""Main leveling command"""
if ctx .invoked_subcommand is None :

View File

@@ -81,7 +81,7 @@ class Messages(commands.Cog):
conn.commit()
conn.close()
@commands.command(name="messages", aliases=["msg"])
@commands.hybrid_command(name="messages", aliases=["msg"])
async def messages(self, ctx, member: discord.Member = None):
member = member or ctx.author
today = datetime.utcnow().strftime("%Y-%m-%d")

View File

@@ -21,7 +21,7 @@ class Messagespack(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.command(name="addmessages", aliases=["addmsg"])
@commands.hybrid_command(name="addmessages", aliases=["addmsg"])
@commands.has_permissions(manage_messages=True)
async def addmessages(self, ctx, member: discord.Member, amount: int):
if amount <= 0:
@@ -46,7 +46,7 @@ class Messagespack(commands.Cog):
conn.close()
await ctx.send(f"Added {amount} messages to {member.mention} for today.")
@commands.command(name="removemessages", aliases=["removemsg"])
@commands.hybrid_command(name="removemessages", aliases=["removemsg"])
@commands.has_permissions(manage_messages=True)
async def removemessages(self, ctx, member: discord.Member, amount: int):
if amount <= 0:
@@ -70,7 +70,7 @@ class Messagespack(commands.Cog):
await ctx.send(f"{member.mention} has no messages recorded for today.")
conn.close()
@commands.command(name="clearmessage", aliases=["clearmsg"])
@commands.hybrid_command(name="clearmessage", aliases=["clearmsg"])
@commands.has_permissions(manage_messages=True)
async def clearmessage(self, ctx, member: discord.Member):
conn = sqlite3.connect(db_path("messages.db"))

View File

@@ -585,7 +585,7 @@ class Music(commands.Cog):
bar = '' * filled_length + '' * (length - filled_length)
return bar
@commands.command(name="play", aliases=['p'], usage="play <query>", help="Plays a song or playlist.")
@commands.hybrid_command(name="play", aliases=['p'], usage="play <query>", help="Plays a song or playlist.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -594,7 +594,7 @@ class Music(commands.Cog):
await self.play_source(ctx, query)
@commands.command(name="search", usage="search <query>", help="Searches music from multiple platforms.")
@commands.hybrid_command(name="search", usage="search <query>", help="Searches music from multiple platforms.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -606,7 +606,7 @@ class Music(commands.Cog):
await ctx.send(view=PlatformSelectView(ctx, query))
@commands.command(name="nowplaying", aliases=["nop"], usage="nowplaying", help="Shows the info about current playing song.")
@commands.hybrid_command(name="nowplaying", aliases=["nop"], usage="nowplaying", help="Shows the info about current playing song.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -659,7 +659,7 @@ class Music(commands.Cog):
await ctx.send(view=view)
@commands.command(name="autoplay", usage="autoplay", help="Toggles autoplay mode.")
@commands.hybrid_command(name="autoplay", usage="autoplay", help="Toggles autoplay mode.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -679,7 +679,7 @@ class Music(commands.Cog):
)
await ctx.send(view=CV2(f"{TICK} Autoplay {'enabled' if vc.autoplay == wavelink.AutoPlayMode.enabled else 'disabled'} by {ctx.author.mention}."))
@commands.command(name="loop", usage="loop", help="Toggles loop mode.")
@commands.hybrid_command(name="loop", usage="loop", help="Toggles loop mode.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -700,7 +700,7 @@ class Music(commands.Cog):
await ctx.send(view=CV2("I'm not connected to a voice channel."))
@commands.command(name="pause", usage="pause", help="Pauses the current song.")
@commands.hybrid_command(name="pause", usage="pause", help="Pauses the current song.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -721,7 +721,7 @@ class Music(commands.Cog):
else:
await ctx.send(view=CV2(f"{WARNING} Nothing is playing or already paused."))
@commands.command(name="resume", usage="resume", help="Resumes the paused song.")
@commands.hybrid_command(name="resume", usage="resume", help="Resumes the paused song.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -742,7 +742,7 @@ class Music(commands.Cog):
else:
await ctx.send(view=CV2("Player is not paused."))
@commands.command(name="skip", usage="skip", help="Skips the current song.")
@commands.hybrid_command(name="skip", usage="skip", help="Skips the current song.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -767,7 +767,7 @@ class Music(commands.Cog):
else:
await ctx.send(view=CV2(f"{WARNING} No song is playing or in the queue to skip."))
@commands.command(name="shuffle", usage="shuffle", help="Shuffles the queue.")
@commands.hybrid_command(name="shuffle", usage="shuffle", help="Shuffles the queue.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -787,7 +787,7 @@ class Music(commands.Cog):
else:
await ctx.send(view=CV2("Queue is empty."))
@commands.command(name="stop", usage="stop", help="Stops the current song and clears the queue.")
@commands.hybrid_command(name="stop", usage="stop", help="Stops the current song and clears the queue.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -810,7 +810,7 @@ class Music(commands.Cog):
else:
await ctx.send(view=CV2("Nothing is playing to stop."))
@commands.command(name="volume", aliases=["vol"], usage="volume <level>", help="Sets the volume of the player.")
@commands.hybrid_command(name="volume", aliases=["vol"], usage="volume <level>", help="Sets the volume of the player.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -834,7 +834,7 @@ class Music(commands.Cog):
else:
await ctx.send(view=CV2("Bot is not connected to a voice channel."))
@commands.command(name="queue", usage="queue", help="Shows the current queue.")
@commands.hybrid_command(name="queue", usage="queue", help="Shows the current queue.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -860,7 +860,7 @@ class Music(commands.Cog):
ctx=ctx)
await paginator.paginate()
@commands.command(name="clearqueue", usage="clearqueue", help="Clears the queue.")
@commands.hybrid_command(name="clearqueue", usage="clearqueue", help="Clears the queue.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -881,7 +881,7 @@ class Music(commands.Cog):
else:
await ctx.send(view=CV2("No queue to clear."))
@commands.command(name="replay", usage="replay", help="Replays the current song.")
@commands.hybrid_command(name="replay", usage="replay", help="Replays the current song.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -902,7 +902,7 @@ class Music(commands.Cog):
else:
await ctx.send(view=CV2("No track is currently playing."))
@commands.command(name="join", aliases=["connect"], usage="join", help="Joins the voice channel.")
@commands.hybrid_command(name="join", aliases=["connect"], usage="join", help="Joins the voice channel.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -933,7 +933,7 @@ class Music(commands.Cog):
else:
await ctx.send(view=CV2("Bot is not connected to any voice channel."))
@commands.command(name="seek", usage="seek <percentage>", help="Seeks to a specific percentage of the song.")
@commands.hybrid_command(name="seek", usage="seek <percentage>", help="Seeks to a specific percentage of the song.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)

View File

@@ -28,7 +28,7 @@ class Nitro(commands.Cog):
ctx = await self.bot.get_context(message)
await self.bot.invoke(ctx)
@commands.command(name="nitro")
@commands.hybrid_command(name="nitro")
async def nitro(self, ctx):
embed = discord.Embed(color=0x2B2D31)
embed.add_field(

View File

@@ -34,7 +34,7 @@ class NotifCommands(commands.Cog):
channel_id INTEGER NOT NULL)""")
await db.commit()
@commands.group(invoke_without_command=True)
@commands.hybrid_group(invoke_without_command=True)
async def setnotif(self, ctx):
view = CV2(
"Notification Commands",

View File

@@ -465,7 +465,7 @@ class NoPrefix(commands.Cog):
await ctx.reply(view=embed)
@commands.group(name="autonp", help="Manage auto no-prefix for partner guilds.")
@commands.hybrid_group(name="autonp", help="Manage auto no-prefix for partner guilds.")
@commands.is_owner()
async def autonp(self, ctx):
if ctx.invoked_subcommand is None:

View File

@@ -160,7 +160,7 @@ class Owner(commands.Cog):
async with db.execute('SELECT id FROM staff') as cursor:
self.staff = {row[0] for row in await cursor.fetchall()}
@commands.command(name="staff_add", aliases=["staffadd", "addstaff"], help="Adds a user to the staff list.")
@commands.hybrid_command(name="staff_add", aliases=["staffadd", "addstaff"], help="Adds a user to the staff list.")
@commands.is_owner()
async def staff_add(self, ctx, user: discord.User):
if user.id in self.staff:
@@ -174,7 +174,7 @@ class Owner(commands.Cog):
sonu2 = discord.Embed(title=f"{TICK} Success", description=f"Added {user} to the staff list.", color=0xFF0000)
await ctx.reply(embed=sonu2, mention_author=False)
@commands.command(name="staff_remove", aliases=["staffremove", "removestaff"], help="Removes a user from the staff list.")
@commands.hybrid_command(name="staff_remove", aliases=["staffremove", "removestaff"], help="Removes a user from the staff list.")
@commands.is_owner()
async def staff_remove(self, ctx, user: discord.User):
if user.id not in self.staff:
@@ -188,7 +188,7 @@ class Owner(commands.Cog):
sonu2 = discord.Embed(title=f"{TICK} Success", description=f"Removed {user} from the staff list.", color=0xFF0000)
await ctx.reply(embed=sonu2, mention_author=False)
@commands.command(name="staff_list", aliases=["stafflist", "liststaff", "staffs"], help="Lists all staff members.")
@commands.hybrid_command(name="staff_list", aliases=["stafflist", "liststaff", "staffs"], help="Lists all staff members.")
@commands.is_owner()
async def staff_list(self, ctx):
if not self.staff:
@@ -202,7 +202,7 @@ class Owner(commands.Cog):
sonu = discord.Embed(title=f"{TICK} {BotName} Staffs", description=f"\n{staff_display}", color=0xFF0000)
await ctx.send(embed=sonu)
@commands.command(name="slist")
@commands.hybrid_command(name="slist")
@commands.check(is_owner_or_staff)
async def _slist(self, ctx):
servers = sorted(self.client.guilds, key=lambda g: g.member_count, reverse=True)
@@ -220,7 +220,7 @@ class Owner(commands.Cog):
await paginator.paginate()
@commands.command(name="mutuals", aliases=["mutual"])
@commands.hybrid_command(name="mutuals", aliases=["mutual"])
@commands.is_owner()
async def mutuals(self, ctx, user: discord.User):
guilds = [guild for guild in self.client.guilds if user in guild.members]
@@ -237,7 +237,7 @@ class Owner(commands.Cog):
ctx=ctx)
await paginator.paginate()
@commands.command(name="getinvite", aliases=["gi", "guildinvite"])
@commands.hybrid_command(name="getinvite", aliases=["gi", "guildinvite"])
@commands.is_owner()
async def getinvite(self, ctx: Context, guild= discord.Guild):
if not guild:
@@ -272,13 +272,13 @@ class Owner(commands.Cog):
await ctx.send("Forbidden.")
@commands.command(name="reload", help="Restarts the client.")
@commands.hybrid_command(name="reload", help="Restarts the client.")
@commands.is_owner()
async def _restart(self, ctx: Context):
await ctx.reply(f"{TICK} | **Successfully Restarting {BotName} It Takes 10 seconds**")
restart_program()
@commands.command(name="sync", help="Syncs all database.")
@commands.hybrid_command(name="sync", help="Syncs all database.")
@commands.is_owner()
async def _sync(self, ctx):
await ctx.reply("Syncing...", mention_author=False)
@@ -300,8 +300,35 @@ class Owner(commands.Cog):
with open('config.json', 'w') as f:
json.dump(data, f, indent=4)
@commands.hybrid_command(name="syncslash", help="Re-register all slash (/) commands with Discord.")
@commands.is_owner()
async def syncslash(self, ctx, scope: str = "all"):
"""Force-sync slash commands. scope: all | global | guild"""
if ctx.interaction:
await ctx.defer(ephemeral=True)
from utils.slash_sync import sync_slash_commands
@commands.command(name="owners")
scope = (scope or "all").lower().strip()
if scope == "global":
result = await sync_slash_commands(self.client, guilds=[], global_sync=True)
elif scope == "guild":
if not ctx.guild:
return await ctx.send("Use this in a server, or pass scope `all` / `global`.")
result = await sync_slash_commands(
self.client, guilds=[ctx.guild], global_sync=False
)
else:
result = await sync_slash_commands(self.client)
guild_n = len(result.get("guilds") or {})
err_n = len(result.get("errors") or [])
await ctx.send(
f"{TICK} Slash sync done — tree `{result.get('local_tree')}`, "
f"global `{result.get('global')}`, guilds `{guild_n}`, errors `{err_n}`."
)
@commands.hybrid_command(name="owners")
@commands.is_owner()
async def own_list(self, ctx):
nplist = OWNER_IDS
@@ -324,7 +351,7 @@ class Owner(commands.Cog):
@commands.command()
@commands.hybrid_command()
@commands.is_owner()
async def dm(self, ctx, user: discord.User, *, message: str):
""" DM the user of your choice """
@@ -336,7 +363,7 @@ class Owner(commands.Cog):
@commands.group()
@commands.hybrid_group()
@commands.is_owner()
async def change(self, ctx):
if ctx.invoked_subcommand is None:
@@ -357,7 +384,7 @@ class Owner(commands.Cog):
await ctx.send(err)
@commands.command(name="ownerban", aliases=["forceban", "dna"])
@commands.hybrid_command(name="ownerban", aliases=["forceban", "dna"])
@commands.is_owner()
async def _ownerban(self, ctx: Context, user_id: int, *, reason: str = "No reason provided"):
@@ -391,7 +418,7 @@ class Owner(commands.Cog):
await ctx.reply("User not found in this guild.", mention_author=False, delete_after=3)
await ctx.message.delete()
@commands.command(name="ownerunban", aliases=["forceunban"])
@commands.hybrid_command(name="ownerunban", aliases=["forceunban"])
@commands.is_owner()
async def _ownerunban(self, ctx: Context, user_id: int, *, reason: str = "No reason provided"):
user = self.client.get_user(user_id)
@@ -423,7 +450,7 @@ class Owner(commands.Cog):
@commands.command(name="globalunban")
@commands.hybrid_command(name="globalunban")
@commands.is_owner()
async def globalunban(self, ctx: Context, user: discord.User):
success_guilds = []
@@ -447,7 +474,7 @@ class Owner(commands.Cog):
await ctx.reply(f"{success_message}\n{error_message}", mention_author=False)
@commands.command(name="guildban")
@commands.hybrid_command(name="guildban")
@commands.is_owner()
async def guildban(self, ctx: Context, guild_id: int, user_id: int, *, reason: str = "No reason provided"):
guild = self.client.get_guild(guild_id)
@@ -467,7 +494,7 @@ class Owner(commands.Cog):
else:
await ctx.reply(f"User not found in the specified guild {guild.name}.", mention_author=False)
@commands.command(name="guildunban")
@commands.hybrid_command(name="guildunban")
@commands.is_owner()
async def guildunban(self, ctx: Context, guild_id: int, user_id: int, *, reason: str = "No reason provided"):
guild = self.client.get_guild(guild_id)
@@ -492,7 +519,7 @@ class Owner(commands.Cog):
await ctx.reply(f"An error occurred while unbanning user ID {user_id} in {guild.name}: {str(e)}", mention_author=False)
@commands.command(name="leaveguild", aliases=["leavesv"])
@commands.hybrid_command(name="leaveguild", aliases=["leavesv"])
@commands.is_owner()
async def leave_guild(self, ctx, guild_id: int):
guild = self.client.get_guild(guild_id)
@@ -503,7 +530,7 @@ class Owner(commands.Cog):
await guild.leave()
await ctx.send(f"Left the guild: {guild.name} ({guild.id})")
@commands.command(name="guildinfo")
@commands.hybrid_command(name="guildinfo")
@commands.check(is_owner_or_staff)
async def guild_info(self, ctx, guild_id: int):
guild = self.client.get_guild(guild_id)
@@ -527,7 +554,7 @@ class Owner(commands.Cog):
await ctx.send(embed=embed)
@commands.command()
@commands.hybrid_command()
@commands.is_owner()
async def servertour(self, ctx, time_in_seconds: int, member: discord.Member):
guild = ctx.guild
@@ -594,7 +621,7 @@ class Owner(commands.Cog):
@commands.group()
@commands.hybrid_group()
@commands.check(is_owner_or_staff)
@blacklist_check()
@ignore_check()
@@ -657,7 +684,7 @@ class Owner(commands.Cog):
await ctx.send(embed=embed)
@commands.command(name="forcepurgebots",
@commands.hybrid_command(name="forcepurgebots",
aliases=["fpb"],
help="Clear recently bot messages in channel (Bot owner only)")
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -673,7 +700,7 @@ class Owner(commands.Cog):
await do_removal(ctx, search, predicate)
@commands.command(name="forcepurgeuser",
@commands.hybrid_command(name="forcepurgeuser",
aliases=["fpu"],
help="Clear recent messages of a user in channel (Bot owner only)")
@commands.cooldown(1, 3, commands.BucketType.user)

View File

@@ -25,14 +25,14 @@ class Global(commands.Cog):
self.local_frozen_nicks = {}
self.client.frozen_nicknames = {}
@commands.group(name="global", invoke_without_command=True)
@commands.hybrid_group(name="global", invoke_without_command=True)
@commands.is_owner()
async def global_command(self, ctx: commands.Context):
if ctx.subcommand_passed is None:
await ctx.send_help(ctx.command)
ctx.command.reset_cooldown(ctx)
@commands.command(name="GB",help="Bans the user from all mutual guilds.")
@commands.hybrid_command(name="GB",help="Bans the user from all mutual guilds.")
@commands.is_owner()
async def global_ban(self, ctx: commands.Context, user: discord.User, reason: str = "Severe violations of Discord's terms of service."):
mutual_guilds = [guild for guild in self.client.guilds if guild.get_member(user.id)]
@@ -563,7 +563,7 @@ class Global(commands.Cog):
await ctx.send(f"✅ | Nickname freezing stopped for {user.name}.")
@commands.command(name="freezenick", help="Freezes a member's nickname in the current server.")
@commands.hybrid_command(name="freezenick", help="Freezes a member's nickname in the current server.")
@commands.has_permissions(manage_nicknames=True)
async def freeze_nickname(self, ctx: commands.Context, member: Member, *, nickname: str):
guild_id = ctx.guild.id
@@ -597,7 +597,7 @@ class Global(commands.Cog):
self.client.loop.create_task(monitor_nickname())
@commands.command(name="unfreezenick", help="Unfreezes a member's nickname in the current server.")
@commands.hybrid_command(name="unfreezenick", help="Unfreezes a member's nickname in the current server.")
@commands.has_permissions(manage_nicknames=True)
async def unfreeze_nickname(self, ctx: commands.Context, member: Member):
guild_id = ctx.guild.id

View File

@@ -19,7 +19,7 @@ class QR(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.command(
@commands.hybrid_command(
name="qr",
aliases=["qrcode"],
help="Sends a QR code image.",

View File

@@ -25,7 +25,7 @@ class Slots(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.command(aliases=['slot'])
@commands.hybrid_command(aliases=['slot'])
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)

View File

@@ -23,7 +23,7 @@ class Status(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.command(name="status", help="Shows the status of the user in detail.")
@commands.hybrid_command(name="status", help="Shows the status of the user in detail.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)

View File

@@ -130,7 +130,7 @@ class StickyMessage(commands.Cog):
)
await db.commit()
@commands.group(aliases=['sticky', 'sm'], invoke_without_command=True)
@commands.hybrid_group(aliases=['sticky', 'sm'], invoke_without_command=True)
@commands.has_permissions(manage_messages=True)
async def stickymessage(self, ctx: commands.Context):
if ctx.invoked_subcommand is None:

View File

@@ -136,7 +136,7 @@ class Tracking(commands.Cog):
row = await cursor.fetchone()
return row[0] if row else 0
@commands.command(aliases=["inv"])
@commands.hybrid_command(aliases=["inv"])
async def invites(self, ctx, member: discord.Member = None):
member = member or ctx.author
await self.ensure_tables(ctx.guild.id)
@@ -161,7 +161,7 @@ class Tracking(commands.Cog):
)
await ctx.send(view=CV2(f"Invite Log - {member.name}", desc))
@commands.command(aliases=["addinvs"])
@commands.hybrid_command(aliases=["addinvs"])
@commands.has_permissions(administrator=True)
async def addinvites(self, ctx, member: discord.Member, amount: int):
await self.ensure_tables(ctx.guild.id)
@@ -171,7 +171,7 @@ class Tracking(commands.Cog):
await db.commit()
await ctx.send(view=CV2("✅ Success", f"Added **{amount}** invites to {member.mention}."))
@commands.command(aliases=["setinvs"])
@commands.hybrid_command(aliases=["setinvs"])
@commands.has_permissions(administrator=True)
async def setinvites(self, ctx, member: discord.Member, amount: int):
await self.ensure_tables(ctx.guild.id)
@@ -180,7 +180,7 @@ class Tracking(commands.Cog):
await db.commit()
await ctx.send(view=CV2("✅ Success", f"Set invites of {member.mention} to **{amount}**."))
@commands.command(aliases=["resetinvs"])
@commands.hybrid_command(aliases=["resetinvs"])
@commands.has_permissions(administrator=True)
async def resetinvites(self, ctx, member: discord.Member):
await self.ensure_tables(ctx.guild.id)
@@ -189,7 +189,7 @@ class Tracking(commands.Cog):
await db.commit()
await ctx.send(view=CV2("✅ Success", f"Reset invites of {member.mention}."))
@commands.command(aliases=["invlb"])
@commands.hybrid_command(aliases=["invlb"])
async def invitesleaderboard(self, ctx):
await self.ensure_tables(ctx.guild.id)
async with aiosqlite.connect(INVITE_DB) as db:
@@ -208,7 +208,7 @@ class Tracking(commands.Cog):
await ctx.send(view=CV2("📊 Invite Leaderboard", leaderboard))
@commands.command(aliases=["invlog"])
@commands.hybrid_command(aliases=["invlog"])
@commands.has_permissions(administrator=True)
async def invitelogging(self, ctx, channel: discord.TextChannel):
await self.ensure_tables(ctx.guild.id)

View File

@@ -49,7 +49,7 @@ class VanityRoles(commands.Cog):
await db.execute("ALTER TABLE vanity_roles ADD COLUMN current_status TEXT")
await db.commit()
@commands.group(name="vanityroles", invoke_without_command=True)
@commands.hybrid_group(name="vanityroles", invoke_without_command=True)
@blacklist_check()
@ignore_check()
async def vanityroles(self, ctx):

View File

@@ -29,7 +29,7 @@ class Voice(commands.Cog):
self.bot = bot
self.color = 0xFF0000
@commands.group(name="voice", invoke_without_command=True, aliases=['vc'])
@commands.hybrid_group(name="voice", invoke_without_command=True, aliases=['vc'])
@blacklist_check()
@ignore_check()
async def vc(self, ctx: commands.Context):

View File

@@ -22,7 +22,7 @@ class Youtube(commands.Cog):
self.bot = bot
@commands.command(name='yt', aliases=['youtube'])
@commands.hybrid_command(name='yt', aliases=['youtube'])
async def search_youtube(self, ctx, *, search_query):
query_string = urllib.parse.urlencode({'search_query': search_query})
html_content = urllib.request.urlopen('http://www.youtube.com/results?' + query_string)

View File

@@ -13,7 +13,7 @@
from utils.db_paths import db_path
from utils import getConfig
from utils.config import BotName
from utils.config import BotName, DISCORD_CLIENT_ID
import discord
from utils.emoji import ARROWRED, CODEBASE, HEART3, INDEX, AXIOM_LINKS
from discord.ui import LayoutView, TextDisplay, Separator, Container, ActionRow, Select
@@ -87,7 +87,7 @@ class MentionSelectView(LayoutView):
)
elif selected == "Links":
content = (
f"**[Invite {BotName}](https://discord.com/oauth2/authorize?client_id=1396114795102470196)**\n"
f"**[Invite {BotName}](https://discord.com/oauth2/authorize?client_id={DISCORD_CLIENT_ID or (self.bot.user.id if self.bot.user else '')}&permissions=8&scope=bot%20applications.commands)**\n"
"**[Join Support Server](https://discord.gg/hexahost)**"
)

View File

@@ -89,7 +89,7 @@ class Message(commands.Cog):
self.color = 0xFF0000
@commands.group(invoke_without_command=True, aliases=["purge"], help="Clears the messages")
@commands.hybrid_group(invoke_without_command=True, aliases=["purge"], help="Clears the messages")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -232,7 +232,7 @@ class Message(commands.Cog):
@commands.command(name="purgebots",
@commands.hybrid_command(name="purgebots",
aliases=["cleanup", "pb", "clearbot", "clearbots"],
help="Clear recently bot messages in channel")
@blacklist_check()
@@ -250,7 +250,7 @@ class Message(commands.Cog):
await do_removal(ctx, search, predicate)
@commands.command(name="purgeuser",
@commands.hybrid_command(name="purgeuser",
aliases=["pu", "cu", "clearuser"],
help="Clear recent messages of a user in channel")
@blacklist_check()

View File

@@ -115,7 +115,7 @@ class Moderation(commands.Cog):
@commands.command()
@commands.hybrid_command()
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -793,7 +793,7 @@ class Moderation(commands.Cog):
@commands.command(aliases=["deletesticker", "removesticker"], description="Delete the sticker from the server")
@commands.hybrid_command(aliases=["deletesticker", "removesticker"], description="Delete the sticker from the server")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -815,7 +815,7 @@ class Moderation(commands.Cog):
await ctx.reply("Failed to delete the sticker")
@commands.command(aliases=["deleteemoji", "removeemoji"], description="Deletes the emoji from the server")
@commands.hybrid_command(aliases=["deleteemoji", "removeemoji"], description="Deletes the emoji from the server")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)
@@ -864,7 +864,7 @@ class Moderation(commands.Cog):
@commands.command(description="Changes the icon for the role.")
@commands.hybrid_command(description="Changes the icon for the role.")
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 3, commands.BucketType.user)

View File

@@ -56,7 +56,7 @@ class Role(commands.Cog):
self.color = 0xFF0000
@commands.group(name="role",invoke_without_command=True)
@commands.hybrid_group(name="role",invoke_without_command=True)
@blacklist_check()
@ignore_check()
@commands.cooldown(1, 5, commands.BucketType.user)
@@ -598,7 +598,7 @@ class Role(commands.Cog):
@commands.group(name="removerole",invoke_without_command=True,
@commands.hybrid_group(name="removerole",invoke_without_command=True,
aliases=['rrole'],
help="remove a role from all members .")
@blacklist_check()

View File

@@ -36,7 +36,7 @@ class Snipe(commands.Cog):
'deleted_at': datetime.utcnow()
}
@commands.command(name='snipe', help="Shows the most recently deleted message in the channel.")
@commands.hybrid_command(name='snipe', help="Shows the most recently deleted message in the channel.")
@commands.has_permissions(manage_messages=True)
async def snipe(self, ctx):
# Check if there is a sniped message for the current channel

View File

@@ -53,7 +53,7 @@ class TopCheck(commands.Cog):
await db.execute("UPDATE topcheck SET enabled = 0 WHERE guild_id = ?", (guild_id,))
await db.commit()
@commands.group(
@commands.hybrid_group(
name="topcheck",
help="Manage topcheck settings for the server.",
invoke_without_command=True)

View File

@@ -48,11 +48,10 @@ class Axiom(commands.AutoShardedBot):
owner_ids=OWNER_IDS,
allowed_mentions=discord.AllowedMentions(
everyone=False, replied_user=False, roles=False),
sync_commands_debug=True,
sync_commands=True,
shard_count=1)
self.status_index = 0
self.status_list = []
self._slash_synced = False
async def setup_hook(self):
await setup_db()

View File

@@ -77,6 +77,9 @@ def _parse_ids(env_key: str) -> list[int]:
OWNER_IDS: list[int] = _parse_ids("OWNER_IDS")
OWNER_IDS_STR: list[str] = [str(i) for i in OWNER_IDS]
# Discord application / OAuth client id (same as dashboard DISCORD_CLIENT_ID)
DISCORD_CLIENT_ID = os.getenv("DISCORD_CLIENT_ID", "").strip()
# Aliases kept for backwards compatibility with files that import these names
BOT_OWNER_IDS = OWNER_IDS
BOT_OWNER_IDS_STR = OWNER_IDS_STR

184
bot/utils/slash_sync.py Normal file
View File

@@ -0,0 +1,184 @@
# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ +-+-+-+-+-+-+-+-+ ║
# ║ |H|e|x|a|H|o|s|t| ║
# ║ +-+-+-+-+-+-+-+-+ ║
# ║ ║
# ║ © 2026 HexaHost — All Rights Reserved ║
# ║ ║
# ║ discord ── https://discord.gg/hexahost ║
# ║ github ── https://github.com/theoneandonlymace ║
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝
"""Register slash (/) commands with Discord.
Global sync alone can take up to ~1 hour to appear in clients.
Guild sync makes them available immediately in every server the bot is in.
"""
from __future__ import annotations
import asyncio
import logging
import os
from typing import TYPE_CHECKING, Iterable, Optional
import discord
from discord import app_commands
if TYPE_CHECKING:
from discord.ext import commands
logger = logging.getLogger("axiom.slash_sync")
# Discord hard limit for top-level application commands (global or per-guild)
MAX_TOP_LEVEL = 100
def _parse_guild_ids(raw: str | None) -> list[int]:
if not raw:
return []
out: list[int] = []
for part in raw.split(","):
part = part.strip()
if part.isdigit():
out.append(int(part))
return out
def _tree_command_count(bot: "commands.Bot") -> int:
return len(bot.tree.get_commands())
def _prune_tree_to_limit(bot: "commands.Bot", limit: int = MAX_TOP_LEVEL) -> list[str]:
"""Drop excess top-level app commands so Discord accepts the sync."""
commands_list = list(bot.tree.get_commands())
if len(commands_list) <= limit:
return []
# Prefer keeping groups (more coverage) over single commands; drop from the end
singles = [c for c in commands_list if not isinstance(c, app_commands.Group)]
groups = [c for c in commands_list if isinstance(c, app_commands.Group)]
ordered = groups + singles
removed: list[str] = []
while len(ordered) > limit:
cmd = ordered.pop()
bot.tree.remove_command(cmd.name)
removed.append(cmd.name)
return removed
async def sync_guild(
bot: "commands.Bot",
guild: discord.abc.Snowflake,
*,
copy_global: bool = True,
) -> list[app_commands.AppCommand]:
if copy_global:
bot.tree.copy_global_to(guild=guild)
return await bot.tree.sync(guild=guild)
async def sync_slash_commands(
bot: "commands.Bot",
*,
guilds: Optional[Iterable[discord.abc.Snowflake]] = None,
global_sync: bool = True,
) -> dict:
"""
Sync application commands.
Env:
SLASH_SYNC_GLOBAL=true|false (default true)
SLASH_GUILD_IDS=id,id (optional; if set, only these guilds get instant sync)
SLASH_SYNC_ALL_GUILDS=true (default true — sync every connected guild for instant /)
"""
env_global = os.getenv("SLASH_SYNC_GLOBAL", "true").strip().lower() in ("1", "true", "yes", "on")
do_global = global_sync and env_global
sync_all = os.getenv("SLASH_SYNC_ALL_GUILDS", "true").strip().lower() in ("1", "true", "yes", "on")
env_guild_ids = _parse_guild_ids(os.getenv("SLASH_GUILD_IDS"))
removed = _prune_tree_to_limit(bot)
if removed:
logger.warning(
"Pruned %s top-level slash command(s) to stay under Discord's %s limit: %s",
len(removed),
MAX_TOP_LEVEL,
", ".join(removed[:20]) + ("" if len(removed) > 20 else ""),
)
print(
f"\033[33m◈ Slash tree pruned by {len(removed)} (Discord max {MAX_TOP_LEVEL} top-level)\033[0m"
)
local_count = _tree_command_count(bot)
result: dict = {
"local_tree": local_count,
"global": None,
"guilds": {},
"errors": [],
"pruned": removed,
}
async def _try_sync(label: str, factory):
try:
synced = await factory()
return synced, None
except Exception as e:
detail = str(e)
logger.error("%s failed: %s", label, detail)
dropped = []
for cmd in list(bot.tree.get_commands()):
if cmd.name in detail or getattr(cmd, "qualified_name", "") in detail:
bot.tree.remove_command(cmd.name)
dropped.append(cmd.name)
if dropped:
print(f"\033[33m◈ Removed invalid slash cmd(s) after error: {', '.join(dropped)}\033[0m")
try:
synced = await factory()
return synced, None
except Exception as e2:
return None, f"{label}: {e2}"
return None, f"{label}: {e}"
if do_global:
synced, err = await _try_sync("Global slash sync", lambda: bot.tree.sync())
if err:
result["errors"].append(err)
print(f"\033[31m◈ {err}\033[0m")
else:
result["global"] = len(synced or [])
print(f"◈ Slash sync (global): {result['global']} command(s)")
target_guilds: list[discord.abc.Snowflake] = []
if guilds is not None:
target_guilds = list(guilds)
elif env_guild_ids:
target_guilds = [discord.Object(id=gid) for gid in env_guild_ids]
elif sync_all:
target_guilds = list(bot.guilds)
for guild in target_guilds:
gid = getattr(guild, "id", guild)
def _make_factory(g=guild):
async def _factory():
bot.tree.copy_global_to(guild=g)
return await bot.tree.sync(guild=g)
return _factory
synced, err = await _try_sync(f"Guild {gid} slash sync", _make_factory())
if err:
result["errors"].append(err)
print(f"\033[31m◈ {err}\033[0m")
else:
result["guilds"][str(gid)] = len(synced or [])
print(f"◈ Slash sync (guild {gid}): {result['guilds'][str(gid)]} command(s) — instant")
await asyncio.sleep(0.35)
prefix_count = len(list(bot.commands))
print(
f"Synced Total {prefix_count} Client Commands and "
f"{result.get('global') or local_count} Slash Commands"
+ (f" (guild-synced: {len(result['guilds'])})" if result["guilds"] else "")
)
return result