mirror of
https://github.com/rembo10/headphones.git
synced 2026-05-15 08:09:35 +01:00
Merge branch 'torrent-quick-fixes' into develop
This commit is contained in:
@@ -9,26 +9,26 @@ def getXldProfile(xldProfile):
|
||||
xldProfileNotFound = xldProfile
|
||||
expandedPath = os.path.expanduser('~/Library/Preferences/jp.tmkk.XLD.plist')
|
||||
try:
|
||||
preferences = plistlib.Plist.fromFile(expandedPath)
|
||||
preferences = plistlib.Plist.fromFile(expandedPath)
|
||||
except (expat.ExpatError):
|
||||
os.system("/usr/bin/plutil -convert xml1 %s" % expandedPath )
|
||||
try:
|
||||
preferences = plistlib.Plist.fromFile(expandedPath)
|
||||
except (ImportError):
|
||||
os.system("/usr/bin/plutil -convert binary1 %s" % expandedPath )
|
||||
logger.info('The plist at "%s" has a date in it, and therefore is not useable.' % expandedPath)
|
||||
return(xldProfileNotFound, None, None)
|
||||
os.system("/usr/bin/plutil -convert xml1 %s" % expandedPath )
|
||||
try:
|
||||
preferences = plistlib.Plist.fromFile(expandedPath)
|
||||
except (ImportError):
|
||||
os.system("/usr/bin/plutil -convert binary1 %s" % expandedPath )
|
||||
logger.info('The plist at "%s" has a date in it, and therefore is not useable.' % expandedPath)
|
||||
return(xldProfileNotFound, None, None)
|
||||
except (ImportError):
|
||||
logger.info('The plist at "%s" has a date in it, and therefore is not useable.' % expandedPath)
|
||||
logger.info('The plist at "%s" has a date in it, and therefore is not useable.' % expandedPath)
|
||||
except:
|
||||
logger.info('Unexpected error:', sys.exc_info()[0])
|
||||
return(xldProfileNotFound, None, None)
|
||||
logger.info('Unexpected error:', sys.exc_info()[0])
|
||||
return(xldProfileNotFound, None, None)
|
||||
|
||||
xldProfile = xldProfile.lower()
|
||||
profiles = preferences.get('Profiles')
|
||||
|
||||
|
||||
for profile in profiles:
|
||||
|
||||
|
||||
profilename = profile.get('XLDProfileManager_ProfileName')
|
||||
xldProfileForCmd = profilename
|
||||
profilename = profilename.lower()
|
||||
@@ -36,24 +36,24 @@ def getXldProfile(xldProfile):
|
||||
xldBitrate = None
|
||||
|
||||
if profilename == xldProfile:
|
||||
|
||||
|
||||
OutputFormatName = profile.get('OutputFormatName')
|
||||
ShortDesc = profile.get('ShortDesc')
|
||||
|
||||
|
||||
# Determine format and bitrate
|
||||
|
||||
|
||||
if OutputFormatName == 'WAV':
|
||||
xldFormat = 'wav'
|
||||
|
||||
|
||||
elif OutputFormatName == 'AIFF':
|
||||
xldFormat = 'aiff'
|
||||
|
||||
|
||||
elif 'PCM' in OutputFormatName:
|
||||
xldFormat = 'pcm'
|
||||
|
||||
|
||||
elif OutputFormatName == 'Wave64':
|
||||
xldFormat = 'w64'
|
||||
|
||||
|
||||
elif OutputFormatName == 'MPEG-4 AAC':
|
||||
xldFormat = 'm4a'
|
||||
if 'CBR' in ShortDesc or 'ABR' in ShortDesc or 'CVBR' in ShortDesc:
|
||||
@@ -165,7 +165,7 @@ def getXldProfile(xldProfile):
|
||||
elif XLDVorbisOutput_Quality > 8 and XLDVorbisOutput_Quality <= 9:
|
||||
xldBitrate = 320
|
||||
elif XLDVorbisOutput_Quality > 9:
|
||||
xldBitrate = 500
|
||||
xldBitrate = 400
|
||||
|
||||
elif OutputFormatName == 'WavPack':
|
||||
xldFormat = 'wv'
|
||||
@@ -174,8 +174,8 @@ def getXldProfile(xldProfile):
|
||||
|
||||
# Lossless
|
||||
if xldFormat and not xldBitrate:
|
||||
xldBitrate = 500
|
||||
|
||||
xldBitrate = 400
|
||||
|
||||
return(xldProfileForCmd, xldFormat, xldBitrate)
|
||||
|
||||
|
||||
return(xldProfileNotFound, None, None)
|
||||
@@ -18,7 +18,7 @@ import headphones
|
||||
import shutil
|
||||
import time
|
||||
|
||||
from subprocess import call
|
||||
import subprocess
|
||||
from headphones import logger
|
||||
from lib.beets.mediafile import MediaFile
|
||||
|
||||
@@ -28,7 +28,6 @@ except ImportError:
|
||||
import lib.argparse as argparse
|
||||
|
||||
# xld
|
||||
|
||||
if headphones.ENCODER == 'xld':
|
||||
import getXldProfile
|
||||
XLD = True
|
||||
@@ -38,12 +37,11 @@ else:
|
||||
def encode(albumPath):
|
||||
|
||||
# Return if xld details not found
|
||||
|
||||
if XLD:
|
||||
global xldProfile
|
||||
(xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(headphones.XLDPROFILE)
|
||||
if not xldFormat:
|
||||
logger.error(u'Details for xld profile "%s" not found, will not be reencoded' % (xldProfile))
|
||||
logger.error(u'Details for xld profile %s not found, files will not be re-encoded' % (xldProfile))
|
||||
return None
|
||||
|
||||
tempDirEncode=os.path.join(albumPath,"temp")
|
||||
@@ -51,8 +49,6 @@ def encode(albumPath):
|
||||
musicFinalFiles=[]
|
||||
musicTempFiles=[]
|
||||
encoder =""
|
||||
startAlbumTime=time.time()
|
||||
ifencoded=0
|
||||
|
||||
if not os.path.exists(tempDirEncode):
|
||||
os.mkdir(tempDirEncode)
|
||||
@@ -74,12 +70,12 @@ def encode(albumPath):
|
||||
|
||||
if (headphones.ENCODERLOSSLESS):
|
||||
ext = os.path.normpath(os.path.splitext(music)[1].lstrip(".")).lower()
|
||||
if not XLD and ext == 'flac' or XLD and (ext != xldFormat and (xldInfoMusic.bitrate / 1000 > 500)):
|
||||
if not XLD and ext == 'flac' or XLD and (ext != xldFormat and (xldInfoMusic.bitrate / 1000 > 400)):
|
||||
musicFiles.append(os.path.join(r, music))
|
||||
musicTemp = os.path.normpath(os.path.splitext(music)[0] + '.' + encoderFormat)
|
||||
musicTempFiles.append(os.path.join(tempDirEncode, musicTemp))
|
||||
else:
|
||||
logger.debug('Music "%s" is already encoded' % (music))
|
||||
logger.debug('%s is already encoded' % (music))
|
||||
else:
|
||||
musicFiles.append(os.path.join(r, music))
|
||||
musicTemp = os.path.normpath(os.path.splitext(music)[0] + '.' + encoderFormat)
|
||||
@@ -103,108 +99,170 @@ def encode(albumPath):
|
||||
encoder="ffmpeg"
|
||||
|
||||
i=0
|
||||
encoder_failed = False
|
||||
|
||||
for music in musicFiles:
|
||||
infoMusic=MediaFile(music)
|
||||
|
||||
encode = False
|
||||
|
||||
if XLD:
|
||||
if xldBitrate and (infoMusic.bitrate / 1000 <= xldBitrate):
|
||||
logger.info('Music "%s" has bitrate <= "%skbit", will not be reencoded' % (music.decode(headphones.SYS_ENCODING, 'replace'), xldBitrate))
|
||||
logger.info('%s has bitrate <= %skb, will not be re-encoded' % (music.decode(headphones.SYS_ENCODING, 'replace'), xldBitrate))
|
||||
else:
|
||||
command(encoder,music,musicTempFiles[i],albumPath)
|
||||
ifencoded=1
|
||||
encode = True
|
||||
elif headphones.ENCODER == 'lame':
|
||||
if not any(music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.' + x) for x in ["mp3", "wav"]):
|
||||
logger.warn(u'Lame cant encode "%s" format for "%s", use ffmpeg' % (os.path.splitext(music)[1].decode(headphones.SYS_ENCODING, 'replace'),music.decode(headphones.SYS_ENCODING, 'replace')))
|
||||
logger.warn(u'Lame cannot encode %s format for %s, use ffmpeg' % (os.path.splitext(music)[1].decode(headphones.SYS_ENCODING, 'replace'),music.decode(headphones.SYS_ENCODING, 'replace')))
|
||||
else:
|
||||
if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.mp3') and (int(infoMusic.bitrate/1000)<=headphones.BITRATE)):
|
||||
logger.info('Music "%s" has bitrate<="%skbit" will not be reencoded' % (music.decode(headphones.SYS_ENCODING, 'replace'),headphones.BITRATE))
|
||||
if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.mp3') and (int(infoMusic.bitrate / 1000) <= headphones.BITRATE)):
|
||||
logger.info('%s has bitrate <= %skb, will not be re-encoded' % (music.decode(headphones.SYS_ENCODING, 'replace'),headphones.BITRATE))
|
||||
else:
|
||||
command(encoder,music,musicTempFiles[i],albumPath)
|
||||
ifencoded=1
|
||||
encode = True
|
||||
else:
|
||||
if headphones.ENCODEROUTPUTFORMAT=='ogg':
|
||||
if music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.ogg'):
|
||||
logger.warn('Can not reencode .ogg music "%s"' % (music.decode(headphones.SYS_ENCODING, 'replace')))
|
||||
logger.warn('Cannot re-encode .ogg %s' % (music.decode(headphones.SYS_ENCODING, 'replace')))
|
||||
else:
|
||||
command(encoder,music,musicTempFiles[i],albumPath)
|
||||
ifencoded=1
|
||||
encode = True
|
||||
elif (headphones.ENCODEROUTPUTFORMAT=='mp3' or headphones.ENCODEROUTPUTFORMAT=='m4a'):
|
||||
if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.'+headphones.ENCODEROUTPUTFORMAT) and (int(infoMusic.bitrate/1000)<=headphones.BITRATE)):
|
||||
logger.info('Music "%s" has bitrate<="%skbit" will not be reencoded' % (music.decode(headphones.SYS_ENCODING, 'replace'),headphones.BITRATE))
|
||||
if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.'+headphones.ENCODEROUTPUTFORMAT) and (int(infoMusic.bitrate / 1000 ) <= headphones.BITRATE)):
|
||||
logger.info('%s has bitrate <= %skb, will not be re-encoded' % (music.decode(headphones.SYS_ENCODING, 'replace'),headphones.BITRATE))
|
||||
else:
|
||||
command(encoder,music,musicTempFiles[i],albumPath)
|
||||
ifencoded=1
|
||||
encode = True
|
||||
# encode
|
||||
if encode:
|
||||
if not command(encoder,music,musicTempFiles[i],albumPath):
|
||||
encoder_failed = True
|
||||
break
|
||||
else:
|
||||
musicFiles[i] = None
|
||||
musicTempFiles[i] = None
|
||||
|
||||
i=i+1
|
||||
|
||||
|
||||
musicFiles = filter(None, musicFiles)
|
||||
musicTempFiles = filter(None, musicTempFiles)
|
||||
|
||||
# check all files to be encoded now exist in temp directory
|
||||
if not encoder_failed and musicTempFiles:
|
||||
for dest in musicTempFiles:
|
||||
if not os.path.exists(dest):
|
||||
encoder_failed = True
|
||||
logger.error('Encoded file %s does not exist in the destination temp directory' % (dest.decode(headphones.SYS_ENCODING, 'replace')))
|
||||
|
||||
# No errors, move from temp to parent
|
||||
if not encoder_failed and musicTempFiles:
|
||||
i = 0
|
||||
for dest in musicTempFiles:
|
||||
if os.path.exists(dest):
|
||||
source = musicFiles[i]
|
||||
if headphones.DELETE_LOSSLESS_FILES:
|
||||
os.remove(source)
|
||||
check_dest = os.path.join(albumPath, os.path.split(dest)[1])
|
||||
if os.path.exists(check_dest):
|
||||
os.remove(check_dest)
|
||||
try:
|
||||
shutil.move(dest, albumPath)
|
||||
except Exception, e:
|
||||
logger.error('Could not move %s to %s : %s' % (dest.decode(headphones.SYS_ENCODING, 'replace'), albumPath.decode(headphones.SYS_ENCODING, 'replace'), e))
|
||||
encoder_failed = True
|
||||
break
|
||||
i += 1
|
||||
|
||||
# remove temp directory
|
||||
shutil.rmtree(tempDirEncode)
|
||||
time.sleep(1)
|
||||
|
||||
# Return with error if any encoding errors
|
||||
if encoder_failed:
|
||||
logger.error('One or more files failed to encode, check debuglog and ensure you have the latest version of %s installed' % (headphones.ENCODER))
|
||||
return None
|
||||
|
||||
time.sleep(1)
|
||||
for r,d,f in os.walk(albumPath):
|
||||
for music in f:
|
||||
if any(music.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS):
|
||||
musicFinalFiles.append(os.path.join(r, music))
|
||||
|
||||
if ifencoded==0:
|
||||
logger.info('Encoding for folder "%s" is not needed' % (albumPath.decode(headphones.SYS_ENCODING, 'replace')))
|
||||
if not musicTempFiles:
|
||||
logger.info('Encoding for folder %s is not required' % (albumPath.decode(headphones.SYS_ENCODING, 'replace')))
|
||||
|
||||
return musicFinalFiles
|
||||
|
||||
def command(encoder,musicSource,musicDest,albumPath):
|
||||
|
||||
return_code=1
|
||||
cmd=''
|
||||
|
||||
cmd=[]
|
||||
startMusicTime=time.time()
|
||||
|
||||
if XLD:
|
||||
xldDestDir = os.path.split(musicDest)[0]
|
||||
cmd = '"' + encoder + '"'
|
||||
cmd = cmd + ' "' + musicSource + '"'
|
||||
cmd = cmd + ' --profile'
|
||||
cmd = cmd + ' "' + xldProfile + '"'
|
||||
cmd = cmd + ' -o'
|
||||
cmd = cmd + ' "' + xldDestDir + '"'
|
||||
|
||||
cmd = [encoder]
|
||||
cmd.extend([musicSource])
|
||||
cmd.extend(['--profile'])
|
||||
cmd.extend([xldProfile])
|
||||
cmd.extend(['-o'])
|
||||
cmd.extend([xldDestDir])
|
||||
|
||||
elif headphones.ENCODER == 'lame':
|
||||
cmd = [encoder]
|
||||
opts = []
|
||||
if headphones.ADVANCEDENCODER =='':
|
||||
cmd='"' + encoder + '"' + ' -h'
|
||||
opts.extend(['-h'])
|
||||
if headphones.ENCODERVBRCBR=='cbr':
|
||||
cmd=cmd+ ' --resample ' + str(headphones.SAMPLINGFREQUENCY) + ' -b ' + str(headphones.BITRATE)
|
||||
opts.extend(['--resample', str(headphones.SAMPLINGFREQUENCY), '-b', str(headphones.BITRATE)])
|
||||
elif headphones.ENCODERVBRCBR=='vbr':
|
||||
cmd=cmd+' -V'+str(headphones.ENCODERQUALITY)
|
||||
cmd=cmd+ ' ' + headphones.ADVANCEDENCODER
|
||||
opts.extend(['-v', str(headphones.ENCODERQUALITY)])
|
||||
else:
|
||||
cmd=cmd+' '+ headphones.ADVANCEDENCODER
|
||||
cmd=cmd+ ' "' + musicSource + '"'
|
||||
cmd=cmd+ ' "' + musicDest +'"'
|
||||
|
||||
advanced = (headphones.ADVANCEDENCODER.split())
|
||||
for tok in advanced:
|
||||
opts.extend([tok.encode(headphones.SYS_ENCODING)])
|
||||
opts.extend([musicSource])
|
||||
opts.extend([musicDest])
|
||||
cmd.extend(opts)
|
||||
|
||||
elif headphones.ENCODER == 'ffmpeg':
|
||||
cmd='"' + encoder + '"' + ' -i'
|
||||
cmd=cmd+ ' "' + musicSource + '"'
|
||||
cmd = [encoder, '-i', musicSource]
|
||||
opts = []
|
||||
if headphones.ADVANCEDENCODER =='':
|
||||
if headphones.ENCODEROUTPUTFORMAT=='ogg':
|
||||
cmd=cmd+ ' -acodec libvorbis'
|
||||
opts.extend(['-acodec libvorbis'])
|
||||
if headphones.ENCODEROUTPUTFORMAT=='m4a':
|
||||
cmd=cmd+ ' -strict experimental'
|
||||
opts.extend(['-strict experimental'])
|
||||
if headphones.ENCODERVBRCBR=='cbr':
|
||||
cmd=cmd+ ' -ar ' + str(headphones.SAMPLINGFREQUENCY) + ' -ab ' + str(headphones.BITRATE) + 'k'
|
||||
opts.extend(['-ar', str(headphones.SAMPLINGFREQUENCY), '-ab', str(headphones.BITRATE) + 'k'])
|
||||
elif headphones.ENCODERVBRCBR=='vbr':
|
||||
cmd=cmd+' -aq ' + str(headphones.ENCODERQUALITY)
|
||||
cmd=cmd+ ' -y -ac 2 -vn'
|
||||
opts.extend(['-aq', str(headphones.ENCODERQUALITY)])
|
||||
opts.extend(['-y', '-ac', '2', '-vn'])
|
||||
else:
|
||||
cmd=cmd+' '+ headphones.ADVANCEDENCODER
|
||||
cmd=cmd+ ' "' + musicDest + '"'
|
||||
advanced = (headphones.ADVANCEDENCODER.split())
|
||||
for tok in advanced:
|
||||
opts.extend([tok.encode(headphones.SYS_ENCODING)])
|
||||
opts.extend([musicDest])
|
||||
cmd.extend(opts)
|
||||
|
||||
logger.debug(cmd)
|
||||
try:
|
||||
return_code = call(cmd, shell=True)
|
||||
# Encode
|
||||
|
||||
if (return_code==0) and (os.path.exists(musicDest)):
|
||||
if headphones.DELETE_LOSSLESS_FILES:
|
||||
os.remove(musicSource)
|
||||
shutil.move(musicDest,albumPath)
|
||||
logger.info('Music "%s" encoded in %s' % (musicSource,getTimeEncode(startMusicTime)))
|
||||
logger.info('Encoding %s...' % (musicSource.decode(headphones.SYS_ENCODING, 'replace')))
|
||||
logger.debug(subprocess.list2cmdline(cmd))
|
||||
|
||||
except subprocess.CalledProcessError, e:
|
||||
logger.warn('Music "%s" encoding error : %s' % (musicSource, e.output))
|
||||
p = subprocess.Popen(cmd, stdin=open(os.devnull, 'rb'), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
stdout, stderr = p.communicate(headphones.ENCODER)
|
||||
|
||||
# error if return code not zero
|
||||
if p.returncode:
|
||||
logger.error('Encoding failed for %s' % (musicSource.decode(headphones.SYS_ENCODING, 'replace')))
|
||||
out = stdout if stdout else stderr
|
||||
out = out.decode(headphones.SYS_ENCODING, 'replace')
|
||||
outlast2lines = '\n'.join(out.splitlines()[-2:])
|
||||
logger.error('%s error details: %s' % (headphones.ENCODER, outlast2lines))
|
||||
out = out.rstrip("\n")
|
||||
logger.debug(out)
|
||||
encoded = False
|
||||
else:
|
||||
logger.info('%s encoded in %s' % (musicSource.decode(headphones.SYS_ENCODING, 'replace'),getTimeEncode(startMusicTime)))
|
||||
encoded = True
|
||||
|
||||
return encoded
|
||||
|
||||
def getTimeEncode(start):
|
||||
seconds =int(time.time()-start)
|
||||
@@ -213,3 +271,4 @@ def getTimeEncode(start):
|
||||
minutes = seconds / 60
|
||||
seconds -= 60*minutes
|
||||
return "%02d:%02d:%02d" % (hours, minutes, seconds)
|
||||
|
||||
|
||||
@@ -326,7 +326,7 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
|
||||
# Check to see if we're preserving the torrent dir
|
||||
if headphones.KEEP_TORRENT_FILES and Kind=="torrent":
|
||||
new_folder = os.path.join(albumpath, 'headphones-modified').encode(headphones.SYS_ENCODING, 'replace')
|
||||
logger.info("Copying files to 'headphones-modified' subfolder to preserve downleaded files for seeding")
|
||||
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
|
||||
|
||||
@@ -30,6 +30,7 @@ import gzip, base64
|
||||
|
||||
import os, re, time
|
||||
import string
|
||||
import shutil
|
||||
|
||||
import headphones, exceptions
|
||||
from headphones import logger, db, helpers, classes, sab, nzbget
|
||||
@@ -447,7 +448,7 @@ def searchNZB(albumid=None, new=False, losslessOnly=False):
|
||||
# Add a priority if it has any of the preferred words
|
||||
temp_list = []
|
||||
for result in resultlist:
|
||||
if any(word.lower() in result[0].lower() for word in helpers.split_string(headphones.PREFERRED_WORDS)):
|
||||
if headphones.PREFERRED_WORDS and any(word.lower() in result[0].lower() for word in helpers.split_string(headphones.PREFERRED_WORDS)):
|
||||
temp_list.append((result[0],result[1],result[2],result[3],1))
|
||||
else:
|
||||
temp_list.append((result[0],result[1],result[2],result[3],0))
|
||||
@@ -467,7 +468,7 @@ def searchNZB(albumid=None, new=False, losslessOnly=False):
|
||||
|
||||
if not targetsize:
|
||||
logger.info('No track information for %s - %s. Defaulting to highest quality' % (albums[0], albums[1]))
|
||||
nzblist = sorted(resultlist, key=lambda title: (-title[4] , -title[1]))
|
||||
nzblist = sorted(resultlist, key=lambda title: (title[4], int(title[1])), reverse=True)
|
||||
|
||||
else:
|
||||
logger.info('Target size: %s' % helpers.bytes_to_mb(targetsize))
|
||||
@@ -499,25 +500,27 @@ def searchNZB(albumid=None, new=False, losslessOnly=False):
|
||||
logger.info(result[0] + " is too small for this album - not considering it. (Size: " + helpers.bytes_to_mb(result[1]) + ", Minsize: " + helpers.bytes_to_mb(low_size_limit) + ")")
|
||||
continue
|
||||
|
||||
delta = abs(targetsize - result[1])
|
||||
delta = abs(targetsize - int(result[1]))
|
||||
newlist.append((result[0], result[1], result[2], result[3], result[4], delta))
|
||||
|
||||
nzblist = sorted(newlist, key=lambda title: (-title[4], title[5]))
|
||||
|
||||
if not len(nzblist) and len(flac_list) and headphones.PREFERRED_BITRATE_ALLOW_LOSSLESS:
|
||||
logger.info("Since there were no appropriate lossy matches (and at least one lossless match), going to use lossless instead")
|
||||
nzblist = sorted(flac_list, key=lambda title: (-title[4], -title[1]))
|
||||
nzblist = sorted(flac_list, key=lambda title: (title[4], int(title[1])), reverse=True)
|
||||
|
||||
except Exception, e:
|
||||
|
||||
logger.debug('Error: %s' % str(e))
|
||||
logger.info('No track information for %s - %s. Defaulting to highest quality' % (albums[0], albums[1]))
|
||||
|
||||
nzblist = sorted(resultlist, key=lambda title: (-title[4], -title[1]))
|
||||
nzblist = sorted(resultlist, key=lambda title: (title[4], int(title[1])), reverse=True)
|
||||
|
||||
|
||||
else:
|
||||
|
||||
nzblist = sorted(resultlist, key=lambda title: (-title[4], -title[1]))
|
||||
nzblist = sorted(resultlist, key=lambda title: (title[4], int(title[1])), reverse=True)
|
||||
|
||||
|
||||
|
||||
if new:
|
||||
@@ -925,22 +928,19 @@ def searchTorrent(albumid=None, new=False, losslessOnly=False):
|
||||
logger.info(u'Parsing results from <a href="%s">Waffles.fm</a>' % searchURL)
|
||||
|
||||
d = feedparser.parse(data)
|
||||
|
||||
if not len(d.entries):
|
||||
logger.info(u"No results found from %s for %s" % (provider, term))
|
||||
pass
|
||||
|
||||
else:
|
||||
for item in d.entries:
|
||||
try:
|
||||
title_match = re.search(r"(.+)\[(.+)\]$", item.title)
|
||||
title = title_match.group(1).strip()
|
||||
details = title_match.group(2).split("-")
|
||||
|
||||
try:
|
||||
title = item.title
|
||||
desc_match = re.search(r"Size: (\d+)<", item.description)
|
||||
size = desc_match.group(1)
|
||||
|
||||
url = item.link
|
||||
|
||||
resultlist.append((title, size, url, provider))
|
||||
logger.info('Found %s. Size: %s' % (title, helpers.bytes_to_mb(size)))
|
||||
except Exception, e:
|
||||
@@ -1102,9 +1102,11 @@ def searchTorrent(albumid=None, new=False, losslessOnly=False):
|
||||
|
||||
soup = BeautifulSoup(data)
|
||||
table = soup.find('table')
|
||||
rows = table.findAll('tr')
|
||||
rows = None
|
||||
if table:
|
||||
rows = table.findAll('tr')
|
||||
|
||||
if len(rows) == '1':
|
||||
if not rows or len(rows) == '1':
|
||||
logger.info(u"No results found from %s for %s" % (provider, term))
|
||||
pass
|
||||
|
||||
@@ -1282,14 +1284,13 @@ def searchTorrent(albumid=None, new=False, losslessOnly=False):
|
||||
# Add a priority if it has any of the preferred words
|
||||
temp_list = []
|
||||
for result in resultlist:
|
||||
if any(word.lower() in result[0].lower() for word in helpers.split_string(headphones.PREFERRED_WORDS)):
|
||||
if headphones.PREFERRED_WORDS and any(word.lower() in result[0].lower() for word in helpers.split_string(headphones.PREFERRED_WORDS)):
|
||||
temp_list.append((result[0],result[1],result[2],result[3],1))
|
||||
else:
|
||||
temp_list.append((result[0],result[1],result[2],result[3],0))
|
||||
|
||||
resultlist = temp_list
|
||||
print resultlist
|
||||
|
||||
|
||||
if headphones.PREFERRED_QUALITY == 2 and headphones.PREFERRED_BITRATE:
|
||||
|
||||
logger.debug('Target bitrate: %s kbps' % headphones.PREFERRED_BITRATE)
|
||||
@@ -1303,7 +1304,7 @@ def searchTorrent(albumid=None, new=False, losslessOnly=False):
|
||||
|
||||
if not targetsize:
|
||||
logger.info('No track information for %s - %s. Defaulting to highest quality' % (albums[0], albums[1]))
|
||||
torrentlist = sorted(resultlist, key=lambda title: (-title[4] , -title[1]))
|
||||
torrentlist = sorted(resultlist, key=lambda title: (title[4], int(title[1])), reverse=True)
|
||||
|
||||
else:
|
||||
logger.info('Target size: %s' % helpers.bytes_to_mb(targetsize))
|
||||
@@ -1334,27 +1335,25 @@ def searchTorrent(albumid=None, new=False, losslessOnly=False):
|
||||
logger.info(result[0] + " is too small for this album - not considering it. (Size: " + helpers.bytes_to_mb(result[1]) + ", Minsize: " + helpers.bytes_to_mb(low_size_limit) + ")")
|
||||
continue
|
||||
|
||||
delta = abs(targetsize - result[1])
|
||||
delta = abs(targetsize - int(result[1]))
|
||||
newlist.append((result[0], result[1], result[2], result[3], result[4], delta))
|
||||
|
||||
print newlist
|
||||
torrentlist = sorted(newlist, key=lambda title: (-title[4], title[5]))
|
||||
print torrentlist
|
||||
|
||||
if not len(torrentlist) and len(flac_list) and headphones.PREFERRED_BITRATE_ALLOW_LOSSLESS:
|
||||
logger.info("Since there were no appropriate lossy matches (and at least one lossless match), going to use lossless instead")
|
||||
torrentlist = sorted(flac_list, key=lambda title: (-title[4], -title[1]))
|
||||
torrentlist = sorted(flac_list, key=lambda title: (title[4], int(title[1])), reverse=True)
|
||||
|
||||
except Exception, e:
|
||||
|
||||
logger.debug('Error: %s' % str(e))
|
||||
logger.info('No track information for %s - %s. Defaulting to highest quality' % (albums[0], albums[1]))
|
||||
|
||||
torrentlist = sorted(resultlist, key=lambda title: (-title[4], -title[1]))
|
||||
|
||||
torrentlist = sorted(resultlist, key=lambda title: (title[4], int(title[1])), reverse=True)
|
||||
|
||||
else:
|
||||
|
||||
torrentlist = sorted(resultlist, key=lambda title: (-title[4], -title[1]))
|
||||
|
||||
torrentlist = sorted(resultlist, key=lambda title: (title[4], int(title[1])), reverse=True)
|
||||
|
||||
if new:
|
||||
|
||||
@@ -1420,8 +1419,23 @@ def searchTorrent(albumid=None, new=False, losslessOnly=False):
|
||||
|
||||
elif headphones.TORRENT_DOWNLOADER == 1:
|
||||
logger.info("Sending torrent to Transmission")
|
||||
torrentid = transmission.addTorrent(bestqual[2])
|
||||
|
||||
# rutracker needs cookies to be set, pass the .torrent file instead of url
|
||||
if bestqual[3] == 'rutracker.org':
|
||||
file_or_url = rutracker.get_torrent(bestqual[2])
|
||||
else:
|
||||
file_or_url = bestqual[2]
|
||||
|
||||
torrentid = transmission.addTorrent(file_or_url)
|
||||
torrent_folder_name = transmission.getTorrentFolder(torrentid)
|
||||
logger.info('Torrent folder name: %s' % torrent_folder_name)
|
||||
|
||||
# remove temp .torrent file created above
|
||||
if bestqual[3] == 'rutracker.org':
|
||||
try:
|
||||
shutil.rmtree(os.path.split(file_or_url)[0])
|
||||
except Exception, e:
|
||||
logger.warning('Couldn\'t remove temp dir %s' % e)
|
||||
|
||||
myDB.action('UPDATE albums SET status = "Snatched" WHERE AlbumID=?', [albums[2]])
|
||||
myDB.action('INSERT INTO snatched VALUES( ?, ?, ?, ?, DATETIME("NOW", "localtime"), ?, ?, ?)', [albums[2], bestqual[0], bestqual[1], bestqual[2], "Snatched", torrent_folder_name, "torrent"])
|
||||
|
||||
@@ -9,9 +9,11 @@ import urllib2
|
||||
import cookielib
|
||||
from urlparse import urlparse
|
||||
from bs4 import BeautifulSoup
|
||||
import headphones
|
||||
from headphones import logger, db
|
||||
import lib.bencode as bencode
|
||||
import os
|
||||
from tempfile import mkdtemp
|
||||
|
||||
class Rutracker():
|
||||
|
||||
@@ -90,7 +92,7 @@ class Rutracker():
|
||||
|
||||
def search(self, searchurl, maxsize, minseeders, albumid, bitrate):
|
||||
"""
|
||||
Parse the search results and return the first valid torrent
|
||||
Parse the search results and return valid torrent list
|
||||
"""
|
||||
|
||||
titles = []
|
||||
@@ -154,10 +156,11 @@ class Rutracker():
|
||||
logger.info('headphones track info not found, cannot compare to torrent')
|
||||
return False
|
||||
|
||||
# Return the first valid torrent, unless we want a preferred bitrate then we want all valid entries
|
||||
# Return all valid entries, ignored, required words now checked in searcher.py
|
||||
|
||||
unwantedlist = ['promo', 'vinyl', '[lp]', 'songbook', 'tvrip', 'hdtv', 'dvd']
|
||||
formatlist = ['.ape', '.flac', '.ogg', '.m4a', '.aac', '.mp3', '.wav', '.aif']
|
||||
#unwantedlist = ['promo', 'vinyl', '[lp]', 'songbook', 'tvrip', 'hdtv', 'dvd']
|
||||
|
||||
formatlist = ['ape', 'flac', 'ogg', 'm4a', 'aac', 'mp3', 'wav', 'aif']
|
||||
deluxelist = ['deluxe', 'edition', 'japanese', 'exclusive']
|
||||
|
||||
for torrent in torrentlist:
|
||||
@@ -167,11 +170,9 @@ class Rutracker():
|
||||
seeders = torrent[2]
|
||||
size = torrent[3]
|
||||
|
||||
# Attempt to filter out unwanted
|
||||
|
||||
title = returntitle.lower()
|
||||
|
||||
if not any(unwanted in title for unwanted in unwantedlist) and int(size) <= maxsize and int(seeders) >= minseeders:
|
||||
if int(size) <= maxsize and int(seeders) >= minseeders:
|
||||
|
||||
# Check torrent info
|
||||
|
||||
@@ -202,7 +203,7 @@ class Rutracker():
|
||||
for pathfile in metainfo['files']:
|
||||
path = pathfile['path']
|
||||
for file in path:
|
||||
if any(format in file for format in formatlist):
|
||||
if any(file.lower().endswith('.' + x.lower()) for x in formatlist):
|
||||
trackcount += 1
|
||||
if '.cue' in file:
|
||||
cuecount += 1
|
||||
@@ -255,33 +256,42 @@ class Rutracker():
|
||||
if any(deluxe in title for deluxe in deluxelist):
|
||||
valid = True
|
||||
|
||||
# return 1st valid torrent if not checking by bitrate, else add to list and return at end
|
||||
# Add to list
|
||||
|
||||
if valid:
|
||||
rulist.append((returntitle, size, topicurl))
|
||||
if not bitrate:
|
||||
return rulist
|
||||
|
||||
else:
|
||||
if topicurl:
|
||||
logger.info(u'<a href="%s">Torrent</a> found with %s tracks but the selected headphones release has %s tracks, skipping for rutracker.org' % (topicurl, trackcount, hptrackcount))
|
||||
|
||||
else:
|
||||
logger.info('%s is larger than the maxsize or has too little seeders for this category, skipping. (Size: %i bytes, Seeders: %i)' % (returntitle, int(size), int(seeders)))
|
||||
|
||||
|
||||
return rulist
|
||||
|
||||
def get_torrent(self, url, savelocation=None):
|
||||
|
||||
def get_torrent(self, url, savelocation):
|
||||
|
||||
torrent_id = dict([part.split('=') for part in urlparse(url)[4].split('&')])['t']
|
||||
self.cookiejar.set_cookie(cookielib.Cookie(version=0, name='bb_dl', value=torrent_id, port=None, port_specified=False, domain='.rutracker.org', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False))
|
||||
downloadurl = 'http://dl.rutracker.org/forum/dl.php?t=' + torrent_id
|
||||
downloadurl = 'http://dl.rutracker.org/forum/dl.php?t=' + torrent_id
|
||||
torrent_name = torrent_id + '.torrent'
|
||||
download_path = os.path.join(savelocation, torrent_name)
|
||||
|
||||
|
||||
try:
|
||||
prev = os.umask(headphones.UMASK)
|
||||
page = self.opener.open(downloadurl)
|
||||
torrent = page.read()
|
||||
if savelocation:
|
||||
download_path = os.path.join(savelocation, torrent_name)
|
||||
else:
|
||||
tempdir = mkdtemp(suffix='_rutracker_torrents')
|
||||
download_path = os.path.join(tempdir, torrent_name)
|
||||
fp = open (download_path, 'wb')
|
||||
fp.write (torrent)
|
||||
fp.close ()
|
||||
os.umask(prev)
|
||||
except Exception, e:
|
||||
logger.error('Error getting torrent: %s' % e)
|
||||
return False
|
||||
|
||||
logger.error('Error getting torrent: %s' % e)
|
||||
return False
|
||||
|
||||
return download_path
|
||||
|
||||
|
||||
Reference in New Issue
Block a user