diff --git a/cogs/music/main.py b/cogs/music/main.py index c3c4c5d..0a5d045 100644 --- a/cogs/music/main.py +++ b/cogs/music/main.py @@ -141,37 +141,54 @@ class music(commands.Cog): await queue.play(ctx) - @commands.command( - help="Upload and play an audio file (MP3, MP4, WAV, etc.)", + @commands.hybrid_command( + name="playfile", + description="Upload and play an audio file (MP3, MP4, WAV, etc.)", aliases=['pf', 'file']) - async def playfile(self, ctx: Context): + @app_commands.describe(file="Audio file to play (MP3, MP4, WAV, OGG, FLAC, etc.)") + async def playfile(self, ctx: Context, file: discord.Attachment = None): """Play an uploaded audio file from Discord attachment""" if ctx.guild is None: - await ctx.send("❌ This command must be used in a server!") - return - - # Check if there's an attachment - if not ctx.message.attachments: - await ctx.send( - "❌ No file attached! Please upload an audio file with your message.\n" - "**Supported formats:** MP3, MP4, WAV, OGG, FLAC, M4A, WEBM, AAC, OPUS" - ) + await ctx.send("❌ This command must be used in a server!", ephemeral=True) return server = ctx.guild.id - attachment = ctx.message.attachments[0] + + # Handle both slash command (file parameter) and prefix command (attachment) + if file is not None: + # Slash command with file parameter + attachment = file + elif ctx.message and ctx.message.attachments: + # Prefix command with attached file + attachment = ctx.message.attachments[0] + else: + # No file provided + await ctx.send( + "❌ No file attached! Please upload an audio file.\n" + "**Supported formats:** MP3, MP4, WAV, OGG, FLAC, M4A, WEBM, AAC, OPUS", + ephemeral=True if ctx.interaction else False + ) + return # Validate file extension audio_extensions = ('.mp3', '.mp4', '.wav', '.ogg', '.flac', '.m4a', '.webm', '.aac', '.opus') if not any(attachment.filename.lower().endswith(ext) for ext in audio_extensions): await ctx.send( f"❌ Invalid file type: `{attachment.filename}`\n" - f"**Supported formats:** MP3, MP4, WAV, OGG, FLAC, M4A, WEBM, AAC, OPUS" + f"**Supported formats:** MP3, MP4, WAV, OGG, FLAC, M4A, WEBM, AAC, OPUS", + ephemeral=True if ctx.interaction else False ) return + # Defer for slash commands since processing takes time + if ctx.interaction: + await ctx.defer() + await util.join_vc(ctx) - await ctx.message.add_reaction('📎') + + # Add reaction for prefix commands only + if not ctx.interaction: + await ctx.message.add_reaction('📎') msg = await ctx.send(f"Processing file: `{attachment.filename}`...") @@ -184,7 +201,8 @@ class music(commands.Cog): await msg.delete() if len(audio) == 0: - await ctx.message.add_reaction('🚫') + if not ctx.interaction: + await ctx.message.add_reaction('🚫') await ctx.send("❌ Failed to process the audio file!") return diff --git a/cogs/music/queue.py b/cogs/music/queue.py index 96eac30..0a420e0 100644 --- a/cogs/music/queue.py +++ b/cogs/music/queue.py @@ -39,7 +39,8 @@ def get_effect_options(effect_name): 'earrape': { **BASE_FFMPEG_OPTS, # Aggressive compression + hard clipping + bitcrushing for maximum distortion - 'options': '-vn -af "volume=8,acompressor=threshold=0.001:ratio=30:attack=0.1:release=5,acrusher=bits=8:mix=0.7,volume=2,alimiter=limit=0.8"' + # Note: FFmpeg's acompressor ratio max is 20 + 'options': '-vn -af "volume=8,acompressor=threshold=0.001:ratio=20:attack=0.1:release=5,acrusher=bits=8:mix=0.7,volume=2,alimiter=limit=0.8"' }, 'deepfry': { **BASE_FFMPEG_OPTS,