mirror of
https://github.com/G2-Games/simple-discord-music-bot.git
synced 2025-04-19 07:52:54 -05:00
Refactored queue and per-server state
This commit is contained in:
parent
908619838c
commit
e0cad01148
5 changed files with 155 additions and 162 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.env
|
|
@ -1,5 +1,5 @@
|
||||||
discord==2.3
|
discord==2.3
|
||||||
ffmpeg==1.4
|
ffmpeg-python==0.2
|
||||||
stringprogressbar==1.1
|
stringprogressbar==1.1
|
||||||
pynacl==1.5
|
pynacl==1.5
|
||||||
yt-dlp==2024.8.6
|
yt-dlp==2024.8.6
|
||||||
|
|
BIN
src/__pycache__/utils.cpython-312.pyc
Normal file
BIN
src/__pycache__/utils.cpython-312.pyc
Normal file
Binary file not shown.
|
@ -5,15 +5,18 @@ from yt_dlp import YoutubeDL
|
||||||
from asyncio import sleep
|
from asyncio import sleep
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from StringProgressBar import progressBar
|
from StringProgressBar import progressBar
|
||||||
import uuid
|
|
||||||
import logging
|
import logging
|
||||||
|
import json
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
## LOCAL IMPORTS ##
|
||||||
|
import utils
|
||||||
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
intents = discord.Intents.default()
|
intents = discord.Intents.default()
|
||||||
intents.message_content = True
|
intents.message_content = True
|
||||||
|
|
||||||
# Dictionary to store queues between servers
|
# Dictionary to store queues between servers
|
||||||
queue_list = {}
|
|
||||||
server_info = {}
|
server_info = {}
|
||||||
downloading = 0
|
downloading = 0
|
||||||
paused = False
|
paused = False
|
||||||
|
@ -21,45 +24,25 @@ paused = False
|
||||||
# Create a new Discord client
|
# Create a new Discord client
|
||||||
bot = commands.Bot(command_prefix="!",intents=discord.Intents.all(), shard_count=1)
|
bot = commands.Bot(command_prefix="!",intents=discord.Intents.all(), shard_count=1)
|
||||||
|
|
||||||
|
|
||||||
@bot.event
|
@bot.event
|
||||||
async def on_ready():
|
async def on_ready():
|
||||||
print("Bot is ready!")
|
print("Bot is ready!")
|
||||||
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.listening, name="Nanahira"))
|
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.listening, name="ななひら"))
|
||||||
|
|
||||||
async def delete_after_delay(ctx, delay):
|
|
||||||
await sleep(delay)
|
|
||||||
await ctx.message.delete()
|
|
||||||
|
|
||||||
async def get_ids(ctx):
|
|
||||||
await ctx.message.delete(delay=3)
|
|
||||||
server_id = ctx.message.guild.id
|
|
||||||
voice_channel = ctx.message.guild.voice_client
|
|
||||||
user_voice_channel = ctx.author.voice
|
|
||||||
return server_id, voice_channel, user_voice_channel
|
|
||||||
|
|
||||||
async def getFileNames(server_id):
|
|
||||||
downloading = 1
|
|
||||||
# Get the current unix timestamp to the nearest millisecond for the filename
|
|
||||||
uuid_stamp = uuid.uuid1()
|
|
||||||
audioname = str(uuid_stamp) + "audio"
|
|
||||||
thumbname = str(uuid_stamp) + "image"
|
|
||||||
|
|
||||||
# Create the id and thumbnail of the attachment as "tmp<timestamp>.flac" and "tmp<timestamp>.png" respectively
|
|
||||||
# And add the server ID as the path, making it unique
|
|
||||||
audioname = os.path.join(str(server_id), audioname)
|
|
||||||
thumbname = os.path.join(str(server_id), thumbname)
|
|
||||||
return audioname, thumbname
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def play(ctx, *, query: str = None):
|
async def play(ctx, *, query: str = None):
|
||||||
# Get all the id and channel info
|
# Get all the id and channel info
|
||||||
server_id, voice_channel, user_voice_channel = await get_ids(ctx)
|
server_id, voice_channel, user_voice_channel = await utils.get_ids(ctx)
|
||||||
|
|
||||||
# Create a queue and info dictionary for the current server
|
# Create a queue and info dictionary for the current server
|
||||||
if server_id not in queue_list:
|
if server_id not in server_info:
|
||||||
queue_list[server_id] = [1]
|
|
||||||
server_info[server_id] = {
|
server_info[server_id] = {
|
||||||
"loop": False
|
"loop": False,
|
||||||
|
"paused": False,
|
||||||
|
"queue_position": 0,
|
||||||
|
"queue": [],
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create the server ID folder for storing downloads
|
# Create the server ID folder for storing downloads
|
||||||
|
@ -70,7 +53,7 @@ async def play(ctx, *, query: str = None):
|
||||||
|
|
||||||
# If the user is not in a voice channel, return an error message
|
# If the user is not in a voice channel, return an error message
|
||||||
if user_voice_channel is None:
|
if user_voice_channel is None:
|
||||||
await ctx.send("You must be in a voice channel to use this command.", delete_after=3)
|
await ctx.send(":no_entry_sign: You must be in a voice channel to use this command.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Connect to the voice channel if not already connected
|
# Connect to the voice channel if not already connected
|
||||||
|
@ -79,13 +62,13 @@ async def play(ctx, *, query: str = None):
|
||||||
|
|
||||||
# If the user is not in a voice channel or the voice channel is not the same one as the bot, return an error message
|
# If the user is not in a voice channel or the voice channel is not the same one as the bot, return an error message
|
||||||
if user_voice_channel.channel != voice_channel.channel:
|
if user_voice_channel.channel != voice_channel.channel:
|
||||||
await ctx.send("You must be in the same voice channel as the bot to use this command.", delete_after=3)
|
await ctx.send(":no_entry_sign: You must be in the same voice channel as the bot to use this command.")
|
||||||
return
|
return
|
||||||
|
|
||||||
if query == None and not ctx.message.attachments:
|
if query == None and not ctx.message.attachments:
|
||||||
# If the bot is already playing, return an error message
|
# If the bot is already playing, return an error message
|
||||||
if voice_channel.is_playing():
|
if voice_channel.is_playing():
|
||||||
await ctx.send(":no_entry_sign: The bot is already playing", delete_after=3)
|
await ctx.send(":no_entry_sign: The bot is already playing")
|
||||||
return
|
return
|
||||||
|
|
||||||
# If the bot is paused, resume playback
|
# If the bot is paused, resume playback
|
||||||
|
@ -101,13 +84,11 @@ async def play(ctx, *, query: str = None):
|
||||||
if voice_channel.is_playing():
|
if voice_channel.is_playing():
|
||||||
await ctx.send("The bot is already playing, adding song to queue", delete_after=3)
|
await ctx.send("The bot is already playing, adding song to queue", delete_after=3)
|
||||||
|
|
||||||
print("1");
|
|
||||||
|
|
||||||
if ctx.message.attachments:
|
if ctx.message.attachments:
|
||||||
downloading = 1
|
downloading = 1
|
||||||
notice = await ctx.send(":arrow_double_up: Uploading...", suppress_embeds=True)
|
notice = await ctx.send(":arrow_double_up: Uploading...", suppress_embeds=True)
|
||||||
for song in ctx.message.attachments:
|
for song in ctx.message.attachments:
|
||||||
filename, thumbname = await getFileNames(server_id)
|
filename, thumbname = await utils.getFileNames(server_id)
|
||||||
|
|
||||||
# Make sure the file is either audio or video
|
# Make sure the file is either audio or video
|
||||||
filetype = song.content_type
|
filetype = song.content_type
|
||||||
|
@ -118,33 +99,38 @@ async def play(ctx, *, query: str = None):
|
||||||
await song.save(filename)
|
await song.save(filename)
|
||||||
|
|
||||||
# Grab thumbnail from file
|
# Grab thumbnail from file
|
||||||
f = open("tmp", "w")
|
ffmpeg_cli = ffmpeg\
|
||||||
subprocess.run(["ffmpeg", "-y", "-i", filename, "-map", "0:v", "-map", "-0:V", "-c", "copy", thumbname], stderr=subprocess.STDOUT, stdout=f)
|
.input(
|
||||||
|
filename,
|
||||||
|
t=1,
|
||||||
|
)\
|
||||||
|
.output(
|
||||||
|
thumbname,
|
||||||
|
f="image2"
|
||||||
|
)\
|
||||||
|
.overwrite_output()
|
||||||
|
|
||||||
|
print(ffmpeg_cli.get_args())
|
||||||
|
ffmpeg_cli.run()
|
||||||
|
|
||||||
|
|
||||||
# Grab metadata from file
|
# Grab metadata from file
|
||||||
f = open("tmp", "w")
|
try:
|
||||||
subprocess.run(["ffmpeg", "-y", "-i", filename, "-f", "ffmetadata", str(server_id) + "/meta.txt"], stderr=subprocess.STDOUT, stdout=f)
|
metadata = ffmpeg.probe(filename)
|
||||||
|
except:
|
||||||
|
metadata = {}
|
||||||
|
|
||||||
file_title = song.filename
|
file_title = song.filename
|
||||||
file_artist = None
|
if "TITLE" in metadata["format"]["tags"]:
|
||||||
file_album = None
|
file_title = metadata["format"]["tags"]["TITLE"]
|
||||||
|
|
||||||
with open(str(server_id) + '/meta.txt', 'r') as m:
|
file_artist = ""
|
||||||
lines = m.readlines()
|
if "ARTIST" in metadata["format"]["tags"]:
|
||||||
file_artist = "Unknown"
|
file_artist = metadata["format"]["tags"]["ARTIST"]
|
||||||
file_album = "Unknown"
|
|
||||||
for line in lines:
|
file_album = ""
|
||||||
if re.search(r'TITLE=', line, re.IGNORECASE):
|
if "ALBUM" in metadata["format"]["tags"]:
|
||||||
file_title = line.split('=')[1]
|
file_album = metadata["format"]["tags"]["ALBUM"]
|
||||||
break
|
|
||||||
for line in lines:
|
|
||||||
if re.search(r'ARTIST=', line, re.IGNORECASE):
|
|
||||||
file_artist = line.split('=')[1]
|
|
||||||
break
|
|
||||||
for line in lines:
|
|
||||||
if re.search(r'ALBUM=', line, re.IGNORECASE):
|
|
||||||
file_album = line.split('=')[1]
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
if os.path.exists(thumbname):
|
if os.path.exists(thumbname):
|
||||||
|
@ -153,7 +139,7 @@ async def play(ctx, *, query: str = None):
|
||||||
thumbnail = "assets/unknown.png"
|
thumbnail = "assets/unknown.png"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
duration = ffmpeg.probe(filename)['format']['duration']
|
duration = metadata['format']['duration']
|
||||||
except:
|
except:
|
||||||
duration = None
|
duration = None
|
||||||
|
|
||||||
|
@ -165,16 +151,16 @@ async def play(ctx, *, query: str = None):
|
||||||
"url": song.url,
|
"url": song.url,
|
||||||
"id": filename,
|
"id": filename,
|
||||||
"thumbnail": thumbnail,
|
"thumbnail": thumbnail,
|
||||||
|
"thumbnail_url": None,
|
||||||
"duration": duration
|
"duration": duration
|
||||||
}
|
}
|
||||||
|
|
||||||
await notice.edit(content=":white_check_mark: Successfully uploaded \"" + song.filename + "\"")
|
await notice.edit(content=":white_check_mark: Successfully uploaded \"" + song.filename + "\"")
|
||||||
queue_list[server_id].append(item)
|
server_info[server_id]["queue"].append(item)
|
||||||
|
|
||||||
downloading = 0
|
downloading = 0
|
||||||
await notice.edit(content=":white_check_mark: Successfully uploaded \"" + song.filename + "\"", delete_after=3)
|
|
||||||
elif query[0:4] != "http" and query[0:3] != "www":
|
elif query[0:4] != "http" and query[0:3] != "www":
|
||||||
filename, thumbname = await getFileNames(server_id)
|
filename, thumbname = await utils.getFileNames(server_id)
|
||||||
|
|
||||||
# Let the user know the bot is searching for a video
|
# Let the user know the bot is searching for a video
|
||||||
notice = await ctx.send(":mag_right: Searching for \"" + query + "\" ...", suppress_embeds=True)
|
notice = await ctx.send(":mag_right: Searching for \"" + query + "\" ...", suppress_embeds=True)
|
||||||
|
@ -201,11 +187,11 @@ async def play(ctx, *, query: str = None):
|
||||||
"duration": duration
|
"duration": duration
|
||||||
}
|
}
|
||||||
|
|
||||||
await notice.edit(content=":white_check_mark: Downloaded " + title + ": " + audio_url, suppress=True, delete_after=3)
|
await notice.edit(content=":white_check_mark: Found " + title + ": " + audio_url, suppress=True, delete_after=3)
|
||||||
queue_list[server_id].append(item)
|
server_info[server_id]["queue"].append(item)
|
||||||
downloading = 0
|
downloading = 0
|
||||||
elif query[0:4] == "http" or query[0:3] == "www":
|
elif query[0:4] == "http" or query[0:3] == "www":
|
||||||
filename, thumbname = await getFileNames(server_id)
|
filename, thumbname = await utils.getFileNames(server_id)
|
||||||
|
|
||||||
# Let the user know the bot is searching for a video
|
# Let the user know the bot is searching for a video
|
||||||
notice = await ctx.send(":mag_right: Searching for \"" + query + "\" ...", suppress_embeds=True)
|
notice = await ctx.send(":mag_right: Searching for \"" + query + "\" ...", suppress_embeds=True)
|
||||||
|
@ -236,8 +222,8 @@ async def play(ctx, *, query: str = None):
|
||||||
"duration": duration
|
"duration": duration
|
||||||
}
|
}
|
||||||
|
|
||||||
await notice.edit(content=":white_check_mark: Added \"" + title + "\": " + query, suppress=True, delete_after=3)
|
await notice.edit(content=":white_check_mark: Found \"" + title + "\": " + query, suppress=True, delete_after=3)
|
||||||
queue_list[server_id].append(item)
|
server_info[server_id]["queue"].append(item)
|
||||||
downloading = 0
|
downloading = 0
|
||||||
else:
|
else:
|
||||||
print("Error")
|
print("Error")
|
||||||
|
@ -253,26 +239,27 @@ async def play(ctx, *, query: str = None):
|
||||||
playing = await ctx.send(embed=embed)
|
playing = await ctx.send(embed=embed)
|
||||||
|
|
||||||
# Loop that repeats as long as the queue position has not reached the length of the queue
|
# Loop that repeats as long as the queue position has not reached the length of the queue
|
||||||
while len(queue_list[server_id]) - 1 >= queue_list[server_id][0]:
|
while len(server_info[server_id]["queue"]) >= server_info[server_id]["queue_position"]:
|
||||||
# Get the current queue position
|
# Get the current queue position
|
||||||
queue_position = queue_list[server_id][0]
|
queue_position = server_info[server_id]["queue_position"]
|
||||||
|
queue = server_info[server_id]["queue"]
|
||||||
|
|
||||||
# Set song variables
|
# Set song variables
|
||||||
song_id = queue_list[server_id][queue_position]['id']
|
song_id = queue[queue_position]['id']
|
||||||
song_url = queue_list[server_id][queue_position]['url']
|
song_url = queue[queue_position]['url']
|
||||||
song_name = queue_list[server_id][queue_position]['name']
|
song_name = queue[queue_position]['name']
|
||||||
song_thumb = queue_list[server_id][queue_position]['thumbnail']
|
song_thumb = queue[queue_position]['thumbnail']
|
||||||
song_duration = queue_list[server_id][queue_position]['duration']
|
song_duration = queue[queue_position]['duration']
|
||||||
song_thumb_url = queue_list[server_id][queue_position]['thumbnail_url']
|
song_thumb_url = queue[queue_position]['thumbnail_url']
|
||||||
song_thumbname = str(int(time.time())) + ".png"
|
song_thumbname = str(int(time.time())) + ".png"
|
||||||
|
|
||||||
# Create the embed
|
# Create the embed
|
||||||
if queue_list[server_id][queue_position]['artist'] and queue_list[server_id][queue_position]['album']:
|
if queue[queue_position]['artist'] and queue[queue_position]['album']:
|
||||||
song_desc = "Name: " + song_name + "\nArtist: " + queue_list[server_id][queue_position]['artist'] + "\nAlbum: " + queue_list[server_id][queue_position]['album']
|
song_desc = "Artist: " + queue[queue_position]['artist'] + "\nAlbum: " + queue[queue_position]['album']
|
||||||
else:
|
else:
|
||||||
song_desc = "Name: " + song_name + "\nURL: " + song_url
|
song_desc = ""
|
||||||
|
|
||||||
embed=discord.Embed(title="▶️ Playing: " + song_name, url=song_url, description=song_desc, color=0x42f5a7)
|
embed=discord.Embed(title=":arrow_forward: Playing: " + song_name, url=song_url, description=song_desc, color=0x42f5a7)
|
||||||
if song_thumb is not None:
|
if song_thumb is not None:
|
||||||
await playing.add_files(discord.File(song_thumb, filename=song_thumbname))
|
await playing.add_files(discord.File(song_thumb, filename=song_thumbname))
|
||||||
embed.set_thumbnail(url="attachment://" + song_thumbname)
|
embed.set_thumbnail(url="attachment://" + song_thumbname)
|
||||||
|
@ -328,22 +315,15 @@ async def play(ctx, *, query: str = None):
|
||||||
)
|
)
|
||||||
await playing.edit(embed=embed)
|
await playing.edit(embed=embed)
|
||||||
|
|
||||||
if server_info[server_id]["loop"]:
|
if not server_info[server_id]["loop"]:
|
||||||
continue
|
# Increment the queue position by 1
|
||||||
|
try:
|
||||||
# Increment the queue position by 1
|
server_info[server_id]["queue_position"] += 1
|
||||||
try:
|
except:
|
||||||
queue_list[server_id][0] += 1
|
print(str(server_id) + " | " + "Queue position out of range.")
|
||||||
except:
|
break
|
||||||
print(str(server_id) + " | " + "Queue position out of range.")
|
|
||||||
break
|
|
||||||
print(str(server_id) + " | " + "Play position: " + str(queue_position))
|
print(str(server_id) + " | " + "Play position: " + str(queue_position))
|
||||||
|
|
||||||
try:
|
|
||||||
await q(ctx)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Display the stop embed
|
# Display the stop embed
|
||||||
try:
|
try:
|
||||||
await q(ctx, "hide")
|
await q(ctx, "hide")
|
||||||
|
@ -358,8 +338,8 @@ async def play(ctx, *, query: str = None):
|
||||||
# Disconnect from the voice channel if the loop finishes
|
# Disconnect from the voice channel if the loop finishes
|
||||||
await voice_channel.disconnect()
|
await voice_channel.disconnect()
|
||||||
|
|
||||||
queue_list[server_id].clear()
|
server_info[server_id]["queue"].clear()
|
||||||
queue_list[server_id].insert(0, 1)
|
server_info[server_id]["queue_position"] = 0
|
||||||
|
|
||||||
# Remove all queued files and folders
|
# Remove all queued files and folders
|
||||||
fileList = glob.glob(os.path.join(str(server_id),'*'))
|
fileList = glob.glob(os.path.join(str(server_id),'*'))
|
||||||
|
@ -370,10 +350,11 @@ async def play(ctx, *, query: str = None):
|
||||||
print("Error while deleting file")
|
print("Error while deleting file")
|
||||||
os.rmdir(str(server_id))
|
os.rmdir(str(server_id))
|
||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def skip(ctx, direction = None, number = None):
|
async def skip(ctx, direction = None, number = None):
|
||||||
# Get all the id and channel info
|
# Get all the id and channel info
|
||||||
server_id, voice_channel, user_voice_channel = await get_ids(ctx)
|
server_id, voice_channel, user_voice_channel = await utils.get_ids(ctx)
|
||||||
|
|
||||||
if voice_channel is None:
|
if voice_channel is None:
|
||||||
await ctx.send(":no_entry_sign: Bot must be playing to skip!", delete_after=3)
|
await ctx.send(":no_entry_sign: Bot must be playing to skip!", delete_after=3)
|
||||||
|
@ -394,16 +375,15 @@ async def skip(ctx, direction = None, number = None):
|
||||||
try:
|
try:
|
||||||
if direction.isnumeric():
|
if direction.isnumeric():
|
||||||
if int(direction) > 0:
|
if int(direction) > 0:
|
||||||
queue_list[server_id][0] += int(direction) - 1
|
server_info[server_id]["queue_position"] += int(direction) - 1
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
if number != None and number > 0:
|
if number != None and number > 0:
|
||||||
queue_list[server_id][0] += number - 1
|
server_info[server_id]["queue_position"] += number - 1
|
||||||
|
|
||||||
# Stop the audio playback
|
# Stop the audio playback
|
||||||
voice_channel.stop()
|
voice_channel.stop()
|
||||||
|
elif direction == "back" and not server_info[server_id]["queue_position"] == 1:
|
||||||
elif direction == "back" and not queue_list[server_id][0] == 1:
|
|
||||||
|
|
||||||
# Decrement the queue position
|
# Decrement the queue position
|
||||||
back = 2
|
back = 2
|
||||||
|
@ -412,19 +392,16 @@ async def skip(ctx, direction = None, number = None):
|
||||||
if number != None and number > 0:
|
if number != None and number > 0:
|
||||||
back = number + 1
|
back = number + 1
|
||||||
|
|
||||||
queue_list[server_id][0] -= back
|
server_info[server_id]["queue_position"] -= back
|
||||||
|
|
||||||
# Stop the audio playback of the current track
|
# Stop the audio playback of the current track
|
||||||
voice_channel.stop()
|
voice_channel.stop()
|
||||||
|
|
||||||
elif direction == "to" and number is not None:
|
elif direction == "to" and number is not None:
|
||||||
queue_list[server_id][0] = number - 1
|
server_info[server_id]["queue_position"] = number
|
||||||
|
|
||||||
voice_channel.stop()
|
voice_channel.stop()
|
||||||
|
elif server_info[server_id]["queue_position"] == 0:
|
||||||
elif queue_list[server_id][0] == 1:
|
|
||||||
await ctx.send(":no_entry_sign: Already at first song in queue.", delete_after=3)
|
await ctx.send(":no_entry_sign: Already at first song in queue.", delete_after=3)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
await ctx.send(":no_entry_sign: Invalid argument.", delete_after=3)
|
await ctx.send(":no_entry_sign: Invalid argument.", delete_after=3)
|
||||||
|
|
||||||
|
@ -434,10 +411,11 @@ async def skip(ctx, direction = None, number = None):
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def stop(ctx):
|
async def stop(ctx):
|
||||||
# Get all the id and channel info
|
# Get all the id and channel info
|
||||||
server_id, voice_channel, user_voice_channel = await get_ids(ctx)
|
server_id, voice_channel, user_voice_channel = await utils.get_ids(ctx)
|
||||||
|
|
||||||
if voice_channel is None:
|
if voice_channel is None:
|
||||||
await ctx.send(":no_entry_sign: Bot must be playing to stop!", delete_after=3)
|
await ctx.send(":no_entry_sign: Bot must be playing to stop!", delete_after=3)
|
||||||
|
@ -447,16 +425,17 @@ async def stop(ctx):
|
||||||
await ctx.send(":no_entry_sign: You must be in the same voice channel as the bot to use this command.", delete_after=3)
|
await ctx.send(":no_entry_sign: You must be in the same voice channel as the bot to use this command.", delete_after=3)
|
||||||
return
|
return
|
||||||
|
|
||||||
queue_list[server_id].clear()
|
server_info[server_id]["queue"].clear()
|
||||||
queue_list[server_id].insert(0, 1)
|
server_info[server_id]["queue_position"] = 0
|
||||||
await sleep(0.5)
|
await sleep(0.5)
|
||||||
voice_channel.stop()
|
voice_channel.stop()
|
||||||
await voice_channel.disconnect()
|
await voice_channel.disconnect()
|
||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def pause(ctx):
|
async def pause(ctx):
|
||||||
# Get all the id and channel info
|
# Get all the id and channel info
|
||||||
server_id, voice_channel, user_voice_channel = await get_ids(ctx)
|
server_id, voice_channel, user_voice_channel = await utils.get_ids(ctx)
|
||||||
|
|
||||||
if voice_channel is None or not voice_channel.is_playing():
|
if voice_channel is None or not voice_channel.is_playing():
|
||||||
await ctx.send(":no_entry_sign: Bot must be playing to pause!", delete_after=3)
|
await ctx.send(":no_entry_sign: Bot must be playing to pause!", delete_after=3)
|
||||||
|
@ -469,28 +448,16 @@ async def pause(ctx):
|
||||||
global paused
|
global paused
|
||||||
paused = True
|
paused = True
|
||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def queue(ctx, action = None, selection = None):
|
async def queue(ctx, action = None, selection = None):
|
||||||
await q(ctx, action, selection)
|
await q(ctx, action, selection)
|
||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def q(ctx, action = None, selection = None):
|
async def q(ctx, action = None, selection = None):
|
||||||
# Get all the id and channel info
|
# Get all the id and channel info
|
||||||
server_id, voice_channel, user_voice_channel = await get_ids(ctx)
|
server_id, voice_channel, user_voice_channel = await utils.get_ids(ctx)
|
||||||
global queue_embed
|
|
||||||
if action == "hide":
|
|
||||||
try:
|
|
||||||
queue_embed
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if queue_embed is None:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
await queue_embed.delete()
|
|
||||||
queue_embed = None
|
|
||||||
del queue_embed
|
|
||||||
return
|
|
||||||
|
|
||||||
if voice_channel is None:
|
if voice_channel is None:
|
||||||
await ctx.send(":no_entry_sign: Bot must be in a channel to view the queue!", delete_after=3)
|
await ctx.send(":no_entry_sign: Bot must be in a channel to view the queue!", delete_after=3)
|
||||||
|
@ -501,40 +468,34 @@ async def q(ctx, action = None, selection = None):
|
||||||
return
|
return
|
||||||
|
|
||||||
if action == "show" or action == "list" or action == None:
|
if action == "show" or action == "list" or action == None:
|
||||||
if action == "show":
|
print(str(server_id) + " | " + "Updating queue, position: " + str(server_info[server_id]["queue_position"]))
|
||||||
try:
|
index = 0
|
||||||
await q(ctx, "hide")
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
print(str(server_id) + " | " + "Updating queue, position: " + str(queue_list[server_id][0]))
|
|
||||||
x = 0
|
|
||||||
qu = ""
|
qu = ""
|
||||||
d = ""
|
d = ""
|
||||||
p = ""
|
p = ""
|
||||||
now_playing = "⠀"
|
now_playing = "⠀"
|
||||||
for entry in queue_list[server_id]:
|
for entry in server_info[server_id]["queue"]:
|
||||||
if x != 0:
|
if index == server_info[server_id]["queue_position"]:
|
||||||
if x == queue_list[server_id][0]:
|
now_playing = ":arrow_right:"
|
||||||
now_playing = ":arrow_right:"
|
else:
|
||||||
else:
|
now_playing = "⠀"
|
||||||
now_playing = "⠀"
|
|
||||||
|
|
||||||
|
|
||||||
if len(entry['name']) >= 30:
|
if len(entry['name']) >= 30:
|
||||||
entry_cut = entry['name'][0:30]
|
entry_cut = entry['name'][0:30]
|
||||||
else:
|
else:
|
||||||
entry_cut = entry['name']
|
entry_cut = entry['name']
|
||||||
|
|
||||||
p += now_playing + "\n"
|
p += now_playing + "\n"
|
||||||
qu += "**" + str(x) + ":** " + entry_cut + "\n"
|
qu += "**" + str(index + 1) + ":** " + entry_cut + "\n"
|
||||||
if str(strftime("%H", gmtime(int(float(entry['duration'])))))[0:1] == "00":
|
if str(strftime("%H", gmtime(int(float(entry['duration'])))))[0:1] == "00":
|
||||||
d += str(strftime("%M:%S", gmtime(int(float(entry['duration']))))) + "\n"
|
d += str(strftime("%M:%S", gmtime(int(float(entry['duration']))))) + "\n"
|
||||||
else:
|
else:
|
||||||
d += str(strftime("%H:%M:%S", gmtime(int(float(entry['duration']))))) + "\n"
|
d += str(strftime("%H:%M:%S", gmtime(int(float(entry['duration']))))) + "\n"
|
||||||
x += 1
|
|
||||||
|
|
||||||
embed=discord.Embed(title="Queue:", description="", color=0xa032a8)
|
index += 1
|
||||||
|
|
||||||
|
embed = discord.Embed(title="Queue:", description="", color=0xa032a8)
|
||||||
try:
|
try:
|
||||||
embed.add_field(name="⠀", value=p, inline=True)
|
embed.add_field(name="⠀", value=p, inline=True)
|
||||||
embed.add_field(name="List", value=qu, inline=True)
|
embed.add_field(name="List", value=qu, inline=True)
|
||||||
|
@ -555,19 +516,20 @@ async def q(ctx, action = None, selection = None):
|
||||||
|
|
||||||
if action == "remove":
|
if action == "remove":
|
||||||
print(str(server_id) + " | " + "Removing item #" + str(selection) + " from queue")
|
print(str(server_id) + " | " + "Removing item #" + str(selection) + " from queue")
|
||||||
|
selection = selection - 1
|
||||||
selection = int(selection)
|
selection = int(selection)
|
||||||
position = queue_list[server_id][0]
|
position = server_info[server_id]["queue_position"]
|
||||||
id = queue_list[server_id][selection]['id']
|
id = server_info[server_id]["queue"][selection]['id']
|
||||||
if queue_list[server_id][selection]['thumbnail'] != "/assets/unknown.png":
|
if server_info[server_id]["queue"][selection]['thumbnail'] != "/assets/unknown.png":
|
||||||
thumbnail = None
|
thumbnail = None
|
||||||
else:
|
else:
|
||||||
thumbnail = queue_list[server_id][selection]['thumbnail']
|
thumbnail = server_info[server_id]["queue"][selection]['thumbnail']
|
||||||
|
|
||||||
if selection is position:
|
if selection is position:
|
||||||
await ctx.send(":no_entry_sign: Error, cannot remove currently playing item", delete_after=3)
|
await ctx.send(":no_entry_sign: Error, cannot remove currently playing item", delete_after=3)
|
||||||
return
|
return
|
||||||
|
|
||||||
if selection != 0 and not int(selection) > len(queue_list[server_id]):
|
if selection != 0 and not int(selection) > len(server_info[server_id]["queue"]):
|
||||||
try:
|
try:
|
||||||
os.remove(id)
|
os.remove(id)
|
||||||
if not thumbnail is None:
|
if not thumbnail is None:
|
||||||
|
@ -580,21 +542,22 @@ async def q(ctx, action = None, selection = None):
|
||||||
|
|
||||||
if selection < position and position > 1:
|
if selection < position and position > 1:
|
||||||
try:
|
try:
|
||||||
queue_list[server_id][0] -= 1
|
server_info[server_id]["queue_position"] -= 1
|
||||||
except:
|
except:
|
||||||
print(str(server_id) + " | " + "Queue position out of range.")
|
print(str(server_id) + " | " + "Queue position out of range.")
|
||||||
pass
|
pass
|
||||||
|
|
||||||
await ctx.send(":white_check_mark: Removed item #" + str(selection) + " from queue.", delete_after=3)
|
await ctx.send(":white_check_mark: Removed item #" + str(selection) + " from queue.", delete_after=3)
|
||||||
queue_list[server_id].pop(selection)
|
server_info[server_id]["queue"].pop(selection)
|
||||||
await q(ctx)
|
await q(ctx)
|
||||||
else:
|
else:
|
||||||
await ctx.send(":no_entry_sign: Error, item #" + str(selection) + "not a valid queue item", delete_after=3)
|
await ctx.send(":no_entry_sign: Error, item #" + str(selection) + "not a valid queue item", delete_after=3)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
@bot.command()
|
@bot.command()
|
||||||
async def loop(ctx, number = None):
|
async def loop(ctx, number = None):
|
||||||
server_id, voice_channel, user_voice_channel = await get_ids(ctx)
|
server_id, voice_channel, user_voice_channel = await utils.get_ids(ctx)
|
||||||
|
|
||||||
if voice_channel is None or not voice_channel.is_playing() and not voice_channel.is_paused():
|
if voice_channel is None or not voice_channel.is_playing() and not voice_channel.is_paused():
|
||||||
await ctx.send(":no_entry_sign: Bot must be playing to loop!", delete_after=3)
|
await ctx.send(":no_entry_sign: Bot must be playing to loop!", delete_after=3)
|
||||||
|
@ -616,11 +579,14 @@ async def loop(ctx, number = None):
|
||||||
print(server_info[server_id]["loop"])
|
print(server_info[server_id]["loop"])
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
@bot.event
|
@bot.event
|
||||||
async def on_command_error(ctx, error):
|
async def on_command_error(ctx, error):
|
||||||
server_id, voice_channel, user_voice_channel = await get_ids(ctx)
|
server_id, voice_channel, user_voice_channel = await utils.get_ids(ctx)
|
||||||
if isinstance(error, commands.CommandNotFound):
|
if isinstance(error, commands.CommandNotFound):
|
||||||
await ctx.send("Unknown command", delete_after=3)
|
await ctx.send("Unknown command", delete_after=3)
|
||||||
|
else:
|
||||||
|
print(error)
|
||||||
|
|
||||||
# Run the bot using the Discord bot token
|
# Run the bot using the Discord bot token
|
||||||
bot.run("<>")
|
bot.run("")
|
26
src/utils.py
Normal file
26
src/utils.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import uuid, os
|
||||||
|
|
||||||
|
async def delete_after_delay(ctx, delay):
|
||||||
|
await sleep(delay)
|
||||||
|
await ctx.message.delete()
|
||||||
|
|
||||||
|
|
||||||
|
async def get_ids(ctx):
|
||||||
|
server_id = ctx.message.guild.id
|
||||||
|
voice_channel = ctx.message.guild.voice_client
|
||||||
|
user_voice_channel = ctx.author.voice
|
||||||
|
return server_id, voice_channel, user_voice_channel
|
||||||
|
|
||||||
|
|
||||||
|
async def getFileNames(server_id):
|
||||||
|
downloading = 1
|
||||||
|
# Get the current unix timestamp to the nearest millisecond for the filename
|
||||||
|
uuid_stamp = uuid.uuid1()
|
||||||
|
audioname = str(uuid_stamp) + "audio"
|
||||||
|
thumbname = str(uuid_stamp) + "image"
|
||||||
|
|
||||||
|
# Create the id and thumbnail of the attachment as "tmp<timestamp>.flac" and "tmp<timestamp>.png" respectively
|
||||||
|
# And add the server ID as the path, making it unique
|
||||||
|
audioname = os.path.join(str(server_id), audioname)
|
||||||
|
thumbname = os.path.join(str(server_id), thumbname)
|
||||||
|
return audioname, thumbname
|
Loading…
Reference in a new issue