From 769579bed2c7a4d134c5157ce9040520d13d0556 Mon Sep 17 00:00:00 2001 From: Remy Date: Mon, 1 Aug 2011 22:21:46 -0700 Subject: [PATCH] Fixed beets m4a album artist bug, redirect to artist page after adding, new folder naming option, fixed bug with folder names and forward slashes, have tracks update instantly on index page after processing, new filter for release groups --- headphones/helpers.py | 2 +- headphones/importer.py | 2 +- headphones/mb.py | 27 ++++++++++++++++++--------- headphones/mover.py | 13 ------------- headphones/postprocessor.py | 37 ++++++++++++++++++++++++++++++------- headphones/searcher.py | 10 +++++----- headphones/templates.py | 3 ++- headphones/webserve.py | 20 +++++++++----------- lib/beets/mediafile.py | 3 +-- 9 files changed, 67 insertions(+), 50 deletions(-) delete mode 100644 headphones/mover.py diff --git a/headphones/helpers.py b/headphones/helpers.py index cc6e4c21..6486ac40 100644 --- a/headphones/helpers.py +++ b/headphones/helpers.py @@ -48,7 +48,7 @@ def latinToAscii(unicrap): 0xdd:'Y', 0xde:'th', 0xdf:'ss', 0xe0:'a', 0xe1:'a', 0xe2:'a', 0xe3:'a', 0xe4:'a', 0xe5:'a', 0xe6:'ae', 0xe7:'c', - 0xe8:'e', 0xe9:'e', 0xea:'e', 0xeb:'e', + 0xe8:'e', 0xe9:'e', 0xea:'e', 0xeb:'e', 0x0259:'e', 0xec:'i', 0xed:'i', 0xee:'i', 0xef:'i', 0xf0:'th', 0xf1:'n', 0xf2:'o', 0xf3:'o', 0xf4:'o', 0xf5:'o', 0xf6:'o', 0xf8:'o', diff --git a/headphones/importer.py b/headphones/importer.py index 9b6c2e6f..3b9a43ad 100644 --- a/headphones/importer.py +++ b/headphones/importer.py @@ -182,7 +182,7 @@ def addArtisttoDB(artistid, extrasonly=False): try: release_dict = mb.getReleaseGroup(rgid) except Exception, e: - logger.info('Unable to get release information for %s - it may not be a valid release group (or it might just not be tagged right in MusicBrainz)' % rg['title']) + logger.info('Unable to get release information for %s - there may not be any official releases in this release group' % rg['title']) continue if not release_dict: diff --git a/headphones/mb.py b/headphones/mb.py index df83ce0a..e0dd2ee6 100644 --- a/headphones/mb.py +++ b/headphones/mb.py @@ -157,7 +157,7 @@ def getArtist(artistid, extrasonly=False): def getReleaseGroup(rgid): """ - Returns the best release out of any given release group + Returns a dictionary of the best stuff from a release group """ with mb_lock: @@ -185,7 +185,7 @@ def getReleaseGroup(rgid): # to get more detailed release info (ASIN, track count, etc.) for release in releaseGroup.releases: - inc = ws.ReleaseIncludes(tracks=True, releaseEvents=True) + inc = ws.ReleaseIncludes(tracks=True, releaseEvents=True) releaseResult = None attempt = 0 @@ -201,9 +201,13 @@ def getReleaseGroup(rgid): if not releaseResult: continue - - if releaseResult.title.lower() != releaseGroup.title.lower(): - continue + + # Release filter for non-official live albums + types = releaseResult.getTypes() + if any('Live' in type for type in types): + if not any('Official' in type for type in types): + logger.debug('%s is not an official live album. Skipping' % releaseResult.name) + continue time.sleep(1) @@ -219,7 +223,7 @@ def getReleaseGroup(rgid): country = { 'US': '0', 'GB': '1', - 'JP': '1', + 'JP': '2', } @@ -231,7 +235,7 @@ def getReleaseGroup(rgid): try: country = int(replace_all(releaseResult.releaseEvents[0].country, country)) except: - country = 2 + country = 3 release_dict = { 'hasasin': bool(releaseResult.asin), @@ -260,8 +264,13 @@ def getReleaseGroup(rgid): release_dict['tracks'] = tracks releaselist.append(release_dict) - - a = multikeysort(releaselist, ['-hasasin', 'country', 'format', 'trackscount']) + + average_tracks = sum(x['trackscount'] for x in releaselist) / len(releaselist) + + for item in releaselist: + item['trackscount_delta'] = abs(average_tracks - item['trackscount']) + + a = multikeysort(releaselist, ['-hasasin', 'country', 'format', 'trackscount_delta']) release_dict = {'releaseid' :a[0]['releaseid'], 'releasedate' : releaselist[0]['releasedate'], diff --git a/headphones/mover.py b/headphones/mover.py deleted file mode 100644 index 9b19f0fe..00000000 --- a/headphones/mover.py +++ /dev/null @@ -1,13 +0,0 @@ -import glob, os, shutil - -import headphones - -from headphones import logger - -def moveFiles(): - for root, dirs, files in os.walk(headphones.DOWNLOAD_DIR): - for file in files: - if file[-4:].lower() == '.mp3' and os.path.isfile(file): - print file - shutil.copy2(os.path.join(root, file), - os.path.join(path_to_itunes, file)) diff --git a/headphones/postprocessor.py b/headphones/postprocessor.py index aacae6d7..8d23df2a 100644 --- a/headphones/postprocessor.py +++ b/headphones/postprocessor.py @@ -114,6 +114,17 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list) albumpath = moveFiles(albumpath, release, tracks) myDB = db.DBConnection() + # There's gotta be a better way to update the have tracks - sqlite + + trackcount = myDB.select('SELECT HaveTracks from artists WHERE ArtistID=?', [release['ArtistID']]) + + if not trackcount[0][0]: + cur_track_count = 0 + else: + cur_track_count = trackcount[0][0] + + new_track_count = cur_track_count + len(downloaded_track_list) + myDB.action('UPDATE artists SET HaveTracks=? WHERE ArtistID=?', [new_track_count, release['ArtistID']]) myDB.action('UPDATE albums SET status = "Downloaded" WHERE AlbumID=?', [albumid]) myDB.action('UPDATE snatched SET status = "Processed" WHERE AlbumID=?', [albumid]) updateHave(albumpath) @@ -158,10 +169,20 @@ def moveFiles(albumpath, release, tracks): year = release['ReleaseDate'][:4] except TypeError: year = '' + + artist = release['ArtistName'].replace('/', '_') + album = release['AlbumTitle'].replace('/', '_') + + if artist[0].isdigit(): + firstchar = '0-9' + else: + firstchar = artist[0] + - values = { 'artist': release['ArtistName'], - 'album': release['AlbumTitle'], - 'year': year + values = { 'artist': artist, + 'album': album, + 'year': year, + 'first': firstchar, } @@ -171,7 +192,7 @@ def moveFiles(albumpath, release, tracks): if folder.endswith('.'): folder = folder.replace(folder[len(folder)-1], '_') - destination_path = os.path.join(headphones.DESTINATION_DIR, folder) + destination_path = os.path.normpath(os.path.join(headphones.DESTINATION_DIR, folder)) if os.path.exists(destination_path): i = 1 @@ -183,8 +204,7 @@ def moveFiles(albumpath, release, tracks): destination_path = new_folder_name break - - logger.info('Moving files from %s to %s' % (folder, destination_path)) + logger.info('Moving files from %s to %s' % (albumpath, destination_path)) try: os.makedirs(destination_path) @@ -356,7 +376,10 @@ def forcePostProcess(): else: logger.info('Querying MusicBrainz for the release group id for: %s - %s' % (name, album)) from headphones import mb - rgid = unicode(mb.findAlbumID(name, album)) + try: + rgid = unicode(mb.findAlbumID(name, album)) + except: + logger.error('Can not get release information for this album') if rgid: verify(rgid, albumpath) diff --git a/headphones/searcher.py b/headphones/searcher.py index 05a5159f..5fabc701 100644 --- a/headphones/searcher.py +++ b/headphones/searcher.py @@ -77,8 +77,8 @@ def searchNZB(albumid=None, new=False): cleanartistalbum = helpers.latinToAscii(helpers.replace_all(albums[0]+' '+albums[1], dic)) # FLAC usually doesn't have a year for some reason so I'll leave it out: - term = re.sub('[\.\-]', ' ', '%s' % (cleanartistalbum)).encode('utf-8') - altterm = re.sub('[\.\-]', ' ', '%s %s' % (cleanartistalbum, year)).encode('utf-8') + term = re.sub('[\.\-\/]', ' ', '%s' % (cleanartistalbum)).encode('utf-8') + altterm = re.sub('[\.\-\/]', ' ', '%s %s' % (cleanartistalbum, year)).encode('utf-8') # Only use the year if the term could return a bunch of different albums, i.e. self-titled albums if albums[0] in albums[1] or len(albums[0]) < 4 or len(albums[1]) < 4: @@ -381,7 +381,7 @@ def searchNZB(albumid=None, new=False): data = urllib.urlopen(url, data=params).read() nzb = classes.NZBDataSearchResult() nzb.extraInfo.append(data) - nzb_folder_name = '%s - %s [%s]' % (helpers.latinToAscii(albums[0]).encode('UTF-8'), helpers.latinToAscii(albums[1]).encode('UTF-8'), year) + nzb_folder_name = '%s - %s [%s]' % (helpers.latinToAscii(albums[0]).encode('UTF-8').replace('/', '_'), helpers.latinToAscii(albums[1]).encode('UTF-8').replace('/', '_'), year) nzb.name = nzb_folder_name logger.info(u"Sending FILE to SABNZBD: " + nzb.name) sab.sendNZB(nzb) @@ -390,8 +390,8 @@ def searchNZB(albumid=None, new=False): myDB.action('INSERT INTO snatched VALUES( ?, ?, ?, ?, DATETIME("NOW", "localtime"), ?, ?)', [albums[2], bestqual[0], bestqual[1], bestqual[2], "Snatched", nzb_folder_name]) else: downloadurl = bestqual[2] - nzb_folder_name = '%s - %s [%s]' % (helpers.latinToAscii(albums[0]).encode('UTF-8'), helpers.latinToAscii(albums[1]).encode('UTF-8'), year) - + nzb_folder_name = '%s - %s [%s]' % (helpers.latinToAscii(albums[0]).encode('UTF-8').replace('/', '_'), helpers.latinToAscii(albums[1]).encode('UTF-8').replace('/', '_'), year) + if headphones.SAB_HOST and not headphones.BLACKHOLE: linkparams = {} diff --git a/headphones/templates.py b/headphones/templates.py index a5efb9cf..8f2b3a77 100644 --- a/headphones/templates.py +++ b/headphones/templates.py @@ -337,7 +337,8 @@ configform = form = '''

Folder Format:

- Use: artist, album and year, '/' for directories.
E.g.: artist/album [year]
+ Use: artist, album, year and first (first letter in artist name)
+ E.g.: first/artist/album [year] = G/Girl Talk/All Day [2010]

File Format:
diff --git a/headphones/webserve.py b/headphones/webserve.py index f20f5a97..c7b75390 100644 --- a/headphones/webserve.py +++ b/headphones/webserve.py @@ -1,13 +1,8 @@ -import os, sys +import os import cherrypy -import lib.musicbrainz2.webservice as ws -import lib.musicbrainz2.model as m -import lib.musicbrainz2.utils as u - import time -import datetime import threading import headphones @@ -101,10 +96,13 @@ class WebInterface(object): page.append(templates._nav) myDB = db.DBConnection() - artist = myDB.select('SELECT ArtistName, IncludeExtras from artists WHERE ArtistID=?', [ArtistID]) - + artist = myDB.select('SELECT ArtistName, IncludeExtras, Status from artists WHERE ArtistID=?', [ArtistID]) + while not artist: + time.sleep(1) page.append('''

%s

''' % artist[0][0]) + if artist[0][2] == 'Loading': + page.append('

Loading...

') if templates.displayAlbums(ArtistID, 'Album'): page.append(templates.displayAlbums(ArtistID, 'Album')) @@ -222,12 +220,12 @@ class WebInterface(object): artistInfo.exposed = True - def addArtist(self, artistid, redirect='home'): + def addArtist(self, artistid): threading.Thread(target=importer.addArtisttoDB, args=[artistid]).start() time.sleep(5) threading.Thread(target=lastfm.getSimilar).start() - raise cherrypy.HTTPRedirect(redirect) + raise cherrypy.HTTPRedirect("artistPage?ArtistID=%s" % artistid) addArtist.exposed = True @@ -693,7 +691,7 @@ class WebInterface(object):
    ''') for item in cloudlist: - page.append('
  • %s
  • ' % (item['ArtistID'], item['Count'], item['ArtistName'])) + page.append('
  • %s
  • ' % (item['ArtistID'], item['Count'], item['ArtistName'])) page.append('


') page.append(templates._footer % headphones.CURRENT_VERSION) return page diff --git a/lib/beets/mediafile.py b/lib/beets/mediafile.py index c9e7b0b2..647f8b65 100644 --- a/lib/beets/mediafile.py +++ b/lib/beets/mediafile.py @@ -789,8 +789,7 @@ class MediaFile(object): ) albumartist = MediaField( mp3 = StorageStyle('TPE2'), - mp4 = StorageStyle( - '----:com.apple.iTunes:Album Artist'), + mp4 = StorageStyle('aART'), etc = [StorageStyle('album artist'), StorageStyle('albumartist')] )