Update configuration and README for improved setup and security; disable default API and emoji sync, and enhance Discord permission checks in API routes.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
122
bot/cogs/events/Errors.py
Normal file
122
bot/cogs/events/Errors.py
Normal file
@@ -0,0 +1,122 @@
|
||||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ ║
|
||||
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀ ║
|
||||
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█ ║
|
||||
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀ ║
|
||||
# ║ ║
|
||||
# ║ © 2026 CodeX Devs — All Rights Reserved ║
|
||||
# ║ ║
|
||||
# ║ discord ── https://discord.gg/codexdev ║
|
||||
# ║ youtube ── https://youtube.com/@CodeXDevs ║
|
||||
# ║ github ── https://github.com/RayExo ║
|
||||
# ║ ║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
import discord
|
||||
import json
|
||||
import aiosqlite
|
||||
from discord.ext import commands
|
||||
from utils.config import serverLink
|
||||
from core import zyrox, Cog, Context
|
||||
from utils.Tools import get_ignore_data
|
||||
|
||||
class Errors(Cog):
|
||||
def __init__(self, client: zyrox):
|
||||
self.client = client
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_command_error(self, ctx: Context, error):
|
||||
if ctx.command is None:
|
||||
return
|
||||
|
||||
|
||||
if isinstance(error, commands.CommandNotFound):
|
||||
return
|
||||
|
||||
if isinstance(error, commands.MissingRequiredArgument):
|
||||
await ctx.send_help(ctx.command)
|
||||
ctx.command.reset_cooldown(ctx)
|
||||
return
|
||||
|
||||
if isinstance(error, commands.CheckFailure):
|
||||
data = await get_ignore_data(ctx.guild.id)
|
||||
ch = data["channel"]
|
||||
iuser = data["user"]
|
||||
cmd = data["command"]
|
||||
buser = data["bypassuser"]
|
||||
|
||||
if str(ctx.author.id) in buser:
|
||||
return
|
||||
|
||||
if str(ctx.channel.id) in ch:
|
||||
await ctx.reply(f"{ctx.author.mention} **This channel was in ignored list try my commands on other channel**.",
|
||||
delete_after=8)
|
||||
return
|
||||
|
||||
if str(ctx.author.id) in iuser:
|
||||
await ctx.reply(f"{ctx.author.mention} **You are set as an ignored user for this guild. Please try my commands in a different guild.**", delete_after=8)
|
||||
return
|
||||
|
||||
if ctx.command.name in cmd or any(alias in cmd for alias in ctx.command.aliases):
|
||||
await ctx.reply(f"{ctx.author.mention} **This command is ignored in this guild. Please use other commands or try this command in a different guild**", delete_after=8)
|
||||
return
|
||||
|
||||
if isinstance(error, commands.NoPrivateMessage):
|
||||
embed = discord.Embed(color=0xFF0000, description="You can't use my commands in DMs.")
|
||||
embed.set_author(name=ctx.author, icon_url=ctx.author.avatar.url if ctx.author.avatar else ctx.author.default_avatar.url)
|
||||
embed.set_thumbnail(url=ctx.author.avatar.url if ctx.author.avatar else ctx.author.default_avatar.url)
|
||||
await ctx.reply(embed=embed, delete_after=20)
|
||||
return
|
||||
|
||||
if isinstance(error, commands.TooManyArguments):
|
||||
await ctx.send_help(ctx.command)
|
||||
ctx.command.reset_cooldown(ctx)
|
||||
return
|
||||
|
||||
if isinstance(error, commands.CommandOnCooldown):
|
||||
embed = discord.Embed(color=0xFF0000, description=f"**{ctx.author.mention} Couldown is here Bro Tryy commands in {error.retry_after:.2f} seconds**.")
|
||||
embed.set_author(name="Cooldown", icon_url=self.client.user.avatar.url)
|
||||
|
||||
embed.set_footer(text=f"Requested by {ctx.author}", icon_url=ctx.author.avatar.url if ctx.author.avatar else ctx.author.default_avatar.url)
|
||||
await ctx.reply(embed=embed, delete_after=10)
|
||||
return
|
||||
|
||||
if isinstance(error, commands.MaxConcurrencyReached):
|
||||
embed = discord.Embed(color=0xFF0000, description=f"{ctx.author.mention} This command is already in progress. Please let it finish and try again afterward.")
|
||||
embed.set_author(name="Command in Progress.", icon_url=self.client.user.avatar.url)
|
||||
|
||||
embed.set_footer(text=f"Requested by {ctx.author}", icon_url=ctx.author.avatar.url if ctx.author.avatar else ctx.author.default_avatar.url)
|
||||
await ctx.reply(embed=embed, delete_after=10)
|
||||
ctx.command.reset_cooldown(ctx)
|
||||
return
|
||||
|
||||
if isinstance(error, commands.MissingPermissions):
|
||||
missing = [perm.replace("_", " ").replace("guild", "server").title() for perm in error.missing_permissions]
|
||||
fmt = "{}, and {}".format(", ".join(missing[:-1]), missing[-1]) if len(missing) > 2 else " and ".join(missing)
|
||||
embed = discord.Embed(color=0xFF0000, description=f"**Ops! You don't have {fmt} Permission to run the {ctx.command.name} command!**")
|
||||
embed.set_author(name="Missing Permissions", icon_url=self.client.user.avatar.url)
|
||||
|
||||
embed.set_footer(text=f"Requested by {ctx.author}", icon_url=ctx.author.avatar.url if ctx.author.avatar else ctx.author.default_avatar.url)
|
||||
await ctx.reply(embed=embed, delete_after=7)
|
||||
ctx.command.reset_cooldown(ctx)
|
||||
return
|
||||
|
||||
if isinstance(error, commands.BadArgument):
|
||||
await ctx.send_help(ctx.command)
|
||||
ctx.command.reset_cooldown(ctx)
|
||||
return
|
||||
|
||||
if isinstance(error, commands.BotMissingPermissions):
|
||||
missing = ", ".join(error.missing_permissions)
|
||||
await ctx.reply(f'** Huh! I need {missing} Permission to run the {ctx.command.qualified_name}command! Give me {missing} Permission**', delete_after=7)
|
||||
return
|
||||
|
||||
if isinstance(error, discord.HTTPException):
|
||||
print(f"[ERROR] HTTPException in {ctx.command}: {error}")
|
||||
return
|
||||
|
||||
if isinstance(error, commands.CommandInvokeError):
|
||||
print(f"[ERROR] CommandInvokeError in {ctx.command}: {error}")
|
||||
print(f" Original: {error.original}")
|
||||
return
|
||||
|
||||
27
bot/cogs/events/ai.py
Normal file
27
bot/cogs/events/ai.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ ║
|
||||
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀ ║
|
||||
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█ ║
|
||||
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀ ║
|
||||
# ║ ║
|
||||
# ║ © 2026 CodeX Devs — All Rights Reserved ║
|
||||
# ║ ║
|
||||
# ║ discord ── https://discord.gg/codexdev ║
|
||||
# ║ youtube ── https://youtube.com/@CodeXDevs ║
|
||||
# ║ github ── https://github.com/RayExo ║
|
||||
# ║ ║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
class AIResponses(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_ready(self):
|
||||
pass
|
||||
|
||||
async def setup(bot):
|
||||
await bot.add_cog(AIResponses(bot))
|
||||
52
bot/cogs/events/auto.py
Normal file
52
bot/cogs/events/auto.py
Normal file
@@ -0,0 +1,52 @@
|
||||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ ║
|
||||
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀ ║
|
||||
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█ ║
|
||||
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀ ║
|
||||
# ║ ║
|
||||
# ║ © 2026 CodeX Devs — All Rights Reserved ║
|
||||
# ║ ║
|
||||
# ║ discord ── https://discord.gg/codexdev ║
|
||||
# ║ youtube ── https://youtube.com/@CodeXDevs ║
|
||||
# ║ github ── https://github.com/RayExo ║
|
||||
# ║ ║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
import discord
|
||||
from utils.emoji import ARROWRED, ZMODULE
|
||||
from discord.utils import *
|
||||
from core import zyrox, Cog
|
||||
from utils.Tools import *
|
||||
from utils.config import BotName, serverLink
|
||||
from discord.ext import commands
|
||||
from discord.ui import Button, View
|
||||
|
||||
class Autorole(Cog):
|
||||
def __init__(self, bot: zyrox):
|
||||
self.bot = bot
|
||||
|
||||
|
||||
@commands.Cog.listener(name="on_guild_join")
|
||||
async def send_msg_to_adder(self, guild: discord.Guild):
|
||||
async for entry in guild.audit_logs(limit=3):
|
||||
if entry.action == discord.AuditLogAction.bot_add:
|
||||
embed = discord.Embed(
|
||||
description=f"{ZMODULE} **Thanks for adding me.**\n\n{ARROWRED} My default prefix is `>`\n{ARROWRED}> Use the `>help` command to see a list of commands\n{ARROWRED} For detailed guides, FAQ and information, visit our **[Support Server](https://discord.gg/codexdev)**",
|
||||
color=0xFF0000
|
||||
)
|
||||
embed.set_thumbnail(url=entry.user.avatar.url if entry.user.avatar else entry.user.default_avatar.url)
|
||||
embed.set_author(name=f"{guild.name}", icon_url=guild.me.display_avatar.url)
|
||||
|
||||
website_button = Button(label='Website', style=discord.ButtonStyle.link, url='https://.vercel.app')
|
||||
support_button = Button(label='Support', style=discord.ButtonStyle.link, url='https://discord.gg/codexdev')
|
||||
vote_button = Button(label='Vote for Me', style=discord.ButtonStyle.link, url=f'https://top.gg/bot/{self.bot.user.id}/vote')
|
||||
view = View()
|
||||
view.add_item(support_button)
|
||||
#view.add_item(website_button)
|
||||
#view.add_item(vote_button)
|
||||
if guild.icon:
|
||||
embed.set_author(name=guild.name, icon_url=guild.icon.url)
|
||||
try:
|
||||
await entry.user.send(embed=embed, view=view)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
161
bot/cogs/events/autoblacklist.py
Normal file
161
bot/cogs/events/autoblacklist.py
Normal file
@@ -0,0 +1,161 @@
|
||||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ ║
|
||||
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀ ║
|
||||
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█ ║
|
||||
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀ ║
|
||||
# ║ ║
|
||||
# ║ © 2026 CodeX Devs — All Rights Reserved ║
|
||||
# ║ ║
|
||||
# ║ discord ── https://discord.gg/codexdev ║
|
||||
# ║ youtube ── https://youtube.com/@CodeXDevs ║
|
||||
# ║ github ── https://github.com/RayExo ║
|
||||
# ║ ║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
import discord
|
||||
from utils.emoji import ZWARNING
|
||||
from core import zyrox, Cog
|
||||
from discord.ext import commands
|
||||
import aiosqlite
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
class AutoBlacklist(Cog):
|
||||
def __init__(self, client: zyrox):
|
||||
self.client = client
|
||||
self.spam_cd_mapping = commands.CooldownMapping.from_cooldown(5, 5, commands.BucketType.member)
|
||||
self.spam_command_mapping = commands.CooldownMapping.from_cooldown(6, 10, commands.BucketType.member)
|
||||
self.last_spam = {}
|
||||
self.spam_threshold = 5
|
||||
self.spam_window = timedelta(minutes=10)
|
||||
self.db_path = 'db/block.db'
|
||||
self.bot_user_id = self.client.user.id if self.client.user else None
|
||||
self.guild_command_tracking = {}
|
||||
|
||||
async def add_to_blacklist(self, user_id=None, guild_id=None, channel=None):
|
||||
try:
|
||||
async with aiosqlite.connect(self.db_path) as db:
|
||||
timestamp = datetime.utcnow()
|
||||
if guild_id:
|
||||
await db.execute('''
|
||||
INSERT OR IGNORE INTO guild_blacklist (guild_id, timestamp) VALUES (?, ?)
|
||||
''', (guild_id, timestamp))
|
||||
if channel:
|
||||
embed = discord.Embed(
|
||||
title=f"{ZWARNING} Guild Blacklisted",
|
||||
description=(
|
||||
f"This guild has been blacklisted due to spamming or automation. "
|
||||
f"If you believe this is a mistake, please contact our [Support Server](https://discord.gg/codexdev) with any proof if possible."
|
||||
),
|
||||
color=0xFF0000
|
||||
)
|
||||
await channel.send(embed=embed)
|
||||
elif user_id:
|
||||
await db.execute('''
|
||||
INSERT OR IGNORE INTO user_blacklist (user_id, timestamp) VALUES (?, ?)
|
||||
''', (user_id, timestamp))
|
||||
await db.commit()
|
||||
except aiosqlite.Error as e:
|
||||
print(f"Database error: {e}")
|
||||
|
||||
async def check_and_blacklist_guild(self, guild_id):
|
||||
async with aiosqlite.connect(self.db_path) as db:
|
||||
async with db.execute(
|
||||
'''
|
||||
SELECT COUNT(DISTINCT user_id) FROM user_blacklist
|
||||
WHERE timestamp >= ?
|
||||
''',
|
||||
(datetime.utcnow() - self.spam_window,)
|
||||
) as cursor:
|
||||
count = await cursor.fetchone()
|
||||
if count[0] >= self.spam_threshold:
|
||||
async with db.execute('SELECT channel_id FROM guild_settings WHERE guild_id = ?', (guild_id,)) as cursor:
|
||||
channel_id = await cursor.fetchone()
|
||||
if channel_id:
|
||||
channel = self.client.get_channel(channel_id[0])
|
||||
if channel:
|
||||
await self.add_to_blacklist(None, guild_id, channel)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_message(self, message):
|
||||
if message.author.bot:
|
||||
return
|
||||
|
||||
|
||||
guild_id = message.guild.id if message.guild else None
|
||||
if guild_id:
|
||||
if guild_id not in self.guild_command_tracking:
|
||||
self.guild_command_tracking[guild_id] = []
|
||||
|
||||
|
||||
self.guild_command_tracking[guild_id].append(datetime.utcnow())
|
||||
|
||||
|
||||
self.guild_command_tracking[guild_id] = [
|
||||
timestamp for timestamp in self.guild_command_tracking[guild_id] if timestamp >= datetime.utcnow() - timedelta(seconds=2)
|
||||
]
|
||||
|
||||
|
||||
if len(self.guild_command_tracking[guild_id]) > 8:
|
||||
|
||||
await self.add_to_blacklist(guild_id=guild_id, channel=message.channel)
|
||||
embed = discord.Embed(
|
||||
title=f"{ZWARNING} Guild Blacklisted",
|
||||
description=(
|
||||
f"The guild has been blacklisted for excessive command usage. "
|
||||
f"If you believe this is a mistake, please contact our [Support Server](https://discord.gg/codexdev)."
|
||||
),
|
||||
color=0xFF0000
|
||||
)
|
||||
await message.channel.send(embed=embed)
|
||||
return
|
||||
|
||||
|
||||
bucket = self.spam_cd_mapping.get_bucket(message)
|
||||
retry = bucket.update_rate_limit()
|
||||
|
||||
if retry:
|
||||
async with aiosqlite.connect(self.db_path) as db:
|
||||
async with db.execute('SELECT user_id FROM user_blacklist WHERE user_id = ?', (message.author.id,)) as cursor:
|
||||
if await cursor.fetchone():
|
||||
return
|
||||
|
||||
if message.content in (f'<@{self.bot_user_id}>', f'<@!{self.bot_user_id}>'):
|
||||
await self.add_to_blacklist(user_id=message.author.id)
|
||||
embed = discord.Embed(
|
||||
title=f"{ZWARNING} User Blacklisted",
|
||||
description=f"**{message.author.mention} has been blacklisted for repeatedly mentioning me. If you believe this is a mistake, please contact our [Support Server](https://discord.gg/codexdev) with any proof if possible.**",
|
||||
color=0xFF0000
|
||||
)
|
||||
await message.channel.send(embed=embed)
|
||||
return
|
||||
|
||||
if message.guild:
|
||||
if message.author.id not in self.last_spam:
|
||||
self.last_spam[message.author.id] = []
|
||||
self.last_spam[message.author.id].append(datetime.utcnow())
|
||||
recent_spam = [timestamp for timestamp in self.last_spam.get(message.author.id, []) if timestamp >= datetime.utcnow() - self.spam_window]
|
||||
self.last_spam[message.author.id] = recent_spam
|
||||
if len(recent_spam) >= self.spam_threshold:
|
||||
await self.check_and_blacklist_guild(message.guild.id)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_command(self, ctx):
|
||||
if ctx.author.bot:
|
||||
return
|
||||
|
||||
bucket = self.spam_command_mapping.get_bucket(ctx.message)
|
||||
retry = bucket.update_rate_limit()
|
||||
|
||||
if retry:
|
||||
async with aiosqlite.connect(self.db_path) as db:
|
||||
async with db.execute('SELECT user_id FROM user_blacklist WHERE user_id = ?', (ctx.author.id,)) as cursor:
|
||||
if await cursor.fetchone():
|
||||
return
|
||||
|
||||
await self.add_to_blacklist(user_id=ctx.author.id)
|
||||
embed = discord.Embed(
|
||||
title=f"{ZWARNING} User Blacklisted",
|
||||
description=f"**{ctx.author.mention} has been blacklisted for spamming commands. If you believe this is a mistake, please contact our [Support Server](https://discord.gg/codexdev) with any proof if possible.**",
|
||||
color=0xFF0000
|
||||
)
|
||||
await ctx.reply(embed=embed)
|
||||
72
bot/cogs/events/autoreact.py
Normal file
72
bot/cogs/events/autoreact.py
Normal file
@@ -0,0 +1,72 @@
|
||||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ ║
|
||||
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀ ║
|
||||
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█ ║
|
||||
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀ ║
|
||||
# ║ ║
|
||||
# ║ © 2026 CodeX Devs — All Rights Reserved ║
|
||||
# ║ ║
|
||||
# ║ discord ── https://discord.gg/codexdev ║
|
||||
# ║ youtube ── https://youtube.com/@CodeXDevs ║
|
||||
# ║ github ── https://github.com/RayExo ║
|
||||
# ║ ║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
import aiosqlite
|
||||
import re
|
||||
import asyncio
|
||||
|
||||
class AutoReactListener(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.db_path = 'db/autoreact.db'
|
||||
self.rate_limited_users = set()
|
||||
|
||||
async def get_triggers(self, guild_id):
|
||||
async with aiosqlite.connect(self.db_path) as db:
|
||||
cursor = await db.execute("SELECT trigger, emojis FROM autoreact WHERE guild_id = ?", (guild_id,))
|
||||
return await cursor.fetchall()
|
||||
|
||||
async def add_rate_limit(self, user_id):
|
||||
self.rate_limited_users.add(user_id)
|
||||
await asyncio.sleep(5)
|
||||
self.rate_limited_users.remove(user_id)
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_message(self, message):
|
||||
if message.author.bot or not message.guild:
|
||||
return
|
||||
|
||||
if message.author.id in self.rate_limited_users:
|
||||
return
|
||||
|
||||
triggers = await self.get_triggers(message.guild.id)
|
||||
if not triggers:
|
||||
return
|
||||
|
||||
content = message.content.strip().lower()
|
||||
for trigger, emojis in triggers:
|
||||
if content == trigger:
|
||||
emoji_list = emojis.split()
|
||||
for emoji in emoji_list:
|
||||
try:
|
||||
|
||||
if re.match(r"<a?:\w+:\d+>", emoji):
|
||||
emoji_obj = discord.PartialEmoji.from_str(emoji)
|
||||
else:
|
||||
|
||||
emoji_obj = emoji
|
||||
|
||||
await message.add_reaction(emoji_obj)
|
||||
except discord.errors.NotFound:
|
||||
continue
|
||||
except discord.errors.Forbidden:
|
||||
continue
|
||||
except discord.errors.HTTPException:
|
||||
continue
|
||||
|
||||
await self.add_rate_limit(message.author.id)
|
||||
break
|
||||
|
||||
76
bot/cogs/events/autorole.py
Normal file
76
bot/cogs/events/autorole.py
Normal file
@@ -0,0 +1,76 @@
|
||||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ ║
|
||||
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀ ║
|
||||
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█ ║
|
||||
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀ ║
|
||||
# ║ ║
|
||||
# ║ © 2026 CodeX Devs — All Rights Reserved ║
|
||||
# ║ ║
|
||||
# ║ discord ── https://discord.gg/codexdev ║
|
||||
# ║ youtube ── https://youtube.com/@CodeXDevs ║
|
||||
# ║ github ── https://github.com/RayExo ║
|
||||
# ║ ║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
import discord
|
||||
import aiohttp
|
||||
import aiosqlite
|
||||
import asyncio
|
||||
import logging
|
||||
from discord.ext import commands
|
||||
from core import zyrox, Cog
|
||||
from utils.config import *
|
||||
|
||||
DATABASE_PATH = 'db/autorole.db'
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class Autorole2(Cog):
|
||||
def __init__(self, bot: zyrox):
|
||||
self.bot = bot
|
||||
self.headers = {"Authorization": f"Bot {self.bot.http.token}"}
|
||||
|
||||
async def get_autorole(self, guild_id: int):
|
||||
async with aiosqlite.connect(DATABASE_PATH) as db:
|
||||
async with db.execute("SELECT bots, humans FROM autorole WHERE guild_id = ?", (guild_id,)) as cursor:
|
||||
row = await cursor.fetchone()
|
||||
if row:
|
||||
bots, humans = row
|
||||
bots = [int(role_id) for role_id in bots.replace('[', '').replace(']', '').replace(' ', '').split(',') if role_id]
|
||||
humans = [int(role_id) for role_id in humans.replace('[', '').replace(']', '').split(',') if role_id]
|
||||
return {"bots": bots, "humans": humans}
|
||||
else:
|
||||
return {"bots": [], "humans": []}
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_member_join(self, member):
|
||||
data = await self.get_autorole(member.guild.id)
|
||||
bot_roles = data["bots"]
|
||||
human_roles = data["humans"]
|
||||
|
||||
if member.bot:
|
||||
roles_to_add = bot_roles
|
||||
else:
|
||||
roles_to_add = human_roles
|
||||
|
||||
for role_id in roles_to_add:
|
||||
role = member.guild.get_role(role_id)
|
||||
if role:
|
||||
try:
|
||||
await member.add_roles(role, reason=f"{BRAND_NAME} | Autoroles")
|
||||
except discord.Forbidden:
|
||||
print(f"Bot lacks permissions to add role in a guild during Autorole Event .")
|
||||
except discord.HTTPException as e:
|
||||
if e.status == 429:
|
||||
retry_after = e.response.headers.get('Retry-After')
|
||||
if retry_after:
|
||||
retry_after = float(retry_after)
|
||||
print(f"(Autorole) Rate limit encountered. Retrying after {retry_after} seconds.")
|
||||
await asyncio.sleep(retry_after)
|
||||
await member.add_roles(role, reason=f"{BRAND_NAME} | Autoroles")
|
||||
except discord.errors.RateLimited as e:
|
||||
print(f"Rate limit encountered: {e}. Retrying in {e.retry_after} seconds.")
|
||||
await asyncio.sleep(e.retry_after)
|
||||
await member.add_roles(role, reason=f"{BRAND_NAME} | Autoroles")
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error in Autorole: {e}")
|
||||
|
||||
115
bot/cogs/events/greet2.py
Normal file
115
bot/cogs/events/greet2.py
Normal file
@@ -0,0 +1,115 @@
|
||||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ ║
|
||||
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀ ║
|
||||
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█ ║
|
||||
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀ ║
|
||||
# ║ ║
|
||||
# ║ © 2026 CodeX Devs — All Rights Reserved ║
|
||||
# ║ ║
|
||||
# ║ discord ── https://discord.gg/codexdev ║
|
||||
# ║ youtube ── https://youtube.com/@CodeXDevs ║
|
||||
# ║ github ── https://github.com/RayExo ║
|
||||
# ║ ║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
import discord
|
||||
import aiosqlite
|
||||
import json
|
||||
import re
|
||||
import asyncio
|
||||
from discord.ext import commands
|
||||
|
||||
class greet(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.join_queue = {}
|
||||
self.processing = set()
|
||||
|
||||
async def safe_format(self, text, placeholders):
|
||||
placeholders_lower = {k.lower(): v for k, v in placeholders.items()}
|
||||
def replace_var(match):
|
||||
var_name = match.group(1).lower()
|
||||
return str(placeholders_lower.get(var_name, f"{{{var_name}}}"))
|
||||
return re.sub(r"\{(\w+)\}", replace_var, text or "")
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_member_join(self, member):
|
||||
if member.guild.id not in self.join_queue:
|
||||
self.join_queue[member.guild.id] = []
|
||||
self.join_queue[member.guild.id].append(member)
|
||||
if member.guild.id not in self.processing:
|
||||
self.processing.add(member.guild.id)
|
||||
await self.process_queue(member.guild)
|
||||
|
||||
async def process_queue(self, guild):
|
||||
while self.join_queue[guild.id]:
|
||||
member = self.join_queue[guild.id].pop(0)
|
||||
async with aiosqlite.connect("db/welcome.db") as db:
|
||||
async with db.execute("SELECT welcome_type, welcome_message, channel_id, embed_data, auto_delete_duration FROM welcome WHERE guild_id = ?", (guild.id,)) as cursor:
|
||||
row = await cursor.fetchone()
|
||||
if row is None:
|
||||
continue
|
||||
welcome_type, welcome_message, channel_id, embed_data, auto_delete_duration = row
|
||||
welcome_channel = self.bot.get_channel(channel_id)
|
||||
if not welcome_channel:
|
||||
continue
|
||||
placeholders = {
|
||||
"user": member.mention,
|
||||
"user_avatar": member.avatar.url if member.avatar else member.default_avatar.url,
|
||||
"user_name": member.name,
|
||||
"user_id": member.id,
|
||||
"user_nick": member.display_name,
|
||||
"user_joindate": member.joined_at.strftime("%a, %b %d, %Y"),
|
||||
"user_createdate": member.created_at.strftime("%a, %b %d, %Y"),
|
||||
"server_name": guild.name,
|
||||
"server_id": guild.id,
|
||||
"server_membercount": guild.member_count,
|
||||
"server_icon": guild.icon.url if guild.icon else "https://cdn.discordapp.com/embed/avatars/0.png",
|
||||
"timestamp": discord.utils.format_dt(discord.utils.utcnow())
|
||||
}
|
||||
try:
|
||||
if welcome_type == "simple" and welcome_message:
|
||||
content = await self.safe_format(welcome_message, placeholders)
|
||||
sent_message = await welcome_channel.send(content=content)
|
||||
elif welcome_type == "embed" and embed_data:
|
||||
embed_info = json.loads(embed_data)
|
||||
color_value = embed_info.get("color", None)
|
||||
embed_color = 0x2f3136
|
||||
if color_value and isinstance(color_value, str) and color_value.startswith("#"):
|
||||
embed_color = discord.Color(int(color_value.lstrip("#"), 16))
|
||||
elif isinstance(color_value, int):
|
||||
embed_color = discord.Color(color_value)
|
||||
content = await self.safe_format(embed_info.get("message", ""), placeholders) or None
|
||||
embed = discord.Embed(
|
||||
title=await self.safe_format(embed_info.get("title", ""), placeholders),
|
||||
description=await self.safe_format(embed_info.get("description", ""), placeholders),
|
||||
color=embed_color
|
||||
)
|
||||
embed.timestamp = discord.utils.utcnow()
|
||||
if embed_info.get("footer_text"):
|
||||
embed.set_footer(
|
||||
text=await self.safe_format(embed_info["footer_text"], placeholders),
|
||||
icon_url=await self.safe_format(embed_info.get("footer_icon", ""), placeholders)
|
||||
)
|
||||
if embed_info.get("author_name"):
|
||||
embed.set_author(
|
||||
name=await self.safe_format(embed_info["author_name"], placeholders),
|
||||
icon_url=await self.safe_format(embed_info.get("author_icon", ""), placeholders)
|
||||
)
|
||||
if embed_info.get("thumbnail"):
|
||||
embed.set_thumbnail(url=await self.safe_format(embed_info["thumbnail"], placeholders))
|
||||
if embed_info.get("image"):
|
||||
embed.set_image(url=await self.safe_format(embed_info["image"], placeholders))
|
||||
sent_message = await welcome_channel.send(content=content, embed=embed)
|
||||
if auto_delete_duration:
|
||||
await sent_message.delete(delay=auto_delete_duration)
|
||||
except discord.Forbidden:
|
||||
continue
|
||||
except discord.HTTPException as e:
|
||||
if e.code == 50035 or e.status == 429:
|
||||
await asyncio.sleep(1)
|
||||
self.join_queue[guild.id].append(member)
|
||||
continue
|
||||
await asyncio.sleep(2)
|
||||
self.processing.remove(guild.id)
|
||||
|
||||
155
bot/cogs/events/mention.py
Normal file
155
bot/cogs/events/mention.py
Normal file
@@ -0,0 +1,155 @@
|
||||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ ║
|
||||
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀ ║
|
||||
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█ ║
|
||||
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀ ║
|
||||
# ║ ║
|
||||
# ║ © 2026 CodeX Devs — All Rights Reserved ║
|
||||
# ║ ║
|
||||
# ║ discord ── https://discord.gg/codexdev ║
|
||||
# ║ youtube ── https://youtube.com/@CodeXDevs ║
|
||||
# ║ github ── https://github.com/RayExo ║
|
||||
# ║ ║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
from utils import getConfig
|
||||
from utils.config import BotName
|
||||
import discord
|
||||
from utils.emoji import ARROWRED, CODEBASE, HEART3, INDEX, ZYROXLINKS
|
||||
from discord.ui import LayoutView, TextDisplay, Separator, Container, ActionRow, Select
|
||||
from discord.ext import commands
|
||||
from utils.Tools import get_ignore_data
|
||||
import aiosqlite
|
||||
|
||||
|
||||
class MentionSelectView(LayoutView):
|
||||
def __init__(self, message, bot, prefix):
|
||||
super().__init__(timeout=300)
|
||||
self.message = message
|
||||
self.bot = bot
|
||||
self.prefix = prefix
|
||||
|
||||
self.select = Select(
|
||||
placeholder=f"Start With {BotName}",
|
||||
options=[
|
||||
discord.SelectOption(
|
||||
label="Home",
|
||||
emoji=INDEX,
|
||||
description="Go to the main menu",
|
||||
),
|
||||
discord.SelectOption(
|
||||
label="Developer Info",
|
||||
emoji=CODEBASE,
|
||||
description="See who created me",
|
||||
),
|
||||
discord.SelectOption(
|
||||
label="Links",
|
||||
emoji=ZYROXLINKS,
|
||||
description="Useful bot links",
|
||||
),
|
||||
],
|
||||
)
|
||||
self.select.callback = self.on_select
|
||||
|
||||
self.add_item(
|
||||
Container(
|
||||
TextDisplay(f"**{message.guild.name}**"),
|
||||
Separator(visible=True),
|
||||
TextDisplay(
|
||||
f"> {HEART3} **Hey {message.author.mention}**\n"
|
||||
f"> {ARROWRED} **Prefix For This Server: `{prefix}`**\n\n"
|
||||
f"___Type `{prefix}help` for more information.___"
|
||||
),
|
||||
ActionRow(self.select),
|
||||
)
|
||||
)
|
||||
|
||||
async def on_select(self, interaction: discord.Interaction):
|
||||
if interaction.user.id != self.message.author.id:
|
||||
await interaction.response.send_message(
|
||||
"This menu is not for you!", ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
selected = interaction.data.get("values", ["Home"])[0]
|
||||
|
||||
if selected == "Home":
|
||||
content = (
|
||||
f"> {HEART3} **Hey {interaction.user.mention}**\n"
|
||||
f"> {ARROWRED} **Prefix For This Server: `{self.prefix}`**\n\n"
|
||||
f"___Type `{self.prefix}help` for more information.___"
|
||||
)
|
||||
elif selected == "Developer Info":
|
||||
content = (
|
||||
"There are only 2 Founders Who Created Me. Thanks You To Them 💞.\n\n"
|
||||
"**The Founder**\n"
|
||||
"**[01]. [Ray](https://discord.com/users/870179991462236170)**\n**[02]. [runxking](https://discord.com/users/767979794411028491)**"
|
||||
)
|
||||
elif selected == "Links":
|
||||
content = (
|
||||
f"**[Invite {BotName}](https://discord.com/oauth2/authorize?client_id=1396114795102470196)**\n"
|
||||
"**[Join Support Server](https://discord.gg/codexdev)**"
|
||||
)
|
||||
|
||||
new_container = Container(
|
||||
TextDisplay(f"**{self.message.guild.name}**"),
|
||||
Separator(visible=True),
|
||||
TextDisplay(content),
|
||||
ActionRow(self.select),
|
||||
)
|
||||
|
||||
self.clear_items()
|
||||
self.add_item(new_container)
|
||||
|
||||
await interaction.response.edit_message(view=self)
|
||||
|
||||
|
||||
class Mention(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.color = 0xFF0000
|
||||
self.bot_name = BotName
|
||||
|
||||
async def is_blacklisted(self, message):
|
||||
async with aiosqlite.connect("db/block.db") as db:
|
||||
cursor = await db.execute(
|
||||
"SELECT 1 FROM guild_blacklist WHERE guild_id = ?", (message.guild.id,)
|
||||
)
|
||||
if await cursor.fetchone():
|
||||
return True
|
||||
cursor = await db.execute(
|
||||
"SELECT 1 FROM user_blacklist WHERE user_id = ?", (message.author.id,)
|
||||
)
|
||||
if await cursor.fetchone():
|
||||
return True
|
||||
return False
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_message(self, message: discord.Message):
|
||||
if message.author.bot or not message.guild:
|
||||
return
|
||||
|
||||
if await self.is_blacklisted(message):
|
||||
return
|
||||
|
||||
ignore_data = await get_ignore_data(message.guild.id)
|
||||
if (
|
||||
str(message.author.id) in ignore_data["user"]
|
||||
or str(message.channel.id) in ignore_data["channel"]
|
||||
):
|
||||
return
|
||||
|
||||
if (
|
||||
self.bot.user in message.mentions
|
||||
and len(message.content.strip().split()) == 1
|
||||
):
|
||||
guild_id = message.guild.id
|
||||
data = await getConfig(guild_id)
|
||||
prefix = data["prefix"]
|
||||
|
||||
view = MentionSelectView(message, self.bot, prefix)
|
||||
await message.channel.send(view=view)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Mention(bot))
|
||||
67
bot/cogs/events/mentionold.txt
Normal file
67
bot/cogs/events/mentionold.txt
Normal file
@@ -0,0 +1,67 @@
|
||||
from utils import getConfig
|
||||
import discord
|
||||
from utils.emoji import ARROWRED, HEART3
|
||||
from discord.ext import commands
|
||||
from utils.Tools import get_ignore_data
|
||||
import aiosqlite
|
||||
|
||||
class Mention(commands.Cog):
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.color = 0xFF0000
|
||||
self.bot_name = "Zyrox X"
|
||||
|
||||
async def is_blacklisted(self, message):
|
||||
async with aiosqlite.connect("db/block.db") as db:
|
||||
cursor = await db.execute("SELECT 1 FROM guild_blacklist WHERE guild_id = ?", (message.guild.id,))
|
||||
if await cursor.fetchone():
|
||||
return True
|
||||
|
||||
cursor = await db.execute("SELECT 1 FROM user_blacklist WHERE user_id = ?", (message.author.id,))
|
||||
if await cursor.fetchone():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_message(self, message):
|
||||
if message.author.bot or not message.guild:
|
||||
return
|
||||
|
||||
if await self.is_blacklisted(message):
|
||||
return
|
||||
|
||||
ignore_data = await get_ignore_data(message.guild.id)
|
||||
if str(message.author.id) in ignore_data["user"] or str(message.channel.id) in ignore_data["channel"]:
|
||||
return
|
||||
|
||||
if message.reference and message.reference.resolved:
|
||||
if isinstance(message.reference.resolved, discord.Message):
|
||||
if message.reference.resolved.author.id == self.bot.user.id:
|
||||
return
|
||||
|
||||
guild_id = message.guild.id
|
||||
data = await getConfig(guild_id)
|
||||
prefix = data["prefix"]
|
||||
|
||||
if self.bot.user in message.mentions:
|
||||
if len(message.content.strip().split()) == 1:
|
||||
embed = discord.Embed(
|
||||
title=f"{message.guild.name}",
|
||||
color=self.color,
|
||||
description=f"> {HEART3} **Hey {message.author.mention}**\n> {ARROWRED} **Prefix For This Server `{prefix}`**\n\n___Type `{prefix}help` for more information.___"
|
||||
)
|
||||
embed.set_thumbnail(url=self.bot.user.avatar.url)
|
||||
embed.set_footer(text="Powered by Zyrox Development™", icon_url=self.bot.user.avatar.url)
|
||||
|
||||
buttons = [
|
||||
discord.ui.Button(label="Invite", style=discord.ButtonStyle.link, url="https://discord.com/oauth2/authorize?client_id=1396114795102470196&permissions=8&integration_type=0&scope=bot+applications.commands"),
|
||||
discord.ui.Button(label="Support", style=discord.ButtonStyle.link, url="https://discord.gg/codexdev"),
|
||||
]
|
||||
|
||||
view = discord.ui.View()
|
||||
for button in buttons:
|
||||
view.add_item(button)
|
||||
|
||||
await message.channel.send(embed=embed, view=view)
|
||||
223
bot/cogs/events/on_guild.py
Normal file
223
bot/cogs/events/on_guild.py
Normal file
@@ -0,0 +1,223 @@
|
||||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ ║
|
||||
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀ ║
|
||||
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█ ║
|
||||
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀ ║
|
||||
# ║ ║
|
||||
# ║ © 2026 CodeX Devs — All Rights Reserved ║
|
||||
# ║ ║
|
||||
# ║ discord ── https://discord.gg/codexdev ║
|
||||
# ║ youtube ── https://youtube.com/@CodeXDevs ║
|
||||
# ║ github ── https://github.com/RayExo ║
|
||||
# ║ ║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
from discord.ext import commands
|
||||
from core import zyrox, Cog
|
||||
import discord
|
||||
from utils.emoji import ARROWRED, KING, ZBOT, ZHUMAN, ZROCKET
|
||||
import logging
|
||||
from discord.ui import View, Button, Select
|
||||
from utils.config import *
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="\x1b[38;5;197m[\x1b[0m%(asctime)s\x1b[38;5;197m]\x1b[0m -> \x1b[38;5;197m%(message)s\x1b[0m",
|
||||
datefmt="%H:%M:%S",
|
||||
)
|
||||
|
||||
client = zyrox()
|
||||
|
||||
|
||||
class Guild(Cog):
|
||||
def __init__(self, client: zyrox):
|
||||
self.client = client
|
||||
self.recently_removed_guilds = set()
|
||||
self._removal_timestamps = {}
|
||||
|
||||
@client.event
|
||||
@commands.Cog.listener(name="on_guild_join")
|
||||
async def on_guild_add(self, guild):
|
||||
try:
|
||||
rope = [
|
||||
inv
|
||||
for inv in await guild.invites()
|
||||
if inv.max_age == 0 and inv.max_uses == 0
|
||||
]
|
||||
ch = LOG_CHANNEL_ID
|
||||
if not ch:
|
||||
return
|
||||
me = self.client.get_channel(ch)
|
||||
if me is None:
|
||||
logging.error(f"Channel with ID {ch} not found.")
|
||||
return
|
||||
|
||||
channels = len(set(self.client.get_all_channels()))
|
||||
embed = discord.Embed(title=f"{guild.name}'s Information", color=0xFF0000)
|
||||
|
||||
embed.set_author(name="Guild Joined")
|
||||
embed.set_footer(text=f"Added in {guild.name}")
|
||||
|
||||
embed.add_field(
|
||||
name="**__About__**",
|
||||
value=f"**Name : ** {guild.name}\n**ID :** {guild.id}\n**Owner {KING} :** {guild.owner} (<@{guild.owner_id}>)\n**Created At : **{guild.created_at.month}/{guild.created_at.day}/{guild.created_at.year}\n**Members :** {len(guild.members)}",
|
||||
inline=False,
|
||||
)
|
||||
embed.add_field(
|
||||
name="**__Description__**",
|
||||
value=f"""{guild.description}""",
|
||||
inline=False,
|
||||
)
|
||||
embed.add_field(
|
||||
name="**__Members__**",
|
||||
value=f"""{ZROCKET} Members : {len(guild.members)}\n {ZHUMAN} Humans : {len(list(filter(lambda m: not m.bot, guild.members)))}\n {ZBOT} Bots : {len(list(filter(lambda m: m.bot, guild.members)))}
|
||||
""",
|
||||
inline=False,
|
||||
)
|
||||
embed.add_field(
|
||||
name="**__Channels__**",
|
||||
value=f"""
|
||||
Categories : {len(guild.categories)}
|
||||
Text Channels : {len(guild.text_channels)}
|
||||
Voice Channels : {len(guild.voice_channels)}
|
||||
Threads : {len(guild.threads)}
|
||||
""",
|
||||
inline=False,
|
||||
)
|
||||
embed.add_field(
|
||||
name="__Bot Stats:__",
|
||||
value=f"Servers: `{len(self.client.guilds)}`\nUsers: `{len(self.client.users)}`\nChannels: `{channels}`",
|
||||
inline=False,
|
||||
)
|
||||
|
||||
if guild.icon is not None:
|
||||
embed.set_thumbnail(url=guild.icon.url)
|
||||
|
||||
embed.timestamp = discord.utils.utcnow()
|
||||
await me.send(
|
||||
f"{rope[0]}" if rope else "No Pre-Made Invite Found", embed=embed
|
||||
)
|
||||
|
||||
if not guild.chunked:
|
||||
await guild.chunk()
|
||||
|
||||
embed = discord.Embed(
|
||||
description=f"{ARROWRED} Prefix For This Server is `>`\n{ARROWRED} Get Started with `>help`\n{ARROWRED} For detailed guides, FAQ & information, visit our **[Support Server](https://discord.gg/codexdev)**",
|
||||
color=0xFF0000,
|
||||
)
|
||||
embed.set_author(
|
||||
name="Thanks for adding me!", icon_url=guild.me.display_avatar.url
|
||||
)
|
||||
embed.set_footer(
|
||||
text=f"Powered by {BRAND_NAME}™",
|
||||
)
|
||||
if guild.icon:
|
||||
embed.set_thumbnail(url=guild.icon.url)
|
||||
|
||||
support = Button(
|
||||
label="Support",
|
||||
style=discord.ButtonStyle.link,
|
||||
url=f"https://discord.gg/codexdev",
|
||||
)
|
||||
|
||||
view = View()
|
||||
view.add_item(support)
|
||||
channel = discord.utils.get(guild.text_channels, name="general")
|
||||
if not channel:
|
||||
channels = [
|
||||
channel
|
||||
for channel in guild.text_channels
|
||||
if channel.permissions_for(guild.me).send_messages
|
||||
]
|
||||
if channels:
|
||||
channel = channels[0]
|
||||
else:
|
||||
logging.error(
|
||||
f"No channel found with send permissions in guild: {guild.name}"
|
||||
)
|
||||
return
|
||||
|
||||
await channel.send(embed=embed, view=view)
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Error in on_guild_join: {e}")
|
||||
|
||||
@client.event
|
||||
@commands.Cog.listener(name="on_guild_remove")
|
||||
async def on_guild_remove(self, guild):
|
||||
import time
|
||||
|
||||
current_time = time.time()
|
||||
|
||||
if guild.id in self.recently_removed_guilds:
|
||||
last_removal = self._removal_timestamps.get(guild.id, 0)
|
||||
if current_time - last_removal < 60:
|
||||
return
|
||||
|
||||
self.recently_removed_guilds.add(guild.id)
|
||||
self._removal_timestamps[guild.id] = current_time
|
||||
|
||||
if len(self.recently_removed_guilds) > 100:
|
||||
self.recently_removed_guilds.clear()
|
||||
|
||||
try:
|
||||
ch = LOG_CHANNEL_ID
|
||||
if not ch:
|
||||
return
|
||||
idk = self.client.get_channel(ch)
|
||||
if idk is None:
|
||||
logging.error(f"Channel with ID {ch} not found.")
|
||||
return
|
||||
|
||||
channels = len(set(self.client.get_all_channels()))
|
||||
embed = discord.Embed(title=f"{guild.name}'s Information", color=0xFF0000)
|
||||
|
||||
embed.set_author(name="Guild Removed")
|
||||
embed.set_footer(text=f"{guild.name}")
|
||||
|
||||
embed.add_field(
|
||||
name="**__About__**",
|
||||
value=f"**Name : ** {guild.name}\n**ID :** {guild.id}\n**Owner {KING} :** {guild.owner} (<@{guild.owner_id}>)\n**Created At : **{guild.created_at.month}/{guild.created_at.day}/{guild.created_at.year}\n**Members :** {len(guild.members)}",
|
||||
inline=False,
|
||||
)
|
||||
embed.add_field(
|
||||
name="**__Description__**",
|
||||
value=f"""{guild.description}""",
|
||||
inline=False,
|
||||
)
|
||||
|
||||
embed.add_field(
|
||||
name="**__Members__**",
|
||||
value=f"""
|
||||
Members : {len(guild.members)}
|
||||
Humans : {len(list(filter(lambda m: not m.bot, guild.members)))}
|
||||
Bots : {len(list(filter(lambda m: m.bot, guild.members)))}
|
||||
""",
|
||||
inline=False,
|
||||
)
|
||||
embed.add_field(
|
||||
name="**__Channels__**",
|
||||
value=f"""
|
||||
Categories : {len(guild.categories)}
|
||||
Text Channels : {len(guild.text_channels)}
|
||||
Voice Channels : {len(guild.voice_channels)}
|
||||
Threads : {len(guild.threads)}
|
||||
""",
|
||||
inline=False,
|
||||
)
|
||||
embed.add_field(
|
||||
name="__Bot Stats:__",
|
||||
value=f"Servers: `{len(self.client.guilds)}`\nUsers: `{len(self.client.users)}`\nChannels: `{channels}`",
|
||||
inline=False,
|
||||
)
|
||||
|
||||
if guild.icon is not None:
|
||||
embed.set_thumbnail(url=guild.icon.url)
|
||||
|
||||
embed.timestamp = discord.utils.utcnow()
|
||||
await idk.send(embed=embed)
|
||||
except Exception as e:
|
||||
logging.error(f"Error in on_guild_remove: {e}")
|
||||
|
||||
|
||||
# client.add_cog(Guild(client))
|
||||
57
bot/cogs/events/react.py
Normal file
57
bot/cogs/events/react.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ ║
|
||||
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀ ║
|
||||
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█ ║
|
||||
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀ ║
|
||||
# ║ ║
|
||||
# ║ © 2026 CodeX Devs — All Rights Reserved ║
|
||||
# ║ ║
|
||||
# ║ discord ── https://discord.gg/codexdev ║
|
||||
# ║ youtube ── https://youtube.com/@CodeXDevs ║
|
||||
# ║ github ── https://github.com/RayExo ║
|
||||
# ║ ║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
import discord
|
||||
from utils.emoji import ACTIVE_DEVELOPER, BLACKCROWN, MINGLE, STAFF
|
||||
from discord.ext import commands
|
||||
from utils.config import OWNER_IDS
|
||||
import asyncio
|
||||
|
||||
class React(commands.Cog):
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_message(self, message):
|
||||
if message.author.bot:
|
||||
return
|
||||
for owner in self.bot.owner_ids:
|
||||
if f"<@{owner}>" in message.content:
|
||||
try:
|
||||
# Primary owner (first in OWNER_IDS) gets an extra emoji
|
||||
if owner == OWNER_IDS[0]:
|
||||
emojis = [
|
||||
BLACKCROWN,
|
||||
ACTIVE_DEVELOPER,
|
||||
STAFF,
|
||||
MINGLE,
|
||||
]
|
||||
else:
|
||||
emojis = [
|
||||
BLACKCROWN,
|
||||
ACTIVE_DEVELOPER,
|
||||
STAFF,
|
||||
]
|
||||
|
||||
for emoji in emojis:
|
||||
try:
|
||||
await message.add_reaction(emoji)
|
||||
except discord.HTTPException:
|
||||
pass # ignore if emoji is invalid or not accessible
|
||||
|
||||
except discord.errors.RateLimited as e:
|
||||
await asyncio.sleep(e.retry_after)
|
||||
except Exception as e:
|
||||
print(f"An unexpected error occurred Auto react owner mention: {e}")
|
||||
208
bot/cogs/events/stickymessage.py
Normal file
208
bot/cogs/events/stickymessage.py
Normal file
@@ -0,0 +1,208 @@
|
||||
# ╔══════════════════════════════════════════════════════════════════╗
|
||||
# ║ ║
|
||||
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀ ║
|
||||
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█ ║
|
||||
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀ ║
|
||||
# ║ ║
|
||||
# ║ © 2026 CodeX Devs — All Rights Reserved ║
|
||||
# ║ ║
|
||||
# ║ discord ── https://discord.gg/codexdev ║
|
||||
# ║ youtube ── https://youtube.com/@CodeXDevs ║
|
||||
# ║ github ── https://github.com/RayExo ║
|
||||
# ║ ║
|
||||
# ╚══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
import discord
|
||||
import aiosqlite
|
||||
import json
|
||||
import asyncio
|
||||
from discord.ext import commands
|
||||
from utils.config import *
|
||||
|
||||
class StickyMessageListener(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.processing_channels = set()
|
||||
self.last_processed = {}
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_message(self, message):
|
||||
|
||||
if message.author.bot:
|
||||
return
|
||||
|
||||
if not hasattr(message, "guild") or message.guild is None:
|
||||
return
|
||||
|
||||
if message.channel.id in self.processing_channels:
|
||||
return
|
||||
|
||||
async with aiosqlite.connect("db/stickymessages.db") as db:
|
||||
cursor = await db.execute("""
|
||||
SELECT id, message_type, message_content, embed_data, last_message_id,
|
||||
enabled, delay_seconds, auto_delete_after, ignore_bots,
|
||||
ignore_commands, trigger_count, current_count
|
||||
FROM sticky_messages
|
||||
WHERE guild_id = ? AND channel_id = ? AND enabled = 1
|
||||
""", (message.guild.id, message.channel.id))
|
||||
sticky_data = await cursor.fetchone()
|
||||
|
||||
if not sticky_data:
|
||||
return
|
||||
|
||||
(
|
||||
sticky_id, msg_type, msg_content, embed_data, last_msg_id,
|
||||
enabled, delay_seconds, auto_delete_after, ignore_bots,
|
||||
ignore_commands, trigger_count, current_count
|
||||
) = sticky_data
|
||||
|
||||
if ignore_bots and message.author.bot:
|
||||
return
|
||||
|
||||
if ignore_commands and message.content.startswith(await self.get_prefix(message)):
|
||||
return
|
||||
|
||||
self.processing_channels.add(message.channel.id)
|
||||
|
||||
try:
|
||||
new_count = current_count + 1
|
||||
|
||||
if new_count >= trigger_count:
|
||||
await self.update_counter(message.guild.id, message.channel.id, 0)
|
||||
|
||||
if last_msg_id:
|
||||
try:
|
||||
old_message = await message.channel.fetch_message(last_msg_id)
|
||||
await old_message.delete()
|
||||
except (discord.NotFound, discord.Forbidden, discord.HTTPException):
|
||||
pass
|
||||
|
||||
await asyncio.sleep(delay_seconds)
|
||||
|
||||
new_sticky_msg = await self.send_sticky_message(
|
||||
message.channel, msg_type, msg_content, embed_data
|
||||
)
|
||||
|
||||
if new_sticky_msg:
|
||||
async with aiosqlite.connect("db/stickymessages.db") as db:
|
||||
await db.execute("""
|
||||
UPDATE sticky_messages
|
||||
SET last_message_id = ?
|
||||
WHERE guild_id = ? AND channel_id = ?
|
||||
""", (new_sticky_msg.id, message.guild.id, message.channel.id))
|
||||
await db.commit()
|
||||
|
||||
if auto_delete_after > 0:
|
||||
asyncio.create_task(
|
||||
self.auto_delete_message(new_sticky_msg, auto_delete_after)
|
||||
)
|
||||
else:
|
||||
await self.update_counter(message.guild.id, message.channel.id, new_count)
|
||||
|
||||
except Exception:
|
||||
pass
|
||||
finally:
|
||||
self.processing_channels.discard(message.channel.id)
|
||||
|
||||
async def get_prefix(self, message):
|
||||
try:
|
||||
async with aiosqlite.connect("db/prefix.db") as db:
|
||||
cursor = await db.execute(
|
||||
"SELECT prefix FROM prefix WHERE guild_id = ?",
|
||||
(message.guild.id,)
|
||||
)
|
||||
result = await cursor.fetchone()
|
||||
return result[0] if result else "!"
|
||||
except:
|
||||
return "!"
|
||||
|
||||
async def update_counter(self, guild_id, channel_id, new_count):
|
||||
async with aiosqlite.connect("db/stickymessages.db") as db:
|
||||
await db.execute("""
|
||||
UPDATE sticky_messages
|
||||
SET current_count = ?
|
||||
WHERE guild_id = ? AND channel_id = ?
|
||||
""", (new_count, guild_id, channel_id))
|
||||
await db.commit()
|
||||
|
||||
async def send_sticky_message(self, channel, msg_type, msg_content, embed_data):
|
||||
try:
|
||||
if msg_type == "plain" and msg_content:
|
||||
return await channel.send(content=msg_content)
|
||||
|
||||
elif msg_type == "embed" and embed_data:
|
||||
try:
|
||||
data = json.loads(embed_data)
|
||||
embed = discord.Embed(color=discord.Color.red())
|
||||
|
||||
if data.get("title"):
|
||||
embed.title = data["title"]
|
||||
|
||||
if data.get("description"):
|
||||
embed.description = data["description"]
|
||||
|
||||
if data.get("color"):
|
||||
try:
|
||||
color_str = data["color"]
|
||||
if color_str.startswith("#"):
|
||||
embed.color = discord.Color(
|
||||
int(color_str.lstrip("#"), 16)
|
||||
)
|
||||
except:
|
||||
embed.color = discord.Color.red()
|
||||
|
||||
if data.get("footer"):
|
||||
embed.set_footer(text=data["footer"])
|
||||
else:
|
||||
embed.set_footer(text=f"{BRAND_NAME} Development")
|
||||
|
||||
embed.timestamp = discord.utils.utcnow()
|
||||
return await channel.send(embed=embed)
|
||||
|
||||
except json.JSONDecodeError:
|
||||
return await channel.send(content="*[Embed data corrupted]*")
|
||||
|
||||
except (discord.Forbidden, discord.HTTPException):
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return None
|
||||
|
||||
async def auto_delete_message(self, message, delay):
|
||||
try:
|
||||
await asyncio.sleep(delay)
|
||||
await message.delete()
|
||||
except (discord.NotFound, discord.Forbidden, discord.HTTPException):
|
||||
pass
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_guild_channel_delete(self, channel):
|
||||
try:
|
||||
async with aiosqlite.connect("db/stickymessages.db") as db:
|
||||
await db.execute(
|
||||
"DELETE FROM sticky_messages WHERE channel_id = ?",
|
||||
(channel.id,)
|
||||
)
|
||||
await db.commit()
|
||||
except:
|
||||
pass
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_guild_remove(self, guild):
|
||||
try:
|
||||
async with aiosqlite.connect("db/stickymessages.db") as db:
|
||||
await db.execute(
|
||||
"DELETE FROM sticky_messages WHERE guild_id = ?",
|
||||
(guild.id,)
|
||||
)
|
||||
await db.execute(
|
||||
"DELETE FROM sticky_settings WHERE guild_id = ?",
|
||||
(guild.id,)
|
||||
)
|
||||
await db.commit()
|
||||
except:
|
||||
pass
|
||||
|
||||
async def setup(bot):
|
||||
await bot.add_cog(StickyMessageListener(bot))
|
||||
Reference in New Issue
Block a user