#!/usr/bin/env python3 from __future__ import print_function import sys import os import notify2 import json import argparse import fnmatch from mpd import MPDClient import configparser client = MPDClient() config = configparser.ConfigParser() config.sections() config.read(os.getenv('HOME')+'/.config/clerk/helper_config') change_db = (config['updater']['change_db']) separator = (config['global']['separator']) os.environ['separator'] = str(" "+separator+" ") mpd_host = 'localhost' mpd_port = '6600' mpd_pass = '' if 'MPD_HOST' in os.environ: mpd_connection = os.environ['MPD_HOST'].split('@') if len(mpd_connection) == 1: mpd_host = mpd_connection[0] elif len(mpd_connection) == 2: mpd_host = mpd_connection[1] mpd_pass = mpd_connection[0] else: print('Unable to parse MPD_HOST, using defaults') if 'MPD_PORT' in os.environ: mpd_port = os.environ['MPD_PORT'] client.connect(mpd_host, mpd_port) if mpd_pass: client.password(mpd_pass) def update(args): db = (client.stats()) new_db = db.get('db_update') if change_db == new_db: if (os.path.isfile(os.getenv('HOME')+'/.config/clerk/tracks.cache.json')): quit() else: notify2.init('Clerk') n = notify2.Notification("Clerk", "Updating Cache Files") n.show() createCache(args) else: notify2.init('Clerk') n = notify2.Notification("Clerk", "Updating Cache Files") n.show() createCache(args) config['updater']['change_db'] = str(new_db) with open(os.getenv('HOME')+'/.config/clerk/helper_config', 'w') as configfile: config.write(configfile) def lookup(key, fields): artistlist = client.list(key) for artist in artistlist: for element in client.find(key, artist): entry = {} for field in fields: if field in element: if isinstance(element[field], list): entry[field] = element[field][0] else: entry[field] = element[field] else: entry[field] = '' yield entry def createCache(args): # track cache creation key = 'artist' fields = ('artist', 'track', 'title', 'album') all_tracks = list({repr(t): t for t in lookup(key, fields)}.values()) with open(os.getenv('HOME')+'/.config/clerk/tracks.cache.json', "w") as cache_file: json.dump(all_tracks, cache_file) # album cache creation with only the youngest track modified key = 'albumartist' fields = ('albumartist', 'date', 'album', 'last-modified') album_cache = {} for entry in lookup(key, fields): # key = repr(entry) # cant use repr in this case because last-modified could differ for # songs from the same album and we want these to clash. key = entry['albumartist'] + entry['album'] if key not in album_cache: album_cache[key] = entry else: if entry['last-modified'] > album_cache[key]['last-modified']: album_cache[key] = entry with open(os.getenv('HOME')+'/.config/clerk/albums.cache.json', "w") as cache_file: json.dump([entry for entry in album_cache.values()], cache_file) def getTracks(args): with open(os.getenv('HOME')+'/.config/clerk/tracks.cache.json') as cache_file: content = json.load(cache_file) sorted_content = sorted(content, key=lambda x: (x['artist'], x['album'], x['track'])) print('\n'.join([os.getenv('separator').join([entry['artist'], entry['track'], entry['title'], entry['album']]) for entry in sorted_content])) def getAlbums(args): with open(os.getenv('HOME')+'/.config/clerk/albums.cache.json') as cache_file: content = json.load(cache_file) sorted_content = sorted(content, key=lambda x: (x['albumartist'], x['date'], x['album'])) print('\n'.join([os.getenv('separator').join([entry['albumartist'], entry['date'], entry['album']]) for entry in sorted_content])) def getLatest(args): with open(os.getenv('HOME')+'/.config/clerk/albums.cache.json') as cache_file: content = json.load(cache_file) sorted_content = sorted(content, key=lambda x: (x['last-modified']), reverse=True) print('\n'.join([os.getenv('separator').join([entry['albumartist'], entry['date'], entry['last-modified'], entry['album']]) for entry in sorted_content])) def readComments(args): args = vars(args) comments = (client.readcomments(sys.stdin.read()[:-1])) for key, value in sorted(comments.items()): print('%s : %s' % (key, value)) def prioSong(args): for line in sys.stdin.read().splitlines(): client.prio(255, line) def restoreTrackRating(args): client.clear() matches = [] for root, dirnames, filenames in os.walk(config['global']['music_path']): for filename in fnmatch.filter(filenames, 'track.ratings'): matches.append(os.path.join(root, filename)) for song in matches: ratingfile = open(song, 'r') for line in ratingfile: tag = [] tags = line.split(os.environ['separator']) for x in tags: if isinstance(x, list): tag.append(x[0].rstrip('\n')) else: tag.append(x) rating = tag[0] artist = tag[1] # track = tag[2] title = tag[3] date = tag[4] album = tag[5].rstrip('\n') filename = tag[6].rstrip('\n') if os.path.isfile(config['global']['music_path']+"/"+filename): client.sticker_set('song', filename, 'rating', rating) print("Imported song "+title+" with rating of "+rating) else: client.searchadd('artist', artist, 'album', album, 'title', title, 'date', date) for song in client.playlistinfo(): if song['title'] in line and song['date'] in line and song['album'] in line: client.sticker_set('song', song['file'], 'rating', rating) print("Imported song "+song['title']+" with rating of "+rating) def restoreAlbumRating(args): matches = [] for root, dirnames, filenames in os.walk(config['global']['music_path']): for filename in fnmatch.filter(filenames, 'album.rating'): matches.append(os.path.join(root, filename)) for song in matches: ratingfile = open(song, 'r') for line in ratingfile: tag = [] tags = line.split(os.environ['separator']) for x in tags: if isinstance(x, list): tag.append(x[0].rstrip('\n')) else: tag.append(x) rating = tag[0] artist = tag[1] # track = tag[2] title = tag[3] date = tag[4] album = tag[5].rstrip('\n') filename = tag[6].rstrip('\n') if os.path.isfile(config['global']['music_path']+"/"+filename): client.sticker_set('song', filename, 'albumrating', rating) print("Imported album "+album+" with rating of "+rating) else: client.searchadd('albumartist', artist, 'album', album, 'title', title, 'date', date) for song in client.playlistinfo(): if song['title'] in line and song['date'] in line and song['album'] in line: client.sticker_set('song', song['file'], 'albumrating', rating) print("Imported album "+song['album']+" with rating of "+rating) def savetoPlaylist(args): for line in sys.stdin: if line.strip(): line = line.strip() client.playlistadd("clerk", line) # print(line, end="") # create commandline arguments parser = argparse.ArgumentParser(prog='clerk_helper', description='Companion script for clerk') subparsers = parser.add_subparsers() parser_prio = subparsers.add_parser('prio', help="prioritize song") parser_prio.set_defaults(call=prioSong) parser_update = subparsers.add_parser('update', help="update cache files") parser_update.set_defaults(call=update) parser_readcomments = subparsers.add_parser('readcomments', help="show all tags of current song") parser_readcomments.set_defaults(call=readComments) parser_saveto = subparsers.add_parser('saveto', help="save stdin to playlist \"clerk\"") parser_saveto.set_defaults(call=savetoPlaylist) parser_createcache = subparsers.add_parser('createcache', help="create track cache for clerk") parser_createcache.set_defaults(call=createCache) parser_gettracks = subparsers.add_parser('getTracks', help="get all tracks from track cache for clerk") parser_gettracks.set_defaults(call=getTracks) parser_getalbums = subparsers.add_parser('getAlbums', help="get all albums from album cache for clerk") parser_getalbums.set_defaults(call=getAlbums) parser_getlatest = subparsers.add_parser('getLatest', help="get all albums from album cache for clerk, sorted by mtime") parser_getlatest.set_defaults(call=getLatest) parser_restoretracks = subparsers.add_parser('restoretracks', help="restore sticker database from rating files") parser_restoretracks.set_defaults(call=restoreTrackRating) parser_restorealbums = subparsers.add_parser('restorealbums', help="restore sticker database from rating files") parser_restorealbums.set_defaults(call=restoreAlbumRating) # parse arguments (thanks jat) args = parser.parse_args() try: args.call(args) except AttributeError: print("No arguments given. Try clerk_helper -h")