Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions cogs/music.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,46 @@ async def on_submit(self, interaction: discord.Interaction):
)


class VolumeSelect(discord.ui.Select):
def __init__(self, cog: "MusicCog", player: lavalink.DefaultPlayer):
self.cog = cog
self.player = player
current = player.volume

options = []
for vol in range(0, 101, 10):
emoji = {0: "🔇", 10: "🔈", 20: "🔈", 30: "🔉", 40: "🔉",
50: "🔉", 60: "🔊", 70: "🔊", 80: "🔊", 90: "🔊", 100: "🔊"}.get(vol, "🔊")
label = f"{vol}%"
desc = "Mute" if vol == 0 else "Máximo" if vol == 100 else ""
options.append(
discord.SelectOption(
label=label, value=str(vol), emoji=emoji, description=desc, default=(vol == current)
)
)

super().__init__(placeholder="Selecciona un volumen...", min_values=1, max_values=1, options=options)

async def callback(self, interaction: discord.Interaction):
vol = int(self.values[0])
await self.player.set_volume(vol)
print(f"[VOLUME] guild={interaction.guild.id} volumen={vol}%")

for opt in self.options:
opt.default = (opt.value == str(vol))
embed = discord.Embed(
description=f"🔊 Volumen: **{vol}%**",
color=0x2B2D31,
)
await interaction.response.edit_message(embed=embed, view=self.view)


class VolumeSelectView(discord.ui.View):
def __init__(self, cog: "MusicCog", player: lavalink.DefaultPlayer):
super().__init__(timeout=60)
self.add_item(VolumeSelect(cog, player))


class NowPlayingView(discord.ui.View):
def __init__(self, cog: "MusicCog", player: lavalink.DefaultPlayer, interaction: discord.Interaction | None = None):
super().__init__(timeout=None)
Expand All @@ -212,6 +252,10 @@ def __init__(self, cog: "MusicCog", player: lavalink.DefaultPlayer, interaction:
style=discord.ButtonStyle.url, url=track.uri,
label="Abrir", emoji="🔗", row=1,
))
for child in self.children:
if isinstance(child, discord.ui.Button) and "np_volume" in (child.custom_id or ""):
child.label = f"{player.volume}%"
break

async def _check_control(self, interaction: discord.Interaction) -> bool:
if not interaction.user.voice or interaction.user.voice.channel.id != self.player.channel_id:
Expand Down Expand Up @@ -246,6 +290,9 @@ async def _refresh_view(self, interaction: discord.Interaction):
elif "np_sort" in cid:
child.disabled = len(self.player.queue) < 2
continue
elif "np_volume" in cid:
child.label = f"{self.player.volume}%"
continue
elif child.style == discord.ButtonStyle.url:
track = self.player.current
if track and track.uri:
Expand Down Expand Up @@ -388,6 +435,23 @@ async def sort_queue(self, interaction: discord.Interaction, button: discord.ui.
view = MoveQueueView(self.cog, self.player)
await interaction.response.send_message(embed=embed, view=view, ephemeral=True)

@discord.ui.button(emoji="🔊", label="Volumen", style=discord.ButtonStyle.secondary, row=2, custom_id="np_volume")
async def volume_btn(self, interaction: discord.Interaction, button: discord.ui.Button):
if not await self._check_control(interaction):
return
embed = discord.Embed(
title="🔊 Selecciona un volumen",
description=(
"Elige un nivel con el menú desplegable.\n"
"⏱️ Este menú expira en **60 segundos** — si se cierra, "
"solo toca 🔊 para abrir uno nuevo.\n\n"
"También puedes usar `/volume 0-100`."
),
color=0x2B2D31,
)
view = VolumeSelectView(self.cog, self.player)
await interaction.response.send_message(embed=embed, view=view, ephemeral=True)

async def _cleanup(self):
if self.message is None:
return
Expand Down Expand Up @@ -622,6 +686,10 @@ async def _build_nowplaying_embed(
percent = min((position_ms / max(track.duration, 1)) * 100, 100.0)
embed.add_field(name="Avance", value=f"{percent:.1f}%", inline=True)

vol = player.volume
vol_bar = "█" * (vol // 10) + "░" * (10 - vol // 10)
embed.add_field(name="Volumen", value=f"{vol}% {vol_bar}", inline=True)

return embed

async def _build_nowplaying_embed_auto(
Expand Down Expand Up @@ -696,6 +764,10 @@ async def _build_nowplaying_embed_auto(
percent = min((position_ms / max(track.duration, 1)) * 100, 100.0)
embed.add_field(name="Avance", value=f"{percent:.1f}%", inline=True)

vol = player.volume
vol_bar = "█" * (vol // 10) + "░" * (10 - vol // 10)
embed.add_field(name="Volumen", value=f"{vol}% {vol_bar}", inline=True)

return embed

async def _send_embed(self, interaction: discord.Interaction, embed: discord.Embed):
Expand Down Expand Up @@ -1697,6 +1769,38 @@ async def shuffle(self, interaction: discord.Interaction):
print(f"[SHUFFLE] ✗ Error: {e}")
await self._send_error(interaction, f"Error: {e}")

@app_commands.command(
name="volume", description="Ajusta el volumen (0-100%)",
)
@app_commands.describe(vol="Nivel de volumen de 0 a 100")
async def volume(self, interaction: discord.Interaction, vol: int | None = None):
"""Ver o cambiar el volumen actual (0-100)."""
try:
player, error_message = self._require_control_player(interaction)
if player is None:
return await self._send_error(interaction, error_message)

if vol is None:
return await self._send_embed(
interaction,
self._build_embed(
interaction,
"🔊 Volumen actual",
f"El volumen está al **{player.volume}%**.",
color=BOT_PRIMARY,
),
)

if not 0 <= vol <= 100:
return await self._send_error(interaction, "El volumen debe estar entre 0 y 100.")

await player.set_volume(vol)
print(f"[VOLUME] guild={interaction.guild.id} volumen={vol}%")
await interaction.response.defer()
Comment on lines +1797 to +1799
except Exception as e:
print(f"[VOLUME] ✗ Error: {e}")
await self._send_error(interaction, f"Error: {e}")

@app_commands.command(
name="play", description="Reproduce una canción (nombre o URL)"
)
Expand Down