made changes to disconnect, began queue implementation

This commit is contained in:
Jellyfishsh 2025-04-19 00:01:53 -07:00
parent bdfec840dd
commit f63d6f2484

94
bot.py
View File

@ -1,5 +1,6 @@
# Imports
import os
from discord.webhook.async_ import interaction_message_response_params
import requests
import discord
from discord.ext import commands
@ -47,6 +48,8 @@ bot = JellyfinBot()
async def on_ready():
print(f"🪼 Logged in as {bot.user}")
# ----- Helpful Structures ----- #
guild_queue_dict = dict()
# ----- Helper Functions ----- #
@ -82,15 +85,15 @@ async def make_request(url: str, params: dict, interaction: discord.Interaction)
# Play a song
# Play function
# Plays a song with the given title in wherever the user is
# start play -----
@bot.tree.command(name="play", description="Play a song from Jellyfin")
@app_commands.describe(title="Song title to play")
async def play(interaction: discord.Interaction, title: str):
# Makes the reaction visible to everyone
await interaction.response.defer()
@ -101,18 +104,16 @@ async def play(interaction: discord.Interaction, title: str):
voice_status = await interaction.user.fetch_voice()
user_channel = voice_status.channel
voice_client = interaction.guild.voice_client # Enables the voice feature for the bot
# If its not connected to a voice channel, then connect to the channel that the caller is in
if voice_client is None:
voice_client = await user_channel.connect()
# If the caller is in a channel that its not already in, move there
elif voice_client.channel != user_channel:
await voice_client.move_to(user_channel)
voice_client = await user_channel.connect()
#Pause the music that is currently playing
# First check if it is already in a voice channel
if voice_client.channel != user_channel:
voice_client.disconnect()
if voice_client.is_playing():
voice_client.stop()
# Finally, connect
await user_channel.connect()
except discord.errors.NotFound as e:
print(f"Error: {e}")
await interaction.followup.send("Nope! Not in a voice!")
@ -141,37 +142,56 @@ async def play(interaction: discord.Interaction, title: str):
print(f"Found {len(data)} items matching `{title}`.")
# Deconstructing the dict 'data'
song = data[0]
song_id = song.get('Id')
song_title = song.get('Name')
song_artist = song.get('AlbumArtist', ['Unknown Artist'])
query_song = data[0]
query_song_id = query_song.get('Id')
query_song_title = query_song.get('Name')
query_song_artist = query_song.get('AlbumArtist', ['Unknown Artist'])
# First, we make a dictionary that has a list inside.
# Then, we get the name of the guild and put that in the dictionary
# then AFTER, we put the song inside the list that the guild points to
# on the play command, we add that song to the list
try:
#Setup for ffmpeg
audio_stream_url = f"{JELLYFIN_URL}/Audio/{song_id}/stream?static=True"
print(f"Stream URL: {audio_stream_url}")
headers_str = f"-headers \"X-Emby-Token: {JELLYFIN_API_KEY}\""
# Check if the guild is not known guilds
if guild_queue_dict.get(interaction.guild_id) == None:
# add it to the playlist dict
guild_queue_dict[interaction.guild_id] = list()
# >>----- start PROBLEMS
guild_queue_dict[interaction.guild_id].append((query_song_id, query_song_title, query_song_artist))
# Here is the problematic library.
# It might just be looking for Opus and not finding it
source = discord.FFmpegOpusAudio(audio_stream_url,
before_options=f'{headers_str} -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
options="-vn")
# If someone is already playing something, we just add to their queue.
# Probably a better way of piggybacking
if voice_client.is_playing():
await interaction.followup.send(f"Queued: **{query_song_title}** by *{query_song_artist}*")
return
# end PROBLEMS -----<<
headers_str = f"-headers \"X-Emby-Token: {JELLYFIN_API_KEY}\""
for song in guild_queue_dict[interaction.guild_id]:
try:
# Song information from tuple
song_id = song[0]
song_title = song[1]
song_artist = song[2]
# Play the audio file
voice_client.play(source, after=lambda e: print(f"Finished playing: {e}"))
await interaction.followup.send(f"🎶 Now playing: **{song_title}** by *{song_artist}*")
audio_stream_url = f"{JELLYFIN_URL}/Audio/{song_id}/stream?static=True"
source = discord.FFmpegOpusAudio(audio_stream_url,
before_options=f'{headers_str} -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
options="-vn")
# Play the grabbed audio file
voice_client.play(source, after=lambda e: print(f"Finished playing: {e}"))
await interaction.followup.send(f"Now playing: **{song_title}** by *{song_artist}*")
#Cheap way of holding the loop until its done
while voice_client.is_playing():
continue
# If the library does not exist, we fail it
except discord.ClientException as e:
await interaction.followup.send("Unable to decode your song!")
print(f"Potential FFMPEG/OPUS decoding error: {e}")
# Then, we get rid of this queued item
guild_queue_dict[interaction.guild_id].pop(0)
except discord.ClientException as e:
await interaction.followup.send("Unable to decode your song!")
print(f"Potential FFMPEG/OPUS decoding error: {e}")
# end play -----
@ -215,11 +235,17 @@ async def search(interaction: discord.Interaction, title: str):
# Disconnects from the voice channel
@bot.tree.command(name="disconnect", description="Disconnects from current voice channel!")
async def disconnect(interaction: discord.Interaction):
# Checks if not in a voice channel
if interaction.guild.voice_client == None:
await interaction.followup.send("I am not in any voice channel!")
return
# disconnects with a helpful message
await interaction.guild.voice_client.disconnect()
await interaction.followup.send("Disconnected!")
return
# Queues
# Enqueue an item