From 98385ff4c8f423e17698b5e7f3fffeb516db42a8 Mon Sep 17 00:00:00 2001 From: Ade Date: Sat, 10 May 2014 09:32:05 +1200 Subject: [PATCH 1/4] Transmission change for rutracker use metainfo for local .torrent files (will only be rutracker) --- headphones/transmission.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/headphones/transmission.py b/headphones/transmission.py index e2e321b3..17ad434e 100644 --- a/headphones/transmission.py +++ b/headphones/transmission.py @@ -30,7 +30,14 @@ from headphones import logger, notifiers, request def addTorrent(link): method = 'torrent-add' - arguments = {'filename': link, 'download-dir': headphones.DOWNLOAD_TORRENT_DIR} + + if link.endswith('.torrent'): + f = open(link,'rb') + metainfo = str(base64.b64encode(f.read())) + f.close() + arguments = {'metainfo': metainfo, 'download-dir':headphones.DOWNLOAD_TORRENT_DIR} + else: + arguments = {'filename': link, 'download-dir': headphones.DOWNLOAD_TORRENT_DIR} response = torrentAction(method,arguments) From 6f3c8c68d4b3a5dc4d790460f70f2d62ada6da35 Mon Sep 17 00:00:00 2001 From: Ade Date: Sat, 10 May 2014 18:53:58 +1200 Subject: [PATCH 2/4] Lossless min/max filter filter results if calculated target size outside bitrate range --- data/interfaces/default/config.html | 26 +++++++++++++++++++++++--- headphones/__init__.py | 8 +++++++- headphones/searcher.py | 28 ++++++++++++++++++++++++++++ headphones/webserve.py | 8 ++++++-- 4 files changed, 64 insertions(+), 6 deletions(-) diff --git a/data/interfaces/default/config.html b/data/interfaces/default/config.html index d38fa710..9e48eadb 100644 --- a/data/interfaces/default/config.html +++ b/data/interfaces/default/config.html @@ -470,7 +470,14 @@
- + +
+ + Reject if target size is not in bitrate range: \ + to\ + kbps + +
Preferred Bitrate: kbps
Reject if less than % or more than % of the target size (leave blank for no limit)

@@ -1587,6 +1594,15 @@ } }); + if ($("#lossless_only").is(":checked")) + { + $("#lossless_only_options").show(); + } + else + { + $("#lossless_only_options").hide(); + } + if ($("#preferred_bitrate").is(":checked")) { $("#preferred_bitrate_options").show(); @@ -1632,18 +1648,22 @@ if ($("#preferred_bitrate").is(":checked")) { $("#preferred_bitrate_options").slideDown("fast"); + $("#lossless_only_options").slideUp("fast"); } if ($("#preferred_quality0").is(":checked")) { $("#preferred_bitrate_options").slideUp("fast"); + $("#lossless_only_options").slideUp("fast"); } if ($("#preferred_quality1").is(":checked")) { $("#preferred_bitrate_options").slideUp("fast"); + $("#lossless_only_options").slideUp("fast"); } - if ($("#preferred_quality3").is(":checked")) + if ($("#lossless_only").is(":checked")) { - $("#preferred_bitrate_options").slideUp("fast"); + $("#lossless_only_options").slideDown("fast"); + $("#preferred_bitrate_options").slideUp("fast"); } if ($("#nzb_downloader_sabnzbd").is(":checked")) { diff --git a/headphones/__init__.py b/headphones/__init__.py index 380a31bf..4a9ab38f 100644 --- a/headphones/__init__.py +++ b/headphones/__init__.py @@ -103,6 +103,8 @@ PREFERRED_BITRATE_HIGH_BUFFER = None PREFERRED_BITRATE_LOW_BUFFER = None PREFERRED_BITRATE_ALLOW_LOSSLESS = False DETECT_BITRATE = False +LOSSLESS_BITRATE_FROM = None +LOSSLESS_BITRATE_TO = None ADD_ARTISTS = False CORRECT_METADATA = False MOVE_FILES = False @@ -358,7 +360,7 @@ def initialize(): PUSHBULLET_ENABLED, PUSHBULLET_APIKEY, PUSHBULLET_DEVICEID, PUSHBULLET_ONSNATCH, \ MIRROR, CUSTOMHOST, CUSTOMPORT, CUSTOMSLEEP, HPUSER, HPPASS, XBMC_ENABLED, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, XBMC_UPDATE, \ XBMC_NOTIFY, LMS_ENABLED, LMS_HOST, NMA_ENABLED, NMA_APIKEY, NMA_PRIORITY, NMA_ONSNATCH, SYNOINDEX_ENABLED, ALBUM_COMPLETION_PCT, PREFERRED_BITRATE_HIGH_BUFFER, \ - PREFERRED_BITRATE_LOW_BUFFER, PREFERRED_BITRATE_ALLOW_LOSSLESS, CACHE_SIZEMB, JOURNAL_MODE, UMASK, ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY, \ + PREFERRED_BITRATE_LOW_BUFFER, PREFERRED_BITRATE_ALLOW_LOSSLESS, LOSSLESS_BITRATE_FROM, LOSSLESS_BITRATE_TO, CACHE_SIZEMB, JOURNAL_MODE, UMASK, ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY, \ PLEX_ENABLED, PLEX_SERVER_HOST, PLEX_CLIENT_HOST, PLEX_USERNAME, PLEX_PASSWORD, PLEX_UPDATE, PLEX_NOTIFY, PUSHALOT_ENABLED, PUSHALOT_APIKEY, \ PUSHALOT_ONSNATCH, SONGKICK_ENABLED, SONGKICK_APIKEY, SONGKICK_LOCATION, SONGKICK_FILTER_ENABLED @@ -438,6 +440,8 @@ def initialize(): PREFERRED_BITRATE_LOW_BUFFER = check_setting_int(CFG, 'General', 'preferred_bitrate_low_buffer', '') PREFERRED_BITRATE_ALLOW_LOSSLESS = bool(check_setting_int(CFG, 'General', 'preferred_bitrate_allow_lossless', 0)) DETECT_BITRATE = bool(check_setting_int(CFG, 'General', 'detect_bitrate', 0)) + LOSSLESS_BITRATE_FROM = check_setting_int(CFG, 'General', 'lossless_bitrate_from', '') + LOSSLESS_BITRATE_TO = check_setting_int(CFG, 'General', 'lossless_bitrate_to', '') ADD_ARTISTS = bool(check_setting_int(CFG, 'General', 'auto_add_artists', 1)) CORRECT_METADATA = bool(check_setting_int(CFG, 'General', 'correct_metadata', 0)) MOVE_FILES = bool(check_setting_int(CFG, 'General', 'move_files', 0)) @@ -862,6 +866,8 @@ def config_write(): new_config['General']['preferred_bitrate_low_buffer'] = PREFERRED_BITRATE_LOW_BUFFER new_config['General']['preferred_bitrate_allow_lossless'] = int(PREFERRED_BITRATE_ALLOW_LOSSLESS) new_config['General']['detect_bitrate'] = int(DETECT_BITRATE) + new_config['General']['lossless_bitrate_from'] = LOSSLESS_BITRATE_FROM + new_config['General']['lossless_bitrate_to'] = LOSSLESS_BITRATE_TO new_config['General']['auto_add_artists'] = int(ADD_ARTISTS) new_config['General']['correct_metadata'] = int(CORRECT_METADATA) new_config['General']['move_files'] = int(MOVE_FILES) diff --git a/headphones/searcher.py b/headphones/searcher.py index 1cc78b84..8c2a699d 100644 --- a/headphones/searcher.py +++ b/headphones/searcher.py @@ -218,6 +218,34 @@ 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) diff --git a/headphones/webserve.py b/headphones/webserve.py index 6db4c1f3..709de4f0 100644 --- a/headphones/webserve.py +++ b/headphones/webserve.py @@ -1000,6 +1000,8 @@ class WebInterface(object): "pref_bitrate_low" : headphones.PREFERRED_BITRATE_LOW_BUFFER, "pref_bitrate_allow_lossless" : checked(headphones.PREFERRED_BITRATE_ALLOW_LOSSLESS), "detect_bitrate" : checked(headphones.DETECT_BITRATE), + "lossless_bitrate_from" : headphones.LOSSLESS_BITRATE_FROM, + "lossless_bitrate_to" : headphones.LOSSLESS_BITRATE_TO, "move_files" : checked(headphones.MOVE_FILES), "rename_files" : checked(headphones.RENAME_FILES), "correct_metadata" : checked(headphones.CORRECT_METADATA), @@ -1136,8 +1138,8 @@ class WebInterface(object): xbmc_update=0, xbmc_notify=0, nma_enabled=False, nma_apikey=None, nma_priority=0, nma_onsnatch=0, pushalot_enabled=False, pushalot_apikey=None, pushalot_onsnatch=0, synoindex_enabled=False, lms_enabled=0, lms_host=None, pushover_enabled=0, pushover_onsnatch=0, pushover_keys=None, pushover_priority=0, pushover_apitoken=None, pushbullet_enabled=0, pushbullet_onsnatch=0, pushbullet_apikey=None, pushbullet_deviceid=None, twitter_enabled=0, twitter_onsnatch=0, osx_notify_enabled=0, osx_notify_onsnatch=0, osx_notify_app=None, boxcar_enabled=0, boxcar_onsnatch=0, boxcar_token=None, mirror=None, customhost=None, customport=None, customsleep=None, hpuser=None, hppass=None, - preferred_bitrate_high_buffer=None, preferred_bitrate_low_buffer=None, preferred_bitrate_allow_lossless=0, cache_sizemb=None, enable_https=0, https_cert=None, https_key=None, file_permissions=None, folder_permissions=None, - plex_enabled=0, plex_server_host=None, plex_client_host=None, plex_username=None, plex_password=None, plex_update=0, plex_notify=0, + preferred_bitrate_high_buffer=None, preferred_bitrate_low_buffer=None, preferred_bitrate_allow_lossless=0, lossless_bitrate_from=None, lossless_bitrate_to=None, cache_sizemb=None, enable_https=0, https_cert=None, https_key=None, + file_permissions=None, folder_permissions=None, plex_enabled=0, plex_server_host=None, plex_client_host=None, plex_username=None, plex_password=None, plex_update=0, plex_notify=0, songkick_enabled=0, songkick_apikey=None, songkick_location=None, songkick_filter_enabled=0, encoder_multicore=False, encoder_multicore_count=0, mpc_enabled=False, **kwargs ): headphones.HTTP_HOST = http_host @@ -1216,6 +1218,8 @@ class WebInterface(object): headphones.PREFERRED_BITRATE_LOW_BUFFER = preferred_bitrate_low_buffer headphones.PREFERRED_BITRATE_ALLOW_LOSSLESS = preferred_bitrate_allow_lossless headphones.DETECT_BITRATE = detect_bitrate + headphones.LOSSLESS_BITRATE_FROM = lossless_bitrate_from + headphones.LOSSLESS_BITRATE_TO = lossless_bitrate_to headphones.MOVE_FILES = move_files headphones.CORRECT_METADATA = correct_metadata headphones.RENAME_FILES = rename_files From 8ab19f8121344651aeb9a643d76da89664a22e44 Mon Sep 17 00:00:00 2001 From: Ade Date: Sat, 10 May 2014 19:06:09 +1200 Subject: [PATCH 3/4] remove rutracker track count check should be able to filter out unwanted entries with Quality and Search Word settings --- headphones/searcher_rutracker.py | 220 +++++++++++++++---------------- 1 file changed, 107 insertions(+), 113 deletions(-) diff --git a/headphones/searcher_rutracker.py b/headphones/searcher_rutracker.py index 8837d205..3c799f24 100644 --- a/headphones/searcher_rutracker.py +++ b/headphones/searcher_rutracker.py @@ -18,6 +18,7 @@ from tempfile import mkdtemp class Rutracker(): logged_in = False + # Stores a number of login attempts to prevent recursion. #login_counter = 0 @@ -29,7 +30,7 @@ class Rutracker(): def login(self, login, password): """Implements tracker login procedure.""" - + self.logged_in = False if login is None or password is None: @@ -51,7 +52,6 @@ class Rutracker(): pass # Check if we're logged in - for cookie in self.cookiejar: if cookie.name == 'bb_data': self.logged_in = True @@ -64,7 +64,6 @@ class Rutracker(): """ # Build search url - searchterm = '' if artist != 'Various Artists': searchterm = artist @@ -82,8 +81,7 @@ class Rutracker(): else: format = '+mp3||aac' - # sort by size, descending. - + # sort by size, descending. sort = '&o=7&s=2' searchurl = "%s?nm=%s%s%s" % (providerurl, urllib.quote(searchterm), format, sort) @@ -111,25 +109,21 @@ class Rutracker(): #logger.debug (soup.prettify()) # Title - for link in soup.find_all('a', attrs={'class' : 'med tLink hl-tags bold'}): title = link.get_text() titles.append(title) # Download URL - for link in soup.find_all('a', attrs={'class' : 'small tr-dl dl-stub'}): url = link.get('href') urls.append(url) # Seeders - for link in soup.find_all('b', attrs={'class' : 'seedmed'}): seeder = link.get_text() seeders.append(seeder) # Size - for link in soup.find_all('td', attrs={'class' : 'row4 small nowrap tor-size'}): size = link.u.string sizes.append(size) @@ -138,30 +132,33 @@ class Rutracker(): pass # Combine lists - torrentlist = zip(titles, urls, seeders, sizes) # return if nothing found - if not torrentlist: return False - - # get headphones track count for album, return if not found - - myDB = db.DBConnection() - tracks = myDB.select('SELECT * from tracks WHERE AlbumID=?', [albumid]) - hptrackcount = len(tracks) - - if not hptrackcount: - logger.info('headphones track info not found, cannot compare to torrent') - return False - - # 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'] - deluxelist = ['deluxe', 'edition', 'japanese', 'exclusive'] + # don't bother checking track counts anymore, let searcher filter instead + # leave code in just in case + check_track_count = False + + if check_track_count: + + # get headphones track count for album, return if not found + myDB = db.DBConnection() + tracks = myDB.select('SELECT * from tracks WHERE AlbumID=?', [albumid]) + hptrackcount = len(tracks) + + if not hptrackcount: + logger.info('headphones track info not found, cannot compare to torrent') + return False + + # 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'] + deluxelist = ['deluxe', 'edition', 'japanese', 'exclusive'] for torrent in torrentlist: @@ -169,105 +166,102 @@ class Rutracker(): url = torrent[1] seeders = torrent[2] size = torrent[3] - - title = returntitle.lower() - - if int(size) <= maxsize and int(seeders) >= minseeders: - - # Check torrent info - - 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)) - - # Debug - #for cookie in self.cookiejar: - # logger.debug ('Cookie: %s' % cookie) - - try: - page = self.opener.open(url) - torrent = page.read() - if torrent: - decoded = bencode.bdecode(torrent) - metainfo = decoded['info'] - page.close () - except Exception, e: - logger.error('Error getting torrent: %s' % e) - return False - - # get torrent track count and check for cue - - trackcount = 0 - cuecount = 0 - - if 'files' in metainfo: # multi - for pathfile in metainfo['files']: - path = pathfile['path'] - for file in path: - if any(file.lower().endswith('.' + x.lower()) for x in formatlist): - trackcount += 1 - if '.cue' in file: - cuecount += 1 - - #Torrent topic page - - topicurl = 'http://rutracker.org/forum/viewtopic.php?t=' + torrent_id - logger.debug ('torrent title: %s' % title) - logger.debug ('headphones trackcount: %s' % hptrackcount) - logger.debug ('rutracker trackcount: %s' % trackcount) - # If torrent track count less than headphones track count, and there's a cue, then attempt to get track count from log(s) - # This is for the case where we have a single .flac/.wav which can be split by cue - # Not great, but shouldn't be doing this too often - - totallogcount = 0 - if trackcount < hptrackcount and cuecount > 0 and cuecount < hptrackcount: - page = self.opener.open(topicurl, timeout=60) - soup = BeautifulSoup(page.read()) - findtoc = soup.find_all(text='TOC of the extracted CD') - if not findtoc: - findtoc = soup.find_all(text='TOC извлечённого CD') - for toc in findtoc: - logcount = 0 - for toccontent in toc.find_all_next(text=True): - cut_string = toccontent.split('|') - new_string = cut_string[0].lstrip().rstrip() - if new_string == '1' or new_string == '01': - logcount = 1 - elif logcount > 0: - if new_string.isdigit(): - logcount += 1 - else: - break - totallogcount = totallogcount + logcount - - if totallogcount > 0: - trackcount = totallogcount - logger.debug ('rutracker logtrackcount: %s' % totallogcount) - - # If torrent track count = hp track count then return torrent, - # if greater, check for deluxe/special/foreign editions - # if less, then allow if it's a single track with a cue - - valid = False - - if trackcount == hptrackcount: + if int(size) <= maxsize and int(seeders) >= minseeders: + + #Torrent topic page + torrent_id = dict([part.split('=') for part in urlparse(url)[4].split('&')])['t'] + topicurl = 'http://rutracker.org/forum/viewtopic.php?t=' + torrent_id + + # add to list + if not check_track_count: valid = True - elif trackcount > hptrackcount: - if any(deluxe in title for deluxe in deluxelist): + else: + + # Check torrent info + 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)) + + # Debug + #for cookie in self.cookiejar: + # logger.debug ('Cookie: %s' % cookie) + + try: + page = self.opener.open(url) + torrent = page.read() + if torrent: + decoded = bencode.bdecode(torrent) + metainfo = decoded['info'] + page.close () + except Exception, e: + logger.error('Error getting torrent: %s' % e) + return False + + # get torrent track count and check for cue + trackcount = 0 + cuecount = 0 + + if 'files' in metainfo: # multi + for pathfile in metainfo['files']: + path = pathfile['path'] + for file in path: + if any(file.lower().endswith('.' + x.lower()) for x in formatlist): + trackcount += 1 + if '.cue' in file: + cuecount += 1 + + title = returntitle.lower() + logger.debug ('torrent title: %s' % title) + logger.debug ('headphones trackcount: %s' % hptrackcount) + logger.debug ('rutracker trackcount: %s' % trackcount) + + # If torrent track count less than headphones track count, and there's a cue, then attempt to get track count from log(s) + # This is for the case where we have a single .flac/.wav which can be split by cue + # Not great, but shouldn't be doing this too often + totallogcount = 0 + if trackcount < hptrackcount and cuecount > 0 and cuecount < hptrackcount: + page = self.opener.open(topicurl, timeout=60) + soup = BeautifulSoup(page.read()) + findtoc = soup.find_all(text='TOC of the extracted CD') + if not findtoc: + findtoc = soup.find_all(text='TOC извлечённого CD') + for toc in findtoc: + logcount = 0 + for toccontent in toc.find_all_next(text=True): + cut_string = toccontent.split('|') + new_string = cut_string[0].lstrip().rstrip() + if new_string == '1' or new_string == '01': + logcount = 1 + elif logcount > 0: + if new_string.isdigit(): + logcount += 1 + else: + break + totallogcount = totallogcount + logcount + + if totallogcount > 0: + trackcount = totallogcount + logger.debug ('rutracker logtrackcount: %s' % totallogcount) + + # If torrent track count = hp track count then return torrent, + # if greater, check for deluxe/special/foreign editions + # if less, then allow if it's a single track with a cue + valid = False + + if trackcount == hptrackcount: valid = True + elif trackcount > hptrackcount: + if any(deluxe in title for deluxe in deluxelist): + valid = True # Add to list - if valid: rulist.append((returntitle, size, topicurl)) else: if topicurl: logger.info(u'Torrent 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): From 52a76e87adcd33ab5cb873e787c9fa8465e19e12 Mon Sep 17 00:00:00 2001 From: Ade Date: Sun, 11 May 2014 19:35:41 +1200 Subject: [PATCH 4/4] Allow search provider names in preferred words MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds to the priority if the word matches the search provider. The provider priority is weighted based on position in list. Preferred words in title take precedence over preferred providers. Would be great if we could do something like sb, so until then… --- data/interfaces/default/config.html | 2 +- headphones/searcher.py | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/data/interfaces/default/config.html b/data/interfaces/default/config.html index 9e48eadb..5ee7a95b 100644 --- a/data/interfaces/default/config.html +++ b/data/interfaces/default/config.html @@ -503,7 +503,7 @@
- Results with these words in the title will be preferred over results without them + Results with these words in the title will be preferred over results without them (search provider names can also be entered)
diff --git a/headphones/searcher.py b/headphones/searcher.py index 8c2a699d..d733a2f3 100644 --- a/headphones/searcher.py +++ b/headphones/searcher.py @@ -151,11 +151,20 @@ def sort_search_results(resultlist, album, new): # Add a priority if it has any of the preferred words temp_list = [] + preferred_words = None + if headphones.PREFERRED_WORDS: + preferred_words = helpers.split_string(headphones.PREFERRED_WORDS) for result in resultlist: - 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],result[4],1)) - else: - temp_list.append((result[0],result[1],result[2],result[3],result[4],0)) + priority = 0 + if preferred_words: + if any(word.lower() in result[0].lower() for word in preferred_words): + priority = 1 + # add a search provider priority (weighted based on position) + i = next((i for i, word in enumerate(preferred_words) if word in result[3].lower()), None) + if i != None: + priority += round((len(preferred_words) - i) / float(len(preferred_words)),2) + + temp_list.append((result[0],result[1],result[2],result[3],result[4],priority)) resultlist = temp_list