forked from jojara/JellyfinDiscordBot
Compare commits
No commits in common. "main" and "main" have entirely different histories.
486
bot.py
486
bot.py
@ -1,24 +1,25 @@
|
|||||||
# Imports
|
# Imports
|
||||||
import os
|
import os
|
||||||
from discord.webhook.async_ import interaction_message_response_params
|
|
||||||
import requests
|
import requests
|
||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord import DiscordException, NotFound, app_commands, guild, user, voice_client
|
from discord import DiscordException, NotFound, app_commands
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ----- Setups ----- #
|
|
||||||
|
|
||||||
# Environment vars
|
# Environment vars
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
TOKEN = os.getenv("DISCORD_TOKEN")
|
TOKEN = os.getenv("DISCORD_TOKEN")
|
||||||
JELLYFIN_URL = os.getenv("JELLYFIN_URL")
|
JELLYFIN_URL = os.getenv("JELLYFIN_URL")
|
||||||
JELLYFIN_API_KEY = os.getenv("JELLYFIN_API_KEY")
|
JELLYFIN_API_KEY = os.getenv("JELLYFIN_API_KEY")
|
||||||
|
|
||||||
|
|
||||||
# Constants
|
# Constants
|
||||||
QUERY_LIMIT = 10
|
PLAY_QUERY_LIMIT = 1
|
||||||
|
SEARCH_QUERY_LIMIT = 5
|
||||||
|
|
||||||
|
|
||||||
|
# Setting the opus path, since Linux can't read it
|
||||||
|
|
||||||
# Request headers
|
# Request headers
|
||||||
headers= {
|
headers= {
|
||||||
@ -33,7 +34,6 @@ intents.voice_states = True
|
|||||||
|
|
||||||
|
|
||||||
# ----- Classes ----- #
|
# ----- Classes ----- #
|
||||||
|
|
||||||
# TODO: turn this in to an import in a separate file
|
# TODO: turn this in to an import in a separate file
|
||||||
class JellyfinBot(commands.Bot):
|
class JellyfinBot(commands.Bot):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -43,35 +43,22 @@ class JellyfinBot(commands.Bot):
|
|||||||
await self.tree.sync()
|
await self.tree.sync()
|
||||||
|
|
||||||
bot = JellyfinBot()
|
bot = JellyfinBot()
|
||||||
|
|
||||||
# Events
|
|
||||||
@bot.event
|
@bot.event
|
||||||
async def on_ready():
|
async def on_ready():
|
||||||
print(f"🪼 Logged in as {bot.user}")
|
print(f"🪼 Logged in as {bot.user}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ----- Helpful Structures ----- #
|
|
||||||
guild_queue_dict = dict()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ----- Helper Functions ----- #
|
# ----- Helper Functions ----- #
|
||||||
|
|
||||||
# makeRequest:
|
# makeRequest:
|
||||||
# makes a request to the jellyfin server.
|
# makes a request to the jellyfin server.
|
||||||
# Returns an error string or an empty dict
|
# Returns an error string or
|
||||||
|
|
||||||
# begin makeRequest -----
|
# begin makeRequest -----
|
||||||
async def make_request(title: str, interaction: discord.Interaction) -> dict:
|
async def make_request(url: str, params: dict, interaction: discord.Interaction) -> dict:
|
||||||
# Default return value
|
# Default return value
|
||||||
data = dict()
|
data = dict()
|
||||||
url = f"{JELLYFIN_URL}/Items"
|
|
||||||
params = {
|
|
||||||
"searchTerm": title,
|
|
||||||
"Recursive": True,
|
|
||||||
"IncludeItemTypes": "Audio",
|
|
||||||
"Limit": QUERY_LIMIT
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Makes the request
|
# Makes the request
|
||||||
@ -88,405 +75,152 @@ async def make_request(title: str, interaction: discord.Interaction) -> dict:
|
|||||||
return data
|
return data
|
||||||
# end makeRequest -----
|
# end makeRequest -----
|
||||||
|
|
||||||
|
# channelPlay
|
||||||
# playTrack:
|
# does logic for songs in a voice channel
|
||||||
# guild wide play function
|
|
||||||
async def playTrack(interaction: discord.Interaction):
|
|
||||||
voice_client = interaction.guild.voice_client
|
|
||||||
|
|
||||||
# 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
|
|
||||||
headers_str = f"-headers \"X-Emby-Token: {JELLYFIN_API_KEY}\""
|
|
||||||
try:
|
|
||||||
while len(guild_queue_dict[interaction.guild_id]) > 0:
|
|
||||||
|
|
||||||
# Get song information
|
|
||||||
song = guild_queue_dict[interaction.guild_id][0]
|
|
||||||
|
|
||||||
song_id = song[0]
|
|
||||||
song_title = song[1]
|
|
||||||
song_artist = song[2]
|
|
||||||
|
|
||||||
# Get voice client
|
|
||||||
voice_client = interaction.guild.voice_client
|
|
||||||
|
|
||||||
# Then fetch this song
|
|
||||||
headers_str = f"-headers \"X-Emby-Token: {JELLYFIN_API_KEY}\""
|
|
||||||
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")
|
|
||||||
|
|
||||||
# Then play it on the voice client
|
|
||||||
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 wait
|
|
||||||
# TODO: Make a better way of waiting
|
|
||||||
while voice_client.is_playing() or voice_client.is_paused():
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Dequeue the array
|
|
||||||
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}")
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
# clearQueue
|
|
||||||
# clears the queue. useful for a variety of functions where it needs to
|
|
||||||
# interrupt the player
|
|
||||||
def clearQueue(interaction: discord.Interaction):
|
|
||||||
guild_queue_dict[interaction.guild_id].clear()
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ----- Commands ----- #
|
# ----- Commands ----- #
|
||||||
|
|
||||||
# Connect
|
# Play a song
|
||||||
# Connects to a voice channel
|
|
||||||
@bot.tree.command(name="connect", description="Connects to the current voice channel")
|
|
||||||
async def connect(interaction: discord.Interaction):
|
|
||||||
# Makes the reaction visible to everyone
|
|
||||||
await interaction.response.defer()
|
|
||||||
|
|
||||||
try:
|
|
||||||
voice_status = await interaction.user.fetch_voice()
|
|
||||||
user_channel = voice_status.channel
|
|
||||||
voice_client = interaction.guild.voice_client
|
|
||||||
if voice_client is None:
|
|
||||||
voice_client = await user_channel.connect()
|
|
||||||
elif voice_client.channel != user_channel:
|
|
||||||
await voice_client.disconnect()
|
|
||||||
voice_client = await user_channel.connect()
|
|
||||||
|
|
||||||
except discord.errors.NotFound as e:
|
|
||||||
print(f"Error: {e}")
|
|
||||||
await interaction.followup.send("You are not in a voice channel!")
|
|
||||||
return
|
|
||||||
except discord.errors.Forbidden as e:
|
|
||||||
print(f"Error: {e}")
|
|
||||||
await interaction.followup.send(f"I am not allowed in that voice channel!")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
await interaction.followup.send(f"Connected!")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
# Play function
|
||||||
|
# Plays a song with the given title in wherever the user is
|
||||||
|
|
||||||
# Disconnect
|
# start play -----
|
||||||
# Disconnects from the voice channel
|
@bot.tree.command(name="play", description="Play a song from Jellyfin")
|
||||||
@bot.tree.command(name="disconnect", description="Disconnects from current voice channel")
|
@app_commands.describe(title="Song title to play")
|
||||||
async def disconnect(interaction: discord.Interaction):
|
async def play(interaction: discord.Interaction, title: str):
|
||||||
# Makes the reaction visible to everyone
|
# Makes the reaction visible to everyone
|
||||||
await interaction.response.defer()
|
await interaction.response.defer()
|
||||||
|
|
||||||
# Checks if not in a voice channel
|
# Checks if not in a voice channel
|
||||||
if interaction.guild.voice_client == None:
|
# Checks if in a voice channel
|
||||||
await interaction.followup.send("I am not in any voice channel!")
|
try:
|
||||||
|
# A better way of checking status
|
||||||
|
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
|
||||||
|
if voice_client.is_playing():
|
||||||
|
voice_client.stop()
|
||||||
|
except discord.errors.NotFound as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
|
await interaction.followup.send("Nope! Not in a voice!")
|
||||||
|
return
|
||||||
|
except discord.errors.Forbidden as e:
|
||||||
|
print(f"Error: {e}")
|
||||||
|
await interaction.followup.send("Not allowed in here!")
|
||||||
return
|
return
|
||||||
|
|
||||||
# disconnects with a helpful message
|
|
||||||
await interaction.guild.voice_client.disconnect()
|
|
||||||
await interaction.followup.send("Disconnected!")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
url = f"{JELLYFIN_URL}/Items"
|
||||||
|
params = {
|
||||||
|
"searchTerm": title,
|
||||||
|
"Recursive": True,
|
||||||
|
"IncludeItemTypes": "Audio",
|
||||||
|
"Limit": PLAY_QUERY_LIMIT
|
||||||
|
}
|
||||||
|
|
||||||
# Insert
|
# makes a request to the server, and returns the data it acquires
|
||||||
# Inserts a song in the player
|
data = await make_request(url, params, interaction)
|
||||||
@bot.tree.command(name="insert", description="Insert a song into the queue")
|
if not data:
|
||||||
async def insert(interaction: discord.Interaction, title: str):
|
await interaction.followup.send(f"❌ No song found matching `{title}`.")
|
||||||
# Makes the reaction visible to everyone
|
|
||||||
await interaction.response.defer()
|
|
||||||
|
|
||||||
|
|
||||||
await interaction.followup.send(f"Inserted a song!")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
# Play
|
|
||||||
# Play the song at the top of the queue
|
|
||||||
@bot.tree.command(name="play", description="Plays a song at the top of the queue")
|
|
||||||
async def play(interaction: discord.Interaction):
|
|
||||||
# Makes the reaction visible to everyone
|
|
||||||
await interaction.response.defer()
|
|
||||||
|
|
||||||
if guild_queue_dict.get(interaction.guild_id) == None:
|
|
||||||
guild_queue_dict[interaction.guild_id] = []
|
|
||||||
|
|
||||||
# Some basic checks
|
|
||||||
try:
|
|
||||||
# Check if the bot is connected to a channel
|
|
||||||
if interaction.guild.voice_client.channel != interaction.user.voice.channel:
|
|
||||||
await interaction.followup.send(f"Not connected to your voice channel!")
|
|
||||||
return # After this point, we know that it is in a channel
|
|
||||||
|
|
||||||
|
|
||||||
# Check if the queue is empty
|
|
||||||
if len(guild_queue_dict[interaction.guild_id]) == 0:
|
|
||||||
await interaction.followup.send(f"Queue is empty!")
|
|
||||||
return # After this point, we know the queue has something in it
|
|
||||||
except discord.errors.NotFound:
|
|
||||||
await interaction.followup.send(f"You're not connected to a voice channel!")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# Play all items in the queue
|
# Finds the item, and displays information about the location
|
||||||
await playTrack(interaction)
|
print(f"Found {len(data)} items matching `{title}`.")
|
||||||
|
|
||||||
return
|
# Deconstructing the dict 'data'
|
||||||
|
song = data[0]
|
||||||
|
song_id = song.get('Id')
|
||||||
|
song_title = song.get('Name')
|
||||||
|
song_artist = song.get('AlbumArtist', ['Unknown Artist'])
|
||||||
|
|
||||||
|
|
||||||
# Stop
|
|
||||||
# Stops the currently playing song, and empties the queue
|
|
||||||
# TODO: Make clear modular
|
|
||||||
@bot.tree.command(name="stop", description="Stops the player and empties the queue")
|
|
||||||
async def stop(interaction: discord.Interaction):
|
|
||||||
# Makes the reaction visible to everyone
|
|
||||||
await interaction.response.defer()
|
|
||||||
|
|
||||||
# Some basic checks
|
|
||||||
try:
|
try:
|
||||||
# Check if the bot is connected to a channel
|
#Setup for ffmpeg
|
||||||
if interaction.guild.voice_client.channel != interaction.user.voice.channel:
|
audio_stream_url = f"{JELLYFIN_URL}/Audio/{song_id}/stream?static=True"
|
||||||
await interaction.followup.send(f"Not connected to your voice channel!")
|
print(f"Stream URL: {audio_stream_url}")
|
||||||
return # After this point, we know that it is in a channel
|
headers_str = f"-headers \"X-Emby-Token: {JELLYFIN_API_KEY}\""
|
||||||
|
|
||||||
# Check if the queue is empty
|
# >>----- start PROBLEMS
|
||||||
if guild_queue_dict[interaction.guild_id].count() == 0:
|
|
||||||
await interaction.followup.send(f"Queue is empty!")
|
|
||||||
return # After this point, we know the queue has something in it
|
|
||||||
except:
|
|
||||||
await interaction.followup.send(f"You're not connected to a voice channel!")
|
|
||||||
|
|
||||||
#First, empty the queue, so that if some other user is playing, it ends its play
|
# Here is the problematic library.
|
||||||
clearQueue(interaction)
|
# 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")
|
||||||
|
|
||||||
# Then, stop the player
|
# end PROBLEMS -----<<
|
||||||
interaction.guild.voice_client.stop()
|
|
||||||
|
# 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}*")
|
||||||
|
|
||||||
|
|
||||||
|
# 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}")
|
||||||
|
# end play -----
|
||||||
|
|
||||||
await interaction.followup.send(f"Stopped the player!")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Search command
|
# Search command
|
||||||
# searches for a song
|
# searches for a song
|
||||||
|
|
||||||
|
# Search function
|
||||||
# start search -----
|
# start search -----
|
||||||
@bot.tree.command(name="search", description="Search for a song on Jellyfin")
|
@bot.tree.command(name="search", description="Search for a song on Jellyfin")
|
||||||
@app_commands.describe(title="Song title to search for")
|
@app_commands.describe(title="Song title to search for")
|
||||||
async def search(interaction: discord.Interaction, title: str):
|
async def search(interaction: discord.Interaction, title: str):
|
||||||
# Makes the reaction visible to everyone
|
|
||||||
await interaction.response.defer()
|
await interaction.response.defer()
|
||||||
|
|
||||||
|
# Builds the url
|
||||||
|
url = f"{JELLYFIN_URL}/Items"
|
||||||
|
params = {
|
||||||
|
"searchTerm": title,
|
||||||
|
"Recursive": True,
|
||||||
|
"IncludeItemTypes": "Audio",
|
||||||
|
"Limit": SEARCH_QUERY_LIMIT
|
||||||
|
}
|
||||||
|
|
||||||
# Get the data
|
# Get the data
|
||||||
data = await make_request(title, interaction)
|
data = await make_request(url, params, interaction)
|
||||||
|
|
||||||
if not data:
|
if not data:
|
||||||
await interaction.followup.send(f"No song found matching `{title}`.")
|
await interaction.followup.send(f"No song found matching `{title}`.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
|
||||||
|
|
||||||
result_list = []
|
|
||||||
for song in data:
|
for song in data:
|
||||||
result_list.append(f"**{song.get("Name")}** by *{song.get("AlbumArtist", ["Unknown Artist"])}*")
|
title = song.get("Name")
|
||||||
|
artist = song.get("AlbumArtist", ["Unknown Artist"])
|
||||||
await interaction.followup.send("\n".join(result_list))
|
lines.append(f"**{title}** by *{artist}*")
|
||||||
return
|
await interaction.followup.send("\n".join(lines))
|
||||||
|
# end search -----
|
||||||
|
|
||||||
|
|
||||||
|
# Disconnect command!
|
||||||
# Skip
|
# Disconnects from the voice channel
|
||||||
# Skips a song in the player
|
@bot.tree.command(name="disconnect", description="Disconnects from current voice channel!")
|
||||||
@bot.tree.command(name="skip", description="Skip the currently playing song")
|
async def disconnect(interaction: discord.Interaction):
|
||||||
async def skip(interaction: discord.Interaction):
|
if interaction.guild.voice_client == None:
|
||||||
# Makes the reaction visible to everyone
|
await interaction.followup.send("I am not in any voice channel!")
|
||||||
await interaction.response.defer()
|
|
||||||
|
|
||||||
|
|
||||||
# Some basic checks
|
|
||||||
try:
|
|
||||||
# Check if the bot is connected to a channel
|
|
||||||
if interaction.guild.voice_client.channel != interaction.user.voice.channel:
|
|
||||||
await interaction.followup.send(f"Not connected to your voice channel!")
|
|
||||||
return # After this point, we know that it is in a channel
|
|
||||||
|
|
||||||
# Check if the queue is empty
|
|
||||||
if guild_queue_dict[interaction.guild_id].count() == 0:
|
|
||||||
await interaction.followup.send(f"Queue is empty!")
|
|
||||||
return # After this point, we know the queue has something in it
|
|
||||||
except:
|
|
||||||
await interaction.followup.send(f"You're not connected to a voice channel!")
|
|
||||||
|
|
||||||
# Since someone else might be playing, we just stop so that the playTrack function
|
|
||||||
# gets the next track
|
|
||||||
|
|
||||||
# Stops the player to skip
|
|
||||||
interaction.guild.voice_client.stop()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Epilogue
|
|
||||||
await interaction.followup.send(f"Skipped the track!")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
# Pause
|
|
||||||
# Pauses the player
|
|
||||||
@bot.tree.command(name="pause", description="Pauses the currently playing song")
|
|
||||||
async def pause(interaction: discord.Interaction):
|
|
||||||
# Makes the reaction visible to everyone
|
|
||||||
await interaction.response.defer()
|
|
||||||
|
|
||||||
interaction.guild.voice_client.pause()
|
|
||||||
|
|
||||||
await interaction.followup.send(f"Paused!")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
# Resume
|
|
||||||
# Resumes the player
|
|
||||||
@bot.tree.command(name="resume", description="Resumes the currently playing song")
|
|
||||||
async def resume(interaction: discord.Interaction):
|
|
||||||
# Makes the reaction visible to everyone
|
|
||||||
await interaction.response.defer()
|
|
||||||
|
|
||||||
# Some basic checks
|
|
||||||
try:
|
|
||||||
# Check if the bot is connected to a channel
|
|
||||||
if interaction.guild.voice_client.channel != interaction.user.voice.channel:
|
|
||||||
await interaction.followup.send(f"Not connected to your voice channel!")
|
|
||||||
return # After this point, we know that it is in a channel
|
|
||||||
|
|
||||||
if not interaction.guild.voice_client.is_playing():
|
|
||||||
await interaction.followup.send(f"The player has nothing to resume!")
|
|
||||||
return # After this point, we know that it has something to play
|
|
||||||
|
|
||||||
except:
|
|
||||||
await interaction.followup.send(f"You're not connected to a voice channel!")
|
|
||||||
return
|
return
|
||||||
|
await interaction.guild.voice_client.disconnect()
|
||||||
|
|
||||||
|
|
||||||
# Ideal function
|
|
||||||
if interaction.guild.voice_client.is_paused():
|
|
||||||
interaction.guild.voice_client.resume()
|
|
||||||
await interaction.followup.send(f"Resumed!")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Something that it cannot do!
|
|
||||||
await interaction.followup.send("Something unexpected happened, and I cannot resume!")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
# Add
|
|
||||||
# Enqueue an item
|
|
||||||
@bot.tree.command(name="add", description="Queues a song into the list")
|
|
||||||
async def add(interaction: discord.Interaction, title: str):
|
|
||||||
# Makes the reaction visible to everyone
|
|
||||||
await interaction.response.defer()
|
|
||||||
|
|
||||||
# query the item
|
|
||||||
data = await make_request(title, interaction)
|
|
||||||
|
|
||||||
# Check if data is bogus
|
|
||||||
if not data:
|
|
||||||
await interaction.followup.send(f"Couldn't find a song matching {title}")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
# Gets song information
|
|
||||||
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'])
|
|
||||||
|
|
||||||
print(f"Found: {query_song_id}, with the title {query_song_title} and artist {query_song_artist}")
|
|
||||||
|
|
||||||
# Add song information as a tuple
|
|
||||||
if guild_queue_dict.get(interaction.guild_id) == None:
|
|
||||||
guild_queue_dict[interaction.guild_id] = []
|
|
||||||
guild_queue_dict[interaction.guild_id].append((query_song_id, query_song_title, query_song_artist))
|
|
||||||
|
|
||||||
|
|
||||||
# Epilogue
|
|
||||||
|
|
||||||
# Sends informational message
|
|
||||||
await interaction.followup.send(f"Added **{query_song_title}** by *{query_song_artist}*!")
|
|
||||||
tracks_queued = len(guild_queue_dict[interaction.guild_id])
|
|
||||||
|
|
||||||
# Helpfully tells the user how many tracks until their track is played
|
|
||||||
if tracks_queued > 1:
|
|
||||||
await interaction.followup.send(f"Plays after **{tracks_queued}** more tracks.")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
#Clear
|
|
||||||
#Clears the queue
|
|
||||||
@bot.tree.command(name="clear", description="Clears the queue")
|
|
||||||
async def clear(interaction: discord.Interaction):
|
|
||||||
# Makes the reaction visible to everyone
|
|
||||||
await interaction.response.defer()
|
|
||||||
|
|
||||||
clearQueue(interaction)
|
|
||||||
|
|
||||||
await interaction.followup.send(f"Cleared the Queue!")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
#Queue
|
|
||||||
#Allows the user to view the queue
|
|
||||||
@bot.tree.command(name="queue", description="See the queue")
|
|
||||||
async def queue(interaction: discord.Interaction):
|
|
||||||
|
|
||||||
# Makes the reaction visible to everyone
|
|
||||||
await interaction.response.defer()
|
|
||||||
|
|
||||||
# Check if queue is uninitialized
|
|
||||||
if guild_queue_dict.get(interaction.guild_id) == None:
|
|
||||||
guild_queue_dict[interaction.guild_id] = []
|
|
||||||
|
|
||||||
# Add all the items in a queue to a list
|
|
||||||
if len(guild_queue_dict[interaction.guild_id]) == 0:
|
|
||||||
await interaction.followup.send(f"The queue is empty!")
|
|
||||||
return
|
|
||||||
|
|
||||||
# The queue has something in it
|
|
||||||
result_list = []
|
|
||||||
for song in guild_queue_dict[interaction.guild_id]:
|
|
||||||
result_list.append(f"**{song[1]}** by *{song[2]}*")
|
|
||||||
|
|
||||||
await interaction.followup.send("\n".join(result_list))
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#Current
|
|
||||||
# Display currently playing
|
|
||||||
@bot.tree.command(name="current", description="See whats currently playing")
|
|
||||||
async def current(interaction: discord.Interaction):
|
|
||||||
# Makes the reaction visible to everyone
|
|
||||||
await interaction.response.defer()
|
|
||||||
|
|
||||||
#Display the current song
|
|
||||||
|
|
||||||
# Some song information
|
|
||||||
current = guild_queue_dict[interaction.guild_id][0]
|
|
||||||
current_title = current[1]
|
|
||||||
current_artist = current[2]
|
|
||||||
|
|
||||||
await interaction.followup.send(f"Currently Playing: **{current_title}** by *{current_artist}*")
|
|
||||||
|
|
||||||
|
|
||||||
# Cleanup
|
|
||||||
await interaction.followup.send(f"Emptied the queue!")
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
BIN
ffmpeg.exe
Normal file
BIN
ffmpeg.exe
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user