Quick wins: Lower default volume to 25% and add file upload support
- Scale volume by 0.25x to prevent earrape (user still sees 0-200%) - Add support for direct audio file URL links (.mp3, .mp4, etc.) - New =playfile command for Discord file uploads - Supports MP3, MP4, WAV, OGG, FLAC, M4A, WEBM, AAC, OPUS formats
This commit is contained in:
@@ -141,6 +141,72 @@ class music(commands.Cog):
|
||||
await queue.play(ctx)
|
||||
|
||||
|
||||
@commands.command(
|
||||
help="Upload and play an audio file (MP3, MP4, WAV, etc.)",
|
||||
aliases=['pf', 'file'])
|
||||
async def playfile(self, ctx: Context):
|
||||
"""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"
|
||||
)
|
||||
return
|
||||
|
||||
server = ctx.guild.id
|
||||
attachment = ctx.message.attachments[0]
|
||||
|
||||
# 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"
|
||||
)
|
||||
return
|
||||
|
||||
await util.join_vc(ctx)
|
||||
await ctx.message.add_reaction('📎')
|
||||
|
||||
msg = await ctx.send(f"Processing file: `{attachment.filename}`...")
|
||||
|
||||
# Discord provides a CDN URL for the attachment
|
||||
file_url = attachment.url
|
||||
|
||||
# Use translate to process the file URL (yt-dlp handles direct URLs)
|
||||
audio = await translate.main(file_url, self.sp)
|
||||
|
||||
await msg.delete()
|
||||
|
||||
if len(audio) == 0:
|
||||
await ctx.message.add_reaction('🚫')
|
||||
await ctx.send("❌ Failed to process the audio file!")
|
||||
return
|
||||
|
||||
# Override title with filename if yt-dlp didn't get a good title
|
||||
if audio[0]['title'] == 'Unknown' or not audio[0]['title']:
|
||||
audio[0]['title'] = attachment.filename
|
||||
|
||||
# Queue the file
|
||||
audio[0]['position'] = await queue.add_song(
|
||||
server,
|
||||
audio[0],
|
||||
ctx.author.display_name)
|
||||
|
||||
await util.queue_message(ctx, audio[0])
|
||||
|
||||
if await queue.is_server_playing(server):
|
||||
return
|
||||
|
||||
await queue.update_server(server, True)
|
||||
await queue.play(ctx)
|
||||
|
||||
|
||||
@commands.command(
|
||||
help="Queue a song to play next (top of queue)",
|
||||
aliases=['pt', 'pn', 'playnext'])
|
||||
@@ -347,8 +413,9 @@ class music(commands.Cog):
|
||||
new_vol = await queue.set_volume(server.id, level)
|
||||
|
||||
# Update the current playing song's volume if something is playing
|
||||
# Scale down by 0.25 to match queue.py playback scaling
|
||||
if ctx.voice_client and ctx.voice_client.source:
|
||||
ctx.voice_client.source.volume = new_vol / 100.0
|
||||
ctx.voice_client.source.volume = new_vol / 100.0 * 0.25
|
||||
|
||||
# Pick an emoji based on volume
|
||||
if new_vol == 0:
|
||||
|
||||
@@ -497,7 +497,10 @@ async def play(ctx):
|
||||
return
|
||||
|
||||
try:
|
||||
vol = await get_volume(server_id) / 100.0
|
||||
# Scale volume down to prevent earrape
|
||||
# User sees 0-200%, but internally we scale by 0.25
|
||||
# So user's 100% = 0.25 actual volume (25%)
|
||||
vol = await get_volume(server_id) / 100.0 * 0.25
|
||||
fx = await get_effect(server_id)
|
||||
opts = get_effect_options(fx)
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ async def main(url, sp):
|
||||
#url = url.lower()
|
||||
|
||||
# Check if link or search
|
||||
if url.startswith("https://") is False:
|
||||
if not url.startswith("https://") and not url.startswith("http://"):
|
||||
return await search_song(url)
|
||||
|
||||
#TODO add better regex or something
|
||||
@@ -44,7 +44,14 @@ async def main(url, sp):
|
||||
youtube_song = 'watch?v=' in url or 'youtu.be/' in url
|
||||
youtube_playlist = 'playlist?list=' in url
|
||||
|
||||
if soundcloud_song or youtube_song:
|
||||
# Check for direct audio/video file URLs
|
||||
# Supported formats: mp3, mp4, wav, ogg, flac, m4a, webm, aac, opus
|
||||
audio_extensions = ('.mp3', '.mp4', '.wav', '.ogg', '.flac', '.m4a', '.webm', '.aac', '.opus')
|
||||
is_direct_file = any(url.lower().endswith(ext) for ext in audio_extensions)
|
||||
# Also check for URLs with query parameters (e.g., file.mp3?download=true)
|
||||
is_direct_file = is_direct_file or any(ext in url.lower() for ext in audio_extensions)
|
||||
|
||||
if soundcloud_song or youtube_song or is_direct_file:
|
||||
return await song_download(url)
|
||||
|
||||
if youtube_playlist:
|
||||
|
||||
Reference in New Issue
Block a user