diff --git a/command.py b/command.py index da821db..9657f07 100644 --- a/command.py +++ b/command.py @@ -10,7 +10,7 @@ import util import variables as var from librb import radiobrowser from database import SettingsDatabase, MusicDatabase -from media.playlist import get_item_wrapper, get_item_wrapper_by_id +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 from media.url import URLItem @@ -771,6 +771,40 @@ def cmd_mode(bot, user, text, command, parameter): bot.interrupt() bot.launch_music() +def cmd_play_tags(bot, user, text, command, parameter): + if not parameter: + bot.send_msg(constants.strings('bad_parameter', command=command)) + return + + msgs = [constants.strings('multiple_file_added') + "") + var.playlist.extend(music_wrappers) + send_multi_lines(bot, msgs, text, "") + else: + bot.send_msg(constants.strings("no_file"), text) + + +def cmd_tag(bot, user, text, command, parameter): + pass + +def cmd_untag(bot, user, text, command, parameter): + pass + +def cmd_list_tagged(bot, user, text, command, parameter): + pass + def cmd_drop_database(bot, user, text, command, parameter): global log diff --git a/database.py b/database.py index 2352f90..9bcc94a 100644 --- a/database.py +++ b/database.py @@ -161,7 +161,8 @@ class MusicDatabase: id = music_dict['id'] title = music_dict['title'] type = music_dict['type'] - tags = ",".join(music_dict['tags']) + tags = ",".join(music_dict['tags']) + "," + del music_dict['id'] del music_dict['title'] del music_dict['type'] @@ -192,7 +193,7 @@ class MusicDatabase: if isinstance(value, str): condition.append(key + "=?") filler.append(value) - else: + elif isinstance(value, dict): condition.append(key + " " + value[0] + " ?") filler.append(value[1]) @@ -210,7 +211,39 @@ class MusicDatabase: music_dict = json.loads(result[3]) music_dict['type'] = result[1] music_dict['title'] = result[2] - music_dict['tags'] = result[4].split(",") + music_dict['tags'] = result[4].strip(",").split(",") + music_dict['id'] = result[0] + music_dicts.append(music_dict) + + return music_dicts + else: + return None + + + def query_music_by_tags(self, tags): + condition = [] + filler = [] + + for tag in tags: + condition.append('tags LIKE ?') + filler.append("%{:s},%".format(tag)) + + + 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['tags'] = result[4].strip(",").split(",") music_dict['id'] = result[0] music_dicts.append(music_dict) diff --git a/media/file.py b/media/file.py index a336226..0961857 100644 --- a/media/file.py +++ b/media/file.py @@ -74,7 +74,7 @@ class FileItem(BaseItem): self.send_client_message(constants.strings('file_missed', file=self.path)) return False - self.version = 1 # 0 -> 1, notify the wrapper to save me when validate() is visited the first time + self.version += 1 # 0 -> 1, notify the wrapper to save me when validate() is visited the first time self.ready = "yes" return True diff --git a/media/item.py b/media/item.py index ba82237..0ee4326 100644 --- a/media/item.py +++ b/media/item.py @@ -60,6 +60,16 @@ class BaseItem: def prepare(self): return True + def add_tag(self, tag): + if tag not in self.tags: + self.tags.append(tag) + self.version += 1 + + def remove_tag(self, tag): + if tag not in self.tags: + self.tags.remove(tag) + self.version += 1 + def format_song_string(self, user): return self.id diff --git a/media/library.py b/media/library.py index 33c1c05..c37e29b 100644 --- a/media/library.py +++ b/media/library.py @@ -48,6 +48,17 @@ class MusicLibrary(dict): self[id] = item_builders[kwargs['type']](bot, **kwargs) # newly built item will not be saved immediately return self[id] + def get_items_by_tags(self, bot, tags): + music_dicts = self.db.query_music_by_tags(tags) + items = [] + for music_dict in music_dicts: + id = music_dicts['id'] + type = music_dict['type'] + self[id] = item_loaders[type](bot, music_dict) + items.append(self[id]) + + return items + def fetch(self, bot, id): music_dicts = self.db.query_music(id=id) if music_dicts: diff --git a/media/playlist.py b/media/playlist.py index 3f34af5..3dd6a07 100644 --- a/media/playlist.py +++ b/media/playlist.py @@ -19,7 +19,7 @@ class PlaylistItemWrapper: self.user = user self.type = type self.log = logging.getLogger("bot") - self.version = 1 + self.version = 0 def item(self): return self.lib[self.id] @@ -55,6 +55,18 @@ class PlaylistItemWrapper: def uri(self): return self.item().uri() + def add_tag(self, tag): + self.item().add_tag(tag) + if self.item().version > self.version: + self.version = self.item().version + self.lib.save(self.id) + + def remove_tag(self, tag): + self.item().remove_tag(tag) + if self.item().version > self.version: + self.version = self.item().version + self.lib.save(self.id) + def is_ready(self): return self.item().is_ready() @@ -88,6 +100,13 @@ def get_item_wrapper_by_id(bot, id, user): else: return None +def get_item_wrappers_by_tags(bot, tags, user): + items = var.library.get_items_by_tags(bot, tags) + ret = [] + for item in items: + ret.append(PlaylistItemWrapper(var.library, item.id, item.type, user)) + return ret + def get_playlist(mode, _list=None, index=None): if _list and index is None: index = _list.current_index diff --git a/media/radio.py b/media/radio.py index 5216789..364c55b 100644 --- a/media/radio.py +++ b/media/radio.py @@ -111,7 +111,7 @@ class RadioItem(BaseItem): self.type = "radio" def validate(self): - self.version = 1 # 0 -> 1, notify the wrapper to save me when validate() is visited the first time + self.version += 1 # 0 -> 1, notify the wrapper to save me when validate() is visited the first time return True def is_ready(self):