modified: app.py

This commit is contained in:
SimolZimol
2025-10-28 15:00:04 +01:00
parent 2055bc662b
commit caec9b326a

53
app.py
View File

@@ -142,6 +142,15 @@ def get_guild_music(guild_id: int) -> GuildMusic:
music_states[guild_id] = st
return st
async def maybe_defer(ctx: commands.Context):
"""Defer interaction responses to avoid 'interaction failed' on long ops (>3s)."""
try:
inter = getattr(ctx, 'interaction', None)
if inter and not inter.response.is_done():
await inter.response.defer(thinking=True)
except Exception:
pass
def ytdlp_opts() -> dict:
opts = {
'format': 'bestaudio/best',
@@ -227,20 +236,23 @@ async def start_player_loop(ctx: commands.Context):
@bot.hybrid_command(name='join', description='Join your voice channel')
async def cmd_join(ctx):
await maybe_defer(ctx)
vc = await ensure_voice(ctx)
if vc:
await ctx.reply(f"✅ Joined {vc.channel.mention}")
await _safe_send(ctx, f"✅ Joined {vc.channel.mention}")
@bot.hybrid_command(name='leave', description='Leave the voice channel')
async def cmd_leave(ctx):
await maybe_defer(ctx)
if ctx.voice_client and ctx.voice_client.is_connected():
await ctx.voice_client.disconnect()
await ctx.reply("👋 Disconnected.")
await _safe_send(ctx, "👋 Disconnected.")
else:
await ctx.reply(" Not connected.")
await _safe_send(ctx, " Not connected.")
@bot.hybrid_command(name='play', description='Play a YouTube URL or search term')
async def cmd_play(ctx, *, query: str):
await maybe_defer(ctx)
vc = await ensure_voice(ctx)
if not vc:
return
@@ -248,21 +260,23 @@ async def cmd_play(ctx, *, query: str):
song = await yt_extract(query)
state = get_guild_music(ctx.guild.id)
await state.queue.put(song)
await ctx.reply(f"▶️ Queued: **{song.title}**")
await _safe_send(ctx, f"▶️ Queued: **{song.title}**")
await start_player_loop(ctx)
except Exception as e:
await ctx.reply(f"❌ Failed to add: {e}")
await _safe_send(ctx, f"❌ Failed to add: {e}")
@bot.hybrid_command(name='skip', description='Skip the current track')
async def cmd_skip(ctx):
await maybe_defer(ctx)
if ctx.voice_client and ctx.voice_client.is_playing():
ctx.voice_client.stop()
await ctx.reply("⏭️ Skipped.")
await _safe_send(ctx, "⏭️ Skipped.")
else:
await ctx.reply(" Nothing is playing.")
await _safe_send(ctx, " Nothing is playing.")
@bot.hybrid_command(name='stop', description='Stop playback and clear the queue')
async def cmd_stop(ctx):
await maybe_defer(ctx)
state = get_guild_music(ctx.guild.id)
# Clear queue
try:
@@ -272,38 +286,42 @@ async def cmd_stop(ctx):
pass
if ctx.voice_client and ctx.voice_client.is_playing():
ctx.voice_client.stop()
await ctx.reply("⏹️ Stopped and cleared queue.")
await _safe_send(ctx, "⏹️ Stopped and cleared queue.")
@bot.hybrid_command(name='pause', description='Pause playback')
async def cmd_pause(ctx):
await maybe_defer(ctx)
if ctx.voice_client and ctx.voice_client.is_playing():
ctx.voice_client.pause()
await ctx.reply("⏸️ Paused.")
await _safe_send(ctx, "⏸️ Paused.")
else:
await ctx.reply(" Nothing is playing.")
await _safe_send(ctx, " Nothing is playing.")
@bot.hybrid_command(name='resume', description='Resume playback')
async def cmd_resume(ctx):
await maybe_defer(ctx)
if ctx.voice_client and ctx.voice_client.is_paused():
ctx.voice_client.resume()
await ctx.reply("▶️ Resumed.")
await _safe_send(ctx, "▶️ Resumed.")
else:
await ctx.reply(" Nothing is paused.")
await _safe_send(ctx, " Nothing is paused.")
@bot.hybrid_command(name='np', description='Show the currently playing track')
async def cmd_nowplaying(ctx):
await maybe_defer(ctx)
state = get_guild_music(ctx.guild.id)
if state.current:
dur = f" ({state.current.duration//60}:{state.current.duration%60:02d})" if state.current.duration else ""
await ctx.reply(f"🎶 Now playing: **{state.current.title}**{dur}\n{state.current.webpage_url}")
await _safe_send(ctx, f"🎶 Now playing: **{state.current.title}**{dur}\n{state.current.webpage_url}")
else:
await ctx.reply(" Nothing is playing.")
await _safe_send(ctx, " Nothing is playing.")
@bot.hybrid_command(name='queue', description='Show queued tracks')
async def cmd_queue(ctx):
await maybe_defer(ctx)
state = get_guild_music(ctx.guild.id)
if state.queue.empty():
await ctx.reply("🗒️ Queue is empty.")
await _safe_send(ctx, "🗒️ Queue is empty.")
return
# Snapshot queue without draining
items: List[Song] = []
@@ -320,10 +338,11 @@ async def cmd_queue(ctx):
if more > 0:
desc += f"\n...and {more} more"
embed = discord.Embed(title="🎼 Queue", description=desc, color=discord.Color.purple())
await ctx.reply(embed=embed)
await _safe_send(ctx, embed=embed)
@bot.hybrid_command(name='voicediag', description='Diagnose voice playback environment')
async def cmd_voicediag(ctx):
await maybe_defer(ctx)
details = []
details.append(f"discord.py: {discord.__version__}")
# PyNaCl check
@@ -353,7 +372,7 @@ async def cmd_voicediag(ctx):
details.append(f"cookie.txt present: {os.path.exists(COOKIE_FILE)} at {COOKIE_FILE}")
embed = discord.Embed(title='Voice Diagnostics', description='\n'.join(details), color=discord.Color.dark_grey())
await ctx.reply(embed=embed)
await _safe_send(ctx, embed=embed)
@bot.event
async def on_guild_join(guild):