From d79dc8f1ab55bbd0af0a3d9ade18675391d518e0 Mon Sep 17 00:00:00 2001 From: rembo10 Date: Fri, 4 Apr 2014 18:11:20 -0700 Subject: [PATCH 1/2] Most work done to get the ability to choose which release you want --- data/interfaces/default/album.html | 47 +++++++++++++++++++++++++-- data/interfaces/default/css/style.css | 25 ++++++++++++-- headphones/searcher.py | 23 ++++++++++--- headphones/webserve.py | 35 ++++++++++++++++++++ 4 files changed, 121 insertions(+), 9 deletions(-) diff --git a/data/interfaces/default/album.html b/data/interfaces/default/album.html index 008dac4e..e1c5ba8e 100644 --- a/data/interfaces/default/album.html +++ b/data/interfaces/default/album.html @@ -5,8 +5,13 @@ %> <%def name="headerIncludes()"> +
+
+ Delete Album %if album['Status'] == 'Skipped': Mark Album as Wanted @@ -59,9 +64,23 @@
+ Choose Specific Download +
- « Back to ${album['ArtistName']} <%def name="body()"> @@ -197,8 +216,32 @@ "bInfo": false, "bPaginate": false, "bDestroy": true - }); + }); }; + + function getAvailableDownloads() { + $.getJSON("choose_specific_download?AlbumID=${album['AlbumID']}", function(data) { + for( var i = 0, len = data.length; i < len; i++ ) { + $('#downloads_table_body').append(''+data[i].title+''+(data[i].size / (1024*1024)).toFixed(2)+' MB'+data[i].provider+''+data[i].kind+''); + } + $('#downloads_table').dataTable({ + "aoColumns": [ + null, + { "sType": "title-numeric"}, + null, + null + ], + "aaSorting": [], + "bFilter": false, + "bInfo": false, + "bPaginate": false, + "bDestroy": true + }); + $("#choose_specific_download_dialog").dialog({ width: "1000px" }); + return false; + }); + } + $(document).ready(function() { getAlbumInfo(); diff --git a/data/interfaces/default/css/style.css b/data/interfaces/default/css/style.css index 6a5abe23..1c77c778 100644 --- a/data/interfaces/default/css/style.css +++ b/data/interfaces/default/css/style.css @@ -691,7 +691,7 @@ footer { } #subhead #subhead_container #subhead_menu { float: right; - margin-top: 5px; + margin-top: 0px; position: relative; z-index: 99; } @@ -716,6 +716,11 @@ footer { color: #FFF; border-color: #518CC6 #518CC6 #2A65A0; } +#subhead #subhead_container #back_to_previous_link { + margin-top: 20px; + position: relative; + z-index: 99; +} div#searchbar { border-left: 1px solid #FAFAFA; -moz-box-shadow: -1px 0 0 #e0e0e0; @@ -772,7 +777,7 @@ div#searchbar .mini-icon { _height: 302px; background-color: #FFF; clear: both; - margin: 30px auto 0; + margin: 60px auto 0; min-height: 100px; position: relative; width: 100%; @@ -1054,6 +1059,22 @@ div#artistheader h2 a { text-align: center; vertical-align: middle; } +#downloads_table th#title { + text-align: center; + min-width: 500px; +} +#downloads_table th#size { + text-align: center; + min-width: 80px; +} +#downloads_table th#provider { + text-align: center; + min-width: 100px; +} +#downloads_table th#kind { + text-align: center; + min-width: 80px; +} #history_table { background-color: #FFF; font-size: 13px; diff --git a/headphones/searcher.py b/headphones/searcher.py index 16f46c00..de680155 100644 --- a/headphones/searcher.py +++ b/headphones/searcher.py @@ -108,7 +108,7 @@ def patch_http_response_read(func): httplib.HTTPResponse.read = patch_http_response_read(httplib.HTTPResponse.read) -def searchforalbum(albumid=None, new=False, losslessOnly=False): +def searchforalbum(albumid=None, new=False, losslessOnly=False, choose_specific_download=False): myDB = db.DBConnection() @@ -127,17 +127,25 @@ def searchforalbum(albumid=None, new=False, losslessOnly=False): if album['Status'] == "Wanted Lossless": losslessOnly = True + logger.info('Searching for "%s - %s" since it is marked as wanted' % (album['ArtistName'], album['AlbumTitle'])) do_sorted_search(album, new, losslessOnly) + elif albumid and choose_specific_download: + + album = myDB.action('SELECT * from albums WHERE AlbumID=?', [albumid]).fetchone() + logger.info('Searching for "%s - %s"' % (album['ArtistName'], album['AlbumTitle'])) + results = do_sorted_search(album, new, losslessOnly, choose_specific_download=True) + return results + else: album = myDB.action('SELECT * from albums WHERE AlbumID=?', [albumid]).fetchone() - logger.info('Searching for %s' % album['AlbumTitle']) + logger.info('Searching for "%s - %s" since it was marked as wanted' % (album['ArtistName'], album['AlbumTitle'])) do_sorted_search(album, new, losslessOnly) logger.info('Search for Wanted albums complete') -def do_sorted_search(album, new, losslessOnly): +def do_sorted_search(album, new, losslessOnly, choose_specific_download): NZB_PROVIDERS = (headphones.HEADPHONES_INDEXER or headphones.NEWZNAB or headphones.NZBSORG or headphones.NZBSRUS or headphones.OMGWTFNZBS) NZB_DOWNLOADERS = (headphones.SAB_HOST or headphones.BLACKHOLE_DIR or headphones.NZBGET_HOST) @@ -179,6 +187,10 @@ def do_sorted_search(album, new, losslessOnly): torrent_results = [] results = nzb_results + torrent_results + + + if choose_specific_download: + return results sorted_search_results = sort_search_results(results, album, new) @@ -331,7 +343,7 @@ def searchNZB(album, new=False, losslessOnly=False): term = re.sub('[\.\-\/]', ' ', term).encode('utf-8') artistterm = re.sub('[\.\-\/]', ' ', cleanartist).encode('utf-8') - logger.info("Searching for %s since it was marked as wanted" % term) + logger.debug("Using search term: %s" % term) resultlist = [] @@ -912,7 +924,7 @@ def searchTorrent(album, new=False, losslessOnly=False): artistterm = re.sub('[\.\-\/]', ' ', cleanartist).encode('utf-8', 'replace') albumterm = re.sub('[\.\-\/]', ' ', cleanalbum).encode('utf-8', 'replace') - logger.info("Searching torrents for %s since it was marked as wanted" % term) + logger.debug("Using search term: %s" % term) resultlist = [] pre_sorted_results = False @@ -1408,6 +1420,7 @@ def searchTorrent(album, new=False, losslessOnly=False): # THIS IS KIND OF A MESS AND PROBABLY NEEDS TO BE CLEANED UP def preprocess(resultlist): + for result in resultlist: if result[4] == 'torrent': diff --git a/headphones/webserve.py b/headphones/webserve.py index 4f4da10b..3411fce1 100644 --- a/headphones/webserve.py +++ b/headphones/webserve.py @@ -304,6 +304,41 @@ class WebInterface(object): raise cherrypy.HTTPRedirect(redirect) queueAlbum.exposed = True + def choose_specific_download(self, AlbumID): + results = searcher.searchforalbum(AlbumID, choose_specific_download=True) + + results_as_dicts = [] + + for result in results: + + result_dict = { + 'title':result[0], + 'size':result[1], + 'url':result[2], + 'provider':result[3], + 'kind':result[4] + } + results_as_dicts.append(result_dict) + + s = simplejson.dumps(results_as_dicts) + cherrypy.response.headers['Content-type'] = 'application/json' + return s + + choose_specific_download.exposed = True + + def download_specific_release(self, AlbumID, title, size, url, provider, kind): + + result = [(title,int(size),url,provider,kind)] + logger.info(u"Making sure we can download the chosen result") + (data, bestqual) = searcher.preprocess(result) + + if data and bestqual: + myDB = db.DBConnection() + album = myDB.action('SELECT * from albums WHERE AlbumID=?', [AlbumID]).fetchone() + searcher.send_to_downloader(data, bestqual, album) + + download_specific_release.exposed = True + def unqueueAlbum(self, AlbumID, ArtistID): logger.info(u"Marking album: " + AlbumID + "as skipped...") myDB = db.DBConnection() From 91b596fb0f2796215e5085265080141dc2246761 Mon Sep 17 00:00:00 2001 From: rembo10 Date: Fri, 4 Apr 2014 21:06:07 -0700 Subject: [PATCH 2/2] Some bug fixes and styling changes --- data/interfaces/default/album.html | 40 +++++++++++++++++++++++++++--- headphones/searcher.py | 2 +- headphones/webserve.py | 13 ++++++++-- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/data/interfaces/default/album.html b/data/interfaces/default/album.html index e1c5ba8e..98dc51ba 100644 --- a/data/interfaces/default/album.html +++ b/data/interfaces/default/album.html @@ -108,7 +108,6 @@
  • Duration: ${albumduration}
  • -
    @@ -220,9 +219,13 @@ }; function getAvailableDownloads() { + ShowSpinner(); $.getJSON("choose_specific_download?AlbumID=${album['AlbumID']}", function(data) { + loader.remove(); + feedback.fadeOut(); + search_results = data for( var i = 0, len = data.length; i < len; i++ ) { - $('#downloads_table_body').append(''); + $('#downloads_table_body').append(''); } $('#downloads_table').dataTable({ "aoColumns": [ @@ -235,14 +238,43 @@ "bFilter": false, "bInfo": false, "bPaginate": false, - "bDestroy": true }); $("#choose_specific_download_dialog").dialog({ width: "1000px" }); return false; }); } - + function downloadSpecificRelease(i){ + + title = search_results[i].title + size = search_results[i].size + url = search_results[i].url + provider = search_results[i].provider + kind = search_results[i].kind + + ShowSpinner(); + $.getJSON("download_specific_release?AlbumID=${album['AlbumID']}&title="+title+"&size="+size+"&url="+url+"&provider="+provider+"&kind=" + kind, function(data) { + loader.remove(); + feedback.fadeOut(); + refreshSubmenu(); + $("#choose_specific_download_dialog").dialog("close"); + }); + } + + function ShowSpinner() { + feedback = $("#ajaxMsg"); + update = $("#updatebar"); + if ( update.is(":visible") ) { + var height = update.height() + 35; + feedback.css("bottom",height + "px"); + } else { + feedback.removeAttr("style"); + } + loader = $(""); + feedback.prepend(loader); + feedback.fadeIn(); + } + $(document).ready(function() { getAlbumInfo(); initThisPage(); diff --git a/headphones/searcher.py b/headphones/searcher.py index de680155..f1361e1d 100644 --- a/headphones/searcher.py +++ b/headphones/searcher.py @@ -145,7 +145,7 @@ def searchforalbum(albumid=None, new=False, losslessOnly=False, choose_specific_ logger.info('Search for Wanted albums complete') -def do_sorted_search(album, new, losslessOnly, choose_specific_download): +def do_sorted_search(album, new, losslessOnly, choose_specific_download=False): NZB_PROVIDERS = (headphones.HEADPHONES_INDEXER or headphones.NEWZNAB or headphones.NZBSORG or headphones.NZBSRUS or headphones.OMGWTFNZBS) NZB_DOWNLOADERS = (headphones.SAB_HOST or headphones.BLACKHOLE_DIR or headphones.NZBGET_HOST) diff --git a/headphones/webserve.py b/headphones/webserve.py index 3411fce1..a7fdd8ca 100644 --- a/headphones/webserve.py +++ b/headphones/webserve.py @@ -326,9 +326,18 @@ class WebInterface(object): choose_specific_download.exposed = True - def download_specific_release(self, AlbumID, title, size, url, provider, kind): + def download_specific_release(self, AlbumID, title, size, url, provider, kind, **kwargs): + + # Handle situations where the torrent url contains arguments that are parsed + if kwargs: + import urllib, urllib2 + url = urllib2.quote(url, safe=":?/=&") + '&' + urllib.urlencode(kwargs) + + try: + result = [(title,int(size),url,provider,kind)] + except ValueError: + result = [(title,float(size),url,provider,kind)] - result = [(title,int(size),url,provider,kind)] logger.info(u"Making sure we can download the chosen result") (data, bestqual) = searcher.preprocess(result)
    '+data[i].title+''+(data[i].size / (1024*1024)).toFixed(2)+' MB'+data[i].provider+''+data[i].kind+'
    '+data[i].title+''+(data[i].size / (1024*1024)).toFixed(2)+' MB'+data[i].provider+''+data[i].kind+'