better playlist management

This commit is contained in:
Azlux 2018-12-08 23:46:31 +01:00
parent 9def7bd0f8
commit a6b1da43bf
4 changed files with 75 additions and 161 deletions

View File

@ -2,15 +2,25 @@ import youtube_dl
import variables as var import variables as var
def get_playlist_info(): def get_playlist_info(url, start_index=1, user=""):
ydl_opts = { ydl_opts = {
'playlist_items': str(0) 'extract_flat': 'in_playlist'
} }
with youtube_dl.YoutubeDL(ydl_opts) as ydl: with youtube_dl.YoutubeDL(ydl_opts) as ydl:
for i in range(2): for i in range(2):
try: try:
info = ydl.extract_info(var.playlist[-1]['url'], download=False) info = ydl.extract_info(url, download=False)
var.playlist[-1]['playlist_title'] = info['title'] playlist_title = info['title']
for j in range(start_index, start_index + var.config.getint('bot', 'max_track_playlist')):
music = {'type': 'url',
'title': info['entries'][j]['title'],
'url': "https://www.youtube.com/watch?v=" + info['entries'][j]['url'],
'user': user,
'from_playlist': True,
'playlist_title': playlist_title,
'playlist_url': url,
'ready': 'validation'}
var.playlist.append(music)
except youtube_dl.utils.DownloadError: except youtube_dl.utils.DownloadError:
pass pass
else: else:

View File

@ -2,7 +2,7 @@ import youtube_dl
import variables as var import variables as var
def get_url_info(): def get_url_info(index=-1):
ydl_opts = { ydl_opts = {
'noplaylist': True 'noplaylist': True
} }
@ -11,9 +11,9 @@ def get_url_info():
for i in range(2): for i in range(2):
try: try:
print(var.playlist) print(var.playlist)
info = ydl.extract_info(var.playlist[-1]['url'], download=False) info = ydl.extract_info(var.playlist[index]['url'], download=False)
var.playlist[-1]['duration'] = info['duration'] / 60 var.playlist[index]['duration'] = info['duration'] / 60
var.playlist[-1]['title'] = info['title'] var.playlist[index]['title'] = info['title']
except youtube_dl.utils.DownloadError: except youtube_dl.utils.DownloadError:
pass pass
else: else:

View File

@ -182,21 +182,8 @@ class MumbleBot:
offset = int(parameter.split(" ")[-1]) offset = int(parameter.split(" ")[-1])
except ValueError: except ValueError:
pass pass
music = {'type': 'playlist', if media.playlist.get_playlist_info(url=self.get_url_from_input(parameter), start_index=offset, user=user):
'url': self.get_url_from_input(parameter),
'user': user,
'max_track_allowed': var.config.getint('bot', 'max_track_playlist'),
'current_index': 1,
'start_index': offset,
'ready': 'validation',
'current_ready': 'validation',
'next_ready': 'validation'}
var.playlist.append(music)
if media.playlist.get_playlist_info():
var.playlist[-1]['ready'] = 'yes'
self.async_download_next() self.async_download_next()
else:
var.playlist.pop()
elif command == var.config.get('command', 'play_radio') and parameter: elif command == var.config.get('command', 'play_radio') and parameter:
if var.config.has_option('radio', parameter): if var.config.has_option('radio', parameter):
@ -260,6 +247,13 @@ class MumbleBot:
url=var.playlist[0]["title"], url=var.playlist[0]["title"],
user=var.playlist[0]["user"] user=var.playlist[0]["user"]
) )
elif source == "url" and 'from_playlist' in var.playlist[0]:
reply = "[playlist] {title} (from the playlist <a href=\"{url}\">{playlist}</a> by {user}".format(
title=var.playlist[0]["title"],
url=var.playlist[0]["playlist_url"],
playlist=var.playlist[0]["playlist_title"],
user=var.playlist[0]["user"]
)
elif source == "url": elif source == "url":
reply = "[url] {title} (<a href=\"{url}\">{url}</a>) by {user}".format( reply = "[url] {title} (<a href=\"{url}\">{url}</a>) by {user}".format(
title=var.playlist[0]["title"], title=var.playlist[0]["title"],
@ -270,20 +264,9 @@ class MumbleBot:
reply = "[file] {title} by {user}".format( reply = "[file] {title} by {user}".format(
title=var.playlist[0]["title"], title=var.playlist[0]["title"],
user=var.playlist[0]["user"]) user=var.playlist[0]["user"])
elif source == "playlist":
reply = "[playlist] {title} (from the playlist <a href=\"{url}\">{playlist}</a> by {user}".format(
title=var.playlist[0]["current_title"],
url=var.playlist[0]["url"],
playlist=var.playlist[0]["playlist_title"],
user=var.playlist[0]["user"]
)
else: else:
reply = "(?)[{}] {} {} by {}".format( reply = "ERROR"
var.playlist[0]["type"], logging.error(var.playlist)
var.playlist[0]["url"] if 'url' in var.playlist[0] else var.playlist[0]["path"],
var.playlist[0]["title"],
var.playlist[0]["user"]
)
else: else:
reply = var.config.get('strings', 'not_playing') reply = var.config.get('strings', 'not_playing')
@ -340,16 +323,6 @@ class MumbleBot:
@staticmethod @staticmethod
def next(): def next():
# Return True is next is possible
if len(var.playlist) > 0 and var.playlist[0]['type'] == "playlist":
logging.debug("Next into playlist")
var.playlist[0]['current_index'] = var.playlist[0]['current_index'] + 1
if var.playlist[0]['current_index'] <= (var.playlist[0]['start_index'] + var.playlist[0]['max_track_allowed']):
var.playlist[0]['current_ready'] = var.playlist[0]['next_ready']
var.playlist[0]['next_ready'] = "validation"
var.playlist[0]['next_title'] = ""
var.playlist[0]['next_duration'] = 0
return True
logging.debug("Next into the queue") logging.debug("Next into the queue")
if len(var.playlist) > 1: if len(var.playlist) > 1:
var.playlist.pop(0) var.playlist.pop(0)
@ -362,17 +335,17 @@ class MumbleBot:
def launch_music(self): def launch_music(self):
uri = "" uri = ""
logging.debug(var.playlist) if var.playlist[0]["type"] == "url":
if var.playlist[0]["type"] == "url" or var.playlist[0]["type"] == "playlist":
media.system.clear_tmp_folder(var.config.get('bot', 'tmp_folder'), var.config.getint('bot', 'tmp_folder_max_size')) media.system.clear_tmp_folder(var.config.get('bot', 'tmp_folder'), var.config.getint('bot', 'tmp_folder_max_size'))
if var.playlist[0]["type"] == "url": if var.playlist[0]["ready"] == "downloading":
logging.info("Download current single music") return
elif var.playlist[0]["ready"] != "yes":
logging.info("Current music wasn't ready, Downloading...")
self.download_music(index=0) self.download_music(index=0)
else:
logging.info("Download current music into playlist")
self.download_music(index=0, playlist_index=int(var.playlist[0]['current_index']))
uri = var.playlist[0]['path'] uri = var.playlist[0]['path']
if os.path.isfile(uri): if os.path.isfile(uri):
audio = EasyID3(uri) audio = EasyID3(uri)
title = "" title = ""
@ -395,7 +368,6 @@ class MumbleBot:
else: else:
pass pass
elif var.playlist[0]["type"] == "file": elif var.playlist[0]["type"] == "file":
uri = var.config.get('bot', 'music_folder') + var.playlist[0]["path"] uri = var.config.get('bot', 'music_folder') + var.playlist[0]["path"]
@ -414,27 +386,36 @@ class MumbleBot:
self.thread = sp.Popen(command, stdout=sp.PIPE, bufsize=480) self.thread = sp.Popen(command, stdout=sp.PIPE, bufsize=480)
self.is_playing = True self.is_playing = True
def download_music(self, index, playlist_index=0): def download_music(self, index):
logging.debug("Download index:" + str(index) + ", playlist index:" + str(playlist_index)) if var.playlist[index]['type'] == 'url' and var.playlist[index]['ready'] == "validation":
if media.url.get_url_info(index=index):
if var.playlist[index]['duration'] > var.config.getint('bot', 'max_track_duration'):
var.playlist.pop()
self.send_msg(var.config.get('strings', 'too_long'))
else:
var.playlist[index]['ready'] = "no"
else:
var.playlist.pop(index)
self.send_msg(var.config.get('strings', 'unable_download'))
if var.playlist[index]['type'] == 'url' and var.playlist[index]['ready'] == "no":
var.playlist[index]['ready'] = "downloading"
logging.debug("Download index:" + str(index))
logging.debug(var.playlist[index]) logging.debug(var.playlist[index])
url = var.playlist[index]['url'] url = var.playlist[index]['url']
url_hash = hashlib.md5(url.encode()).hexdigest() url_hash = hashlib.md5(url.encode()).hexdigest()
if var.playlist[index]['type'] == 'playlist':
url_hash = url_hash + "-" + str(playlist_index)
path = var.config.get('bot', 'tmp_folder') + url_hash + ".%(ext)s" path = var.config.get('bot', 'tmp_folder') + url_hash + ".%(ext)s"
mp3 = path.replace(".%(ext)s", ".mp3") mp3 = path.replace(".%(ext)s", ".mp3")
if (var.playlist[index]['type'] == 'playlist' and playlist_index == var.playlist[0]['current_index']) or var.playlist[index]['type'] == 'url':
var.playlist[index]['path'] = mp3 var.playlist[index]['path'] = mp3
# if os.path.isfile(mp3): # if os.path.isfile(mp3):
# audio = EasyID3(mp3) # audio = EasyID3(mp3)
# var.playlist[index]['title'] = audio["title"][0] # var.playlist[index]['title'] = audio["title"][0]
ydl_opts = "" ydl_opts = ""
if var.playlist[index]['type'] == 'url' and var.playlist[index]['ready'] == "no":
ydl_opts = { ydl_opts = {
'format': 'bestaudio/best', 'format': 'bestaudio/best',
'outtmpl': path, 'outtmpl': path,
@ -447,61 +428,8 @@ class MumbleBot:
'preferredquality': '192'}, 'preferredquality': '192'},
{'key': 'FFmpegMetadata'}] {'key': 'FFmpegMetadata'}]
} }
var.playlist[index]['ready'] = "downloading"
self.send_msg(var.config.get('strings', "download_in_progress") % var.playlist[index]['title']) self.send_msg(var.config.get('strings', "download_in_progress") % var.playlist[index]['title'])
if var.playlist[index]['type'] == 'playlist':
if var.playlist[index]['current_index'] == playlist_index and var.playlist[index]['current_ready'] == 'validation':
var.playlist[index]['current_ready'] = 'validating'
if media.playlist.get_music_info(playlist_index):
if var.playlist[0]['current_duration'] > var.config.getint('bot', 'max_track_duration'):
self.send_msg(var.config.get('strings', 'too_long'))
if self.next():
self.async_download_next()
return
else:
var.playlist[0]['current_ready'] = 'no'
pass # Music is good
else:
self.send_msg(var.config.get('strings', 'unable_download'))
if self.next():
self.async_download_next()
return
elif var.playlist[index]['current_index'] == playlist_index - 1 and var.playlist[index]['next_ready'] == 'validation':
var.playlist[index]['next_ready'] = 'validating'
if media.playlist.get_music_info(playlist_index):
if var.playlist[0]['next_duration'] > var.config.getint('bot', 'max_track_duration'):
self.send_msg(var.config.get('strings', 'too_long'))
if self.next():
self.async_download_next()
return
else:
var.playlist[0]['next_ready'] = 'no'
pass # Next Music is good
else:
self.send_msg(var.config.get('strings', 'unable_download'))
if self.next():
self.async_download_next()
return
ydl_opts = {
'format': 'bestaudio/best',
'outtmpl': path,
'writethumbnail': True,
'updatetime': False,
'playlist_items': str(playlist_index),
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192'},
{'key': 'FFmpegMetadata'}]
}
if var.playlist[index]['current_index'] == playlist_index and var.playlist[index]['current_ready'] == "no":
var.playlist[index]['current_ready'] = "downloading"
elif var.playlist[index]['current_index'] == playlist_index - 1 and var.playlist[index]['next_ready'] == "no":
var.playlist[index]['next_ready'] = "downloading"
else:
return
logging.info("Information before start downloading :" + str(var.playlist[index])) logging.info("Information before start downloading :" + str(var.playlist[index]))
with youtube_dl.YoutubeDL(ydl_opts) as ydl: with youtube_dl.YoutubeDL(ydl_opts) as ydl:
for i in range(2): for i in range(2):
@ -509,11 +437,6 @@ class MumbleBot:
ydl.extract_info(url) ydl.extract_info(url)
if 'ready' in var.playlist[index] and var.playlist[index]['ready'] == "downloading": if 'ready' in var.playlist[index] and var.playlist[index]['ready'] == "downloading":
var.playlist[index]['ready'] = "yes" var.playlist[index]['ready'] = "yes"
if var.playlist[index]['type'] == 'playlist':
if var.playlist[index]['current_index'] == playlist_index and var.playlist[index]['current_ready'] == "downloading":
var.playlist[index]['current_ready'] = "yes"
elif var.playlist[index]['current_index'] == playlist_index - 1 and var.playlist[index]['next_ready'] == 'downloading':
var.playlist[index]['next_ready'] = "yes"
except youtube_dl.utils.DownloadError: except youtube_dl.utils.DownloadError:
pass pass
else: else:
@ -522,14 +445,11 @@ class MumbleBot:
def async_download_next(self): def async_download_next(self):
logging.info("Async download next asked") logging.info("Async download next asked")
if len(var.playlist) > 0 and var.playlist[0]['type'] == 'playlist' and var.playlist[0]['next_ready'] == 'validation': if len(var.playlist) > 1 and var.playlist[1]['type'] == 'url' and var.playlist[1]['ready'] in ["no", "validation"]:
th = threading.Thread(target=self.download_music, kwargs={'index': 0, 'playlist_index': var.playlist[0]["current_index"] + 1})
elif len(var.playlist) > 1 and var.playlist[1]['type'] == 'url' and var.playlist[1]['ready'] == 'no':
th = threading.Thread(target=self.download_music, kwargs={'index': 1}) th = threading.Thread(target=self.download_music, kwargs={'index': 1})
else: else:
return return
logging.info("Start downloading next in thread")
logging.info("Start download in thread")
th.daemon = True th.daemon = True
th.start() th.start()
@ -565,8 +485,7 @@ class MumbleBot:
self.next() self.next()
if len(var.playlist) > 0: if len(var.playlist) > 0:
if var.playlist[0]['type'] in ['radio', 'file'] \ if var.playlist[0]['type'] in ['radio', 'file'] \
or (var.playlist[0]['type'] == 'url' and var.playlist[0]['ready'] != 'validation') \ or (var.playlist[0]['type'] == 'url' and var.playlist[0]['ready'] not in ['validation', 'downloading']):
or (var.playlist[0]['type'] == 'playlist' and var.playlist[0]['ready'] == 'yes'):
self.launch_music() self.launch_music()
self.async_download_next() self.async_download_next()

View File

@ -6,24 +6,9 @@ type : url
thundnail thundnail
user user
ready (validation, no, downloading, yes) ready (validation, no, downloading, yes)
from_playlist (yes,no)
type : playlist
url
ready
playlist_title playlist_title
nb_track_allowed playlist_url
nb_track_playlist
max_track_allowed
start_index
current_index
current url
current_title
current_duration
current_thundnail
current_ready (validation,no, downloading, yes)
next_ready (validation,no, downloading, yes)
user
type : radio type : radio
url url