feat: 'delete' command to remove files from library

This commit is contained in:
Terry Geng 2020-03-09 00:02:22 +08:00
parent e2f6de5066
commit 048da4046b
8 changed files with 86 additions and 31 deletions

View File

@ -61,6 +61,7 @@ def register_all_commands(bot):
bot.register_command(constants.commands('find_tagged'), cmd_find_tagged) bot.register_command(constants.commands('find_tagged'), cmd_find_tagged)
bot.register_command(constants.commands('search'), cmd_search_library) bot.register_command(constants.commands('search'), cmd_search_library)
bot.register_command(constants.commands('add_from_shortlist'), cmd_shortlist) bot.register_command(constants.commands('add_from_shortlist'), cmd_shortlist)
bot.register_command(constants.commands('delete_from_library'), cmd_delete_from_library)
bot.register_command(constants.commands('drop_database'), cmd_drop_database, True) bot.register_command(constants.commands('drop_database'), cmd_drop_database, True)
bot.register_command(constants.commands('rescan'), cmd_refresh_cache, True) bot.register_command(constants.commands('rescan'), cmd_refresh_cache, True)
@ -305,7 +306,7 @@ def cmd_play_url(bot, user, text, command, parameter):
var.playlist.append(music_wrapper) var.playlist.append(music_wrapper)
log.info("cmd: add to playlist: " + music_wrapper.format_debug_string()) log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
bot.send_msg(constants.strings('file_added', item=music_wrapper.format_short_string()), text) bot.send_msg(constants.strings('file_added', item=music_wrapper.format_song_string()), text)
if len(var.playlist) == 2: if len(var.playlist) == 2:
# If I am the second item on the playlist. (I am the next one!) # If I am the second item on the playlist. (I am the next one!)
bot.async_download_next() bot.async_download_next()
@ -357,6 +358,7 @@ def cmd_play_radio(bot, user, text, command, parameter):
var.playlist.append(music_wrapper) var.playlist.append(music_wrapper)
log.info("cmd: add to playlist: " + music_wrapper.format_debug_string()) 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)
else: else:
bot.send_msg(constants.strings('bad_url')) bot.send_msg(constants.strings('bad_url'))
@ -710,7 +712,7 @@ def cmd_list_file(bot, user, text, command, parameter):
global log global log
files = var.cache.files files = var.cache.files
msgs = [ "<br> <b>Files available:</b>" if not parameter else "<br> <b>Matched files:</b>" ] msgs = [ constants.strings("multiple_file_found") ]
try: try:
count = 0 count = 0
for index, file in enumerate(files): for index, file in enumerate(files):
@ -933,6 +935,7 @@ def cmd_search_library(bot, user, text, command, parameter):
keywords.append(kw) keywords.append(kw)
music_dicts = var.music_db.query_music_by_keywords(keywords) music_dicts = var.music_db.query_music_by_keywords(keywords)
if music_dicts:
items = dicts_to_items(bot, music_dicts) items = dicts_to_items(bot, music_dicts)
song_shortlist = music_dicts song_shortlist = music_dicts
@ -949,10 +952,12 @@ def cmd_search_library(bot, user, text, command, parameter):
send_multi_lines(bot, msgs, text, "") send_multi_lines(bot, msgs, text, "")
else: else:
bot.send_msg(constants.strings("no_file"), text) bot.send_msg(constants.strings("no_file"), text)
else:
bot.send_msg(constants.strings("no_file"), text)
def cmd_shortlist(bot, user, text, command, parameter): def cmd_shortlist(bot, user, text, command, parameter):
global song_shortlist global song_shortlist, log
indexes = [] indexes = []
try: try:
indexes = [ int(i) for i in parameter.split(" ") ] indexes = [ int(i) for i in parameter.split(" ") ]
@ -969,15 +974,13 @@ def cmd_shortlist(bot, user, text, command, parameter):
music_wrapper = get_item_wrapper_from_scrap(bot, **kwargs) music_wrapper = get_item_wrapper_from_scrap(bot, **kwargs)
var.playlist.append(music_wrapper) var.playlist.append(music_wrapper)
log.info("cmd: add to playlist: " + music_wrapper.format_debug_string()) log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
msgs.append("<li><b>{}</b></li>".format(music_wrapper.item().title)) msgs.append("<li>[{}] <b>{}</b></li>".format(music_wrapper.item().type, music_wrapper.item().title))
song_shortlist = []
else: else:
bot.send_msg(constants.strings('bad_parameter', command=command), text) bot.send_msg(constants.strings('bad_parameter', command=command), text)
return return
msgs.append("</ul>") msgs.append("</ul>")
send_multi_lines(bot, msgs, text, "") send_multi_lines(bot, msgs, text, "")
song_shortlist = []
return return
elif len(indexes) == 1: elif len(indexes) == 1:
index = indexes[0] index = indexes[0]
@ -988,12 +991,58 @@ def cmd_shortlist(bot, user, text, command, parameter):
var.playlist.append(music_wrapper) var.playlist.append(music_wrapper)
log.info("cmd: add to playlist: " + music_wrapper.format_debug_string()) 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) bot.send_msg(constants.strings('file_added', item=music_wrapper.format_song_string()), text)
song_shortlist = []
return return
bot.send_msg(constants.strings('bad_parameter', command=command), text) bot.send_msg(constants.strings('bad_parameter', command=command), text)
def cmd_delete_from_library(bot, user, text, command, parameter):
global song_shortlist, log
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>"]
count = 0
for index in indexes:
if 1 <= index <= len(song_shortlist):
music_dict = song_shortlist[index - 1]
if 'id' in music_dict:
music_wrapper = get_item_wrapper_by_id(bot, music_dict['id'], user)
log.info("cmd: remove from library: " + music_wrapper.format_debug_string())
msgs.append("<li>[{}] <b>{}</b></li>".format(music_wrapper.item().type ,music_wrapper.item().title))
var.playlist.remove_by_id(music_dict['id'])
var.cache.free_and_delete(music_dict['id'])
count += 1
else:
bot.send_msg(constants.strings('bad_parameter', command=command), text)
return
if count == 0:
bot.send_msg(constants.strings('bad_parameter', command=command), text)
return
msgs.append("</ul>")
send_multi_lines(bot, msgs, text, "")
return
elif len(indexes) == 1:
index = indexes[0]
if 1 <= index <= len(song_shortlist):
music_dict = song_shortlist[index - 1]
if 'id' in music_dict:
music_wrapper = get_item_wrapper_by_id(bot, music_dict['id'], user)
bot.send_msg(constants.strings('file_deleted', item=music_wrapper.format_song_string()), text)
log.info("cmd: remove from library: " + music_wrapper.format_debug_string())
var.playlist.remove_by_id(music_dict['id'])
var.cache.free_and_delete(music_dict['id'])
return
bot.send_msg(constants.strings('bad_parameter', command=command), text)
def cmd_drop_database(bot, user, text, command, parameter): def cmd_drop_database(bot, user, text, command, parameter):
global log global log

View File

@ -162,6 +162,7 @@ add_tag = addtag
remove_tag = untag remove_tag = untag
find_tagged = findtagged, ft find_tagged = findtagged, ft
search = search search = search
delete_from_library = delete
add_from_shortlist = shortlist, sl add_from_shortlist = shortlist, sl
user_ban = userban user_ban = userban
@ -188,8 +189,10 @@ not_admin = You are not an admin!
not_playing = Nothing is playing right now. not_playing = Nothing is playing right now.
no_file = File not found. no_file = File not found.
wrong_pattern = Invalid regex: {error}. wrong_pattern = Invalid regex: {error}.
file_added = Added: {item}. file_added = Added {item}.
multiple_file_added = Multiple files added: file_deleted = Deleted {item} from the library.
multiple_file_added = Multiple items added:
multiple_file_deleted = Multiple items deleted from the library:
multiple_file_found = Found: multiple_file_found = Found:
bad_url = Bad URL requested. bad_url = Bad URL requested.
preconfigurated_radio = Preconfigurated Radio available: preconfigurated_radio = Preconfigurated Radio available:
@ -287,6 +290,7 @@ help = <h3>Commands</h3>
<li> <b>!<u>un</u>tag </b> {index/*} {tags} - remove {tags} from {index}-th item on the playlist. </li> <li> <b>!<u>un</u>tag </b> {index/*} {tags} - remove {tags} from {index}-th item on the playlist. </li>
<li> <b>!<u>un</u>tag </b> {index/*} * - remove all tags from {index}-th item on the playlist. </li> <li> <b>!<u>un</u>tag </b> {index/*} * - remove all tags from {index}-th item on the playlist. </li>
<li> <b>!<u>fin</u>dtagged </b> (or <b>!ft</b>) {tags} - find item with {tags} in the music library. </li> <li> <b>!<u>fin</u>dtagged </b> (or <b>!ft</b>) {tags} - find item with {tags} in the music library. </li>
<li> <b>!<u>del</u>ete </b> {index} - delete {index}-th item on the shortlist from the music library. </li>
</ul> </ul>
<b>Other</b> <b>Other</b>
<ul> <ul>

View File

@ -80,7 +80,7 @@ class MusicCache(dict):
self.log.debug("library: music save into database: %s" % self[id].format_debug_string()) self.log.debug("library: music save into database: %s" % self[id].format_debug_string())
self.db.insert_music(self[id].to_dict()) self.db.insert_music(self[id].to_dict())
def delete(self, id): def free_and_delete(self, id):
item = self.get_item_by_id(None, id) item = self.get_item_by_id(None, id)
if item: if item:
self.log.debug("library: DELETE item from the database: %s" % item.format_debug_string()) self.log.debug("library: DELETE item from the database: %s" % item.format_debug_string())

View File

@ -110,6 +110,6 @@ class BaseItem:
self.bot.send_msg(msg) self.bot.send_msg(msg)
def to_dict(self): def to_dict(self):
return {"type" : "base", "id": self.id, "ready": self.ready, "path": self.path, "tags": self.tags} return {"type" : self.type, "id": self.id, "ready": self.ready, "path": self.path, "tags": self.tags}

View File

@ -3,6 +3,7 @@ import random
import threading import threading
import logging import logging
import random import random
import time
import variables as var import variables as var
from media.file import FileItem from media.file import FileItem
@ -325,6 +326,7 @@ class BasePlaylist(list):
def start_async_validating(self): def start_async_validating(self):
if not self.validating_thread_lock.locked(): if not self.validating_thread_lock.locked():
time.sleep(0.1) # Just avoid validation finishes too fast and delete songs while something is reading it.
th = threading.Thread(target=self._check_valid, name="Validating") th = threading.Thread(target=self._check_valid, name="Validating")
th.daemon = True th.daemon = True
th.start() th.start()
@ -337,7 +339,7 @@ class BasePlaylist(list):
self.log.debug("playlist: validating %s" % item.format_debug_string()) self.log.debug("playlist: validating %s" % item.format_debug_string())
if not item.validate() or item.is_failed(): if not item.validate() or item.is_failed():
self.log.debug("playlist: validating failed.") self.log.debug("playlist: validating failed.")
var.cache.delete(item.id) var.cache.free_and_delete(item.id)
self.remove_by_id(item.id) self.remove_by_id(item.id)
self.log.debug("playlist: validating finished.") self.log.debug("playlist: validating finished.")

View File

@ -83,7 +83,7 @@ def get_radio_title(url):
requests.exceptions.Timeout) as e: requests.exceptions.Timeout) as e:
error_traceback = traceback.format_exc() error_traceback = traceback.format_exc()
error = error_traceback.rstrip().split("\n")[-1] error = error_traceback.rstrip().split("\n")[-1]
log.debug("radio: unsuccessful attempts on fetching radio title (icy): " + e) log.debug("radio: unsuccessful attempts on fetching radio title (icy): " + error)
return url return url

View File

@ -224,7 +224,7 @@ class URLItem(BaseItem):
def format_song_string(self, user): def format_song_string(self, user):
if self.ready in ['validated', 'yes']: if self.ready in ['validated', 'yes']:
return constants.strings("url_item", return constants.strings("url_item",
title=self.title, title=self.title if self.title else "??",
url=self.url, url=self.url,
user=user) user=user)
return self.url return self.url

View File

@ -347,7 +347,7 @@ class MumbleBot:
break break
else: else:
var.playlist.remove_by_id(next.id) var.playlist.remove_by_id(next.id)
var.cache.delete(next.id) var.cache.free_and_delete(next.id)
# ======================= # =======================
@ -407,7 +407,7 @@ class MumbleBot:
self.send_msg(constants.strings('download_in_progress', item=current.format_short_string())) self.send_msg(constants.strings('download_in_progress', item=current.format_short_string()))
else: else:
var.playlist.remove_by_id(current.id) var.playlist.remove_by_id(current.id)
var.cache.delete(current.id) var.cache.free_and_delete(current.id)
else: else:
self._loop_status = 'Empty queue' self._loop_status = 'Empty queue'
else: else: