quick-wins #2
@@ -141,37 +141,54 @@ class music(commands.Cog):
|
|||||||
await queue.play(ctx)
|
await queue.play(ctx)
|
||||||
|
|
||||||
|
|
||||||
@commands.command(
|
@commands.hybrid_command(
|
||||||
help="Upload and play an audio file (MP3, MP4, WAV, etc.)",
|
name="playfile",
|
||||||
|
description="Upload and play an audio file (MP3, MP4, WAV, etc.)",
|
||||||
aliases=['pf', 'file'])
|
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"""
|
"""Play an uploaded audio file from Discord attachment"""
|
||||||
if ctx.guild is None:
|
if ctx.guild is None:
|
||||||
await ctx.send("❌ This command must be used in a server!")
|
await ctx.send("❌ This command must be used in a server!", ephemeral=True)
|
||||||
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"
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
server = ctx.guild.id
|
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
|
# Validate file extension
|
||||||
audio_extensions = ('.mp3', '.mp4', '.wav', '.ogg', '.flac', '.m4a', '.webm', '.aac', '.opus')
|
audio_extensions = ('.mp3', '.mp4', '.wav', '.ogg', '.flac', '.m4a', '.webm', '.aac', '.opus')
|
||||||
if not any(attachment.filename.lower().endswith(ext) for ext in audio_extensions):
|
if not any(attachment.filename.lower().endswith(ext) for ext in audio_extensions):
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
f"❌ Invalid file type: `{attachment.filename}`\n"
|
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
|
return
|
||||||
|
|
||||||
|
# Defer for slash commands since processing takes time
|
||||||
|
if ctx.interaction:
|
||||||
|
await ctx.defer()
|
||||||
|
|
||||||
await util.join_vc(ctx)
|
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}`...")
|
msg = await ctx.send(f"Processing file: `{attachment.filename}`...")
|
||||||
|
|
||||||
@@ -184,7 +201,8 @@ class music(commands.Cog):
|
|||||||
await msg.delete()
|
await msg.delete()
|
||||||
|
|
||||||
if len(audio) == 0:
|
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!")
|
await ctx.send("❌ Failed to process the audio file!")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ def get_effect_options(effect_name):
|
|||||||
'earrape': {
|
'earrape': {
|
||||||
**BASE_FFMPEG_OPTS,
|
**BASE_FFMPEG_OPTS,
|
||||||
# Aggressive compression + hard clipping + bitcrushing for maximum distortion
|
# 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': {
|
'deepfry': {
|
||||||
**BASE_FFMPEG_OPTS,
|
**BASE_FFMPEG_OPTS,
|
||||||
|
|||||||
Reference in New Issue
Block a user