Merge branch 'ade' of https://github.com/AdeHub/headphones into AdeHub-ade

This commit is contained in:
Ade
2014-07-08 19:15:25 +12:00
12 changed files with 407 additions and 155 deletions

View File

@@ -89,9 +89,15 @@
<div id="albumImg">
<img height="200" alt="" class="albumArt" src="artwork/album/${album['AlbumID']}">
</div>
<h1><a href="http://musicbrainz.org/release-group/${album['AlbumID']}">${album['AlbumTitle']}</a></h1>
<h2><a href="http://musicbrainz.org/artist/${album['ArtistID']}">${album['ArtistName']}</a></h2>
<h1 id="albumname">
<a href="http://musicbrainz.org/release-group/${album['AlbumID']}" id="albumnamelink">${album['AlbumTitle']}</a>
</h1>
<h2 id="artistname">
<a href="http://musicbrainz.org/artist/${album['ArtistID']}" id="artistnamelink">${album['ArtistName']}</a>
</h2>
<%
totalduration = myDB.action("SELECT SUM(TrackDuration) FROM tracks WHERE AlbumID=?", [album['AlbumID']]).fetchone()[0]
totaltracks = len(myDB.select("SELECT TrackTitle from tracks WHERE AlbumID=?", [album['AlbumID']]))
@@ -275,9 +281,58 @@
feedback.fadeIn();
}
var loadingMessage = false;
var spinner_active = false;
var loadingtext_active = false;
var refreshInterval;
var wasLoading = false;
var x = 0;
function checkAlbumStatus() {
$.getJSON("getAlbumjson?AlbumID=${album['AlbumID']}", function(data) {
if (data['Status'] == "Loading"){
wasLoading = true;
$('#albumnamelink').text(data["AlbumTitle"]);
$('#artistnamelink').text(data["ArtistName"]);
if (loadingMessage == false){
$("#ajaxMsg").after( "<div id='ajaxMsg2' class='ajaxMsg'></div>" );
showArtistMsg("Getting album information");
loadingMessage = true;
}
if (spinner_active == false){
$('#albumname').prepend('<i class="fa fa-refresh fa-spin" id="albumnamespinner"></i>')
spinner_active = true;
}
if (loadingtext_active == false){
$('#albumname').append('<h3 id="loadingtext"><i>(Album information is currently being loaded)</i></h3>')
loadingtext_active = true;
}
}
else{
if (++x === 5) {
clearInterval(refreshInterval);
}
var sts = $("#artistname").text();
if (wasLoading == true || sts == "Loading"){
location.reload();
$('#albumnamespinner').remove()
$('#loadingtext').remove()
$('#ajaxMsg2').remove()
spinner_active = false
loadingtext_active = false
loadingMessage = false
}
}
});
}
$(document).ready(function() {
getAlbumInfo();
initThisPage();
checkAlbumStatus();
refreshInterval = setInterval(function(){
checkAlbumStatus();
}, 3000);
});
</script>

View File

@@ -58,7 +58,7 @@
<form action="search" method="get">
<input type="text" value="" placeholder="Search" onfocus="if(this.value==this.defaultValue) this.value='';" name="name" />
<i class='fa fa-search mini-icon'></i>
<select name="type">
<select name="type" id="search_type">
<option value="artist">Artist</option>
<option value="album">Album</option>
</select>
@@ -115,3 +115,25 @@
<%def name="javascriptIncludes()"></%def>
<%def name="headIncludes()"></%def>
<%def name="headerIncludes()"></%def>
<!--persist search type using local storage-->
<script type="text/javascript">
$(document).ready(function() {
$('form:first *:input[type!=hidden]:first').focus();
try{
var type = window.localStorage.getItem('search_type');
$("#search_type").val(type);
} catch(e) {
}
});
$('select[id=search_type]').change(function() {
var type = $(this).val()
try{
window.localStorage.setItem('search_type', type);
} catch(e) {
}
});
</script>

View File

@@ -758,7 +758,7 @@ div#searchbar input[type=text] {
line-height: normal;
margin-right: 5px;
padding: 4px 5px 4px 25px;
width: 150px;
width: 200px;
}
div#searchbar .mini-icon {
color: #999;
@@ -1126,13 +1126,34 @@ div#artistheader h2 a {
padding: 2px 10px;
}
#searchresults_table th#albumname {
min-width: 225px;
min-width: 250px;
text-align: left;
font-size: 14px;
}
#searchresults_table th#artistname {
min-width: 325px;
text-align: left;
}
#searchresults_table th#artistnamesmall {
min-width: 125px;
text-align: left;
font-size: 14px;
}
#searchresults_table th#reldate {
min-width: 80px;
text-align: center;
font-size: 14px;
}
#searchresults_table th#format {
min-width: 50px;
text-align: left;
font-size: 14px;
}
#searchresults_table th#tracks {
min-width: 50px;
text-align: left;
font-size: 14px;
}
#searchresults_table #artistImg {
background: url("../images/loader_black.gif") no-repeat scroll center center #ffffff;
border: 3px solid #FFFFFF;
@@ -1144,15 +1165,40 @@ div#artistheader h2 a {
width: 50px;
}
#searchresults_table td#albumname {
min-width: 200px;
min-width: 250px;
text-align: left;
vertical-align: middle;
font-size: 14px;
}
#searchresults_table td#artistname {
min-width: 300px;
text-align: left;
vertical-align: middle;
}
#searchresults_table td#artistnamesmall {
min-width: 100px;
text-align: left;
vertical-align: middle;
font-size: 14px;
}
#searchresults_table td#reldate {
min-width: 80px;
text-align: center;
vertical-align: middle;
font-size: 14px;
}
#searchresults_table td#format {
min-width: 50px;
text-align: left;
vertical-align: middle;
font-size: 14px;
}
#searchresults_table td#tracks {
min-width: 50px;
text-align: left;
vertical-align: middle;
font-size: 12px;
}
#searchresults_table td#add {
vertical-align: middle;
}
@@ -1416,6 +1462,11 @@ div#artistheader h3 span {
min-width: 75px;
text-align: center;
}
#searchresults_table th#scoresmall {
min-width: 50px;
text-align: center;
font-size: 14px;
}
#track_table td#bitrate,
#track_table td#format {
font-size: 12px;

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@@ -11,36 +11,49 @@
<th id="albumart"></th>
%if type == 'album':
<th id="albumname">Album Name</th>
<th id="artistnamesmall">Artist Name</th>
<th id="format">Format</th>
<th id="tracks">Tracks</th>
<th id="reldate">Date</th>
<th id="scoresmall">Score</th>
%else:
<th id="artistname">Artist Name</th>
<th id="score">Score</th>
%endif
<th id="artistname">Artist Name</th>
<th id="score">Score</th>
<th id="add"></th>
<th id="mb"></th>
</tr>
</thead>
<tbody>
%if searchresults:
%for result in searchresults:
<%
if result['score'] == 100:
grade = 'A'
else:
grade = 'Z'
%>
%for result in searchresults:
<%
if result['score'] == 100:
grade = 'A'
else:
grade = 'Z'
if type == 'album':
albuminfo = 'Type: ' + result['rgtype'] + ', Country: ' + result['country']
caa_group_url = "http://coverartarchive.org/release-group/%s/front-250.jpg" %result['rgid']
%>
<tr class="grade${grade}">
%if type == 'album':
<td id="albumart"><div id="artistImg"><img title="${result['albumid']}" class="albumArt" height="50" width="50"></div></td>
<td id="albumart" style=" text-align: center; vertical-align: middle;"><div id="artistImg"><img title="${result['albumid']}" class="albumArt" height="50" width="50" onerror="this.src='${caa_group_url}'"></div></td>
%else:
<td id="albumart"><div id="artistImg"><img title="${result['id']}" class="albumArt" height="50" width="50"></div></td>
%endif
%if type == 'album':
<td id="albumname"><a href="${result['albumurl']}">${result['title']}</a></td>
%endif
<td id="artistname"><a href="addArtist?artistid=${result['id']}" title="${result['uniquename']}">${result['uniquename']}</a></td>
<td id="score"><div class="bar"><div class="score" style="width: ${result['score']}px">${result['score']}</div></div></td>
%if type == 'album':
<td id="add"><a href="addReleaseById?rid=${result['albumid']}"><i class="fa fa-plus"></i> Add this album</a></td>
%else:
<td id="add"><a href="${result['url']}"></i> View on MusicBrainz</a></td>
<td id="albumname"><a href="addReleaseById?rid=${result['albumid']}&rgid=${result['rgid']}" title="${albuminfo}">${result['title']}</a></td>
<td id="artistnamesmall"><a href="addArtist?artistid=${result['id']}" title="${result['uniquename']}">${result['uniquename']}</a></td>
<td id="format">${result['formats']}</td>
<td id="tracks">${result['tracks']}</td>
<td id="reldate">${result['date']}</td>
<td id="score"><a href="${result['albumurl']} "title="View on MusicBrainz"><div class="bar"><div class="score" style="width: ${result['score']}px">${result['score']}</div></div></a></td>
<td id="musicbrainz" style=" text-align: center; line-height: 0; vertical-align: middle;"><a href="${result['albumurl']}"><img src="interfaces/default/images/MusicBrainz_Album_Icon.png" title="View on MusicBrainz" height="20" width="20"></a></td>
%else:
<td id="artistname"><a href="addArtist?artistid=${result['id']}" title="${result['uniquename']}">${result['uniquename']}</a></td>
<td id="score"><a href="${result['url']} "title="View on MusicBrainz"><div class="bar"><div class="score" style="width: ${result['score']}px">${result['score']}</div></div></a></td>
<td id="musicbrainz" style=" text-align: center; line-height: 0; vertical-align: middle;"><a href="${result['url']}"><img src="interfaces/default/images/MusicBrainz_Artist_Icon.png" title="View on MusicBrainz" height="20" width="20"></a></td>
%endif
</tr>
%endfor
@@ -75,7 +88,7 @@
{
"bDestroy": true,
"aoColumnDefs": [
{ 'bSortable': false, 'aTargets': [ 0,3 ] }
{ 'bSortable': false, 'aTargets': [ 0 ] }
],
"oLanguage": {
"sLengthMenu":"Show _MENU_ results per page",

View File

@@ -233,15 +233,15 @@ class Cache(object):
return
try:
image_url = data['artist']['image'][-1]['#text']
image_url = data['album']['image'][-1]['#text']
except Exception:
logger.debug('No artist image found')
logger.debug('No album image found on last.fm')
image_url = None
thumb_url = self._get_thumb_url(data)
if not thumb_url:
logger.debug('No artist thumbnail image found')
logger.debug('No album thumbnail image found on last.fm')
return {'artwork' : image_url, 'thumbnail' : thumb_url }

View File

@@ -528,10 +528,23 @@ def finalize_update(artistid, artistname, errors=False):
myDB.upsert("artists", newValueDict, controlValueDict)
def addReleaseById(rid):
def addReleaseById(rid, rgid=None):
myDB = db.DBConnection()
# Create minimum info upfront if added from searchresults
status = ''
if rgid:
dbalbum = myDB.select("SELECT * from albums WHERE AlbumID=?", [rgid])
if not dbalbum:
status = 'Loading'
controlValueDict = {"AlbumID": rgid}
newValueDict = {"AlbumTitle": rgid,
"ArtistName": status,
"Status": status}
myDB.upsert("albums", newValueDict, controlValueDict)
time.sleep(1)
rgid = None
artistid = None
release_dict = None
@@ -547,9 +560,13 @@ def addReleaseById(rid):
release_dict = mb.getRelease(rid)
except Exception, e:
logger.info('Unable to get release information for Release %s: %s', rid, e)
if status == 'Loading':
myDB.action("DELETE FROM albums WHERE AlbumID=?", [rgid])
return
if not release_dict:
logger.info('Unable to get release information for Release %s: no dict', rid)
if status == 'Loading':
myDB.action("DELETE FROM albums WHERE AlbumID=?", [rgid])
return
rgid = release_dict['rgid']
@@ -567,7 +584,6 @@ def addReleaseById(rid):
else:
sortname = release_dict['artist_name']
logger.info(u"Now manually adding: " + release_dict['artist_name'] + " - with status Paused")
controlValueDict = {"ArtistID": release_dict['artist_id']}
newValueDict = {"ArtistName": release_dict['artist_name'],
@@ -583,12 +599,16 @@ def addReleaseById(rid):
elif not artist_exists and not release_dict:
logger.error("Artist does not exist in the database and did not get a valid response from MB. Skipping release.")
if status == 'Loading':
myDB.action("DELETE FROM albums WHERE AlbumID=?", [rgid])
return
if not rg_exists and release_dict: #it should never be the case that we have an rg and not the artist
#but if it is this will fail
if not rg_exists and release_dict or status == 'Loading' and release_dict: #it should never be the case that we have an rg and not the artist
#but if it is this will fail
logger.info(u"Now adding-by-id album (" + release_dict['title'] + ") from id: " + rgid)
controlValueDict = {"AlbumID": rgid}
if status != 'Loading':
status = 'Wanted'
newValueDict = {"ArtistID": release_dict['artist_id'],
"ReleaseID": rgid,
@@ -597,8 +617,9 @@ def addReleaseById(rid):
"AlbumASIN": release_dict['asin'],
"ReleaseDate": release_dict['date'],
"DateAdded": helpers.today(),
"Status": 'Wanted',
"Type": release_dict['rg_type']
"Status": status,
"Type": release_dict['rg_type'],
"ReleaseID": rid
}
myDB.upsert("albums", newValueDict, controlValueDict)
@@ -638,11 +659,19 @@ def addReleaseById(rid):
myDB.upsert("tracks", newValueDict, controlValueDict)
# Reset status
if status == 'Loading':
controlValueDict = {"AlbumID": rgid}
newValueDict = {"Status": "Wanted"}
myDB.upsert("albums", newValueDict, controlValueDict)
#start a search for the album
import searcher
searcher.searchforalbum(rgid, False)
elif not rg_exists and not release_dict:
logger.error("ReleaseGroup does not exist in the database and did not get a valid response from MB. Skipping release.")
if status == 'Loading':
myDB.action("DELETE FROM albums WHERE AlbumID=?", [rgid])
return
else:
logger.info('Release ' + str(rid) + " already exists in the database!")

View File

@@ -23,6 +23,8 @@ from headphones.helpers import multikeysort, replace_all
import lib.musicbrainzngs as musicbrainzngs
from lib.musicbrainzngs import WebServiceError
from lib.simplejson import OrderedDict
mb_lock = threading.Lock()
@@ -117,7 +119,7 @@ def findArtist(name, limit=1):
})
return artistlist
def findRelease(name, limit=1):
def findRelease(name, limit=1, artist=None):
with mb_lock:
releaselist = []
@@ -126,25 +128,62 @@ def findRelease(name, limit=1):
chars = set('!?')
if any((c in chars) for c in name):
name = '"'+name+'"'
# additional artist search
if not artist and ':' in name:
name, artist = name.rsplit(":",1)
try:
releaseResults = musicbrainzngs.search_releases(query=name,limit=limit)['release-list']
releaseResults = musicbrainzngs.search_releases(query=name,limit=limit,artist=artist)['release-list']
except WebServiceError, e: #need to update exceptions
logger.warn('Attempt to query MusicBrainz for "%s" failed: %s' % (name, str(e)))
time.sleep(5)
if not releaseResults:
return False
for result in releaseResults:
releaselist.append({
title = result['title']
if 'disambiguation' in result:
title += ' (' + result['disambiguation'] + ')'
# Get formats and track counts
format_dict = OrderedDict()
formats = ''
tracks = ''
for medium in result['medium-list']:
if 'format' in medium:
format = medium['format']
if format not in format_dict:
format_dict[format] = 0
format_dict[format] += 1
if 'track-count' in medium:
if tracks:
tracks += ' + '
tracks += str(medium['track-count'])
for format, count in format_dict.items():
if formats:
formats += ' + '
if count > 1:
formats += str(count) + 'x'
formats += format
releaselist.append({
'uniquename': unicode(result['artist-credit'][0]['artist']['name']),
'title': unicode(result['title']),
'title': unicode(title),
'id': unicode(result['artist-credit'][0]['artist']['id']),
'albumid': unicode(result['id']),
'url': unicode("http://musicbrainz.org/artist/" + result['artist-credit'][0]['artist']['id']),#probably needs to be changed
'albumurl': unicode("http://musicbrainz.org/release/" + result['id']),#probably needs to be changed
'score': int(result['ext:score'])
})
'score': int(result['ext:score']),
'date': unicode(result['date']) if 'date' in result else '',
'country': unicode(result['country']) if 'country' in result else '',
'formats': unicode(formats),
'tracks': unicode(tracks),
'rgid': unicode(result['release-group']['id']),
'rgtype': unicode(result['release-group']['type']) if 'type' in result['release-group'] else ''
})
return releaselist
def getArtist(artistid, extrasonly=False):

View File

@@ -94,22 +94,24 @@ def do_sorted_search(album, new, losslessOnly, choose_specific_download=False):
TORRENT_PROVIDERS = (headphones.KAT or headphones.PIRATEBAY or headphones.ISOHUNT or headphones.MININOVA or headphones.WAFFLES or headphones.RUTRACKER or headphones.WHATCD)
results = []
myDB = db.DBConnection()
albumlength = myDB.select('SELECT sum(TrackDuration) from tracks WHERE AlbumID=?', [album['AlbumID']])[0][0]
if headphones.PREFER_TORRENTS == 0:
if NZB_PROVIDERS and NZB_DOWNLOADERS:
results = searchNZB(album, new, losslessOnly)
results = searchNZB(album, new, losslessOnly, albumlength)
if not results and TORRENT_PROVIDERS:
results = searchTorrent(album, new, losslessOnly)
results = searchTorrent(album, new, losslessOnly, albumlength)
elif headphones.PREFER_TORRENTS == 1:
if TORRENT_PROVIDERS:
results = searchTorrent(album, new, losslessOnly)
results = searchTorrent(album, new, losslessOnly, albumlength)
if not results and NZB_PROVIDERS and NZB_DOWNLOADERS:
results = searchNZB(album, new, losslessOnly)
results = searchNZB(album, new, losslessOnly, albumlength)
else:
@@ -117,10 +119,10 @@ def do_sorted_search(album, new, losslessOnly, choose_specific_download=False):
torrent_results = None
if NZB_PROVIDERS and NZB_DOWNLOADERS:
nzb_results = searchNZB(album, new, losslessOnly)
nzb_results = searchNZB(album, new, losslessOnly, albumlength)
if TORRENT_PROVIDERS:
torrent_results = searchTorrent(album, new, losslessOnly)
torrent_results = searchTorrent(album, new, losslessOnly, albumlength)
if not nzb_results:
nzb_results = []
@@ -134,7 +136,7 @@ def do_sorted_search(album, new, losslessOnly, choose_specific_download=False):
if choose_specific_download:
return results
sorted_search_results = sort_search_results(results, album, new)
sorted_search_results = sort_search_results(results, album, new, albumlength)
if not sorted_search_results:
return
@@ -145,10 +147,69 @@ def do_sorted_search(album, new, losslessOnly, choose_specific_download=False):
if data and bestqual:
send_to_downloader(data, bestqual, album)
def sort_search_results(resultlist, album, new):
def more_filtering(results, album, albumlength, new):
low_size_limit = None
high_size_limit = None
allow_lossless = False
myDB = db.DBConnection()
# Lossless - ignore results if target size outside bitrate range
if headphones.PREFERRED_QUALITY == 3 and albumlength and (headphones.LOSSLESS_BITRATE_FROM or headphones.LOSSLESS_BITRATE_TO):
if headphones.LOSSLESS_BITRATE_FROM:
low_size_limit = albumlength/1000 * int(headphones.LOSSLESS_BITRATE_FROM) * 128
if headphones.LOSSLESS_BITRATE_TO:
high_size_limit = albumlength/1000 * int(headphones.LOSSLESS_BITRATE_TO) * 128
# Preferred Bitrate - ignore results if target size outside % buffer
elif headphones.PREFERRED_QUALITY == 2 and headphones.PREFERRED_BITRATE:
logger.debug('Target bitrate: %s kbps' % headphones.PREFERRED_BITRATE)
if albumlength:
targetsize = albumlength/1000 * int(headphones.PREFERRED_BITRATE) * 128
logger.info('Target size: %s' % helpers.bytes_to_mb(targetsize))
if headphones.PREFERRED_BITRATE_LOW_BUFFER:
low_size_limit = targetsize - (targetsize * int(headphones.PREFERRED_BITRATE_LOW_BUFFER)/100)
if headphones.PREFERRED_BITRATE_HIGH_BUFFER:
high_size_limit = targetsize + (targetsize * int(headphones.PREFERRED_BITRATE_HIGH_BUFFER)/100)
if headphones.PREFERRED_BITRATE_ALLOW_LOSSLESS:
allow_lossless = True
if low_size_limit or high_size_limit or new:
newlist = []
for result in results:
if low_size_limit and (int(result[1]) < low_size_limit):
logger.info("%s from %s is too small for this album - not considering it. (Size: %s, Minsize: %s)", result[0], result[3], helpers.bytes_to_mb(result[1]), helpers.bytes_to_mb(low_size_limit))
continue
if high_size_limit and (int(result[1]) > high_size_limit):
logger.info("%s from %s is too large for this album - not considering it. (Size: %s, Maxsize: %s)", result[0], result[3], helpers.bytes_to_mb(result[1]), helpers.bytes_to_mb(high_size_limit))
# Keep lossless results if there are no good lossy matches
if not (allow_lossless and 'flac' in result[0].lower()):
continue
if new:
alreadydownloaded = myDB.select('SELECT * from snatched WHERE URL=?', [result[2]])
if len(alreadydownloaded):
logger.info('%s has already been downloaded from %s. Skipping.' % (result[0], result[3]))
continue
newlist.append(result)
results = newlist
return results
def sort_search_results(resultlist, album, new, albumlength):
if new and not len(resultlist):
logger.info('No more results found for: %s - %s' % (album['ArtistName'], album['AlbumTitle']))
return None
# Add a priority if it has any of the preferred words
temp_list = []
preferred_words = None
@@ -170,13 +231,7 @@ def sort_search_results(resultlist, album, new):
if headphones.PREFERRED_QUALITY == 2 and headphones.PREFERRED_BITRATE:
logger.debug('Target bitrate: %s kbps' % headphones.PREFERRED_BITRATE)
tracks = myDB.select('SELECT TrackDuration from tracks WHERE AlbumID=?', [album['AlbumID']])
try:
albumlength = sum([pair[0] for pair in tracks])
targetsize = albumlength/1000 * int(headphones.PREFERRED_BITRATE) * 128
if not targetsize:
@@ -184,33 +239,14 @@ def sort_search_results(resultlist, album, new):
finallist = sorted(resultlist, key=lambda title: (title[5], int(title[1])), reverse=True)
else:
logger.info('Target size: %s' % helpers.bytes_to_mb(targetsize))
newlist = []
flac_list = []
if headphones.PREFERRED_BITRATE_HIGH_BUFFER:
high_size_limit = targetsize * int(headphones.PREFERRED_BITRATE_HIGH_BUFFER)/100
else:
high_size_limit = None
if headphones.PREFERRED_BITRATE_LOW_BUFFER:
low_size_limit = targetsize * int(headphones.PREFERRED_BITRATE_LOW_BUFFER)/100
else:
low_size_limit = None
for result in resultlist:
if high_size_limit and (int(result[1]) > high_size_limit):
logger.info("%s is too large for this album - not considering it. (Size: %s, Maxsize: %s)", result[0], helpers.bytes_to_mb(result[1]), helpers.bytes_to_mb(high_size_limit))
# Add lossless nzbs to the "flac list" which we can use if there are no good lossy matches
if 'flac' in result[0].lower():
flac_list.append((result[0], result[1], result[2], result[3], result[4], result[5]))
continue
if low_size_limit and (int(result[1]) < low_size_limit):
logger.info("%s is too small for this album - not considering it. (Size: %s, Minsize: %s)", result[0], helpers.bytes_to_mb(result[1]), helpers.bytes_to_mb(low_size_limit))
# Add lossless results to the "flac list" which we can use if there are no good lossy matches
if 'flac' in result[0].lower():
flac_list.append((result[0], result[1], result[2], result[3], result[4], result[5]))
continue
delta = abs(targetsize - int(result[1]))
@@ -227,56 +263,10 @@ def sort_search_results(resultlist, album, new):
finallist = sorted(resultlist, key=lambda title: (title[5], int(title[1])), reverse=True)
# lossless - ignore results if target size outside bitrate range
elif headphones.PREFERRED_QUALITY == 3 and (headphones.LOSSLESS_BITRATE_FROM or headphones.LOSSLESS_BITRATE_TO):
finallist = []
tracks = myDB.select('SELECT TrackDuration from tracks WHERE AlbumID=?', [album['AlbumID']])
if len(tracks):
albumlength = sum([pair[0] for pair in tracks])
mintargetsize = 0
maxtargetsize = 0
if headphones.LOSSLESS_BITRATE_FROM:
mintargetsize = albumlength/1000 * int(headphones.LOSSLESS_BITRATE_FROM) * 128
if headphones.LOSSLESS_BITRATE_TO:
maxtargetsize = albumlength/1000 * int(headphones.LOSSLESS_BITRATE_TO) * 128
if mintargetsize > 0 or maxtargetsize > 0:
for i, result in reversed(list(enumerate(resultlist))):
if int(result[1]) < mintargetsize and mintargetsize > 0 or int(result[1]) > maxtargetsize and maxtargetsize > 0:
if int(result[1]) < mintargetsize:
logger.info("%s is too small for this album - not considering it. (Size: %s, Minsize: %s)", result[0], helpers.bytes_to_mb(result[1]), helpers.bytes_to_mb(mintargetsize))
else:
logger.info("%s is too large for this album - not considering it. (Size: %s, Maxsize: %s)", result[0], helpers.bytes_to_mb(result[1]), helpers.bytes_to_mb(maxtargetsize))
del resultlist[i]
if len (resultlist):
finallist = sorted(resultlist, key=lambda title: (title[5], int(title[1])), reverse=True)
else:
finallist = sorted(resultlist, key=lambda title: (title[5], int(title[1])), reverse=True)
if new:
while True:
if len(finallist):
alreadydownloaded = myDB.select('SELECT * from snatched WHERE URL=?', [finallist[0][2]])
if len(alreadydownloaded):
logger.info('%s has already been downloaded. Skipping.' % finallist[0][0])
finallist.pop(0)
else:
break
else:
logger.info('No more results found for: %s - %s' % (album['ArtistName'], album['AlbumTitle']))
return None
if not len(finallist):
logger.info('No appropriate matches found for %s - %s', album['ArtistName'], album['AlbumTitle'])
return None
@@ -292,7 +282,7 @@ def get_year_from_release_date(release_date):
return year
def searchNZB(album, new=False, losslessOnly=False):
def searchNZB(album, new=False, losslessOnly=False, albumlength=None):
albumid = album['AlbumID']
reldate = album['ReleaseDate']
@@ -322,6 +312,12 @@ def searchNZB(album, new=False, losslessOnly=False):
term = re.sub('[\.\-\/]', ' ', term).encode('utf-8')
artistterm = re.sub('[\.\-\/]', ' ', cleanartist).encode('utf-8')
# If Preferred Bitrate and High Limit and Allow Lossless then get both lossy and lossless
if headphones.PREFERRED_QUALITY == 2 and headphones.PREFERRED_BITRATE and headphones.PREFERRED_BITRATE_HIGH_BUFFER and headphones.PREFERRED_BITRATE_ALLOW_LOSSLESS:
allow_lossless = True
else:
allow_lossless = False
logger.debug("Using search term: %s" % term)
resultlist = []
@@ -331,7 +327,7 @@ def searchNZB(album, new=False, losslessOnly=False):
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
categories = "3040"
elif headphones.PREFERRED_QUALITY:
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
categories = "3040,3010"
else:
categories = "3010"
@@ -389,7 +385,7 @@ def searchNZB(album, new=False, losslessOnly=False):
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
categories = "3040"
elif headphones.PREFERRED_QUALITY:
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
categories = "3040,3010"
else:
categories = "3010"
@@ -451,7 +447,7 @@ def searchNZB(album, new=False, losslessOnly=False):
provider = "nzbsorg"
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
categories = "3040"
elif headphones.PREFERRED_QUALITY:
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
categories = "3040,3010"
else:
categories = "3010"
@@ -500,7 +496,7 @@ def searchNZB(album, new=False, losslessOnly=False):
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
sub = "16"
elif headphones.PREFERRED_QUALITY:
elif headphones.PREFERRED_QUALITY ==1 or allow_lossless:
sub = ""
else:
sub = "15"
@@ -551,7 +547,7 @@ def searchNZB(album, new=False, losslessOnly=False):
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
categories = "22"
elif headphones.PREFERRED_QUALITY:
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
categories = "22,7"
else:
categories = "7"
@@ -599,7 +595,13 @@ def searchNZB(album, new=False, losslessOnly=False):
#
# Also will filter flac & remix albums if not specifically looking for it
# This code also checks the ignored words and required words
return [result for result in resultlist if verifyresult(result[0], artistterm, term, losslessOnly)]
results = [result for result in resultlist if verifyresult(result[0], artistterm, term, losslessOnly)]
# Additional filtering for size etc
if results:
results = more_filtering(results, album, albumlength, new)
return results
def send_to_downloader(data, bestqual, album):
@@ -921,7 +923,7 @@ def getresultNZB(result):
return nzb
def searchTorrent(album, new=False, losslessOnly=False):
def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
global gazelle # persistent what.cd api object to reduce number of login attempts
# rutracker login
@@ -973,6 +975,12 @@ def searchTorrent(album, new=False, losslessOnly=False):
artistterm = re.sub('[\.\-\/]', ' ', cleanartist).encode('utf-8', 'replace')
albumterm = re.sub('[\.\-\/]', ' ', cleanalbum).encode('utf-8', 'replace')
# If Preferred Bitrate and High Limit and Allow Lossless then get both lossy and lossless
if headphones.PREFERRED_QUALITY == 2 and headphones.PREFERRED_BITRATE and headphones.PREFERRED_BITRATE_HIGH_BUFFER and headphones.PREFERRED_BITRATE_ALLOW_LOSSLESS:
allow_lossless = True
else:
allow_lossless = False
logger.debug("Using search term: %s" % term)
resultlist = []
@@ -986,7 +994,7 @@ def searchTorrent(album, new=False, losslessOnly=False):
categories = "7" #music
format = "2" #flac
maxsize = 10000000000
elif headphones.PREFERRED_QUALITY:
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
categories = "7" #music
format = "10" #mp3+flac
maxsize = 10000000000
@@ -1044,7 +1052,7 @@ def searchTorrent(album, new=False, losslessOnly=False):
format = "FLAC"
bitrate = "(Lossless)"
maxsize = 10000000000
elif headphones.PREFERRED_QUALITY:
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
format = "FLAC OR MP3"
maxsize = 10000000000
else:
@@ -1101,33 +1109,26 @@ def searchTorrent(album, new=False, losslessOnly=False):
logger.error(u"An error occurred while trying to parse the response from Waffles.fm: %s" % e)
# rutracker.org
if headphones.RUTRACKER and rulogin:
provider = "rutracker.org"
# Ignore if release date not specified, results too unpredictable
if not year and not usersearchterm:
logger.info(u'Release date not specified, ignoring for rutracker.org')
else:
bitrate = False
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
format = 'lossless'
maxsize = 10000000000
elif headphones.PREFERRED_QUALITY == 1:
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
format = 'lossless+mp3'
maxsize = 10000000000
else:
format = 'mp3'
maxsize = 300000000
if headphones.PREFERRED_QUALITY == 2 and headphones.PREFERRED_BITRATE:
bitrate = True
# build search url based on above
if not usersearchterm:
searchURL = rutracker.searchurl(artistterm, albumterm, year, format)
else:
@@ -1136,11 +1137,9 @@ def searchTorrent(album, new=False, losslessOnly=False):
logger.info(u'Parsing results from <a href="%s">rutracker.org</a>' % searchURL)
# parse results and get best match
rulist = rutracker.search(searchURL, maxsize, minimumseeders, albumid, bitrate)
rulist = rutracker.search(searchURL, maxsize, minimumseeders, albumid)
# add best match to overall results list
if rulist:
for ru in rulist:
title = ru[0].decode('utf-8')
@@ -1171,7 +1170,7 @@ def searchTorrent(album, new=False, losslessOnly=False):
if bitrate_string not in gazelleencoding.ALL_ENCODINGS:
logger.info(u"Your preferred bitrate is not one of the available What.cd filters, so not using it as a search parameter.")
maxsize = 10000000000
elif headphones.PREFERRED_QUALITY == 1: # Highest quality including lossless
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless: # Highest quality including lossless
search_formats = [gazelleformat.FLAC, gazelleformat.MP3]
maxsize = 10000000000
else: # Highest quality excluding lossless
@@ -1250,7 +1249,7 @@ def searchTorrent(album, new=False, losslessOnly=False):
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
category = '104' #flac
maxsize = 10000000000
elif headphones.PREFERRED_QUALITY:
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
category = '100' #audio cat
maxsize = 10000000000
else:
@@ -1317,7 +1316,7 @@ def searchTorrent(album, new=False, losslessOnly=False):
categories = "7" #music
format = "2" #flac
maxsize = 10000000000
elif headphones.PREFERRED_QUALITY:
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
categories = "7" #music
format = "10" #mp3+flac
maxsize = 10000000000
@@ -1383,7 +1382,7 @@ def searchTorrent(album, new=False, losslessOnly=False):
categories = "7" #music
format = "2" #flac
maxsize = 10000000000
elif headphones.PREFERRED_QUALITY:
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
categories = "7" #music
format = "10" #mp3+flac
maxsize = 10000000000
@@ -1433,7 +1432,13 @@ def searchTorrent(album, new=False, losslessOnly=False):
#attempt to verify that this isn't a substring result
#when looking for "Foo - Foo" we don't want "Foobar"
#this should be less of an issue when it isn't a self-titled album so we'll only check vs artist
return [result for result in resultlist if verifyresult(result[0], artistterm, term, losslessOnly)]
results = [result for result in resultlist if verifyresult(result[0], artistterm, term, losslessOnly)]
# Additional filtering for size etc
if results:
results = more_filtering(results, album, albumlength, new)
return results
# THIS IS KIND OF A MESS AND PROBABLY NEEDS TO BE CLEANED UP
def preprocess(resultlist):

View File

@@ -88,7 +88,7 @@ class Rutracker():
return searchurl
def search(self, searchurl, maxsize, minseeders, albumid, bitrate):
def search(self, searchurl, maxsize, minseeders, albumid):
"""
Parse the search results and return valid torrent list
"""

View File

@@ -110,6 +110,19 @@ class WebInterface(object):
album = myDB.action('SELECT * from albums WHERE AlbumID=?', [AlbumID]).fetchone()
tracks = myDB.select('SELECT * from tracks WHERE AlbumID=? ORDER BY CAST(TrackNumber AS INTEGER)', [AlbumID])
description = myDB.action('SELECT * from descriptions WHERE ReleaseGroupID=?', [AlbumID]).fetchone()
retry = 0
while retry < 5:
if not album:
time.sleep(1)
album = myDB.action('SELECT * from albums WHERE AlbumID=?', [AlbumID]).fetchone()
retry += 1
else:
break
if not album:
raise cherrypy.HTTPRedirect("home")
if not album['ArtistName']:
title = ' - '
else:
@@ -872,6 +885,17 @@ class WebInterface(object):
return artist_json
getArtistjson.exposed=True
def getAlbumjson(self, AlbumID, **kwargs):
myDB = db.DBConnection()
album = myDB.action('SELECT * from albums WHERE AlbumID=?', [AlbumID]).fetchone()
album_json = json.dumps({
'AlbumTitle': album['AlbumTitle'],
'ArtistName': album['ArtistName'],
'Status': album['Status']
})
return album_json
getAlbumjson.exposed=True
def clearhistory(self, type=None, date_added=None, title=None):
myDB = db.DBConnection()
if type:
@@ -1403,9 +1427,12 @@ class WebInterface(object):
return page
extras.exposed = True
def addReleaseById(self, rid):
threading.Thread(target=importer.addReleaseById, args=[rid]).start()
raise cherrypy.HTTPRedirect("home")
def addReleaseById(self, rid, rgid=None):
threading.Thread(target=importer.addReleaseById, args=[rid, rgid]).start()
if rgid:
raise cherrypy.HTTPRedirect("albumPage?AlbumID=%s" % rgid)
else:
raise cherrypy.HTTPRedirect("home")
addReleaseById.exposed = True
def updateCloud(self):
@@ -1458,6 +1485,17 @@ class WebInterface(object):
from headphones import cache
image_dict = cache.getImageLinks(ArtistID, AlbumID)
# Return the Cover Art Archive urls if not found on last.fm
if AlbumID and not image_dict:
image_url = "http://coverartarchive.org/release/%s/front-500.jpg" % AlbumID
thumb_url = "http://coverartarchive.org/release/%s/front-250.jpg" % AlbumID
image_dict = {'artwork' : image_url, 'thumbnail' : thumb_url}
elif AlbumID and (not image_dict['artwork'] or not image_dict['thumbnail']):
if not image_dict['artwork']:
image_dict['artwork'] = "http://coverartarchive.org/release/%s/front-500.jpg" % AlbumID
if not image_dict['thumbnail']:
image_dict['thumbnail'] = "http://coverartarchive.org/release/%s/front-250.jpg" % AlbumID
return simplejson.dumps(image_dict)
getImageLinks.exposed = True