from beets import ui from beets.plugins import BeetsPlugin from beets.ui import Subcommand, print_ from beets.ui.commands import print_and_modify from beets.dbcore import types from beets.dbcore import FieldQuery import optparse import json def do_modify_labels(lib, objs, label, action): changed = [] for obj in objs: labels = {} if action != 2: if "mylabels" in obj: labels = json.loads(obj["mylabels"]) split = label.split(":") if action == 0: if len(split) == 1: labels[label] = 0 else: labels[split[0]] = int(split[1]) elif label in labels: del labels[label] obj_mods = { "mylabels": json.dumps(labels) } if print_and_modify(obj, obj_mods, []) and obj not in changed: changed.append(obj) # Still something to do? if not changed: print_("No changes to make.") return # Confirm action. changed = ui.input_select_objects( "Really modify", changed, lambda o: print_and_modify(o, mods, dels), ) # Apply changes to database and files with lib.transaction(): for obj in changed: obj.try_sync(True, False, False) action_map = { "add": 0, "remove": 1, "removeall": 2, "show": 3 } def modify_labels(lib, opts, args): action = args[0] if action not in action_map: print_("%s is not a valid action. " % action) print_("Valid actions are: add, remove, removeall, show") return actnum = action_map[action] if actnum >= 2: label = None query = args[1:] else: label = args[1] query = args[2:] items = lib.items(query=query) if actnum == 3: for obj in items: print_(obj.title) if "mylabels" in obj: print_(" " + "; ".join(obj["mylabels"])) else: do_modify_labels(lib, items, label, actnum) labels_command = Subcommand('labels', help='Add or remove labels') labels_command.func = modify_labels class JSONHas(FieldQuery): @classmethod def value_match(self, pattern, val): if val is not None: labels = json.loads(val) return pattern in labels return False class BeetsLabelsPlugin(BeetsPlugin): # item_queries = { 'has_label': DelimitedHasExact } # item_types = {'mylabels': types.SEMICOLON_SPACE_DSV} def queries(self): return { "JSON@" : JSONHas } def commands(self): return [labels_command]