from redbot.core import commands, Config from redbot.core.bot import Red import discord import shlex import asyncio class ExtendedCommands(commands.Cog): """Extended command functionality for Red bots.""" def __init__(self, bot: Red): self.bot = bot self.config = Config.get_conf(self, identifier=867530998, force_registration=True) @commands.Cog.listener() async def on_message(self, message: discord.Message): if message.author.bot: return # Check if message starts with any bot prefix prefixes = await self.bot.get_valid_prefixes(message.guild) has_prefix = False content = message.content prefix_used = None for prefix in prefixes: if content.startswith(prefix): has_prefix = True prefix_used = prefix content = content[len(prefix):] break if not has_prefix: return # Check if message contains && if "&&" not in content: return # Stop the original message from triggering commands message._process_commands = False # Split commands and execute them in sequence commands_to_run = [cmd.strip() for cmd in content.split("&&")] async with message.channel.typing(): for cmd in commands_to_run: if not cmd: # Skip empty commands continue # Create a new message object with the command new_message = discord.Message( state=message._state, channel=message.channel, data={ "id": message.id, "content": prefix_used + cmd, # Use the prefix that was used "author": message.author.to_dict(), "pinned": False, "mention_everyone": False, "tts": False, "type": 0, "flags": 0, } ) try: # Process the command await self.bot.process_commands(new_message) # Add a small delay between commands await asyncio.sleep(0.5) except Exception as e: await message.channel.send(f"Error executing command `{cmd}`: {str(e)}") break # Stop executing remaining commands on error @commands.command() async def chain(self, ctx: commands.Context, *, commands_str: str): """Chain multiple commands together using &&. Example: [p]chain ping && info && glb show """ if "&&" not in commands_str: await ctx.send("Please provide multiple commands separated by &&") return commands_to_run = [cmd.strip() for cmd in commands_str.split("&&")] async with ctx.typing(): for cmd in commands_to_run: if not cmd: # Skip empty commands continue # Create a new message object with the command new_message = discord.Message( state=ctx.message._state, channel=ctx.channel, data={ "id": ctx.message.id, "content": ctx.prefix + cmd, "author": ctx.author.to_dict(), "pinned": False, "mention_everyone": False, "tts": False, "type": 0, "flags": 0, } ) try: # Process the command await self.bot.process_commands(new_message) # Add a small delay between commands await asyncio.sleep(0.5) except Exception as e: await ctx.send(f"Error executing command `{cmd}`: {str(e)}") break # Stop executing remaining commands on error