feat: 'search' command to search the db, and 'shortlist' to add songs from search result
This commit is contained in:
parent
45b83af4ba
commit
f7042db657
171
command.py
171
command.py
@ -10,6 +10,7 @@ import util
|
||||
import variables as var
|
||||
from librb import radiobrowser
|
||||
from database import SettingsDatabase, MusicDatabase
|
||||
from media.item import item_builders, item_loaders, item_id_generators, dict_to_item, dicts_to_items
|
||||
from media.playlist import get_item_wrapper, get_item_wrapper_by_id, get_item_wrappers_by_tags
|
||||
from media.file import FileItem
|
||||
from media.url_from_playlist import PlaylistURLItem, get_playlist_info
|
||||
@ -58,6 +59,8 @@ def register_all_commands(bot):
|
||||
bot.register_command(constants.commands('add_tag'), cmd_add_tag)
|
||||
bot.register_command(constants.commands('remove_tag'), cmd_remove_tag)
|
||||
bot.register_command(constants.commands('find_tagged'), cmd_find_tagged)
|
||||
bot.register_command(constants.commands('search'), cmd_search_library)
|
||||
bot.register_command(constants.commands('add_from_shortlist'), cmd_shortlist)
|
||||
bot.register_command(constants.commands('drop_database'), cmd_drop_database, True)
|
||||
bot.register_command(constants.commands('rescan'), cmd_refresh_cache, True)
|
||||
|
||||
@ -81,6 +84,10 @@ def send_multi_lines(bot, lines, text, linebreak="<br />"):
|
||||
|
||||
bot.send_msg(msg, text)
|
||||
|
||||
# ---------------- Variables -----------------
|
||||
|
||||
song_shortlist = []
|
||||
|
||||
# ---------------- Commands ------------------
|
||||
|
||||
|
||||
@ -169,13 +176,13 @@ def cmd_pause(bot, user, text, command, parameter):
|
||||
|
||||
|
||||
def cmd_play_file(bot, user, text, command, parameter, do_not_refresh_cache=False):
|
||||
global log
|
||||
global log, song_shortlist
|
||||
|
||||
# if parameter is {index}
|
||||
if parameter.isdigit():
|
||||
files = var.library.files
|
||||
files = var.cache.files
|
||||
if int(parameter) < len(files):
|
||||
music_wrapper = get_item_wrapper_by_id(bot, var.library.file_id_lookup[files[int(parameter)]], user)
|
||||
music_wrapper = get_item_wrapper_by_id(bot, var.cache.file_id_lookup[files[int(parameter)]], user)
|
||||
var.playlist.append(music_wrapper)
|
||||
log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
|
||||
bot.send_msg(constants.strings('file_added', item=music_wrapper.format_song_string()), text)
|
||||
@ -189,7 +196,7 @@ def cmd_play_file(bot, user, text, command, parameter, do_not_refresh_cache=Fals
|
||||
# bot.send_msg(constants.strings('no_file'), text)
|
||||
# return
|
||||
|
||||
if parameter in var.library.files:
|
||||
if parameter in var.cache.files:
|
||||
music_wrapper = get_item_wrapper(bot, type='file', path=parameter, user=user)
|
||||
var.playlist.append(music_wrapper)
|
||||
log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
|
||||
@ -197,14 +204,14 @@ def cmd_play_file(bot, user, text, command, parameter, do_not_refresh_cache=Fals
|
||||
return
|
||||
|
||||
# if parameter is {folder}
|
||||
files = var.library.dir.get_files(parameter)
|
||||
files = var.cache.dir.get_files(parameter)
|
||||
if files:
|
||||
msgs = [constants.strings('multiple_file_added')]
|
||||
count = 0
|
||||
|
||||
for file in files:
|
||||
count += 1
|
||||
music_wrapper = get_item_wrapper_by_id(bot, var.library.file_id_lookup[file],user)
|
||||
music_wrapper = get_item_wrapper_by_id(bot, var.cache.file_id_lookup[file], user)
|
||||
var.playlist.append(music_wrapper)
|
||||
log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
|
||||
msgs.append("{} ({})".format(music_wrapper.item().title, music_wrapper.item().path))
|
||||
@ -215,28 +222,34 @@ def cmd_play_file(bot, user, text, command, parameter, do_not_refresh_cache=Fals
|
||||
|
||||
else:
|
||||
# try to do a partial match
|
||||
files = var.library.files
|
||||
matches = [(index, file) for index, file in enumerate(files) if parameter.lower() in file.lower()]
|
||||
files = var.cache.files
|
||||
matches = [ file for file in files if parameter.lower() in file.lower()]
|
||||
if len(matches) == 1:
|
||||
file = matches[0][1]
|
||||
music_wrapper = get_item_wrapper_by_id(bot, var.library.file_id_lookup[file],user)
|
||||
file = matches[0]
|
||||
music_wrapper = get_item_wrapper_by_id(bot, var.cache.file_id_lookup[file], user)
|
||||
var.playlist.append(music_wrapper)
|
||||
log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
|
||||
bot.send_msg(constants.strings('file_added', item=music_wrapper.format_song_string()), text)
|
||||
return
|
||||
elif len(matches) > 1:
|
||||
msgs = [ constants.strings('multiple_matches') ]
|
||||
for match in matches:
|
||||
music_wrapper = get_item_wrapper_by_id(bot, var.library.file_id_lookup[match[1]], user)
|
||||
msgs.append("<b>{:0>3d}</b> - <b>{:s}</b> ({:s})".format(
|
||||
match[0], music_wrapper.item().title, match[1]))
|
||||
song_shortlist = []
|
||||
for index, match in enumerate(matches):
|
||||
id = var.cache.file_id_lookup[match]
|
||||
music_dict = var.music_db.query_music_by_id(id)
|
||||
item = dict_to_item(bot, music_dict)
|
||||
|
||||
song_shortlist.append(music_dict)
|
||||
|
||||
msgs.append("<b>{:d}</b> - <b>{:s}</b> ({:s})".format(
|
||||
index + 1, item.title, match))
|
||||
send_multi_lines(bot, msgs, text)
|
||||
return
|
||||
|
||||
if do_not_refresh_cache:
|
||||
bot.send_msg(constants.strings("no_file"), text)
|
||||
else:
|
||||
var.library.build_dir_cache(bot)
|
||||
var.cache.build_dir_cache(bot)
|
||||
cmd_play_file(bot, user, text, command, parameter, do_not_refresh_cache=True)
|
||||
|
||||
|
||||
@ -245,7 +258,7 @@ def cmd_play_file_match(bot, user, text, command, parameter, do_not_refresh_cach
|
||||
|
||||
music_folder = var.music_folder
|
||||
if parameter:
|
||||
files = var.library.files
|
||||
files = var.cache.files
|
||||
msgs = [ constants.strings('multiple_file_added') + "<ul>"]
|
||||
count = 0
|
||||
try:
|
||||
@ -254,7 +267,7 @@ def cmd_play_file_match(bot, user, text, command, parameter, do_not_refresh_cach
|
||||
match = re.search(parameter, file)
|
||||
if match and match[0]:
|
||||
count += 1
|
||||
music_wrapper = get_item_wrapper_by_id(bot, var.library.file_id_lookup[file], user)
|
||||
music_wrapper = get_item_wrapper_by_id(bot, var.cache.file_id_lookup[file], user)
|
||||
music_wrappers.append(music_wrapper)
|
||||
log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
|
||||
msgs.append("<li><b>{}</b> ({})</li>".format(music_wrapper.item().title,
|
||||
@ -273,7 +286,7 @@ def cmd_play_file_match(bot, user, text, command, parameter, do_not_refresh_cach
|
||||
if do_not_refresh_cache:
|
||||
bot.send_msg(constants.strings("no_file"), text)
|
||||
else:
|
||||
var.library.build_dir_cache(bot)
|
||||
var.cache.build_dir_cache(bot)
|
||||
cmd_play_file_match(bot, user, text, command, parameter, do_not_refresh_cache=True)
|
||||
|
||||
except re.error as e:
|
||||
@ -435,7 +448,7 @@ def cmd_rb_play(bot, user, text, command, parameter):
|
||||
url = radiobrowser.geturl_byid(parameter)
|
||||
if url != "-1":
|
||||
log.info('cmd: Found url: ' + url)
|
||||
music_wrapper = get_item_wrapper(bot, type='radio', url=url, name=stationname)
|
||||
music_wrapper = get_item_wrapper(bot, type='radio', url=url, name=stationname, user=user)
|
||||
var.playlist.append(music_wrapper)
|
||||
log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
|
||||
bot.async_download_next()
|
||||
@ -448,7 +461,7 @@ yt_last_result = []
|
||||
yt_last_page = 0 # TODO: if we keep adding global variables, we need to consider sealing all commands up into classes.
|
||||
|
||||
def cmd_yt_search(bot, user, text, command, parameter):
|
||||
global log, yt_last_result, yt_last_page
|
||||
global log, yt_last_result, yt_last_page, song_shortlist
|
||||
item_per_page = 5
|
||||
|
||||
if parameter:
|
||||
@ -456,6 +469,10 @@ def cmd_yt_search(bot, user, text, command, parameter):
|
||||
if parameter.startswith("-n"):
|
||||
yt_last_page += 1
|
||||
if len(yt_last_result) > yt_last_page * item_per_page:
|
||||
song_shortlist = [{'type': 'url',
|
||||
'url': "https://www.youtube.com/watch?v=" + result[0],
|
||||
'title': result[1]
|
||||
} for result in yt_last_result[yt_last_page * item_per_page: item_per_page]]
|
||||
msg = _yt_format_result(yt_last_result, yt_last_page * item_per_page, item_per_page)
|
||||
bot.send_msg(constants.strings('yt_result', result_table=msg), text)
|
||||
else:
|
||||
@ -467,6 +484,8 @@ def cmd_yt_search(bot, user, text, command, parameter):
|
||||
if results:
|
||||
yt_last_result = results
|
||||
yt_last_page = 0
|
||||
song_shortlist = [{'type': 'url', 'url': "https://www.youtube.com/watch?v=" + result[0]}
|
||||
for result in results[0: item_per_page]]
|
||||
msg = _yt_format_result(results, 0, item_per_page)
|
||||
bot.send_msg(constants.strings('yt_result', result_table=msg), text)
|
||||
else:
|
||||
@ -478,7 +497,7 @@ def _yt_format_result(results, start, count):
|
||||
msg = '<table><tr><th width="10%">Index</th><th>Title</th><th width="20%">Uploader</th></tr>'
|
||||
for index, item in enumerate(results[start:start+count]):
|
||||
msg += '<tr><td>{index:d}</td><td>{title}</td><td>{uploader}</td></tr>'.format(
|
||||
index=index + 1 + start, title=item[1], uploader=item[2])
|
||||
index=index + 1, title=item[1], uploader=item[2])
|
||||
msg += '</table>'
|
||||
|
||||
return msg
|
||||
@ -488,18 +507,14 @@ def cmd_yt_play(bot, user, text, command, parameter):
|
||||
global log, yt_last_result, yt_last_page
|
||||
|
||||
if parameter:
|
||||
if parameter.isdigit() and 0 <= int(parameter) - 1 < len(yt_last_result):
|
||||
url = "https://www.youtube.com/watch?v=" + yt_last_result[int(parameter) - 1][0]
|
||||
results = util.youtube_search(parameter)
|
||||
if results:
|
||||
yt_last_result = results
|
||||
yt_last_page = 0
|
||||
url = "https://www.youtube.com/watch?v=" + yt_last_result[0][0]
|
||||
cmd_play_url(bot, user, text, command, url)
|
||||
else:
|
||||
results = util.youtube_search(parameter)
|
||||
if results:
|
||||
yt_last_result = results
|
||||
yt_last_page = 0
|
||||
url = "https://www.youtube.com/watch?v=" + yt_last_result[0][0]
|
||||
cmd_play_url(bot, user, text, command, url)
|
||||
else:
|
||||
bot.send_msg(constants.strings('yt_query_error'))
|
||||
bot.send_msg(constants.strings('yt_query_error'))
|
||||
else:
|
||||
bot.send_msg(constants.strings('bad_parameter', command=command), text)
|
||||
|
||||
@ -690,7 +705,7 @@ def cmd_remove(bot, user, text, command, parameter):
|
||||
def cmd_list_file(bot, user, text, command, parameter):
|
||||
global log
|
||||
|
||||
files = var.library.files
|
||||
files = var.cache.files
|
||||
msgs = [ "<br> <b>Files available:</b>" if not parameter else "<br> <b>Matched files:</b>" ]
|
||||
try:
|
||||
count = 0
|
||||
@ -871,6 +886,8 @@ def cmd_remove_tag(bot, user, text, command, parameter):
|
||||
bot.send_msg(constants.strings('bad_parameter', command=command), text)
|
||||
|
||||
def cmd_find_tagged(bot, user, text, command, parameter):
|
||||
global song_shortlist
|
||||
|
||||
if not parameter:
|
||||
bot.send_msg(constants.strings('bad_parameter', command=command))
|
||||
return
|
||||
@ -880,17 +897,99 @@ def cmd_find_tagged(bot, user, text, command, parameter):
|
||||
|
||||
tags = parameter.split(",")
|
||||
tags = list(map(lambda t: t.strip(), tags))
|
||||
music_wrappers = get_item_wrappers_by_tags(bot, tags, user)
|
||||
for music_wrapper in music_wrappers:
|
||||
|
||||
music_dicts = var.music_db.query_music_by_tags(tags)
|
||||
song_shortlist = music_dicts
|
||||
items = dicts_to_items(bot, music_dicts)
|
||||
|
||||
for i, item in enumerate(items):
|
||||
count += 1
|
||||
msgs.append("<li><b>{}</b> (<i>{}</i>)</li>".format(music_wrapper.item().title, ", ".join(music_wrapper.item().tags)))
|
||||
msgs.append("<li><b>{:d}</b> - <b>{}</b> (<i>{}</i>)</li>".format(i+1, item.title, ", ".join(item.tags)))
|
||||
|
||||
if count != 0:
|
||||
msgs.append("</ul>")
|
||||
msgs.append(constants.strings("shortlist_instruction"))
|
||||
send_multi_lines(bot, msgs, text, "")
|
||||
else:
|
||||
bot.send_msg(constants.strings("no_file"), text)
|
||||
|
||||
def cmd_search_library(bot, user, text, command, parameter):
|
||||
global song_shortlist
|
||||
if not parameter:
|
||||
bot.send_msg(constants.strings('bad_parameter', command=command))
|
||||
return
|
||||
|
||||
msgs = [constants.strings('multiple_file_found') + "<ul>"]
|
||||
count = 0
|
||||
|
||||
_keywords = parameter.split(" ")
|
||||
keywords = []
|
||||
for kw in _keywords:
|
||||
if kw:
|
||||
keywords.append(kw)
|
||||
|
||||
music_dicts = var.music_db.query_music_by_keywords(keywords)
|
||||
items = dicts_to_items(bot, music_dicts)
|
||||
song_shortlist = music_dicts
|
||||
|
||||
for item in items:
|
||||
count += 1
|
||||
if len(item.tags) > 0:
|
||||
msgs.append("<li><b>{:d}</b> - [{}] <b>{}</b> (<i>{}</i>)</li>".format(count, item.display_type(), item.title, ", ".join(item.tags)))
|
||||
else:
|
||||
msgs.append("<li><b>{:d}</b> - [{}] <b>{}</b> </li>".format(count, item.display_type(), item.title, ", ".join(item.tags)))
|
||||
|
||||
if count != 0:
|
||||
msgs.append("</ul>")
|
||||
msgs.append(constants.strings("shortlist_instruction"))
|
||||
send_multi_lines(bot, msgs, text, "")
|
||||
else:
|
||||
bot.send_msg(constants.strings("no_file"), text)
|
||||
|
||||
|
||||
def cmd_shortlist(bot, user, text, command, parameter):
|
||||
global song_shortlist
|
||||
indexes = []
|
||||
try:
|
||||
indexes = [ int(i) for i in parameter.split(" ") ]
|
||||
except ValueError:
|
||||
bot.send_msg(constants.strings('bad_parameter', command=command), text)
|
||||
return
|
||||
|
||||
if len(indexes) > 1:
|
||||
msgs = [constants.strings('multiple_file_added') + "<ul>"]
|
||||
for index in indexes:
|
||||
if 1 <= index <= len(song_shortlist):
|
||||
kwargs = song_shortlist[index - 1]
|
||||
kwargs['user'] = user
|
||||
music_wrapper = get_item_wrapper(bot, **kwargs)
|
||||
var.playlist.append(music_wrapper)
|
||||
log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
|
||||
msgs.append("<li><b>{}</b></li>".format(music_wrapper.item().title))
|
||||
song_shortlist = []
|
||||
else:
|
||||
bot.send_msg(constants.strings('bad_parameter', command=command), text)
|
||||
return
|
||||
|
||||
msgs.append("</ul>")
|
||||
send_multi_lines(bot, msgs, text, "")
|
||||
song_shortlist = []
|
||||
return
|
||||
elif len(indexes) == 1:
|
||||
index = indexes[0]
|
||||
if 1 <= index <= len(song_shortlist):
|
||||
kwargs = song_shortlist[index - 1]
|
||||
kwargs['user'] = user
|
||||
music_wrapper = get_item_wrapper(bot, **kwargs)
|
||||
var.playlist.append(music_wrapper)
|
||||
log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
|
||||
bot.send_msg(constants.strings('file_added', item=music_wrapper.format_song_string()), text)
|
||||
song_shortlist = []
|
||||
return
|
||||
|
||||
bot.send_msg(constants.strings('bad_parameter', command=command), text)
|
||||
|
||||
|
||||
def cmd_drop_database(bot, user, text, command, parameter):
|
||||
global log
|
||||
|
||||
@ -907,7 +1006,7 @@ def cmd_drop_database(bot, user, text, command, parameter):
|
||||
def cmd_refresh_cache(bot, user, text, command, parameter):
|
||||
global log
|
||||
if bot.is_admin(user):
|
||||
var.library.build_dir_cache(bot)
|
||||
var.cache.build_dir_cache(bot)
|
||||
log.info("command: Local file cache refreshed.")
|
||||
bot.send_msg(constants.strings('cache_refreshed'), text)
|
||||
else:
|
||||
|
@ -160,6 +160,8 @@ play_tag = tag
|
||||
add_tag = addtag
|
||||
remove_tag = untag
|
||||
find_tagged = findtagged, ft
|
||||
search = search
|
||||
add_from_shortlist = shortlist, sl
|
||||
|
||||
user_ban = userban
|
||||
user_unban = userunban
|
||||
@ -225,7 +227,7 @@ unknown_mode = Unknown playback mode '{mode}'. It should be one of <i>one-shot</
|
||||
current_mode = Current playback mode is <i>{mode}</i>.
|
||||
change_mode = Playback mode set to <i>{mode}</i> by {user}.
|
||||
repeat = Repeat {song} for {n} times.
|
||||
yt_result = Youtube query result: {result_table} Use <i>!ytplay</i> {{index}} to play the item you want. <br />
|
||||
yt_result = Youtube query result: {result_table} Use <i>!sl {{indexes}}</i> to play the item you want. <br />
|
||||
<i>!ytquery -n</i> for the next page.
|
||||
yt_no_more = No more results!
|
||||
yt_query_error = Unable to query youtube!
|
||||
@ -237,6 +239,7 @@ removed_tags = Removed tags <i>{tags}</i> from <b>{song}</b>.
|
||||
removed_tags_from_all = Removed tags <i>{tags}</i> from songs on the playlist.
|
||||
cleared_tags = Removed all tags from <b>{song}</b>.
|
||||
cleared_tags_from_all = Removed all tags from songs on the playlist.
|
||||
shortlist_instruction = Use <i>!sl {indexes}</i> to play the item you want.
|
||||
|
||||
help = <h3>Commands</h3>
|
||||
<b>Control</b>
|
||||
@ -264,6 +267,7 @@ help = <h3>Commands</h3>
|
||||
<li> <b>!<u>ur</u>l </b> {url} - add Youtube or SoundCloud music </li>
|
||||
<li> <b>!<u>playl</u>ist </b> {url} [{offset}] - add all items in a Youtube or SoundCloud playlist, and start with the {offset}-th item </li>
|
||||
<li> <b>!<u>t</u>ag </b> {tags} - add all items with tags {tags}, tags separated by ",". </li>
|
||||
<li> <b>!<u>sh</u>ortlist </b> (or <b>!sl</b>) {indexes} - add {indexes}-th item on the shortlist. </li>
|
||||
<li> <b>!rm </b> {num} - remove the num-th song on the playlist </li>
|
||||
<li> <b>!<u>rep</u>eat </b> [{num}] - repeat current song {num} (1 by default) times.</li>
|
||||
<li> <b>!<u>ran</u>dom </b> - randomize the playlist.</li>
|
||||
@ -275,8 +279,9 @@ help = <h3>Commands</h3>
|
||||
<li> <b>!<u>yp</u>lay </b> {index/keywords} - play an item from the list returned by <i>!ytquery</i>, or add the
|
||||
first search result of {keywords} into the playlist.</li>
|
||||
</ul>
|
||||
<b>Tag</b>
|
||||
<b>Music Library</b>
|
||||
<ul>
|
||||
<li> <b>!<u>se</u>arch </b> {keywords} - find item with {keywords} in the music library, keywords separated by space.</li>
|
||||
<li> <b>!<u>addt</u>ag </b> {index} {tags} - add {tags} to {index}-th item on the playlist, tags separated by ",". </li>
|
||||
<li> <b>!<u>addt</u>ag </b> * {tags} - add {tags} to all items on the playlist. </li>
|
||||
<li> <b>!<u>un</u>tag </b> {index/*} {tags} - remove {tags} from {index}-th item on the playlist. </li>
|
||||
|
34
database.py
34
database.py
@ -231,6 +231,40 @@ class MusicDatabase:
|
||||
else:
|
||||
return None
|
||||
|
||||
def query_music_by_keywords(self, keywords):
|
||||
condition = []
|
||||
filler = []
|
||||
|
||||
for keyword in keywords:
|
||||
condition.append('title LIKE ?')
|
||||
filler.append("%{:s}%".format(keyword))
|
||||
|
||||
|
||||
condition_str = " AND ".join(condition)
|
||||
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
results = cursor.execute("SELECT id, type, title, metadata, tags FROM music "
|
||||
"WHERE %s" % condition_str, filler).fetchall()
|
||||
conn.close()
|
||||
|
||||
if len(results) > 0:
|
||||
music_dicts = []
|
||||
for result in results:
|
||||
music_dict = json.loads(result[3])
|
||||
music_dict['type'] = result[1]
|
||||
music_dict['title'] = result[2]
|
||||
music_dict['id'] = result[0]
|
||||
music_dict['tags'] = result[4].strip(",").split(",")
|
||||
if not music_dict['tags'][0]:
|
||||
music_dict['tags'] = []
|
||||
|
||||
music_dicts.append(music_dict)
|
||||
|
||||
return music_dicts
|
||||
else:
|
||||
return None
|
||||
|
||||
def query_music_by_tags(self, tags):
|
||||
condition = []
|
||||
filler = []
|
||||
|
20
interface.py
20
interface.py
@ -119,7 +119,7 @@ def build_tags_color_lookup():
|
||||
|
||||
def build_path_tags_lookup():
|
||||
path_lookup = {}
|
||||
items = var.library.file_id_lookup.items()
|
||||
items = var.cache.file_id_lookup.items()
|
||||
for path, id in items:
|
||||
path_lookup[path] = var.music_db.query_tags_by_id(id)
|
||||
|
||||
@ -133,17 +133,17 @@ def recur_dir(dirobj):
|
||||
@web.route("/", methods=['GET'])
|
||||
@requires_auth
|
||||
def index():
|
||||
while var.library.dir_lock.locked():
|
||||
while var.cache.dir_lock.locked():
|
||||
time.sleep(0.1)
|
||||
|
||||
tags_color_lookup = build_tags_color_lookup()
|
||||
path_tags_lookup = build_path_tags_lookup()
|
||||
|
||||
return render_template('index.html',
|
||||
all_files=var.library.files,
|
||||
all_files=var.cache.files,
|
||||
tags_lookup=path_tags_lookup,
|
||||
tags_color_lookup=tags_color_lookup,
|
||||
music_library=var.library.dir,
|
||||
music_library=var.cache.dir,
|
||||
os=os,
|
||||
playlist=var.playlist,
|
||||
user=var.user,
|
||||
@ -198,7 +198,7 @@ def post():
|
||||
if 'add_file_bottom' in request.form and ".." not in request.form['add_file_bottom']:
|
||||
path = var.music_folder + request.form['add_file_bottom']
|
||||
if os.path.isfile(path):
|
||||
music_wrapper = get_item_wrapper_by_id(var.bot, var.library.file_id_lookup[request.form['add_file_bottom']], user)
|
||||
music_wrapper = get_item_wrapper_by_id(var.bot, var.cache.file_id_lookup[request.form['add_file_bottom']], user)
|
||||
|
||||
var.playlist.append(music_wrapper)
|
||||
log.info('web: add to playlist(bottom): ' + music_wrapper.format_debug_string())
|
||||
@ -206,7 +206,7 @@ def post():
|
||||
elif 'add_file_next' in request.form and ".." not in request.form['add_file_next']:
|
||||
path = var.music_folder + request.form['add_file_next']
|
||||
if os.path.isfile(path):
|
||||
music_wrapper = get_item_wrapper_by_id(var.bot, var.library.file_id_lookup[request.form['add_file_next']], user)
|
||||
music_wrapper = get_item_wrapper_by_id(var.bot, var.cache.file_id_lookup[request.form['add_file_next']], user)
|
||||
var.playlist.insert(var.playlist.current_index + 1, music_wrapper)
|
||||
log.info('web: add to playlist(next): ' + music_wrapper.format_debug_string())
|
||||
|
||||
@ -220,7 +220,7 @@ def post():
|
||||
folder += '/'
|
||||
|
||||
if os.path.isdir(var.music_folder + folder):
|
||||
dir = var.library.dir
|
||||
dir = var.cache.dir
|
||||
if 'add_folder_recursively' in request.form:
|
||||
files = dir.get_files_recursively(folder)
|
||||
else:
|
||||
@ -228,7 +228,7 @@ def post():
|
||||
|
||||
music_wrappers = list(map(
|
||||
lambda file:
|
||||
get_item_wrapper_by_id(var.bot, var.library.file_id_lookup[folder + file], user),
|
||||
get_item_wrapper_by_id(var.bot, var.cache.file_id_lookup[folder + file], user),
|
||||
files))
|
||||
|
||||
var.playlist.extend(music_wrappers)
|
||||
@ -328,7 +328,7 @@ def post():
|
||||
var.db.set('playlist', 'playback_mode', "autoplay")
|
||||
log.info("web: playback mode changed to autoplay.")
|
||||
if action == "rescan":
|
||||
var.library.build_dir_cache(var.bot)
|
||||
var.cache.build_dir_cache(var.bot)
|
||||
log.info("web: Local file cache refreshed.")
|
||||
elif action == "stop":
|
||||
var.bot.stop()
|
||||
@ -413,7 +413,7 @@ def download():
|
||||
log.info('web: Download of file %s requested from %s:' % (requested_file, request.remote_addr))
|
||||
if '../' not in requested_file:
|
||||
folder_path = var.music_folder
|
||||
files = var.library.files
|
||||
files = var.cache.files
|
||||
|
||||
if requested_file in files:
|
||||
filepath = os.path.join(folder_path, requested_file)
|
||||
|
@ -3,13 +3,13 @@ from database import MusicDatabase
|
||||
import json
|
||||
import threading
|
||||
|
||||
from media.item import item_builders, item_loaders, item_id_generators
|
||||
from media.item import item_builders, item_loaders, item_id_generators, dict_to_item, dicts_to_items
|
||||
from database import MusicDatabase
|
||||
import variables as var
|
||||
import util
|
||||
|
||||
|
||||
class MusicLibrary(dict):
|
||||
class MusicCache(dict):
|
||||
def __init__(self, db: MusicDatabase):
|
||||
super().__init__()
|
||||
self.db = db
|
||||
@ -36,7 +36,11 @@ class MusicLibrary(dict):
|
||||
def get_item(self, bot, **kwargs):
|
||||
# kwargs should provide type and id, and parameters to build the item if not existed in the library.
|
||||
# if cached
|
||||
id = item_id_generators[kwargs['type']](**kwargs)
|
||||
if 'id' in kwargs:
|
||||
id = kwargs['id']
|
||||
else:
|
||||
id = item_id_generators[kwargs['type']](**kwargs)
|
||||
|
||||
if id in self:
|
||||
return self[id]
|
||||
|
||||
@ -57,8 +61,7 @@ class MusicLibrary(dict):
|
||||
if music_dicts:
|
||||
for music_dict in music_dicts:
|
||||
id = music_dict['id']
|
||||
type = music_dict['type']
|
||||
self[id] = item_loaders[type](bot, music_dict)
|
||||
self[id] = dict_to_item(bot, music_dict)
|
||||
items.append(self[id])
|
||||
|
||||
return items
|
||||
@ -67,8 +70,7 @@ class MusicLibrary(dict):
|
||||
music_dicts = self.db.query_music(id=id)
|
||||
if music_dicts:
|
||||
music_dict = music_dicts[0]
|
||||
type = music_dict['type']
|
||||
self[id] = item_loaders[type](bot, music_dict)
|
||||
self[id] = dict_to_item(bot, music_dict)
|
||||
return self[id]
|
||||
else:
|
||||
return None
|
@ -154,7 +154,7 @@ class FileItem(BaseItem):
|
||||
def format_song_string(self, user):
|
||||
return constants.strings("file_item",
|
||||
title=self.title,
|
||||
artist=self.artist,
|
||||
artist=self.artist if self.artist else '??',
|
||||
user=user
|
||||
)
|
||||
|
||||
|
@ -28,6 +28,18 @@ item_builders['base'] = example_builder
|
||||
item_loaders['base'] = example_loader
|
||||
item_id_generators['base'] = example_id_generator
|
||||
|
||||
def dicts_to_items(bot, music_dicts):
|
||||
items = []
|
||||
for music_dict in music_dicts:
|
||||
type = music_dict['type']
|
||||
items.append(item_loaders[type](bot, music_dict))
|
||||
return items
|
||||
|
||||
def dict_to_item(bot, music_dict):
|
||||
type = music_dict['type']
|
||||
return item_loaders[type](bot, music_dict)
|
||||
|
||||
|
||||
class BaseItem:
|
||||
def __init__(self, bot, from_dict=None):
|
||||
self.bot = bot
|
||||
|
@ -10,7 +10,7 @@ from media.url import URLItem
|
||||
from media.url_from_playlist import PlaylistURLItem
|
||||
from media.radio import RadioItem
|
||||
from database import MusicDatabase
|
||||
from media.library import MusicLibrary
|
||||
from media.cache import MusicCache
|
||||
|
||||
class PlaylistItemWrapper:
|
||||
def __init__(self, lib, id, type, user):
|
||||
@ -95,24 +95,25 @@ class PlaylistItemWrapper:
|
||||
return self.item().display_type()
|
||||
|
||||
|
||||
# Remember!!! Using these three get wrapper functions will automatically add items into the cache!
|
||||
def get_item_wrapper(bot, **kwargs):
|
||||
item = var.library.get_item(bot, **kwargs)
|
||||
item = var.cache.get_item(bot, **kwargs)
|
||||
if 'user' not in kwargs:
|
||||
raise KeyError("Which user added this song?")
|
||||
return PlaylistItemWrapper(var.library, item.id, kwargs['type'], kwargs['user'])
|
||||
return PlaylistItemWrapper(var.cache, item.id, kwargs['type'], kwargs['user'])
|
||||
|
||||
def get_item_wrapper_by_id(bot, id, user):
|
||||
item = var.library.get_item_by_id(bot, id)
|
||||
item = var.cache.get_item_by_id(bot, id)
|
||||
if item:
|
||||
return PlaylistItemWrapper(var.library, item.id, item.type, user)
|
||||
return PlaylistItemWrapper(var.cache, item.id, item.type, user)
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_item_wrappers_by_tags(bot, tags, user):
|
||||
items = var.library.get_items_by_tags(bot, tags)
|
||||
items = var.cache.get_items_by_tags(bot, tags)
|
||||
ret = []
|
||||
for item in items:
|
||||
ret.append(PlaylistItemWrapper(var.library, item.id, item.type, user))
|
||||
ret.append(PlaylistItemWrapper(var.cache, item.id, item.type, user))
|
||||
return ret
|
||||
|
||||
def get_playlist(mode, _list=None, index=None):
|
||||
@ -235,7 +236,7 @@ class BasePlaylist(list):
|
||||
counter += 1
|
||||
|
||||
if counter == 0:
|
||||
var.library.free(removed.id)
|
||||
var.cache.free(removed.id)
|
||||
return removed
|
||||
|
||||
def remove_by_id(self, id):
|
||||
@ -280,7 +281,7 @@ class BasePlaylist(list):
|
||||
def clear(self):
|
||||
self.version += 1
|
||||
self.current_index = -1
|
||||
var.library.free_all()
|
||||
var.cache.free_all()
|
||||
super().clear()
|
||||
|
||||
def save(self):
|
||||
@ -330,7 +331,7 @@ class BasePlaylist(list):
|
||||
self.log.debug("playlist: validating %s" % item.format_debug_string())
|
||||
if not item.validate() or item.is_failed():
|
||||
self.log.debug("playlist: validating failed.")
|
||||
var.library.delete(item.id)
|
||||
var.cache.delete(item.id)
|
||||
self.remove_by_id(item.id)
|
||||
|
||||
self.log.debug("playlist: validating finished.")
|
||||
|
12
mumbleBot.py
12
mumbleBot.py
@ -30,7 +30,7 @@ import media.file
|
||||
import media.radio
|
||||
import media.system
|
||||
from media.playlist import BasePlaylist
|
||||
from media.library import MusicLibrary
|
||||
from media.cache import MusicCache
|
||||
|
||||
|
||||
class MumbleBot:
|
||||
@ -347,7 +347,7 @@ class MumbleBot:
|
||||
break
|
||||
else:
|
||||
var.playlist.remove_by_id(next.id)
|
||||
var.library.delete(next.id)
|
||||
var.cache.delete(next.id)
|
||||
|
||||
|
||||
# =======================
|
||||
@ -407,7 +407,7 @@ class MumbleBot:
|
||||
self.send_msg(constants.strings('download_in_progress', item=current.format_short_string()))
|
||||
else:
|
||||
var.playlist.remove_by_id(current.id)
|
||||
var.library.delete(current.id)
|
||||
var.cache.delete(current.id)
|
||||
else:
|
||||
self._loop_status = 'Empty queue'
|
||||
else:
|
||||
@ -639,7 +639,7 @@ if __name__ == '__main__':
|
||||
else:
|
||||
var.music_db = MusicDatabase(":memory:")
|
||||
|
||||
var.library = MusicLibrary(var.music_db)
|
||||
var.cache = MusicCache(var.music_db)
|
||||
|
||||
# load playback mode
|
||||
playback_mode = None
|
||||
@ -658,9 +658,9 @@ if __name__ == '__main__':
|
||||
|
||||
if var.config.get("bot", "refresh_cache_on_startup", fallback=True)\
|
||||
or not var.db.has_option("dir_cache", "files"):
|
||||
var.library.build_dir_cache(var.bot)
|
||||
var.cache.build_dir_cache(var.bot)
|
||||
else:
|
||||
var.library.load_dir_cache(var.bot)
|
||||
var.cache.load_dir_cache(var.bot)
|
||||
|
||||
# load playlist
|
||||
if var.config.getboolean('bot', 'save_playlist', fallback=True):
|
||||
|
@ -1,6 +1,6 @@
|
||||
bot = None
|
||||
playlist = None
|
||||
library = None
|
||||
cache = None
|
||||
|
||||
user = ""
|
||||
is_proxified = False
|
||||
|
Loading…
x
Reference in New Issue
Block a user