diff --git a/extendedaudio/extendedaudio.py b/extendedaudio/extendedaudio.py index e55f51a..db3be02 100644 --- a/extendedaudio/extendedaudio.py +++ b/extendedaudio/extendedaudio.py @@ -3,6 +3,7 @@ import logging import time from typing import Optional, List, Dict from collections import defaultdict +from datetime import datetime import discord from redbot.core import Config, commands @@ -27,7 +28,9 @@ class ExtendedAudio(commands.Cog): self.config = Config.get_conf(self, identifier=117117117) default_guild = { "status_channel": None, # Channel ID to post song updates - "status_format": "🎵 Now Playing: **{title}**\nRequested by: {requester}\nDuration: {duration}\nArtist: {author}", # Format for the status message + "embed_color": None, # Custom embed color (optional) + "show_thumbnail": True, # Whether to show track thumbnails in embeds + "show_progress": True, # Whether to show a progress bar "allowed_channels": [], # List of allowed voice channel IDs "bot_managed_only": False, # Whether to only allow bot-created channels "last_status_message": None, # ID of the last status message (for cleanup) @@ -70,15 +73,44 @@ class ExtendedAudio(commands.Cog): guild = ctx.guild conf = await self.config.guild(guild).all() status_channel = ctx.guild.get_channel(conf["status_channel"]) if conf["status_channel"] else None - msg = ( - f"**Current Settings**\n" - f"Status Channel: {status_channel.mention if status_channel else 'Not Set'}\n" - f"Status Format: {conf['status_format']}\n" - f"Clean Old Messages: {'Enabled' if conf['clean_old_messages'] else 'Disabled'}\n\n" - f"Available Variables: {humanize_list([f'{{' + k + '}}' for k in SUPPORTED_VARIABLES.keys()])}\n" - f"Use `{ctx.prefix}extendedaudioset statuschannel` to set the channel for song updates." + embed_color = conf["embed_color"] + if embed_color: + embed_color = discord.Color(embed_color) + else: + embed_color = discord.Color.blue() + + embed = discord.Embed( + title="ExtendedAudio Settings", + color=embed_color, + timestamp=datetime.now() ) - await ctx.send(box(msg)) + embed.add_field( + name="Status Channel", + value=status_channel.mention if status_channel else "Not Set", + inline=False + ) + embed.add_field( + name="Embed Color", + value=str(embed_color) if embed_color else "Default (Blue)", + inline=True + ) + embed.add_field( + name="Show Thumbnails", + value="Enabled" if conf["show_thumbnail"] else "Disabled", + inline=True + ) + embed.add_field( + name="Show Progress Bar", + value="Enabled" if conf["show_progress"] else "Disabled", + inline=True + ) + embed.add_field( + name="Clean Old Messages", + value="Enabled" if conf["clean_old_messages"] else "Disabled", + inline=True + ) + + await ctx.send(embed=embed) @extendedaudioset.command(name="statuschannel") async def set_status_channel(self, ctx: commands.Context, channel: Optional[discord.TextChannel] = None): @@ -90,51 +122,40 @@ class ExtendedAudio(commands.Cog): await self.config.guild(ctx.guild).status_channel.set(channel.id) await ctx.send(f"Song updates will now be posted in {channel.mention}") - @extendedaudioset.command(name="statusformat") - async def set_status_format(self, ctx: commands.Context, *, format_str: str): - """Set the format for song update messages. + @extendedaudioset.command(name="embedcolor") + async def set_embed_color(self, ctx: commands.Context, color: discord.Color = None): + """Set the color for song update embeds. - Available variables: - {title} - Song title - {requester} - User who requested the song - {duration} - Duration of the song - {author} - Song author/artist - - Example: [p]extendedaudioset statusformat 🎵 Now Playing: **{title}** by {author} + Leave empty to reset to default (blue). + Use hex colors like #FF0000 for red. """ - # Validate format string - try: - # Test with sample data - test_data = { - "title": "Test Song", - "requester": "Test User", - "duration": "3:45", - "author": "Test Artist" - } - format_str.format(**test_data) - except KeyError as e: - invalid_var = str(e).strip("'") - supported = humanize_list([f"{{" + k + "}}" for k in SUPPORTED_VARIABLES.keys()]) - await ctx.send( - f"Invalid variable `{invalid_var}` in format string.\n" - f"Supported variables are: {supported}" - ) - return - except Exception as e: - await ctx.send(f"Invalid format string: {e}") - return + if color: + await self.config.guild(ctx.guild).embed_color.set(color.value) + msg = f"Embed color set to {color}" + else: + await self.config.guild(ctx.guild).embed_color.set(None) + msg = "Embed color reset to default (blue)" - await self.config.guild(ctx.guild).status_format.set(format_str) - example = format_str.format( - title="Never Gonna Give You Up", - requester="Rick Astley", - duration="3:32", - author="Rick Astley" - ) - await ctx.send( - f"Status format set! Example:\n" - f"{example}" + embed = discord.Embed( + title="Color Updated", + description=msg, + color=color or discord.Color.blue() ) + await ctx.send(embed=embed) + + @extendedaudioset.command(name="thumbnail") + async def set_show_thumbnail(self, ctx: commands.Context, enabled: bool): + """Set whether to show track thumbnails in embeds.""" + await self.config.guild(ctx.guild).show_thumbnail.set(enabled) + state = "will" if enabled else "will not" + await ctx.send(f"Track thumbnails {state} be shown in song updates.") + + @extendedaudioset.command(name="progress") + async def set_show_progress(self, ctx: commands.Context, enabled: bool): + """Set whether to show a progress bar in embeds.""" + await self.config.guild(ctx.guild).show_progress.set(enabled) + state = "will" if enabled else "will not" + await ctx.send(f"Progress bars {state} be shown in song updates.") @extendedaudioset.command(name="cleanmessages") async def set_clean_messages(self, ctx: commands.Context, enabled: bool): @@ -147,6 +168,25 @@ class ExtendedAudio(commands.Cog): state = "will" if enabled else "will not" await ctx.send(f"Old status messages {state} be deleted when new songs play.") + def format_duration(self, milliseconds: int) -> str: + """Format milliseconds into a readable duration.""" + seconds = milliseconds // 1000 + minutes = seconds // 60 + hours = minutes // 60 + + if hours > 0: + return f"{hours}:{minutes % 60:02d}:{seconds % 60:02d}" + else: + return f"{minutes}:{seconds % 60:02d}" + + def create_progress_bar(self, current: int, total: int, length: int = 20) -> str: + """Create a text progress bar.""" + filled = int((current / total) * length) + bar = "▰" * filled + "▱" * (length - filled) + current_time = self.format_duration(current) + total_time = self.format_duration(total) + return f"{current_time} {bar} {total_time}" + @commands.Cog.listener() async def on_red_audio_track_start(self, guild: discord.Guild, track: dict, requester: discord.Member): """Post song information when a new track starts""" @@ -163,25 +203,57 @@ class ExtendedAudio(commands.Cog): if not channel: return - # Get the format and create the message - format_str = await self.config.guild(guild).status_format() + # Get guild settings + guild_settings = await self.config.guild(guild).all() + embed_color = discord.Color(guild_settings["embed_color"]) if guild_settings["embed_color"] else discord.Color.blue() - # Prepare variables - duration = track.length if hasattr(track, "length") else 0 - minutes = duration // 60000 # Convert milliseconds to minutes - seconds = (duration % 60000) // 1000 # Convert remaining milliseconds to seconds - duration_str = f"{minutes}:{seconds:02d}" + # Create embed + embed = discord.Embed( + title="Now Playing", + color=embed_color, + timestamp=datetime.now() + ) - message = format_str.format( - title=track.title if hasattr(track, "title") else "Unknown", - requester=requester.display_name, - duration=duration_str, - author=track.author if hasattr(track, "author") else "Unknown" + # Add track info + embed.add_field( + name="Title", + value=track.title if hasattr(track, "title") else "Unknown", + inline=False + ) + + if hasattr(track, "author"): + embed.add_field(name="Artist", value=track.author, inline=True) + + embed.add_field(name="Requested By", value=requester.mention, inline=True) + + # Add duration/progress + if guild_settings["show_progress"] and hasattr(track, "length"): + duration = track.length + progress_bar = self.create_progress_bar(0, duration) + embed.add_field(name="Duration", value=progress_bar, inline=False) + elif hasattr(track, "length"): + embed.add_field( + name="Duration", + value=self.format_duration(track.length), + inline=True + ) + + # Add thumbnail if enabled and available + if ( + guild_settings["show_thumbnail"] + and hasattr(track, "thumbnail") + and track.thumbnail + ): + embed.set_thumbnail(url=track.thumbnail) + + # Set footer with additional info + embed.set_footer( + text=f"Track {track.track_id if hasattr(track, 'track_id') else 'Unknown ID'}" ) # Clean up old message if enabled - if await self.config.guild(guild).clean_old_messages(): - last_message_id = await self.config.guild(guild).last_status_message() + if guild_settings["clean_old_messages"]: + last_message_id = guild_settings["last_status_message"] if last_message_id: try: old_message = await channel.fetch_message(last_message_id) @@ -190,7 +262,7 @@ class ExtendedAudio(commands.Cog): pass # Send new message - new_message = await channel.send(message) + new_message = await channel.send(embed=embed) await self.config.guild(guild).last_status_message.set(new_message.id) except Exception as e: