mirror of
https://github.com/rembo10/headphones.git
synced 2026-07-20 16:03:59 +01:00
pep8, pyflakes, and pylint suggested fixes
This commit is contained in:
+298
-167
@@ -13,20 +13,19 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Headphones. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import uuid
|
||||
import beets
|
||||
import threading
|
||||
import itertools
|
||||
import headphones
|
||||
|
||||
import os
|
||||
import re
|
||||
import beets
|
||||
import headphones
|
||||
from beets import autotag
|
||||
from beets import config as beetsconfig
|
||||
from beets.mediafile import MediaFile, FileTypeError, UnreadableFileError
|
||||
from beetsplug import lyrics as beetslyrics
|
||||
|
||||
from headphones import notifiers, utorrent, transmission
|
||||
from headphones import db, albumart, librarysync
|
||||
from headphones import logger, helpers, request, mb, music_encoder
|
||||
@@ -48,19 +47,21 @@ def checkFolder():
|
||||
else:
|
||||
download_dir = headphones.CONFIG.DOWNLOAD_TORRENT_DIR
|
||||
|
||||
album_path = os.path.join(download_dir, album['FolderName']).encode(headphones.SYS_ENCODING, 'replace')
|
||||
album_path = os.path.join(download_dir, album['FolderName']).encode(
|
||||
headphones.SYS_ENCODING, 'replace')
|
||||
logger.debug("Checking if %s exists" % album_path)
|
||||
|
||||
if os.path.exists(album_path):
|
||||
logger.info('Found "' + album['FolderName'] + '" in ' + album['Kind'] + ' download folder. Verifying....')
|
||||
logger.info('Found "' + album['FolderName'] + '" in ' + album[
|
||||
'Kind'] + ' download folder. Verifying....')
|
||||
verify(album['AlbumID'], album_path, album['Kind'])
|
||||
else:
|
||||
logger.info("No folder name found for " + album['Title'])
|
||||
|
||||
logger.debug("Checking download folder finished.")
|
||||
|
||||
def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=False):
|
||||
|
||||
def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=False):
|
||||
myDB = db.DBConnection()
|
||||
release = myDB.action('SELECT * from albums WHERE AlbumID=?', [albumid]).fetchone()
|
||||
tracks = myDB.select('SELECT * from tracks WHERE AlbumID=?', [albumid])
|
||||
@@ -72,11 +73,14 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
||||
try:
|
||||
release_list = mb.getReleaseGroup(albumid)
|
||||
except Exception as e:
|
||||
logger.error('Unable to get release information for manual album with rgid: %s. Error: %s', albumid, e)
|
||||
logger.error(
|
||||
'Unable to get release information for manual album with rgid: %s. Error: %s',
|
||||
albumid, e)
|
||||
return
|
||||
|
||||
if not release_list:
|
||||
logger.error('Unable to get release information for manual album with rgid: %s', albumid)
|
||||
logger.error('Unable to get release information for manual album with rgid: %s',
|
||||
albumid)
|
||||
return
|
||||
|
||||
# Since we're just using this to create the bare minimum information to
|
||||
@@ -85,7 +89,9 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
||||
release_dict = mb.getRelease(releaseid)
|
||||
|
||||
if not release_dict:
|
||||
logger.error('Unable to get release information for manual album with rgid: %s. Cannot continue', albumid)
|
||||
logger.error(
|
||||
'Unable to get release information for manual album with rgid: %s. Cannot continue',
|
||||
albumid)
|
||||
return
|
||||
|
||||
# Check if the artist is added to the database. In case the database is
|
||||
@@ -93,21 +99,26 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
||||
# prevents new artists from appearing suddenly. In case forced is True,
|
||||
# this check is skipped, since it is assumed the user wants this.
|
||||
if headphones.CONFIG.FREEZE_DB and not forced:
|
||||
artist = myDB.select("SELECT ArtistName, ArtistID FROM artists WHERE ArtistId=? OR ArtistName=?", [release_dict['artist_id'], release_dict['artist_name']])
|
||||
artist = myDB.select(
|
||||
"SELECT ArtistName, ArtistID FROM artists WHERE ArtistId=? OR ArtistName=?",
|
||||
[release_dict['artist_id'], release_dict['artist_name']])
|
||||
|
||||
if not artist:
|
||||
logger.warn("Continuing would add new artist '%s' (ID %s), " \
|
||||
"but database is frozen. Will skip postprocessing for " \
|
||||
"album with rgid: %s", release_dict['artist_name'],
|
||||
release_dict['artist_id'], albumid)
|
||||
"but database is frozen. Will skip postprocessing for " \
|
||||
"album with rgid: %s", release_dict['artist_name'],
|
||||
release_dict['artist_id'], albumid)
|
||||
|
||||
myDB.action('UPDATE snatched SET status = "Frozen" WHERE status NOT LIKE "Seed%" and AlbumID=?', [albumid])
|
||||
myDB.action(
|
||||
'UPDATE snatched SET status = "Frozen" WHERE status NOT LIKE "Seed%" and AlbumID=?',
|
||||
[albumid])
|
||||
frozen = re.search(r' \(Frozen\)(?:\[\d+\])?', albumpath)
|
||||
if not frozen:
|
||||
if headphones.CONFIG.RENAME_FROZEN:
|
||||
renameUnprocessedFolder(albumpath, tag="Frozen")
|
||||
else:
|
||||
logger.warn(u"Won't rename %s to mark as 'Frozen', because it is disabled.", albumpath.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.warn(u"Won't rename %s to mark as 'Frozen', because it is disabled.",
|
||||
albumpath.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
return
|
||||
|
||||
logger.info(u"Now adding/updating artist: " + release_dict['artist_name'])
|
||||
@@ -123,7 +134,8 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
||||
"DateAdded": helpers.today(),
|
||||
"Status": "Paused"}
|
||||
|
||||
logger.info("ArtistID: " + release_dict['artist_id'] + " , ArtistName: " + release_dict['artist_name'])
|
||||
logger.info("ArtistID: " + release_dict['artist_id'] + " , ArtistName: " + release_dict[
|
||||
'artist_name'])
|
||||
|
||||
if headphones.CONFIG.INCLUDE_EXTRAS:
|
||||
newValueDict['IncludeExtras'] = 1
|
||||
@@ -150,18 +162,17 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
||||
# Delete existing tracks associated with this AlbumID since we're going to replace them and don't want any extras
|
||||
myDB.action('DELETE from tracks WHERE AlbumID=?', [albumid])
|
||||
for track in release_dict['tracks']:
|
||||
|
||||
controlValueDict = {"TrackID": track['id'],
|
||||
"AlbumID": albumid}
|
||||
|
||||
newValueDict = {"ArtistID": release_dict['artist_id'],
|
||||
"ArtistName": release_dict['artist_name'],
|
||||
"AlbumTitle": release_dict['title'],
|
||||
"AlbumASIN": release_dict['asin'],
|
||||
"TrackTitle": track['title'],
|
||||
"TrackDuration": track['duration'],
|
||||
"TrackNumber": track['number']
|
||||
}
|
||||
"ArtistName": release_dict['artist_name'],
|
||||
"AlbumTitle": release_dict['title'],
|
||||
"AlbumASIN": release_dict['asin'],
|
||||
"TrackTitle": track['title'],
|
||||
"TrackDuration": track['duration'],
|
||||
"TrackNumber": track['number']
|
||||
}
|
||||
|
||||
myDB.upsert("tracks", newValueDict, controlValueDict)
|
||||
|
||||
@@ -169,7 +180,8 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
||||
newValueDict = {"Status": "Paused"}
|
||||
|
||||
myDB.upsert("artists", newValueDict, controlValueDict)
|
||||
logger.info(u"Addition complete for: " + release_dict['title'] + " - " + release_dict['artist_name'])
|
||||
logger.info(u"Addition complete for: " + release_dict['title'] + " - " + release_dict[
|
||||
'artist_name'])
|
||||
|
||||
release = myDB.action('SELECT * from albums WHERE AlbumID=?', [albumid]).fetchone()
|
||||
tracks = myDB.select('SELECT * from tracks WHERE AlbumID=?', [albumid])
|
||||
@@ -185,11 +197,14 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
||||
downloaded_cuecount += 1
|
||||
# if any of the files end in *.part, we know the torrent isn't done yet. Process if forced, though
|
||||
elif files.lower().endswith(('.part', '.utpart')) and not forced:
|
||||
logger.info("Looks like " + os.path.basename(albumpath).decode(headphones.SYS_ENCODING, 'replace') + " isn't complete yet. Will try again on the next run")
|
||||
logger.info(
|
||||
"Looks like " + os.path.basename(albumpath).decode(headphones.SYS_ENCODING,
|
||||
'replace') + " isn't complete yet. Will try again on the next run")
|
||||
return
|
||||
|
||||
# Split cue
|
||||
if headphones.CONFIG.CUE_SPLIT and downloaded_cuecount and downloaded_cuecount >= len(downloaded_track_list):
|
||||
if headphones.CONFIG.CUE_SPLIT and downloaded_cuecount and downloaded_cuecount >= len(
|
||||
downloaded_track_list):
|
||||
if headphones.CONFIG.KEEP_TORRENT_FILES and Kind == "torrent":
|
||||
albumpath = helpers.preserve_torrent_directory(albumpath)
|
||||
if albumpath and helpers.cue_split(albumpath):
|
||||
@@ -202,7 +217,10 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
||||
try:
|
||||
f = MediaFile(downloaded_track)
|
||||
except Exception as e:
|
||||
logger.info(u"Exception from MediaFile for: " + downloaded_track.decode(headphones.SYS_ENCODING, 'replace') + u" : " + unicode(e))
|
||||
logger.info(
|
||||
u"Exception from MediaFile for: " + downloaded_track.decode(headphones.SYS_ENCODING,
|
||||
'replace') + u" : " + unicode(
|
||||
e))
|
||||
continue
|
||||
|
||||
if not f.artist:
|
||||
@@ -219,7 +237,8 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
||||
logger.debug('Matching metadata album: %s with album name: %s' % (metaalbum, dbalbum))
|
||||
|
||||
if metaartist == dbartist and metaalbum == dbalbum:
|
||||
doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, Kind, keep_original_folder)
|
||||
doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, Kind,
|
||||
keep_original_folder)
|
||||
return
|
||||
|
||||
# test #2: filenames
|
||||
@@ -237,7 +256,8 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
||||
logger.debug('Checking if track title: %s is in file name: %s' % (dbtrack, filetrack))
|
||||
|
||||
if dbtrack in filetrack:
|
||||
doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, Kind, keep_original_folder)
|
||||
doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, Kind,
|
||||
keep_original_folder)
|
||||
return
|
||||
|
||||
# test #3: number of songs and duration
|
||||
@@ -269,32 +289,42 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
||||
logger.debug('Database track duration: %i' % db_track_duration)
|
||||
delta = abs(downloaded_track_duration - db_track_duration)
|
||||
if delta < 240:
|
||||
doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, Kind, keep_original_folder)
|
||||
doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, Kind,
|
||||
keep_original_folder)
|
||||
return
|
||||
|
||||
logger.warn(u'Could not identify album: %s. It may not be the intended album.', albumpath.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
myDB.action('UPDATE snatched SET status = "Unprocessed" WHERE status NOT LIKE "Seed%" and AlbumID=?', [albumid])
|
||||
logger.warn(u'Could not identify album: %s. It may not be the intended album.',
|
||||
albumpath.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
myDB.action(
|
||||
'UPDATE snatched SET status = "Unprocessed" WHERE status NOT LIKE "Seed%" and AlbumID=?',
|
||||
[albumid])
|
||||
processed = re.search(r' \(Unprocessed\)(?:\[\d+\])?', albumpath)
|
||||
if not processed:
|
||||
if headphones.CONFIG.RENAME_UNPROCESSED:
|
||||
renameUnprocessedFolder(albumpath, tag="Unprocessed")
|
||||
else:
|
||||
logger.warn(u"Won't rename %s to mark as 'Unprocessed', because it is disabled.", albumpath.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.warn(u"Won't rename %s to mark as 'Unprocessed', because it is disabled.",
|
||||
albumpath.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
|
||||
|
||||
def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, Kind=None, keep_original_folder=False):
|
||||
|
||||
logger.info('Starting post-processing for: %s - %s' % (release['ArtistName'], release['AlbumTitle']))
|
||||
def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, Kind=None,
|
||||
keep_original_folder=False):
|
||||
logger.info(
|
||||
'Starting post-processing for: %s - %s' % (release['ArtistName'], release['AlbumTitle']))
|
||||
# Check to see if we're preserving the torrent dir
|
||||
if (headphones.CONFIG.KEEP_TORRENT_FILES and Kind == "torrent" and 'headphones-modified' not in albumpath) or headphones.CONFIG.KEEP_ORIGINAL_FOLDER or keep_original_folder:
|
||||
new_folder = os.path.join(albumpath, 'headphones-modified'.encode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.info("Copying files to 'headphones-modified' subfolder to preserve downloaded files for seeding")
|
||||
if (
|
||||
headphones.CONFIG.KEEP_TORRENT_FILES and Kind == "torrent" and 'headphones-modified' not in albumpath) or headphones.CONFIG.KEEP_ORIGINAL_FOLDER or keep_original_folder:
|
||||
new_folder = os.path.join(albumpath,
|
||||
'headphones-modified'.encode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.info(
|
||||
"Copying files to 'headphones-modified' subfolder to preserve downloaded files for seeding")
|
||||
try:
|
||||
shutil.copytree(albumpath, new_folder)
|
||||
# Update the album path with the new location
|
||||
albumpath = new_folder
|
||||
except Exception as e:
|
||||
logger.warn("Cannot copy/move files to temp folder: " + new_folder.decode(headphones.SYS_ENCODING, 'replace') + ". Not continuing. Error: " + str(e))
|
||||
logger.warn("Cannot copy/move files to temp folder: " + new_folder.decode(
|
||||
headphones.SYS_ENCODING, 'replace') + ". Not continuing. Error: " + str(e))
|
||||
return
|
||||
|
||||
# Need to update the downloaded track list with the new location.
|
||||
@@ -317,8 +347,8 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
|
||||
return
|
||||
except (FileTypeError, UnreadableFileError):
|
||||
logger.error("Track file is not a valid media file: %s. Not " \
|
||||
"continuing.", downloaded_track.decode(
|
||||
headphones.SYS_ENCODING, "replace"))
|
||||
"continuing.", downloaded_track.decode(
|
||||
headphones.SYS_ENCODING, "replace"))
|
||||
return
|
||||
except IOError:
|
||||
logger.error("Unable to find media file: %s. Not continuing.")
|
||||
@@ -328,9 +358,9 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
|
||||
# files, which requires write permissions. This step just check this, so
|
||||
# it will not try and fail lateron, with strange exceptions.
|
||||
if headphones.CONFIG.EMBED_ALBUM_ART or headphones.CONFIG.CLEANUP_FILES or \
|
||||
headphones.CONFIG.ADD_ALBUM_ART or headphones.CONFIG.CORRECT_METADATA or \
|
||||
headphones.CONFIG.EMBED_LYRICS or headphones.CONFIG.RENAME_FILES or \
|
||||
headphones.CONFIG.MOVE_FILES:
|
||||
headphones.CONFIG.ADD_ALBUM_ART or headphones.CONFIG.CORRECT_METADATA or \
|
||||
headphones.CONFIG.EMBED_LYRICS or headphones.CONFIG.RENAME_FILES or \
|
||||
headphones.CONFIG.MOVE_FILES:
|
||||
|
||||
try:
|
||||
with open(downloaded_track, "a+b") as fp:
|
||||
@@ -338,11 +368,11 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
|
||||
except IOError as e:
|
||||
logger.debug("Write check exact error: %s", e)
|
||||
logger.error("Track file is not writable. This is required " \
|
||||
"for some post processing steps: %s. Not continuing.",
|
||||
downloaded_track.decode(headphones.SYS_ENCODING, "replace"))
|
||||
"for some post processing steps: %s. Not continuing.",
|
||||
downloaded_track.decode(headphones.SYS_ENCODING, "replace"))
|
||||
return
|
||||
|
||||
#start encoding
|
||||
# start encoding
|
||||
if headphones.CONFIG.MUSIC_ENCODER:
|
||||
downloaded_track_list = music_encoder.encode(albumpath)
|
||||
|
||||
@@ -389,7 +419,8 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
|
||||
renameFiles(albumpath, downloaded_track_list, release)
|
||||
|
||||
if headphones.CONFIG.MOVE_FILES and not headphones.CONFIG.DESTINATION_DIR:
|
||||
logger.error('No DESTINATION_DIR has been set. Set "Destination Directory" to the parent directory you want to move the files to')
|
||||
logger.error(
|
||||
'No DESTINATION_DIR has been set. Set "Destination Directory" to the parent directory you want to move the files to')
|
||||
albumpaths = [albumpath]
|
||||
elif headphones.CONFIG.MOVE_FILES and headphones.CONFIG.DESTINATION_DIR:
|
||||
albumpaths = moveFiles(albumpath, release, tracks)
|
||||
@@ -400,15 +431,20 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
|
||||
|
||||
myDB = db.DBConnection()
|
||||
myDB.action('UPDATE albums SET status = "Downloaded" WHERE AlbumID=?', [albumid])
|
||||
myDB.action('UPDATE snatched SET status = "Processed" WHERE Status NOT LIKE "Seed%" and AlbumID=?', [albumid])
|
||||
myDB.action(
|
||||
'UPDATE snatched SET status = "Processed" WHERE Status NOT LIKE "Seed%" and AlbumID=?',
|
||||
[albumid])
|
||||
|
||||
# Check if torrent has finished seeding
|
||||
if headphones.CONFIG.TORRENT_DOWNLOADER == 1 or headphones.CONFIG.TORRENT_DOWNLOADER == 2:
|
||||
seed_snatched = myDB.action('SELECT * from snatched WHERE Status="Seed_Snatched" and AlbumID=?', [albumid]).fetchone()
|
||||
seed_snatched = myDB.action(
|
||||
'SELECT * from snatched WHERE Status="Seed_Snatched" and AlbumID=?',
|
||||
[albumid]).fetchone()
|
||||
if seed_snatched:
|
||||
hash = seed_snatched['FolderName']
|
||||
torrent_removed = False
|
||||
logger.info(u'%s - %s. Checking if torrent has finished seeding and can be removed' % (release['ArtistName'], release['AlbumTitle']))
|
||||
logger.info(u'%s - %s. Checking if torrent has finished seeding and can be removed' % (
|
||||
release['ArtistName'], release['AlbumTitle']))
|
||||
if headphones.CONFIG.TORRENT_DOWNLOADER == 1:
|
||||
torrent_removed = transmission.removeTorrent(hash, True)
|
||||
else:
|
||||
@@ -416,15 +452,20 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
|
||||
|
||||
# Torrent removed, delete the snatched record, else update Status for scheduled job to check
|
||||
if torrent_removed:
|
||||
myDB.action('DELETE from snatched WHERE status = "Seed_Snatched" and AlbumID=?', [albumid])
|
||||
myDB.action('DELETE from snatched WHERE status = "Seed_Snatched" and AlbumID=?',
|
||||
[albumid])
|
||||
else:
|
||||
myDB.action('UPDATE snatched SET status = "Seed_Processed" WHERE status = "Seed_Snatched" and AlbumID=?', [albumid])
|
||||
myDB.action(
|
||||
'UPDATE snatched SET status = "Seed_Processed" WHERE status = "Seed_Snatched" and AlbumID=?',
|
||||
[albumid])
|
||||
|
||||
# Update the have tracks for all created dirs:
|
||||
for albumpath in albumpaths:
|
||||
librarysync.libraryScan(dir=albumpath, append=True, ArtistID=release['ArtistID'], ArtistName=release['ArtistName'])
|
||||
librarysync.libraryScan(dir=albumpath, append=True, ArtistID=release['ArtistID'],
|
||||
ArtistName=release['ArtistName'])
|
||||
|
||||
logger.info(u'Post-processing for %s - %s complete' % (release['ArtistName'], release['AlbumTitle']))
|
||||
logger.info(
|
||||
u'Post-processing for %s - %s complete' % (release['ArtistName'], release['AlbumTitle']))
|
||||
|
||||
pushmessage = release['ArtistName'] + ' - ' + release['AlbumTitle']
|
||||
statusmessage = "Download and Postprocessing completed"
|
||||
@@ -530,7 +571,8 @@ def embedAlbumArt(artwork, downloaded_track_list):
|
||||
try:
|
||||
f = MediaFile(downloaded_track)
|
||||
except:
|
||||
logger.error(u'Could not read %s. Not adding album art' % downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.error(u'Could not read %s. Not adding album art' % downloaded_track.decode(
|
||||
headphones.SYS_ENCODING, 'replace'))
|
||||
continue
|
||||
|
||||
logger.debug('Adding album art to: %s' % downloaded_track)
|
||||
@@ -539,7 +581,8 @@ def embedAlbumArt(artwork, downloaded_track_list):
|
||||
f.art = artwork
|
||||
f.save()
|
||||
except Exception as e:
|
||||
logger.error(u'Error embedding album art to: %s. Error: %s' % (downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), str(e)))
|
||||
logger.error(u'Error embedding album art to: %s. Error: %s' % (
|
||||
downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), str(e)))
|
||||
continue
|
||||
|
||||
|
||||
@@ -552,16 +595,18 @@ def addAlbumArt(artwork, albumpath, release):
|
||||
year = ''
|
||||
|
||||
values = {'$Artist': release['ArtistName'],
|
||||
'$Album': release['AlbumTitle'],
|
||||
'$Year': year,
|
||||
'$artist': release['ArtistName'].lower(),
|
||||
'$album': release['AlbumTitle'].lower(),
|
||||
'$year': year
|
||||
}
|
||||
'$Album': release['AlbumTitle'],
|
||||
'$Year': year,
|
||||
'$artist': release['ArtistName'].lower(),
|
||||
'$album': release['AlbumTitle'].lower(),
|
||||
'$year': year
|
||||
}
|
||||
|
||||
album_art_name = helpers.replace_all(headphones.CONFIG.ALBUM_ART_FORMAT.strip(), values) + ".jpg"
|
||||
album_art_name = helpers.replace_all(headphones.CONFIG.ALBUM_ART_FORMAT.strip(),
|
||||
values) + ".jpg"
|
||||
|
||||
album_art_name = helpers.replace_illegal_chars(album_art_name).encode(headphones.SYS_ENCODING, 'replace')
|
||||
album_art_name = helpers.replace_illegal_chars(album_art_name).encode(headphones.SYS_ENCODING,
|
||||
'replace')
|
||||
|
||||
if headphones.CONFIG.FILE_UNDERSCORES:
|
||||
album_art_name = album_art_name.replace(' ', '_')
|
||||
@@ -587,7 +632,8 @@ def cleanupFiles(albumpath):
|
||||
try:
|
||||
os.remove(os.path.join(r, files))
|
||||
except Exception as e:
|
||||
logger.error(u'Could not remove file: %s. Error: %s' % (files.decode(headphones.SYS_ENCODING, 'replace'), e))
|
||||
logger.error(u'Could not remove file: %s. Error: %s' % (
|
||||
files.decode(headphones.SYS_ENCODING, 'replace'), e))
|
||||
|
||||
|
||||
def renameNFO(albumpath):
|
||||
@@ -596,12 +642,16 @@ def renameNFO(albumpath):
|
||||
for r, d, f in os.walk(albumpath):
|
||||
for file in f:
|
||||
if file.lower().endswith('.nfo'):
|
||||
logger.debug('Renaming: "%s" to "%s"' % (file.decode(headphones.SYS_ENCODING, 'replace'), file.decode(headphones.SYS_ENCODING, 'replace') + '-orig'))
|
||||
logger.debug('Renaming: "%s" to "%s"' % (
|
||||
file.decode(headphones.SYS_ENCODING, 'replace'),
|
||||
file.decode(headphones.SYS_ENCODING, 'replace') + '-orig'))
|
||||
try:
|
||||
new_file_name = os.path.join(r, file)[:-3] + 'orig.nfo'
|
||||
os.rename(os.path.join(r, file), new_file_name)
|
||||
except Exception as e:
|
||||
logger.error(u'Could not rename file: %s. Error: %s' % (os.path.join(r, file).decode(headphones.SYS_ENCODING, 'replace'), e))
|
||||
logger.error(u'Could not rename file: %s. Error: %s' % (
|
||||
os.path.join(r, file).decode(headphones.SYS_ENCODING, 'replace'), e))
|
||||
|
||||
|
||||
def moveFiles(albumpath, release, tracks):
|
||||
logger.info("Moving files: %s" % albumpath)
|
||||
@@ -630,25 +680,26 @@ def moveFiles(albumpath, release, tracks):
|
||||
|
||||
for r, d, f in os.walk(albumpath):
|
||||
try:
|
||||
origfolder = os.path.basename(os.path.normpath(r).decode(headphones.SYS_ENCODING, 'replace'))
|
||||
origfolder = os.path.basename(
|
||||
os.path.normpath(r).decode(headphones.SYS_ENCODING, 'replace'))
|
||||
except:
|
||||
origfolder = u''
|
||||
|
||||
values = {'$Artist': artist,
|
||||
'$SortArtist': sortname,
|
||||
'$Album': album,
|
||||
'$Year': year,
|
||||
'$Type': releasetype,
|
||||
'$OriginalFolder': origfolder,
|
||||
'$First': firstchar.upper(),
|
||||
'$artist': artist.lower(),
|
||||
'$sortartist': sortname.lower(),
|
||||
'$album': album.lower(),
|
||||
'$year': year,
|
||||
'$type': releasetype.lower(),
|
||||
'$first': firstchar.lower(),
|
||||
'$originalfolder': origfolder.lower()
|
||||
}
|
||||
'$SortArtist': sortname,
|
||||
'$Album': album,
|
||||
'$Year': year,
|
||||
'$Type': releasetype,
|
||||
'$OriginalFolder': origfolder,
|
||||
'$First': firstchar.upper(),
|
||||
'$artist': artist.lower(),
|
||||
'$sortartist': sortname.lower(),
|
||||
'$album': album.lower(),
|
||||
'$year': year,
|
||||
'$type': releasetype.lower(),
|
||||
'$first': firstchar.lower(),
|
||||
'$originalfolder': origfolder.lower()
|
||||
}
|
||||
|
||||
folder = helpers.replace_all(headphones.CONFIG.FOLDER_FORMAT.strip(), values, normalize=True)
|
||||
|
||||
@@ -672,15 +723,20 @@ def moveFiles(albumpath, release, tracks):
|
||||
files_to_move.append(os.path.join(r, files))
|
||||
if any(files.lower().endswith('.' + x.lower()) for x in headphones.LOSSY_MEDIA_FORMATS):
|
||||
lossy_media = True
|
||||
if any(files.lower().endswith('.' + x.lower()) for x in headphones.LOSSLESS_MEDIA_FORMATS):
|
||||
if any(files.lower().endswith('.' + x.lower()) for x in
|
||||
headphones.LOSSLESS_MEDIA_FORMATS):
|
||||
lossless_media = True
|
||||
|
||||
# Do some sanity checking to see what directories we need to create:
|
||||
make_lossy_folder = False
|
||||
make_lossless_folder = False
|
||||
|
||||
lossy_destination_path = os.path.normpath(os.path.join(headphones.CONFIG.DESTINATION_DIR, folder)).encode(headphones.SYS_ENCODING, 'replace')
|
||||
lossless_destination_path = os.path.normpath(os.path.join(headphones.CONFIG.LOSSLESS_DESTINATION_DIR, folder)).encode(headphones.SYS_ENCODING, 'replace')
|
||||
lossy_destination_path = os.path.normpath(
|
||||
os.path.join(headphones.CONFIG.DESTINATION_DIR, folder)).encode(headphones.SYS_ENCODING,
|
||||
'replace')
|
||||
lossless_destination_path = os.path.normpath(
|
||||
os.path.join(headphones.CONFIG.LOSSLESS_DESTINATION_DIR, folder)).encode(
|
||||
headphones.SYS_ENCODING, 'replace')
|
||||
|
||||
# If they set a destination dir for lossless media, only create the lossy folder if there is lossy media
|
||||
if headphones.CONFIG.LOSSLESS_DESTINATION_DIR:
|
||||
@@ -704,7 +760,9 @@ def moveFiles(albumpath, release, tracks):
|
||||
try:
|
||||
shutil.rmtree(lossless_destination_path)
|
||||
except Exception as e:
|
||||
logger.error("Error deleting existing folder: %s. Creating duplicate folder. Error: %s" % (lossless_destination_path.decode(headphones.SYS_ENCODING, 'replace'), e))
|
||||
logger.error(
|
||||
"Error deleting existing folder: %s. Creating duplicate folder. Error: %s" % (
|
||||
lossless_destination_path.decode(headphones.SYS_ENCODING, 'replace'), e))
|
||||
create_duplicate_folder = True
|
||||
|
||||
if not headphones.CONFIG.REPLACE_EXISTING_FOLDERS or create_duplicate_folder:
|
||||
@@ -713,7 +771,9 @@ def moveFiles(albumpath, release, tracks):
|
||||
i = 1
|
||||
while True:
|
||||
newfolder = temp_folder + '[%i]' % i
|
||||
lossless_destination_path = os.path.normpath(os.path.join(headphones.CONFIG.LOSSLESS_DESTINATION_DIR, newfolder)).encode(headphones.SYS_ENCODING, 'replace')
|
||||
lossless_destination_path = os.path.normpath(
|
||||
os.path.join(headphones.CONFIG.LOSSLESS_DESTINATION_DIR, newfolder)).encode(
|
||||
headphones.SYS_ENCODING, 'replace')
|
||||
if os.path.exists(lossless_destination_path):
|
||||
i += 1
|
||||
else:
|
||||
@@ -724,7 +784,8 @@ def moveFiles(albumpath, release, tracks):
|
||||
try:
|
||||
os.makedirs(lossless_destination_path)
|
||||
except Exception as e:
|
||||
logger.error('Could not create lossless folder for %s. (Error: %s)' % (release['AlbumTitle'], e))
|
||||
logger.error('Could not create lossless folder for %s. (Error: %s)' % (
|
||||
release['AlbumTitle'], e))
|
||||
if not make_lossy_folder:
|
||||
return [albumpath]
|
||||
|
||||
@@ -737,7 +798,9 @@ def moveFiles(albumpath, release, tracks):
|
||||
try:
|
||||
shutil.rmtree(lossy_destination_path)
|
||||
except Exception as e:
|
||||
logger.error("Error deleting existing folder: %s. Creating duplicate folder. Error: %s" % (lossy_destination_path.decode(headphones.SYS_ENCODING, 'replace'), e))
|
||||
logger.error(
|
||||
"Error deleting existing folder: %s. Creating duplicate folder. Error: %s" % (
|
||||
lossy_destination_path.decode(headphones.SYS_ENCODING, 'replace'), e))
|
||||
create_duplicate_folder = True
|
||||
|
||||
if not headphones.CONFIG.REPLACE_EXISTING_FOLDERS or create_duplicate_folder:
|
||||
@@ -746,7 +809,9 @@ def moveFiles(albumpath, release, tracks):
|
||||
i = 1
|
||||
while True:
|
||||
newfolder = temp_folder + '[%i]' % i
|
||||
lossy_destination_path = os.path.normpath(os.path.join(headphones.CONFIG.DESTINATION_DIR, newfolder)).encode(headphones.SYS_ENCODING, 'replace')
|
||||
lossy_destination_path = os.path.normpath(
|
||||
os.path.join(headphones.CONFIG.DESTINATION_DIR, newfolder)).encode(
|
||||
headphones.SYS_ENCODING, 'replace')
|
||||
if os.path.exists(lossy_destination_path):
|
||||
i += 1
|
||||
else:
|
||||
@@ -757,7 +822,8 @@ def moveFiles(albumpath, release, tracks):
|
||||
try:
|
||||
os.makedirs(lossy_destination_path)
|
||||
except Exception as e:
|
||||
logger.error('Could not create folder for %s. Not moving: %s' % (release['AlbumTitle'], e))
|
||||
logger.error(
|
||||
'Could not create folder for %s. Not moving: %s' % (release['AlbumTitle'], e))
|
||||
return [albumpath]
|
||||
|
||||
logger.info('Checking which files we need to move.....')
|
||||
@@ -768,26 +834,34 @@ def moveFiles(albumpath, release, tracks):
|
||||
|
||||
for file_to_move in files_to_move:
|
||||
|
||||
if any(file_to_move.lower().endswith('.' + x.lower()) for x in headphones.LOSSY_MEDIA_FORMATS):
|
||||
if any(file_to_move.lower().endswith('.' + x.lower()) for x in
|
||||
headphones.LOSSY_MEDIA_FORMATS):
|
||||
helpers.smartMove(file_to_move, lossy_destination_path)
|
||||
|
||||
elif any(file_to_move.lower().endswith('.' + x.lower()) for x in headphones.LOSSLESS_MEDIA_FORMATS):
|
||||
elif any(file_to_move.lower().endswith('.' + x.lower()) for x in
|
||||
headphones.LOSSLESS_MEDIA_FORMATS):
|
||||
helpers.smartMove(file_to_move, lossless_destination_path)
|
||||
|
||||
# If it's a non-music file, move it to both dirs
|
||||
# TODO: Move specific-to-lossless files to the lossless dir only
|
||||
else:
|
||||
|
||||
moved_to_lossy_folder = helpers.smartMove(file_to_move, lossy_destination_path, delete=False)
|
||||
moved_to_lossless_folder = helpers.smartMove(file_to_move, lossless_destination_path, delete=False)
|
||||
moved_to_lossy_folder = helpers.smartMove(file_to_move, lossy_destination_path,
|
||||
delete=False)
|
||||
moved_to_lossless_folder = helpers.smartMove(file_to_move,
|
||||
lossless_destination_path,
|
||||
delete=False)
|
||||
|
||||
if moved_to_lossy_folder or moved_to_lossless_folder:
|
||||
try:
|
||||
os.remove(file_to_move)
|
||||
except Exception as e:
|
||||
logger.error("Error deleting file '" + file_to_move.decode(headphones.SYS_ENCODING, 'replace') + "' from source directory")
|
||||
logger.error(
|
||||
"Error deleting file '" + file_to_move.decode(headphones.SYS_ENCODING,
|
||||
'replace') + "' from source directory")
|
||||
else:
|
||||
logger.error("Error copying '" + file_to_move.decode(headphones.SYS_ENCODING, 'replace') + "'. Not deleting from download directory")
|
||||
logger.error("Error copying '" + file_to_move.decode(headphones.SYS_ENCODING,
|
||||
'replace') + "'. Not deleting from download directory")
|
||||
|
||||
elif make_lossless_folder and not make_lossy_folder:
|
||||
|
||||
@@ -817,11 +891,14 @@ def moveFiles(albumpath, release, tracks):
|
||||
|
||||
if headphones.CONFIG.FOLDER_PERMISSIONS_ENABLED:
|
||||
try:
|
||||
os.chmod(os.path.normpath(temp_f).encode(headphones.SYS_ENCODING, 'replace'), int(headphones.CONFIG.FOLDER_PERMISSIONS, 8))
|
||||
os.chmod(os.path.normpath(temp_f).encode(headphones.SYS_ENCODING, 'replace'),
|
||||
int(headphones.CONFIG.FOLDER_PERMISSIONS, 8))
|
||||
except Exception as e:
|
||||
logger.error("Error trying to change permissions on folder: %s. %s", temp_f.decode(headphones.SYS_ENCODING, 'replace'), e)
|
||||
logger.error("Error trying to change permissions on folder: %s. %s",
|
||||
temp_f.decode(headphones.SYS_ENCODING, 'replace'), e)
|
||||
else:
|
||||
logger.debug("Not changing folder permissions, since it is disabled: %s", temp_f.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.debug("Not changing folder permissions, since it is disabled: %s",
|
||||
temp_f.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
|
||||
# If we failed to move all the files out of the directory, this will fail too
|
||||
try:
|
||||
@@ -840,7 +917,6 @@ def moveFiles(albumpath, release, tracks):
|
||||
|
||||
|
||||
def correctMetadata(albumid, release, downloaded_track_list):
|
||||
|
||||
logger.info('Preparing to write metadata to tracks....')
|
||||
lossy_items = []
|
||||
lossless_items = []
|
||||
@@ -850,14 +926,18 @@ def correctMetadata(albumid, release, downloaded_track_list):
|
||||
|
||||
try:
|
||||
|
||||
if any(downloaded_track.lower().endswith('.' + x.lower()) for x in headphones.LOSSLESS_MEDIA_FORMATS):
|
||||
if any(downloaded_track.lower().endswith('.' + x.lower()) for x in
|
||||
headphones.LOSSLESS_MEDIA_FORMATS):
|
||||
lossless_items.append(beets.library.Item.from_path(downloaded_track))
|
||||
elif any(downloaded_track.lower().endswith('.' + x.lower()) for x in headphones.LOSSY_MEDIA_FORMATS):
|
||||
elif any(downloaded_track.lower().endswith('.' + x.lower()) for x in
|
||||
headphones.LOSSY_MEDIA_FORMATS):
|
||||
lossy_items.append(beets.library.Item.from_path(downloaded_track))
|
||||
else:
|
||||
logger.warn("Skipping: %s because it is not a mutagen friendly file format", downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.warn("Skipping: %s because it is not a mutagen friendly file format",
|
||||
downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
except Exception as e:
|
||||
logger.error("Beets couldn't create an Item from: %s - not a media file? %s", downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), str(e))
|
||||
logger.error("Beets couldn't create an Item from: %s - not a media file? %s",
|
||||
downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), str(e))
|
||||
|
||||
for items in [lossy_items, lossless_items]:
|
||||
|
||||
@@ -865,18 +945,24 @@ def correctMetadata(albumid, release, downloaded_track_list):
|
||||
continue
|
||||
|
||||
try:
|
||||
cur_artist, cur_album, candidates, rec = autotag.tag_album(items, search_artist=helpers.latinToAscii(release['ArtistName']), search_album=helpers.latinToAscii(release['AlbumTitle']))
|
||||
cur_artist, cur_album, candidates, rec = autotag.tag_album(items,
|
||||
search_artist=helpers.latinToAscii(
|
||||
release['ArtistName']),
|
||||
search_album=helpers.latinToAscii(
|
||||
release['AlbumTitle']))
|
||||
except Exception as e:
|
||||
logger.error('Error getting recommendation: %s. Not writing metadata', e)
|
||||
return False
|
||||
if str(rec) == 'Recommendation.none':
|
||||
logger.warn('No accurate album match found for %s, %s - not writing metadata', release['ArtistName'], release['AlbumTitle'])
|
||||
logger.warn('No accurate album match found for %s, %s - not writing metadata',
|
||||
release['ArtistName'], release['AlbumTitle'])
|
||||
return False
|
||||
|
||||
if candidates:
|
||||
dist, info, mapping, extra_items, extra_tracks = candidates[0]
|
||||
else:
|
||||
logger.warn('No accurate album match found for %s, %s - not writing metadata', release['ArtistName'], release['AlbumTitle'])
|
||||
logger.warn('No accurate album match found for %s, %s - not writing metadata',
|
||||
release['ArtistName'], release['AlbumTitle'])
|
||||
return False
|
||||
|
||||
logger.info('Beets recommendation for tagging items: %s' % rec)
|
||||
@@ -896,13 +982,16 @@ def correctMetadata(albumid, release, downloaded_track_list):
|
||||
for item in items:
|
||||
try:
|
||||
item.write()
|
||||
logger.info("Successfully applied metadata to: %s", item.path.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.info("Successfully applied metadata to: %s",
|
||||
item.path.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
except Exception as e:
|
||||
logger.warn("Error writing metadata to '%s': %s", item.path.decode(headphones.SYS_ENCODING, 'replace'), str(e))
|
||||
logger.warn("Error writing metadata to '%s': %s",
|
||||
item.path.decode(headphones.SYS_ENCODING, 'replace'), str(e))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def embedLyrics(downloaded_track_list):
|
||||
logger.info('Adding lyrics')
|
||||
|
||||
@@ -916,14 +1005,18 @@ def embedLyrics(downloaded_track_list):
|
||||
for downloaded_track in downloaded_track_list:
|
||||
|
||||
try:
|
||||
if any(downloaded_track.lower().endswith('.' + x.lower()) for x in headphones.LOSSLESS_MEDIA_FORMATS):
|
||||
if any(downloaded_track.lower().endswith('.' + x.lower()) for x in
|
||||
headphones.LOSSLESS_MEDIA_FORMATS):
|
||||
lossless_items.append(beets.library.Item.from_path(downloaded_track))
|
||||
elif any(downloaded_track.lower().endswith('.' + x.lower()) for x in headphones.LOSSY_MEDIA_FORMATS):
|
||||
elif any(downloaded_track.lower().endswith('.' + x.lower()) for x in
|
||||
headphones.LOSSY_MEDIA_FORMATS):
|
||||
lossy_items.append(beets.library.Item.from_path(downloaded_track))
|
||||
else:
|
||||
logger.warn("Skipping: %s because it is not a mutagen friendly file format", downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.warn("Skipping: %s because it is not a mutagen friendly file format",
|
||||
downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
except Exception as e:
|
||||
logger.error("Beets couldn't create an Item from: %s - not a media file? %s", downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), str(e))
|
||||
logger.error("Beets couldn't create an Item from: %s - not a media file? %s",
|
||||
downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), str(e))
|
||||
|
||||
for items in [lossy_items, lossless_items]:
|
||||
|
||||
@@ -963,7 +1056,8 @@ def renameFiles(albumpath, downloaded_track_list, release):
|
||||
try:
|
||||
f = MediaFile(downloaded_track)
|
||||
except:
|
||||
logger.info("MediaFile couldn't parse: %s", downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.info("MediaFile couldn't parse: %s",
|
||||
downloaded_track.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
continue
|
||||
|
||||
if not f.disc:
|
||||
@@ -998,26 +1092,28 @@ def renameFiles(albumpath, downloaded_track_list, release):
|
||||
sortname = artistname
|
||||
|
||||
values = {'$Disc': discnumber,
|
||||
'$Track': tracknumber,
|
||||
'$Title': title,
|
||||
'$Artist': artistname,
|
||||
'$SortArtist': sortname,
|
||||
'$Album': release['AlbumTitle'],
|
||||
'$Year': year,
|
||||
'$disc': discnumber,
|
||||
'$track': tracknumber,
|
||||
'$title': title.lower(),
|
||||
'$artist': artistname.lower(),
|
||||
'$sortartist': sortname.lower(),
|
||||
'$album': release['AlbumTitle'].lower(),
|
||||
'$year': year
|
||||
}
|
||||
'$Track': tracknumber,
|
||||
'$Title': title,
|
||||
'$Artist': artistname,
|
||||
'$SortArtist': sortname,
|
||||
'$Album': release['AlbumTitle'],
|
||||
'$Year': year,
|
||||
'$disc': discnumber,
|
||||
'$track': tracknumber,
|
||||
'$title': title.lower(),
|
||||
'$artist': artistname.lower(),
|
||||
'$sortartist': sortname.lower(),
|
||||
'$album': release['AlbumTitle'].lower(),
|
||||
'$year': year
|
||||
}
|
||||
|
||||
ext = os.path.splitext(downloaded_track)[1]
|
||||
|
||||
new_file_name = helpers.replace_all(headphones.CONFIG.FILE_FORMAT.strip(), values).replace('/', '_') + ext
|
||||
new_file_name = helpers.replace_all(headphones.CONFIG.FILE_FORMAT.strip(),
|
||||
values).replace('/', '_') + ext
|
||||
|
||||
new_file_name = helpers.replace_illegal_chars(new_file_name).encode(headphones.SYS_ENCODING, 'replace')
|
||||
new_file_name = helpers.replace_illegal_chars(new_file_name).encode(headphones.SYS_ENCODING,
|
||||
'replace')
|
||||
|
||||
if headphones.CONFIG.FILE_UNDERSCORES:
|
||||
new_file_name = new_file_name.replace(' ', '_')
|
||||
@@ -1028,19 +1124,22 @@ def renameFiles(albumpath, downloaded_track_list, release):
|
||||
new_file = os.path.join(albumpath, new_file_name)
|
||||
|
||||
if downloaded_track == new_file_name:
|
||||
logger.debug("Renaming for: " + downloaded_track.decode(headphones.SYS_ENCODING, 'replace') + " is not neccessary")
|
||||
logger.debug("Renaming for: " + downloaded_track.decode(headphones.SYS_ENCODING,
|
||||
'replace') + " is not neccessary")
|
||||
continue
|
||||
|
||||
logger.debug('Renaming %s ---> %s', downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), new_file_name.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.debug('Renaming %s ---> %s',
|
||||
downloaded_track.decode(headphones.SYS_ENCODING, 'replace'),
|
||||
new_file_name.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
try:
|
||||
os.rename(downloaded_track, new_file)
|
||||
except Exception as e:
|
||||
logger.error('Error renaming file: %s. Error: %s', downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), e)
|
||||
logger.error('Error renaming file: %s. Error: %s',
|
||||
downloaded_track.decode(headphones.SYS_ENCODING, 'replace'), e)
|
||||
continue
|
||||
|
||||
|
||||
def updateFilePermissions(albumpaths):
|
||||
|
||||
for folder in albumpaths:
|
||||
logger.info("Updating file permissions in %s", folder)
|
||||
for r, d, f in os.walk(folder):
|
||||
@@ -1053,7 +1152,8 @@ def updateFilePermissions(albumpaths):
|
||||
logger.error("Could not change permissions for file: %s", full_path)
|
||||
continue
|
||||
else:
|
||||
logger.debug("Not changing file permissions, since it is disabled: %s", full_path.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
logger.debug("Not changing file permissions, since it is disabled: %s",
|
||||
full_path.decode(headphones.SYS_ENCODING, 'replace'))
|
||||
|
||||
|
||||
def renameUnprocessedFolder(path, tag):
|
||||
@@ -1076,7 +1176,6 @@ def renameUnprocessedFolder(path, tag):
|
||||
|
||||
|
||||
def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None, keep_original_folder=False):
|
||||
|
||||
logger.info('Force checking download folder for completed downloads')
|
||||
|
||||
ignored = 0
|
||||
@@ -1089,9 +1188,11 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None, keep_orig
|
||||
if dir:
|
||||
download_dirs.append(dir.encode(headphones.SYS_ENCODING, 'replace'))
|
||||
if headphones.CONFIG.DOWNLOAD_DIR and not dir:
|
||||
download_dirs.append(headphones.CONFIG.DOWNLOAD_DIR.encode(headphones.SYS_ENCODING, 'replace'))
|
||||
download_dirs.append(
|
||||
headphones.CONFIG.DOWNLOAD_DIR.encode(headphones.SYS_ENCODING, 'replace'))
|
||||
if headphones.CONFIG.DOWNLOAD_TORRENT_DIR and not dir:
|
||||
download_dirs.append(headphones.CONFIG.DOWNLOAD_TORRENT_DIR.encode(headphones.SYS_ENCODING, 'replace'))
|
||||
download_dirs.append(
|
||||
headphones.CONFIG.DOWNLOAD_TORRENT_DIR.encode(headphones.SYS_ENCODING, 'replace'))
|
||||
|
||||
# If DOWNLOAD_DIR and DOWNLOAD_TORRENT_DIR are the same, remove the duplicate to prevent us from trying to process the same folder twice.
|
||||
download_dirs = list(set(download_dirs))
|
||||
@@ -1108,7 +1209,8 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None, keep_orig
|
||||
# Scan for subfolders
|
||||
subfolders = os.listdir(download_dir)
|
||||
ignored += helpers.path_filter_patterns(subfolders,
|
||||
headphones.CONFIG.IGNORED_FOLDERS, root=download_dir)
|
||||
headphones.CONFIG.IGNORED_FOLDERS,
|
||||
root=download_dir)
|
||||
|
||||
for folder in subfolders:
|
||||
path_to_folder = os.path.join(download_dir, folder)
|
||||
@@ -1125,7 +1227,7 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None, keep_orig
|
||||
if folders:
|
||||
logger.debug('Expanded post processing folders: %s', folders)
|
||||
logger.info('Found %d folders to process (%d ignored).',
|
||||
len(folders), ignored)
|
||||
len(folders), ignored)
|
||||
else:
|
||||
logger.info('Found no folders to process. Aborting.')
|
||||
return
|
||||
@@ -1143,15 +1245,23 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None, keep_orig
|
||||
# underscores -> dots (this might be hit or miss since it assumes all
|
||||
# spaces/underscores came from sab replacing values
|
||||
logger.debug('Attempting to find album in the snatched table')
|
||||
snatched = myDB.action('SELECT AlbumID, Title, Kind, Status from snatched WHERE FolderName LIKE ?', [folder_basename]).fetchone()
|
||||
snatched = myDB.action(
|
||||
'SELECT AlbumID, Title, Kind, Status from snatched WHERE FolderName LIKE ?',
|
||||
[folder_basename]).fetchone()
|
||||
|
||||
if snatched:
|
||||
if headphones.CONFIG.KEEP_TORRENT_FILES and snatched['Kind'] == 'torrent' and snatched['Status'] == 'Processed':
|
||||
logger.info('%s is a torrent folder being preserved for seeding and has already been processed. Skipping.', folder_basename)
|
||||
if headphones.CONFIG.KEEP_TORRENT_FILES and snatched['Kind'] == 'torrent' and snatched[
|
||||
'Status'] == 'Processed':
|
||||
logger.info(
|
||||
'%s is a torrent folder being preserved for seeding and has already been processed. Skipping.',
|
||||
folder_basename)
|
||||
continue
|
||||
else:
|
||||
logger.info('Found a match in the database: %s. Verifying to make sure it is the correct album', snatched['Title'])
|
||||
verify(snatched['AlbumID'], folder, snatched['Kind'], keep_original_folder=keep_original_folder)
|
||||
logger.info(
|
||||
'Found a match in the database: %s. Verifying to make sure it is the correct album',
|
||||
snatched['Title'])
|
||||
verify(snatched['AlbumID'], folder, snatched['Kind'],
|
||||
keep_original_folder=keep_original_folder)
|
||||
continue
|
||||
|
||||
# Attempt 2: strip release group id from filename
|
||||
@@ -1165,13 +1275,19 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None, keep_orig
|
||||
|
||||
if rgid:
|
||||
rgid = possible_rgid
|
||||
release = myDB.action('SELECT ArtistName, AlbumTitle, AlbumID from albums WHERE AlbumID=?', [rgid]).fetchone()
|
||||
release = myDB.action(
|
||||
'SELECT ArtistName, AlbumTitle, AlbumID from albums WHERE AlbumID=?',
|
||||
[rgid]).fetchone()
|
||||
if release:
|
||||
logger.info('Found a match in the database: %s - %s. Verifying to make sure it is the correct album', release['ArtistName'], release['AlbumTitle'])
|
||||
verify(release['AlbumID'], folder, forced=True, keep_original_folder=keep_original_folder)
|
||||
logger.info(
|
||||
'Found a match in the database: %s - %s. Verifying to make sure it is the correct album',
|
||||
release['ArtistName'], release['AlbumTitle'])
|
||||
verify(release['AlbumID'], folder, forced=True,
|
||||
keep_original_folder=keep_original_folder)
|
||||
continue
|
||||
else:
|
||||
logger.info('Found a (possibly) valid Musicbrainz release group id in album folder name.')
|
||||
logger.info(
|
||||
'Found a (possibly) valid Musicbrainz release group id in album folder name.')
|
||||
verify(rgid, folder, forced=True)
|
||||
continue
|
||||
|
||||
@@ -1184,13 +1300,18 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None, keep_orig
|
||||
name = album = year = None
|
||||
|
||||
if name and album:
|
||||
release = myDB.action('SELECT AlbumID, ArtistName, AlbumTitle from albums WHERE ArtistName LIKE ? and AlbumTitle LIKE ?', [name, album]).fetchone()
|
||||
release = myDB.action(
|
||||
'SELECT AlbumID, ArtistName, AlbumTitle from albums WHERE ArtistName LIKE ? and AlbumTitle LIKE ?',
|
||||
[name, album]).fetchone()
|
||||
if release:
|
||||
logger.info('Found a match in the database: %s - %s. Verifying to make sure it is the correct album', release['ArtistName'], release['AlbumTitle'])
|
||||
logger.info(
|
||||
'Found a match in the database: %s - %s. Verifying to make sure it is the correct album',
|
||||
release['ArtistName'], release['AlbumTitle'])
|
||||
verify(release['AlbumID'], folder, keep_original_folder=keep_original_folder)
|
||||
continue
|
||||
else:
|
||||
logger.info('Querying MusicBrainz for the release group id for: %s - %s', name, album)
|
||||
logger.info('Querying MusicBrainz for the release group id for: %s - %s', name,
|
||||
album)
|
||||
try:
|
||||
rgid = mb.findAlbumID(helpers.latinToAscii(name), helpers.latinToAscii(album))
|
||||
except:
|
||||
@@ -1219,13 +1340,18 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None, keep_orig
|
||||
name = album = None
|
||||
|
||||
if name and album:
|
||||
release = myDB.action('SELECT AlbumID, ArtistName, AlbumTitle from albums WHERE ArtistName LIKE ? and AlbumTitle LIKE ?', [name, album]).fetchone()
|
||||
release = myDB.action(
|
||||
'SELECT AlbumID, ArtistName, AlbumTitle from albums WHERE ArtistName LIKE ? and AlbumTitle LIKE ?',
|
||||
[name, album]).fetchone()
|
||||
if release:
|
||||
logger.info('Found a match in the database: %s - %s. Verifying to make sure it is the correct album', release['ArtistName'], release['AlbumTitle'])
|
||||
logger.info(
|
||||
'Found a match in the database: %s - %s. Verifying to make sure it is the correct album',
|
||||
release['ArtistName'], release['AlbumTitle'])
|
||||
verify(release['AlbumID'], folder, keep_original_folder=keep_original_folder)
|
||||
continue
|
||||
else:
|
||||
logger.info('Querying MusicBrainz for the release group id for: %s - %s', name, album)
|
||||
logger.info('Querying MusicBrainz for the release group id for: %s - %s', name,
|
||||
album)
|
||||
try:
|
||||
rgid = mb.findAlbumID(helpers.latinToAscii(name), helpers.latinToAscii(album))
|
||||
except:
|
||||
@@ -1243,13 +1369,18 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None, keep_orig
|
||||
logger.debug('Attempt to extract album name by assuming it is the folder name')
|
||||
|
||||
if '-' not in folder_basename:
|
||||
release = myDB.action('SELECT AlbumID, ArtistName, AlbumTitle from albums WHERE AlbumTitle LIKE ?', [folder_basename]).fetchone()
|
||||
release = myDB.action(
|
||||
'SELECT AlbumID, ArtistName, AlbumTitle from albums WHERE AlbumTitle LIKE ?',
|
||||
[folder_basename]).fetchone()
|
||||
if release:
|
||||
logger.info('Found a match in the database: %s - %s. Verifying to make sure it is the correct album', release['ArtistName'], release['AlbumTitle'])
|
||||
logger.info(
|
||||
'Found a match in the database: %s - %s. Verifying to make sure it is the correct album',
|
||||
release['ArtistName'], release['AlbumTitle'])
|
||||
verify(release['AlbumID'], folder, keep_original_folder=keep_original_folder)
|
||||
continue
|
||||
else:
|
||||
logger.info('Querying MusicBrainz for the release group id for: %s', folder_basename)
|
||||
logger.info('Querying MusicBrainz for the release group id for: %s',
|
||||
folder_basename)
|
||||
try:
|
||||
rgid = mb.findAlbumID(album=helpers.latinToAscii(folder_basename))
|
||||
except:
|
||||
@@ -1264,6 +1395,6 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None, keep_orig
|
||||
|
||||
# Fail here
|
||||
logger.info("Couldn't parse '%s' into any valid format. If adding " \
|
||||
"albums from another source, they must be in an 'Artist - Album " \
|
||||
"[Year]' format, or end with the musicbrainz release group id.",
|
||||
folder_basename)
|
||||
"albums from another source, they must be in an 'Artist - Album " \
|
||||
"[Year]' format, or end with the musicbrainz release group id.",
|
||||
folder_basename)
|
||||
|
||||
Reference in New Issue
Block a user