import discord, aiohttp, aiofiles, zipfile, re from discord.ext import commands from discord import app_commands from discord.ui import Button, View from io import BytesIO class server(commands.Cog): def __init__(self, bot): self.bot = bot async def get_image_data(self, url): async with aiohttp.ClientSession() as session: async with session.get(url) as resp: if resp.status != 200: raise Exception('Failed to download image.') return await resp.read() def parse_duration(self, duration_str): pattern = re.compile(r"(?:(\d{1,2})h)?(?:(\d{1,2})m)?(?:(\d{1,2})s)?") match = pattern.fullmatch(duration_str) if not match: return None hours, minutes, seconds = match.groups(default='0') total_seconds = int(hours) * 3600 + int(minutes) * 60 + int(seconds) return total_seconds @commands.hybrid_command() @commands.has_permissions(manage_guild=True) async def seticon(self, ctx, url: str): try: data = await self.get_image_data(url) await ctx.guild.edit(icon=data) await ctx.send('Guild icon updated successfully.') except Exception as e: await ctx.send(f'An error occurred: {e}') @commands.hybrid_command(name="setsplashbackground", aliases=["ssb"]) @commands.has_permissions(manage_guild=True) async def setsplashbackground(self, ctx, url: str): try: data = await self.get_image_data(url) await ctx.guild.edit(splash=data) await ctx.send('Guild splash background updated successfully.') except Exception as e: await ctx.send(f'An error occurred: {e}') @commands.hybrid_command(name="setbanner", aliases=["sb"]) @commands.has_permissions(manage_guild=True) async def setbanner(self, ctx, url: str): try: data = await self.get_image_data(url) await ctx.guild.edit(banner=data) await ctx.send('Guild banner updated successfully.') except Exception as e: await ctx.send(f'An error occurred: {e}') @commands.hybrid_command() @commands.has_permissions(manage_messages=True) async def unpin(self, ctx, message: str = None): try: if message: message_id = int(re.search(r'/(\d+)$', message).group(1)) msg = await ctx.channel.fetch_message(message_id) else: messages = [msg async for msg in ctx.channel.history(limit=2)] msg = messages[1] await msg.unpin() await ctx.send('Message unpinned successfully.') except discord.NotFound: await ctx.send("Message not found.") except Exception as e: await ctx.send(f'An error occurred: {e}') @commands.hybrid_command() @commands.has_permissions(manage_messages=True) async def pin(self, ctx, message: str = None): try: if message: message_id = int(re.search(r'/(\d+)$', message).group(1)) msg = await ctx.channel.fetch_message(message_id) else: messages = [msg async for msg in ctx.channel.history(limit=2)] msg = messages[1] if msg.type != discord.MessageType.default: raise Exception("Cannot pin a system message.") await msg.pin() await ctx.send('Message pinned successfully.') except discord.NotFound: await ctx.send("Message not found.") except Exception as e: await ctx.send(f'An error occurred: {e}') @commands.hybrid_command() async def firstmessage(self, ctx, channel: discord.TextChannel = None): channel = channel or ctx.channel try: first_message = [message async for message in channel.history(limit=1, oldest_first=True)][0] await ctx.send(f'First message: {first_message.jump_url}') except Exception as e: await ctx.send(f'An error occurred: {e}') @app_commands.command(name="createwebhook") @app_commands.checks.has_permissions(manage_webhooks=True) async def createwebhook(self, interaction: discord.Interaction, name: str, channel: discord.TextChannel = None, avatar: discord.Attachment = None): channel = channel or interaction.channel try: if avatar: avatar_url = avatar.url avatar_data = await self.get_image_data(avatar_url) webhook = await channel.create_webhook(name=name, avatar=avatar_data) else: webhook = await channel.create_webhook(name=name) embed = discord.Embed( title="Webhook Created", description=f"||{webhook.url}||\n**ℹ️ Usage**\nYou can use this in any embed builder including Discohook.\n**⚠️ It's a secret**\nIf someone has this URL, they can send to anyone they want and say anything they want including @everyone mentions.", color=0x2b2d31 ) view = View() button = Button(label="Reveal URL", style=discord.ButtonStyle.blurple) view.add_item(button) async def reveal_callback(interaction): await interaction.response.send_message(webhook.url, ephemeral=True) button.callback = reveal_callback await interaction.response.send_message(embed=embed, view=view, ephemeral=True) except Exception as e: await interaction.response.send_message(f'An error occurred: {e}') @commands.hybrid_command() @commands.has_permissions(manage_webhooks=True) async def deletewebhook(self, ctx, identifier: str): try: webhooks = await ctx.channel.webhooks() webhook = discord.utils.get(webhooks, name=identifier) or discord.utils.get(webhooks, url=identifier) if webhook: await webhook.delete() await ctx.send('Webhook deleted successfully.') else: await ctx.send('Webhook not found.') except Exception as e: await ctx.send(f'An error occurred: {e}') @commands.hybrid_command() @commands.has_permissions(administrator=True) async def extractstickers(self, ctx): try: stickers = ctx.guild.stickers if not stickers: return await ctx.send("No stickers found in this server.") async with aiofiles.tempfile.NamedTemporaryFile(delete=False) as temp_file: with zipfile.ZipFile(temp_file.name, "w") as zipf: for sticker in stickers: async with aiohttp.ClientSession() as session: async with session.get(sticker.url) as resp: if resp.status != 200: continue data = await resp.read() zipf.writestr(f"{sticker.name}.{sticker.format}", data) await ctx.author.send(file=discord.File(temp_file.name, "stickers.zip")) await ctx.send("Stickers extracted and sent to your DMs.") except Exception as e: await ctx.send(f'An error occurred: {e}') @commands.hybrid_command() @commands.has_permissions(administrator=True) async def extractemotes(self, ctx): try: emotes = ctx.guild.emojis if not emotes: return await ctx.send("No emotes found in this server.") async with aiofiles.tempfile.NamedTemporaryFile(delete=False) as temp_file: with zipfile.ZipFile(temp_file.name, "w") as zipf: for emote in emotes: async with aiohttp.ClientSession() as session: async with session.get(emote.url) as resp: if resp.status != 200: continue data = await resp.read() zipf.writestr(f"{emote.name}.png", data) await ctx.author.send(file=discord.File(temp_file.name, "emotes.zip")) await ctx.send("Emotes extracted and sent to your DMs.") except Exception as e: await ctx.send(f'An error occurred: {e}') @commands.hybrid_command(name="nsfwtoggle", aliases=["artoggle", "nsfw"]) @commands.has_permissions(manage_channels=True) async def nsfwtoggle(self, ctx): try: await ctx.channel.edit(nsfw=not ctx.channel.is_nsfw()) await ctx.send('Channel NSFW status toggled.') except Exception as e: await ctx.send(f'An error occurred: {e}') @commands.hybrid_command(name="slowmode", aliases=["sm"]) @commands.has_permissions(manage_channels=True) async def slowmode(self, ctx: commands.Context, duration: str = None) -> None: """ Toggles slowmode on the current channel with the specified amount of time. Provide no parameters to disable. """ if duration: slowmode_seconds = self.parse_duration(duration) if slowmode_seconds is None or slowmode_seconds > 21600: await ctx.send("Invalid duration. Please use the format `h`, `m`, `s` (e.g., `1h`, `30m`, `45s`) and ensure the total duration does not exceed 6 hours.") return else: slowmode_seconds = 0 try: await ctx.channel.edit(slowmode_delay=slowmode_seconds) if slowmode_seconds == 0: await ctx.send("Slowmode has been disabled.") else: await ctx.send(f"Slowmode has been set to {slowmode_seconds} seconds.") except Exception as e: await ctx.send(f"An error occurred: {e}") @commands.hybrid_command(name="createchannel", aliases=["cc", "channelcreate"]) @commands.has_permissions(manage_channels=True) async def createchannel(self, ctx, *, name: str): try: await ctx.guild.create_text_channel(name) await ctx.send(f'Channel "{name}" created successfully.') except Exception as e: await ctx.send(f'An error occurred: {e}') @commands.hybrid_command(name="deletechannel", aliases=["dc", "channeldelete"]) @commands.has_permissions(manage_channels=True) async def deletechannel(self, ctx, *, name: str): try: channel = discord.utils.get(ctx.guild.channels, name=name) if channel: await channel.delete() await ctx.send(f'Channel "{name}" deleted successfully.') else: await ctx.send(f'Channel "{name}" not found.') except Exception as e: await ctx.send(f'An error occurred: {e}') @commands.hybrid_command(name="renamechannel", aliases=["rc", "channelrename"]) @commands.has_permissions(manage_channels=True) async def renamechannel(self, ctx, old_name: str, new_name: str): try: channel = discord.utils.get(ctx.guild.channels, name=old_name) if channel: await channel.edit(name=new_name) await ctx.send(f'Channel "{old_name}" renamed to "{new_name}" successfully.') else: await ctx.send(f'Channel "{old_name}" not found.') except Exception as e: await ctx.send(f'An error occurred: {e}') @commands.hybrid_command() @commands.has_permissions(manage_channels=True) async def topic(self, ctx, *, text: str): """Change the topic of the current channel""" try: await ctx.channel.edit(topic=text) await ctx.send('Channel topic updated successfully.') except Exception as e: await ctx.send(f'An error occurred: {e}') @commands.hybrid_command() @commands.has_permissions(manage_roles=True, manage_channels=True) async def permissions(self, ctx, member: discord.Member = None, channel: discord.TextChannel = None): """Check permissions for a member or yourself in a channel""" member = member or ctx.author channel = channel or ctx.channel permissions = channel.permissions_for(member) perms_str = '\n'.join([perm for perm, value in permissions if value]) await ctx.send(f'Permissions for {member.mention} in {channel.mention}:\n```{perms_str}```') @commands.hybrid_group(name="purge", invoke_without_command=True) @commands.has_permissions(manage_messages=True) async def purge(self, ctx: commands.Context) -> None: """ Group command for various purge options """ await ctx.send_help(ctx.command) @purge.command(name="upto") async def purge_upto(self, ctx: commands.Context, message_link: str) -> None: """ Purge messages up to a message link """ try: message = await commands.MessageConverter().convert(ctx, message_link) await ctx.channel.purge(after=message, limit=100) await ctx.send('Messages purged up to the specified message.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="mentions") async def purge_mentions(self, ctx: commands.Context, member: discord.Member) -> None: """ Purge mentions for a member from chat """ try: def check(message): return member.mention in message.content await ctx.channel.purge(limit=100, check=check) await ctx.send(f'Messages mentioning {member.mention} have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="embeds") async def purge_embeds(self, ctx: commands.Context) -> None: """ Purge embeds from chat """ try: def check(message): return bool(message.embeds) await ctx.channel.purge(limit=100, check=check) await ctx.send('Messages with embeds have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="webhooks") async def purge_webhooks(self, ctx: commands.Context) -> None: """ Purge messages from webhooks in chat """ try: def check(message): return message.webhook_id is not None await ctx.channel.purge(limit=100, check=check) await ctx.send('Messages from webhooks have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="endswith") async def purge_endswith(self, ctx: commands.Context, substring: str) -> None: """ Purge messages that end with a given substring """ try: def check(message): return message.content.endswith(substring) await ctx.channel.purge(limit=100, check=check) await ctx.send(f'Messages ending with "{substring}" have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="links") async def purge_links(self, ctx: commands.Context) -> None: """ Purge messages containing links """ try: def check(message): return any(part.startswith('http') for part in message.content.split()) await ctx.channel.purge(limit=100, check=check) await ctx.send('Messages containing links have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="startswith") async def purge_startswith(self, ctx: commands.Context, substring: str) -> None: """ Purge messages that start with a given substring """ try: def check(message): return message.content.startswith(substring) await ctx.channel.purge(limit=100, check=check) await ctx.send(f'Messages starting with "{substring}" have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="files") async def purge_files(self, ctx: commands.Context) -> None: """ Purge files/attachments from chat """ try: def check(message): return bool(message.attachments) await ctx.channel.purge(limit=100, check=check) await ctx.send('Messages with files/attachments have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="reactions") async def purge_reactions(self, ctx: commands.Context) -> None: """ Purge reactions from messages in chat """ try: def check(message): return bool(message.reactions) await ctx.channel.purge(limit=100, check=check) await ctx.send('Messages with reactions have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="humans") async def purge_humans(self, ctx: commands.Context) -> None: """ Purge messages from humans in chat """ try: def check(message): return not message.author.bot await ctx.channel.purge(limit=100, check=check) await ctx.send('Messages from humans have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="before") async def purge_before(self, ctx: commands.Context, message_id: int) -> None: """ Purge messages before a given message ID """ try: await ctx.channel.purge(before=discord.Object(id=message_id), limit=100) await ctx.send('Messages before the specified message ID have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="images") async def purge_images(self, ctx: commands.Context) -> None: """ Purge images (including links) from chat """ try: def check(message): return any(part.startswith('http') and (part.endswith('.png') or part.endswith('.jpg') or part.endswith('.jpeg') or part.endswith('.gif')) for part in message.content.split()) or bool(message.attachments) await ctx.channel.purge(limit=100, check=check) await ctx.send('Messages with images have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="emotes") async def purge_emotes(self, ctx: commands.Context) -> None: """ Purge emotes from chat """ try: def check(message): return any(part.startswith('<:') and part.endswith('>') for part in message.content.split()) await ctx.channel.purge(limit=100, check=check) await ctx.send('Messages with emotes have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="stickers") async def purge_stickers(self, ctx: commands.Context) -> None: """ Purge stickers from chat """ try: def check(message): return bool(message.stickers) await ctx.channel.purge(limit=100, check=check) await ctx.send('Messages with stickers have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="contains") async def purge_contains(self, ctx: commands.Context, substring: str) -> None: """ Purge messages containing a given substring """ try: def check(message): return substring in message.content await ctx.channel.purge(limit=100, check=check) await ctx.send(f'Messages containing "{substring}" have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="bots") async def purge_bots(self, ctx: commands.Context) -> None: """ Purge messages from bots in chat """ try: def check(message): return message.author.bot await ctx.channel.purge(limit=100, check=check) await ctx.send('Messages from bots have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') @purge.command(name="after") async def purge_after(self, ctx: commands.Context, message_id: int) -> None: """ Purge messages after a given message ID """ try: await ctx.channel.purge(after=discord.Object(id=message_id), limit=100) await ctx.send('Messages after the specified message ID have been purged.') except Exception as e: await ctx.send(f'An error occurred: {e}') async def setup(bot): await bot.add_cog(server(bot))