import asyncio import logging from typing import Optional import discord from redbot.core import Config, commands from redbot.core.bot import Red from redbot.core.utils.chat_formatting import box log = logging.getLogger("red.valerie.extendedaudio") class ExtendedAudio(commands.Cog): """Extends Red's core Audio cog with additional features""" def __init__(self, bot: Red): self.bot = bot self.config = Config.get_conf(self, identifier=117117117) default_guild = { "channel_status": True, # Whether to update voice channel name with current song "status_format": "🎵 {title}", # Format for the channel name } self.config.register_guild(**default_guild) self.task = self.bot.loop.create_task(self.initialize()) self.audio = None async def initialize(self): """Initialize the cog""" await self.bot.wait_until_ready() try: self.audio = self.bot.get_cog("Audio") if not self.audio: log.error("Audio cog not loaded! Some features may not work.") except Exception as e: log.error(f"Failed to initialize ExtendedAudio: {e}") def cog_unload(self): """Cleanup when cog unloads""" if self.task: self.task.cancel() @commands.group(aliases=["eaudioset"]) @commands.guild_only() @commands.admin_or_permissions(manage_guild=True) async def extendedaudioset(self, ctx: commands.Context): """Configure ExtendedAudio settings""" pass @extendedaudioset.command(name="channelstatus") async def set_channel_status(self, ctx: commands.Context, enabled: bool): """Toggle voice channel status updates This will update the voice channel name with the currently playing song Example: [p]extendedaudioset channelstatus true """ await self.config.guild(ctx.guild).channel_status.set(enabled) state = "enabled" if enabled else "disabled" await ctx.send(f"Voice channel status updates {state}.") @extendedaudioset.command(name="statusformat") async def set_status_format(self, ctx: commands.Context, *, format_str: str): """Set the format for voice channel status updates Available variables: {title} - Song title Example: [p]extendedaudioset statusformat 🎵 {title} """ await self.config.guild(ctx.guild).status_format.set(format_str) example = format_str.format(title="Never Gonna Give You Up") await ctx.send( f"Status format set! Example:\n" f"{box(example)}" ) @commands.Cog.listener() async def on_red_audio_track_start(self, guild: discord.Guild, track: dict, requester: discord.Member): """Update voice channel name when a new track starts""" if not guild or not track: return try: # Check if channel status updates are enabled if not await self.config.guild(guild).channel_status(): return # Get the voice channel voice_client = guild.voice_client if not voice_client or not voice_client.channel: return channel = voice_client.channel # Get the format and create the new name format_str = await self.config.guild(guild).status_format() new_name = format_str.format(title=track.get("title", "Unknown")) # Update channel name if different if channel.name != new_name: await channel.edit(name=new_name) except discord.Forbidden: log.warning(f"Missing permissions to edit channel name in {guild.name}") except Exception as e: log.error(f"Error updating channel status in {guild.name}: {e}") @commands.Cog.listener() async def on_red_audio_queue_end(self, guild: discord.Guild, *args, **kwargs): """Reset voice channel name when queue ends""" if not guild: return try: # Check if channel status updates are enabled if not await self.config.guild(guild).channel_status(): return # Get the voice channel voice_client = guild.voice_client if not voice_client or not voice_client.channel: return channel = voice_client.channel # Reset channel name if it was modified (contains 🎵) if "🎵" in channel.name: original_name = channel.name.split("🎵")[-1].strip() await channel.edit(name=original_name) except discord.Forbidden: log.warning(f"Missing permissions to edit channel name in {guild.name}") except Exception as e: log.error(f"Error resetting channel status in {guild.name}: {e}")