forked from jojara/JellyfinDiscordBot
made changes to disconnect, began queue implementation
This commit is contained in:
parent
bdfec840dd
commit
f63d6f2484
94
bot.py
94
bot.py
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user