diff --git a/command.py b/command.py
index cf5dec0..30d5e23 100644
--- a/command.py
+++ b/command.py
@@ -61,6 +61,7 @@ def register_all_commands(bot):
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('delete_from_library'), cmd_delete_from_library)
bot.register_command(constants.commands('drop_database'), cmd_drop_database, 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)
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 I am the second item on the playlist. (I am the next one!)
bot.async_download_next()
@@ -357,6 +358,7 @@ def cmd_play_radio(bot, user, text, command, parameter):
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)
else:
bot.send_msg(constants.strings('bad_url'))
@@ -710,7 +712,7 @@ def cmd_list_file(bot, user, text, command, parameter):
global log
files = var.cache.files
- msgs = [ "
Files available:" if not parameter else "
Matched files:" ]
+ msgs = [ constants.strings("multiple_file_found") ]
try:
count = 0
for index, file in enumerate(files):
@@ -933,26 +935,29 @@ def cmd_search_library(bot, user, text, command, parameter):
keywords.append(kw)
music_dicts = var.music_db.query_music_by_keywords(keywords)
- items = dicts_to_items(bot, music_dicts)
- song_shortlist = music_dicts
+ if music_dicts:
+ items = dicts_to_items(bot, music_dicts)
+ song_shortlist = music_dicts
- for item in items:
- count += 1
- if len(item.tags) > 0:
- msgs.append("
{:d} - [{}] {} ({})".format(count, item.display_type(), item.title, ", ".join(item.tags)))
+ for item in items:
+ count += 1
+ if len(item.tags) > 0:
+ msgs.append("{:d} - [{}] {} ({})".format(count, item.display_type(), item.title, ", ".join(item.tags)))
+ else:
+ msgs.append("{:d} - [{}] {} ".format(count, item.display_type(), item.title, ", ".join(item.tags)))
+
+ if count != 0:
+ msgs.append("")
+ msgs.append(constants.strings("shortlist_instruction"))
+ send_multi_lines(bot, msgs, text, "")
else:
- msgs.append("{:d} - [{}] {} ".format(count, item.display_type(), item.title, ", ".join(item.tags)))
-
- if count != 0:
- msgs.append("")
- msgs.append(constants.strings("shortlist_instruction"))
- send_multi_lines(bot, msgs, 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):
- global song_shortlist
+ global song_shortlist, log
indexes = []
try:
indexes = [ int(i) for i in parameter.split(" ") ]
@@ -969,16 +974,14 @@ def cmd_shortlist(bot, user, text, command, parameter):
music_wrapper = get_item_wrapper_from_scrap(bot, **kwargs)
var.playlist.append(music_wrapper)
log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
- msgs.append("{}".format(music_wrapper.item().title))
- song_shortlist = []
+ msgs.append("[{}] {}".format(music_wrapper.item().type, music_wrapper.item().title))
else:
bot.send_msg(constants.strings('bad_parameter', command=command), text)
return
- msgs.append("")
- send_multi_lines(bot, msgs, text, "")
- song_shortlist = []
- return
+ msgs.append("")
+ send_multi_lines(bot, msgs, text, "")
+ return
elif len(indexes) == 1:
index = indexes[0]
if 1 <= index <= len(song_shortlist):
@@ -988,12 +991,58 @@ def cmd_shortlist(bot, user, text, command, parameter):
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_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') + ""]
+ 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("- [{}] {}
".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("
")
+ 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):
global log
diff --git a/configuration.default.ini b/configuration.default.ini
index b7a19d8..d349dd5 100644
--- a/configuration.default.ini
+++ b/configuration.default.ini
@@ -162,6 +162,7 @@ add_tag = addtag
remove_tag = untag
find_tagged = findtagged, ft
search = search
+delete_from_library = delete
add_from_shortlist = shortlist, sl
user_ban = userban
@@ -188,8 +189,10 @@ not_admin = You are not an admin!
not_playing = Nothing is playing right now.
no_file = File not found.
wrong_pattern = Invalid regex: {error}.
-file_added = Added: {item}.
-multiple_file_added = Multiple files added:
+file_added = Added {item}.
+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:
bad_url = Bad URL requested.
preconfigurated_radio = Preconfigurated Radio available:
@@ -287,6 +290,7 @@ help = Commands
!untag {index/*} {tags} - remove {tags} from {index}-th item on the playlist.
!untag {index/*} * - remove all tags from {index}-th item on the playlist.
!findtagged (or !ft) {tags} - find item with {tags} in the music library.
+ !delete {index} - delete {index}-th item on the shortlist from the music library.
Other
diff --git a/media/cache.py b/media/cache.py
index 6c2d349..736810e 100644
--- a/media/cache.py
+++ b/media/cache.py
@@ -80,7 +80,7 @@ class MusicCache(dict):
self.log.debug("library: music save into database: %s" % self[id].format_debug_string())
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)
if item:
self.log.debug("library: DELETE item from the database: %s" % item.format_debug_string())
diff --git a/media/item.py b/media/item.py
index 3eb8182..5ff5fff 100644
--- a/media/item.py
+++ b/media/item.py
@@ -110,6 +110,6 @@ class BaseItem:
self.bot.send_msg(msg)
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}
diff --git a/media/playlist.py b/media/playlist.py
index 347b423..9387cd7 100644
--- a/media/playlist.py
+++ b/media/playlist.py
@@ -3,6 +3,7 @@ import random
import threading
import logging
import random
+import time
import variables as var
from media.file import FileItem
@@ -325,6 +326,7 @@ class BasePlaylist(list):
def start_async_validating(self):
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.daemon = True
th.start()
@@ -337,7 +339,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.cache.delete(item.id)
+ var.cache.free_and_delete(item.id)
self.remove_by_id(item.id)
self.log.debug("playlist: validating finished.")
diff --git a/media/radio.py b/media/radio.py
index 6c3bdd3..365d218 100644
--- a/media/radio.py
+++ b/media/radio.py
@@ -83,7 +83,7 @@ def get_radio_title(url):
requests.exceptions.Timeout) as e:
error_traceback = traceback.format_exc()
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
diff --git a/media/url.py b/media/url.py
index ee1a950..8b30585 100644
--- a/media/url.py
+++ b/media/url.py
@@ -224,7 +224,7 @@ class URLItem(BaseItem):
def format_song_string(self, user):
if self.ready in ['validated', 'yes']:
return constants.strings("url_item",
- title=self.title,
+ title=self.title if self.title else "??",
url=self.url,
user=user)
return self.url
diff --git a/mumbleBot.py b/mumbleBot.py
index 7726ba1..03cb41b 100644
--- a/mumbleBot.py
+++ b/mumbleBot.py
@@ -347,7 +347,7 @@ class MumbleBot:
break
else:
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()))
else:
var.playlist.remove_by_id(current.id)
- var.cache.delete(current.id)
+ var.cache.free_and_delete(current.id)
else:
self._loop_status = 'Empty queue'
else: