Cleanup search code. Add support for magnet links conversion. Fixes #1926.

This commit is contained in:
Bas Stottelaar
2014-10-21 02:07:56 +02:00
parent 8a8821530a
commit 6b4afd8877
6 changed files with 222 additions and 103 deletions
+22 -5
View File
@@ -317,10 +317,27 @@
<input type="text" name="torrentblackhole_dir" value="${config['torrentblackhole_dir']}" size="50"> <input type="text" name="torrentblackhole_dir" value="${config['torrentblackhole_dir']}" size="50">
<small>Folder your Download program watches for Torrents</small> <small>Folder your Download program watches for Torrents</small>
</div> </div>
<div class="row checkbox">
<label>Open Magnet Links</label> <div class="row">
<input type="checkbox" name="open_magnet_links" value="1" ${config['open_magnet_links']}> <label>Magnet links</label>
<small>Allow Headphones to open magnet links</small>
<label class="inline" title="Invoke shell command to open magnet URL.">
<input type="radio" name="magnet_links" id="magnet_links_0" value="0" ${config['magnet_links_0']}>
Ignore
</label>
<label class="inline" title="Use external service to convert magnet links into torrents.">
<input type="radio" name="magnet_links" id="magnet_links_1" value="1" ${config['magnet_links_1']}>
Open
</label>
<label class="inline">
<input type="radio" name="magnet_links" id="magnet_links_2" value="2" ${config['magnet_links_2']}>
Convert
</label>
<div style="clear: both"></div>
<small>Note: opening magnet URL's is not suitable for headless/console/terminal servers.</small>
</div> </div>
</fieldset> </fieldset>
<fieldset id="transmission_options"> <fieldset id="transmission_options">
@@ -382,7 +399,7 @@
<input type="radio" name="prefer_torrents" id="prefer_torrents_0" value="0" ${config['prefer_torrents_0']}>NZBs <input type="radio" name="prefer_torrents" id="prefer_torrents_0" value="0" ${config['prefer_torrents_0']}>NZBs
<input type="radio" name="prefer_torrents" id="prefer_torrents_1" value="1" ${config['prefer_torrents_1']}>Torrents <input type="radio" name="prefer_torrents" id="prefer_torrents_1" value="1" ${config['prefer_torrents_1']}>Torrents
<input type="radio" name="prefer_torrents" id="prefer_torrents_2" value="2" ${config['prefer_torrents_2']}>No Preference <input type="radio" name="prefer_torrents" id="prefer_torrents_2" value="2" ${config['prefer_torrents_2']}>No Preference
</div> </div>
</fieldset> </fieldset>
</td> </td>
</tr> </tr>
+4
View File
@@ -336,6 +336,10 @@ form .row label {
padding-top: 7px; padding-top: 7px;
width: 175px; width: 175px;
} }
form .row label.inline {
margin-right: 5px;
width: auto;
}
form .row input { form .row input {
margin-right: 5px; margin-right: 5px;
} }
+5
View File
@@ -191,6 +191,11 @@ form {
line-height: normal; line-height: normal;
padding-top: 7px; padding-top: 7px;
width: 175px; width: 175px;
&.inline {
margin-right: 5px;
width: auto;
}
} }
input { margin-right: 5px; } input { margin-right: 5px; }
input[type=text], input[type=password] { input[type=text], input[type=password] {
+4 -4
View File
@@ -134,7 +134,7 @@ AUTOWANT_ALL = False
AUTOWANT_MANUALLY_ADDED = True AUTOWANT_MANUALLY_ADDED = True
KEEP_TORRENT_FILES = False KEEP_TORRENT_FILES = False
PREFER_TORRENTS = None # 0: nzbs, 1: torrents, 2: no preference PREFER_TORRENTS = None # 0: nzbs, 1: torrents, 2: no preference
OPEN_MAGNET_LINKS = False MAGNET_LINKS = None # 0: Ignore, 1: Open, 2: Convert
SEARCH_INTERVAL = 360 SEARCH_INTERVAL = 360
LIBRARYSCAN = False LIBRARYSCAN = False
@@ -361,7 +361,7 @@ def initialize():
HTTP_PORT, HTTP_HOST, HTTP_USERNAME, HTTP_PASSWORD, HTTP_ROOT, HTTP_PROXY, LAUNCH_BROWSER, API_ENABLED, API_KEY, GIT_PATH, GIT_USER, GIT_BRANCH, DO_NOT_OVERRIDE_GIT_BRANCH, \ HTTP_PORT, HTTP_HOST, HTTP_USERNAME, HTTP_PASSWORD, HTTP_ROOT, HTTP_PROXY, LAUNCH_BROWSER, API_ENABLED, API_KEY, GIT_PATH, GIT_USER, GIT_BRANCH, DO_NOT_OVERRIDE_GIT_BRANCH, \
CURRENT_VERSION, LATEST_VERSION, CHECK_GITHUB, CHECK_GITHUB_ON_STARTUP, CHECK_GITHUB_INTERVAL, MUSIC_DIR, DESTINATION_DIR, \ CURRENT_VERSION, LATEST_VERSION, CHECK_GITHUB, CHECK_GITHUB_ON_STARTUP, CHECK_GITHUB_INTERVAL, MUSIC_DIR, DESTINATION_DIR, \
LOSSLESS_DESTINATION_DIR, PREFERRED_QUALITY, PREFERRED_BITRATE, DETECT_BITRATE, ADD_ARTISTS, CORRECT_METADATA, FREEZE_DB, MOVE_FILES, \ LOSSLESS_DESTINATION_DIR, PREFERRED_QUALITY, PREFERRED_BITRATE, DETECT_BITRATE, ADD_ARTISTS, CORRECT_METADATA, FREEZE_DB, MOVE_FILES, \
RENAME_FILES, FOLDER_FORMAT, FILE_FORMAT, FILE_UNDERSCORES, CLEANUP_FILES, KEEP_NFO, INCLUDE_EXTRAS, EXTRAS, AUTOWANT_UPCOMING, AUTOWANT_ALL, AUTOWANT_MANUALLY_ADDED, KEEP_TORRENT_FILES, PREFER_TORRENTS, OPEN_MAGNET_LINKS, \ RENAME_FILES, FOLDER_FORMAT, FILE_FORMAT, FILE_UNDERSCORES, CLEANUP_FILES, KEEP_NFO, INCLUDE_EXTRAS, EXTRAS, AUTOWANT_UPCOMING, AUTOWANT_ALL, AUTOWANT_MANUALLY_ADDED, KEEP_TORRENT_FILES, PREFER_TORRENTS, MAGNET_LINKS, \
ADD_ALBUM_ART, ALBUM_ART_FORMAT, EMBED_ALBUM_ART, EMBED_LYRICS, REPLACE_EXISTING_FOLDERS, DOWNLOAD_DIR, BLACKHOLE, BLACKHOLE_DIR, USENET_RETENTION, SEARCH_INTERVAL, \ ADD_ALBUM_ART, ALBUM_ART_FORMAT, EMBED_ALBUM_ART, EMBED_LYRICS, REPLACE_EXISTING_FOLDERS, DOWNLOAD_DIR, BLACKHOLE, BLACKHOLE_DIR, USENET_RETENTION, SEARCH_INTERVAL, \
TORRENTBLACKHOLE_DIR, NUMBEROFSEEDERS, KAT, KAT_PROXY_URL, KAT_RATIO, PIRATEBAY, PIRATEBAY_PROXY_URL, PIRATEBAY_RATIO, MININOVA, MININOVA_RATIO, WAFFLES, WAFFLES_UID, WAFFLES_PASSKEY, WAFFLES_RATIO, \ TORRENTBLACKHOLE_DIR, NUMBEROFSEEDERS, KAT, KAT_PROXY_URL, KAT_RATIO, PIRATEBAY, PIRATEBAY_PROXY_URL, PIRATEBAY_RATIO, MININOVA, MININOVA_RATIO, WAFFLES, WAFFLES_UID, WAFFLES_PASSKEY, WAFFLES_RATIO, \
RUTRACKER, RUTRACKER_USER, RUTRACKER_PASSWORD, RUTRACKER_RATIO, WHATCD, WHATCD_USERNAME, WHATCD_PASSWORD, WHATCD_RATIO, DOWNLOAD_TORRENT_DIR, \ RUTRACKER, RUTRACKER_USER, RUTRACKER_PASSWORD, RUTRACKER_RATIO, WHATCD, WHATCD_USERNAME, WHATCD_PASSWORD, WHATCD_RATIO, DOWNLOAD_TORRENT_DIR, \
@@ -467,7 +467,7 @@ def initialize():
AUTOWANT_MANUALLY_ADDED = bool(check_setting_int(CFG, 'General', 'autowant_manually_added', 1)) AUTOWANT_MANUALLY_ADDED = bool(check_setting_int(CFG, 'General', 'autowant_manually_added', 1))
KEEP_TORRENT_FILES = bool(check_setting_int(CFG, 'General', 'keep_torrent_files', 0)) KEEP_TORRENT_FILES = bool(check_setting_int(CFG, 'General', 'keep_torrent_files', 0))
PREFER_TORRENTS = check_setting_int(CFG, 'General', 'prefer_torrents', 0) PREFER_TORRENTS = check_setting_int(CFG, 'General', 'prefer_torrents', 0)
OPEN_MAGNET_LINKS = bool(check_setting_int(CFG, 'General', 'open_magnet_links', 0)) MAGNET_LINKS = int(check_setting_int(CFG, 'General', 'magnet_links', 0))
SEARCH_INTERVAL = check_setting_int(CFG, 'General', 'search_interval', 1440) SEARCH_INTERVAL = check_setting_int(CFG, 'General', 'search_interval', 1440)
LIBRARYSCAN = bool(check_setting_int(CFG, 'General', 'libraryscan', 1)) LIBRARYSCAN = bool(check_setting_int(CFG, 'General', 'libraryscan', 1))
@@ -913,7 +913,7 @@ def config_write():
new_config['General']['autowant_manually_added'] = int(AUTOWANT_MANUALLY_ADDED) new_config['General']['autowant_manually_added'] = int(AUTOWANT_MANUALLY_ADDED)
new_config['General']['keep_torrent_files'] = int(KEEP_TORRENT_FILES) new_config['General']['keep_torrent_files'] = int(KEEP_TORRENT_FILES)
new_config['General']['prefer_torrents'] = PREFER_TORRENTS new_config['General']['prefer_torrents'] = PREFER_TORRENTS
new_config['General']['open_magnet_links'] = OPEN_MAGNET_LINKS new_config['General']['magnet_links'] = int(MAGNET_LINKS)
new_config['General']['numberofseeders'] = NUMBEROFSEEDERS new_config['General']['numberofseeders'] = NUMBEROFSEEDERS
new_config['General']['torrentblackhole_dir'] = TORRENTBLACKHOLE_DIR new_config['General']['torrentblackhole_dir'] = TORRENTBLACKHOLE_DIR
+182 -91
View File
@@ -20,18 +20,19 @@ from pygazelle import api as gazelleapi
from pygazelle import encoding as gazelleencoding from pygazelle import encoding as gazelleencoding
from pygazelle import format as gazelleformat from pygazelle import format as gazelleformat
from pygazelle import media as gazellemedia from pygazelle import media as gazellemedia
from xml.dom import minidom
from base64 import b16encode, b32decode from base64 import b16encode, b32decode
from hashlib import sha1 from hashlib import sha1
import os, re, time import os
import re
import time
import string import string
import shutil import shutil
import requests import random
import headphones
import subprocess import subprocess
import unicodedata import unicodedata
import headphones
from headphones.common import USER_AGENT from headphones.common import USER_AGENT
from headphones import logger, db, helpers, classes, sab, nzbget, request from headphones import logger, db, helpers, classes, sab, nzbget, request
from headphones import utorrent, transmission, notifiers from headphones import utorrent, transmission, notifiers
@@ -39,19 +40,136 @@ from headphones import utorrent, transmission, notifiers
from bencode import bencode, bdecode from bencode import bencode, bdecode
import headphones.searcher_rutracker as rutrackersearch import headphones.searcher_rutracker as rutrackersearch
rutracker = rutrackersearch.Rutracker()
# Magnet to torrent services, for Black hole. Stolen from CouchPotato.
TORRENT_TO_MAGNET_SERVICES = [
'https://zoink.it/torrent/%s.torrent',
'http://torrage.com/torrent/%s.torrent',
'https://torcache.net/torrent/%s.torrent',
]
# Persistent What.cd API object # Persistent What.cd API object
gazelle = None gazelle = None
def url_fix(s, charset='utf-8'): # RUtracker search object
rutracker = rutrackersearch.Rutracker()
def fix_url(s, charset="utf-8"):
"""
Fix the URL so it is proper formatted and encoded.
"""
if isinstance(s, unicode): if isinstance(s, unicode):
s = s.encode(charset, 'ignore') s = s.encode(charset, 'ignore')
scheme, netloc, path, qs, anchor = urlparse.urlsplit(s) scheme, netloc, path, qs, anchor = urlparse.urlsplit(s)
path = urllib.quote(path, '/%') path = urllib.quote(path, '/%')
qs = urllib.quote_plus(qs, ':&=') qs = urllib.quote_plus(qs, ':&=')
return urlparse.urlunsplit((scheme, netloc, path, qs, anchor)) return urlparse.urlunsplit((scheme, netloc, path, qs, anchor))
def torrent_to_file(target_file, data):
"""
Write torrent data to file, and change permissions accordingly. Will return
None in case of a write error. If changing permissions fails, it will
continue anyway.
"""
# Write data to file
try:
with open(target_file, "wb") as fp:
fp.write(data)
except IOError as e:
logger.error("Could not write torrent file '%s': %s. Skipping.",
target_file, e.message)
return
# Try to change permissions
try:
os.chmod(target_file, int(headphones.FILE_PERMISSIONS, 8))
except OSError as e:
logger.warn("Could not change permissions for file '%s': %s. " \
"Continuing.", target_file, e.message)
# Done
return True
def read_torrent_name(torrent_file, default_name=None):
"""
Read the torrent file and return the torrent name. If the torrent name
cannot be determined, it will return the `default_name`.
"""
# Open file
try:
with open(torrent_file, "rb") as fp:
torrent_info = bdecode(fp.read())
except IOError as e:
logger.error("Unable to open torrent file: %s", torrent_file)
return
# Read dictionary
if torrent_info:
try:
return torrent_info["info"]["name"]
except KeyError:
if default_name:
logger.warning("Couldn't get name from torrent file: %s. " \
"Defaulting to '%s'", e, default_name)
else:
logger.warning("Couldn't get name from torrent file: %s. No " \
"default given", e)
# Return default
return default_name
def calculate_torrent_hash(link, data=None):
"""
Calculate the torrent hash from a magnet link or data.
"""
if link.startswith("magnet:"):
torrent_hash = re.findall("urn:btih:([\w]{32,40})", link)[0]
if len(torrent_hash) == 32:
torrent_hash = b16encode(b32decode(torrent_hash)).lower()
elif data:
info = bdecode(data)["info"]
torrent_hash = sha1(bencode(info)).hexdigest()
else:
raise ValueError("Cannot calculate torrent hash without magnet link " \
"or data")
return torrent_hash
def get_seed_ratio(provider):
"""
Return the seed ratio for the specified provider, if applicable. Defaults to
None in case of an error.
"""
if provider == 'rutracker.org':
seed_ratio = headphones.RUTRACKER_RATIO
elif provider == 'Kick Ass Torrents':
seed_ratio = headphones.KAT_RATIO
elif provider == 'What.cd':
seed_ratio = headphones.WHATCD_RATIO
elif provider == 'The Pirate Bay':
seed_ratio = headphones.PIRATEBAY_RATIO
elif provider == 'Waffles.fm':
seed_ratio = headphones.WAFFLES_RATIO
elif provider == 'Mininova':
seed_ratio = headphones.MININOVA_RATIO
else:
seed_ratio = None
if seed_ratio is not None:
try:
seed_ratio = float(seed_ratio)
except ValueError:
logger.warn("Could not get seed ratio for %s" % provider)
return seed_ratio
def searchforalbum(albumid=None, new=False, losslessOnly=False, choose_specific_download=False): def searchforalbum(albumid=None, new=False, losslessOnly=False, choose_specific_download=False):
myDB = db.DBConnection() myDB = db.DBConnection()
@@ -80,7 +198,6 @@ def searchforalbum(albumid=None, new=False, losslessOnly=False, choose_specific_
return results return results
else: else:
album = myDB.action('SELECT * from albums WHERE AlbumID=?', [albumid]).fetchone() album = myDB.action('SELECT * from albums WHERE AlbumID=?', [albumid]).fetchone()
logger.info('Searching for "%s - %s" since it was marked as wanted' % (album['ArtistName'], album['AlbumTitle'])) logger.info('Searching for "%s - %s" since it was marked as wanted' % (album['ArtistName'], album['AlbumTitle']))
do_sorted_search(album, new, losslessOnly) do_sorted_search(album, new, losslessOnly)
@@ -233,7 +350,7 @@ def sort_search_results(resultlist, album, new, albumlength):
priority = 1 priority = 1
# add a search provider priority (weighted based on position) # 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) i = next((i for i, word in enumerate(preferred_words) if word in result[3].lower()), None)
if i != None: if i is not None:
priority += round((len(preferred_words) - i) / float(len(preferred_words)),2) 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)) temp_list.append((result[0],result[1],result[2],result[3],result[4],priority))
@@ -622,8 +739,8 @@ def send_to_downloader(data, bestqual, album):
torrent_name = helpers.replace_illegal_chars(folder_name) + '.torrent' torrent_name = helpers.replace_illegal_chars(folder_name) + '.torrent'
download_path = os.path.join(headphones.TORRENTBLACKHOLE_DIR, torrent_name) download_path = os.path.join(headphones.TORRENTBLACKHOLE_DIR, torrent_name)
if bestqual[2].startswith("magnet:"): if bestqual[2].lower().startswith("magnet:"):
if headphones.OPEN_MAGNET_LINKS: if headphones.MAGNET_LINKS == 1:
try: try:
if headphones.SYS_PLATFORM == 'win32': if headphones.SYS_PLATFORM == 'win32':
os.startfile(bestqual[2]) os.startfile(bestqual[2])
@@ -637,37 +754,51 @@ def send_to_downloader(data, bestqual, album):
except Exception as e: except Exception as e:
logger.error("Error opening magnet link: %s" % str(e)) logger.error("Error opening magnet link: %s" % str(e))
return return
else: elif headphones.MAGNET_LINKS == 2:
logger.error("Cannot save magnet files to blackhole. Please switch your torrent downloader to Transmission or uTorrent or allow Headphones to try to open magnet links") # Procedure adapted from CouchPotato
return torrent_hash = calculate_torrent_hash(bestqual[2])
else: # Randomize list of services
try: services = TORRENT_TO_MAGNET_SERVICES[:]
random.shuffle(services)
if bestqual[3] == 'rutracker.org': for service in services:
download_path = rutracker.get_torrent(bestqual[2], headphones.TORRENTBLACKHOLE_DIR) data = request.request_content(service % torrent_hash)
if not download_path:
return if data and "torcache" in data:
if not torrent_to_file(download_path, data):
return
# Extract folder name from torrent
folder_name = read_torrent_name(download_path,
bestqual[0])
# Break for loop
break
else: else:
#Write the torrent file to a path derived from the TORRENTBLACKHOLE_DIR and file name. # No service succeeded
with open(download_path, 'wb') as fp: logger.warning("Unable to convert magnet with hash " \
fp.write(data) "'%s' into a torrent file.", torrent_hash)
return
else:
logger.error("Cannot save magnet link in blackhole. " \
"Please switch your torrent downloader to " \
"Transmission or uTorrent, or allow Headphones " \
"to open or convert magnet links")
return
else:
if bestqual[3] == "rutracker.org":
download_path = rutracker.get_torrent(bestqual[2],
headphones.TORRENTBLACKHOLE_DIR)
try: if not download_path:
os.chmod(download_path, int(headphones.FILE_PERMISSIONS, 8)) return
except: else:
logger.error("Could not change permissions for file: %s", download_path) if not torrent_to_file(download_path, data):
return
# Open the fresh torrent file again so we can extract the # Extract folder name from torrent
# proper torrent name Used later in post-processing. folder_name = read_torrent_name(download_path, bestqual[0])
with open(download_path, 'rb') as fp:
torrent_info = bdecode(fp.read())
folder_name = torrent_info['info'].get('name', '')
logger.info('Torrent folder name: %s' % folder_name)
except Exception as e:
logger.error('Couldn\'t get name from Torrent file: %s. Defaulting to torrent title' % e)
folder_name = bestqual[0]
elif headphones.TORRENT_DOWNLOADER == 1: elif headphones.TORRENT_DOWNLOADER == 1:
logger.info("Sending torrent to Transmission") logger.info("Sending torrent to Transmission")
@@ -699,8 +830,8 @@ def send_to_downloader(data, bestqual, album):
logger.exception("Unhandled exception") logger.exception("Unhandled exception")
# Set Seed Ratio # Set Seed Ratio
seed_ratio = getSeedRatio(bestqual[3]) seed_ratio = get_seed_ratio(bestqual[3])
if seed_ratio != None: if seed_ratio is not None:
transmission.setSeedRatio(torrentid, seed_ratio) transmission.setSeedRatio(torrentid, seed_ratio)
else:# if headphones.TORRENT_DOWNLOADER == 2: else:# if headphones.TORRENT_DOWNLOADER == 2:
@@ -714,7 +845,7 @@ def send_to_downloader(data, bestqual, album):
utorrent.labelTorrent(torrentid) utorrent.labelTorrent(torrentid)
else: else:
file_or_url = bestqual[2] file_or_url = bestqual[2]
torrentid = CalculateTorrentHash(file_or_url, data) torrentid = calculate_torrent_hash(file_or_url, data)
folder_name = utorrent.addTorrent(file_or_url, torrentid) folder_name = utorrent.addTorrent(file_or_url, torrentid)
if folder_name: if folder_name:
@@ -731,8 +862,8 @@ def send_to_downloader(data, bestqual, album):
logger.exception("Unhandled exception") logger.exception("Unhandled exception")
# Set Seed Ratio # Set Seed Ratio
seed_ratio = getSeedRatio(bestqual[3]) seed_ratio = get_seed_ratio(bestqual[3])
if seed_ratio != None: if seed_ratio is not None:
utorrent.setSeedRatio(torrentid, seed_ratio) utorrent.setSeedRatio(torrentid, seed_ratio)
myDB = db.DBConnection() myDB = db.DBConnection()
@@ -740,7 +871,7 @@ def send_to_downloader(data, bestqual, album):
myDB.action('INSERT INTO snatched VALUES( ?, ?, ?, ?, DATETIME("NOW", "localtime"), ?, ?, ?)', [album['AlbumID'], bestqual[0], bestqual[1], bestqual[2], "Snatched", folder_name, kind]) myDB.action('INSERT INTO snatched VALUES( ?, ?, ?, ?, DATETIME("NOW", "localtime"), ?, ?, ?)', [album['AlbumID'], bestqual[0], bestqual[1], bestqual[2], "Snatched", folder_name, kind])
# Store the torrent id so we can check later if it's finished seeding and can be removed # Store the torrent id so we can check later if it's finished seeding and can be removed
if seed_ratio != None and seed_ratio != 0 and torrentid: if seed_ratio is not None and seed_ratio != 0 and torrentid:
myDB.action('INSERT INTO snatched VALUES( ?, ?, ?, ?, DATETIME("NOW", "localtime"), ?, ?, ?)', [album['AlbumID'], bestqual[0], bestqual[1], bestqual[2], "Seed_Snatched", torrentid, kind]) myDB.action('INSERT INTO snatched VALUES( ?, ?, ?, ?, DATETIME("NOW", "localtime"), ?, ?, ?)', [album['AlbumID'], bestqual[0], bestqual[1], bestqual[2], "Seed_Snatched", torrentid, kind])
# notify # notify
@@ -935,9 +1066,9 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
# Use proxy if specified # Use proxy if specified
if headphones.KAT_PROXY_URL: if headphones.KAT_PROXY_URL:
providerurl = url_fix(set_proxy(headphones.KAT_PROXY_URL)) providerurl = fix_url(set_proxy(headphones.KAT_PROXY_URL))
else: else:
providerurl = url_fix("https://kickass.to") providerurl = fix_url("https://kickass.to")
# Build URL # Build URL
providerurl = providerurl + "/usearch/" + ka_term providerurl = providerurl + "/usearch/" + ka_term
@@ -995,7 +1126,7 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
if headphones.WAFFLES: if headphones.WAFFLES:
provider = "Waffles.fm" provider = "Waffles.fm"
providerurl = url_fix("https://www.waffles.fm/browse.php") providerurl = fix_url("https://www.waffles.fm/browse.php")
bitrate = None bitrate = None
if headphones.PREFERRED_QUALITY == 3 or losslessOnly: if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
@@ -1186,9 +1317,9 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
# Use proxy if specified # Use proxy if specified
if headphones.PIRATEBAY_PROXY_URL: if headphones.PIRATEBAY_PROXY_URL:
providerurl = url_fix(set_proxy(headphones.PIRATEBAY_PROXY_URL)) providerurl = fix_url(set_proxy(headphones.PIRATEBAY_PROXY_URL))
else: else:
providerurl = url_fix("https://thepiratebay.se") providerurl = fix_url("https://thepiratebay.se")
# Build URL # Build URL
providerurl = providerurl + "/search/" + tpb_term + "/0/7/" # 7 is sort by seeders providerurl = providerurl + "/search/" + tpb_term + "/0/7/" # 7 is sort by seeders
@@ -1228,7 +1359,7 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
try: try:
url = item.find("a", {"title":"Download this torrent"})['href'] url = item.find("a", {"title":"Download this torrent"})['href']
except TypeError: except TypeError:
if headphones.OPEN_MAGNET_LINKS: if headphones.MAGNET_LINKS != 0:
url = item.findAll("a")[3]['href'] url = item.findAll("a")[3]['href']
else: else:
logger.info('"%s" only has a magnet link, skipping' % title) logger.info('"%s" only has a magnet link, skipping' % title)
@@ -1252,7 +1383,7 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
if headphones.MININOVA: if headphones.MININOVA:
provider = "Mininova" provider = "Mininova"
providerurl = url_fix("http://www.mininova.org/rss/" + term + "/5") providerurl = fix_url("http://www.mininova.org/rss/" + term + "/5")
if headphones.PREFERRED_QUALITY == 3 or losslessOnly: if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
categories = "7" #music categories = "7" #music
@@ -1320,7 +1451,6 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
def preprocess(resultlist): def preprocess(resultlist):
for result in resultlist: for result in resultlist:
if result[4] == 'torrent': if result[4] == 'torrent':
#Get out of here if we're using Transmission #Get out of here if we're using Transmission
if headphones.TORRENT_DOWNLOADER == 1: ## if not a magnet link still need the .torrent to generate hash... uTorrent support labeling if headphones.TORRENT_DOWNLOADER == 1: ## if not a magnet link still need the .torrent to generate hash... uTorrent support labeling
@@ -1329,7 +1459,7 @@ def preprocess(resultlist):
if result[3] == 'rutracker.org': if result[3] == 'rutracker.org':
return True, result return True, result
# Get out of here if it's a magnet link # Get out of here if it's a magnet link
if result[2].startswith("magnet"): if result[2].lower().startswith("magnet:"):
return True, result return True, result
# Download the torrent file # Download the torrent file
@@ -1344,48 +1474,9 @@ def preprocess(resultlist):
return request.request_content(url=result[2], headers=headers), result return request.request_content(url=result[2], headers=headers), result
else: else:
headers = {'User-Agent': USER_AGENT} headers = {'User-Agent': USER_AGENT}
if result[3] == 'headphones': if result[3] == 'headphones':
return request.request_content(url=result[2], headers=headers, auth=(headphones.HPUSER, headphones.HPPASS)), result return request.request_content(url=result[2], headers=headers, auth=(headphones.HPUSER, headphones.HPPASS)), result
else: else:
return request.request_content(url=result[2], headers=headers), result return request.request_content(url=result[2], headers=headers), result
def CalculateTorrentHash(link, data):
if link.startswith('magnet'):
tor_hash = re.findall('urn:btih:([\w]{32,40})', link)[0]
if len(tor_hash) == 32:
tor_hash = b16encode(b32decode(tor_hash)).lower()
else:
info = bdecode(data)["info"]
tor_hash = sha1(bencode(info)).hexdigest()
logger.debug('Torrent Hash: ' + str(tor_hash))
return tor_hash
def getSeedRatio(provider):
seed_ratio = ''
if provider == 'rutracker.org':
seed_ratio = headphones.RUTRACKER_RATIO
elif provider == 'Kick Ass Torrents':
seed_ratio = headphones.KAT_RATIO
elif provider == 'What.cd':
seed_ratio = headphones.WHATCD_RATIO
elif provider == 'The Pirate Bay':
seed_ratio = headphones.PIRATEBAY_RATIO
elif provider == 'Waffles.fm':
seed_ratio = headphones.WAFFLES_RATIO
elif provider == 'Mininova':
seed_ratio = headphones.MININOVA_RATIO
if seed_ratio != '':
try:
seed_ratio_float = float(seed_ratio)
except:
seed_ratio_float = None
logger.warn('Could not get Seed Ratio for %s' % provider)
return seed_ratio_float
else:
return None
+5 -3
View File
@@ -1070,7 +1070,9 @@ class WebInterface(object):
"prefer_torrents_0" : radio(headphones.PREFER_TORRENTS, 0), "prefer_torrents_0" : radio(headphones.PREFER_TORRENTS, 0),
"prefer_torrents_1" : radio(headphones.PREFER_TORRENTS, 1), "prefer_torrents_1" : radio(headphones.PREFER_TORRENTS, 1),
"prefer_torrents_2" : radio(headphones.PREFER_TORRENTS, 2), "prefer_torrents_2" : radio(headphones.PREFER_TORRENTS, 2),
"open_magnet_links" : checked(headphones.OPEN_MAGNET_LINKS), "magnet_links_0" : radio(headphones.MAGNET_LINKS, 0),
"magnet_links_1" : radio(headphones.MAGNET_LINKS, 1),
"magnet_links_2" : radio(headphones.MAGNET_LINKS, 2),
"log_dir" : headphones.LOG_DIR, "log_dir" : headphones.LOG_DIR,
"cache_dir" : headphones.CACHE_DIR, "cache_dir" : headphones.CACHE_DIR,
"interface_list" : interface_list, "interface_list" : interface_list,
@@ -1188,7 +1190,7 @@ class WebInterface(object):
numberofseeders=None, use_piratebay=0, piratebay_proxy_url=None, piratebay_ratio=None, use_kat=0, kat_proxy_url=None, kat_ratio=None, use_mininova=0, mininova_ratio=None, waffles=0, waffles_uid=None, waffles_passkey=None, waffles_ratio=None, whatcd=0, whatcd_username=None, whatcd_password=None, whatcd_ratio=None, numberofseeders=None, use_piratebay=0, piratebay_proxy_url=None, piratebay_ratio=None, use_kat=0, kat_proxy_url=None, kat_ratio=None, use_mininova=0, mininova_ratio=None, waffles=0, waffles_uid=None, waffles_passkey=None, waffles_ratio=None, whatcd=0, whatcd_username=None, whatcd_password=None, whatcd_ratio=None,
rutracker=0, rutracker_user=None, rutracker_password=None, rutracker_ratio=None, rename_files=0, correct_metadata=0, cleanup_files=0, keep_nfo=0, add_album_art=0, album_art_format=None, embed_album_art=0, embed_lyrics=0, replace_existing_folders=False, rutracker=0, rutracker_user=None, rutracker_password=None, rutracker_ratio=None, rename_files=0, correct_metadata=0, cleanup_files=0, keep_nfo=0, add_album_art=0, album_art_format=None, embed_album_art=0, embed_lyrics=0, replace_existing_folders=False,
destination_dir=None, lossless_destination_dir=None, folder_format=None, file_format=None, file_underscores=0, include_extras=0, single=0, ep=0, compilation=0, soundtrack=0, live=0, remix=0, spokenword=0, audiobook=0, other=0, djmix=0, mixtape_street=0, broadcast=0, interview=0, demo=0, destination_dir=None, lossless_destination_dir=None, folder_format=None, file_format=None, file_underscores=0, include_extras=0, single=0, ep=0, compilation=0, soundtrack=0, live=0, remix=0, spokenword=0, audiobook=0, other=0, djmix=0, mixtape_street=0, broadcast=0, interview=0, demo=0,
autowant_upcoming=False, autowant_all=False, autowant_manually_added=False, keep_torrent_files=False, prefer_torrents=0, open_magnet_links=0, interface=None, log_dir=None, cache_dir=None, music_encoder=0, encoder=None, xldprofile=None, autowant_upcoming=False, autowant_all=False, autowant_manually_added=False, keep_torrent_files=False, prefer_torrents=0, magnet_links=0, interface=None, log_dir=None, cache_dir=None, music_encoder=0, encoder=None, xldprofile=None,
bitrate=None, samplingfrequency=None, encoderfolder=None, advancedencoder=None, encoderoutputformat=None, encodervbrcbr=None, encoderquality=None, encoderlossless=0, subsonic_enabled=False, subsonic_host=None, subsonic_username=None, subsonic_password=None, bitrate=None, samplingfrequency=None, encoderfolder=None, advancedencoder=None, encoderoutputformat=None, encodervbrcbr=None, encoderquality=None, encoderlossless=0, subsonic_enabled=False, subsonic_host=None, subsonic_username=None, subsonic_password=None,
delete_lossless_files=0, growl_enabled=0, growl_onsnatch=0, growl_host=None, growl_password=None, prowl_enabled=0, prowl_onsnatch=0, prowl_keys=None, prowl_priority=0, xbmc_enabled=0, xbmc_host=None, xbmc_username=None, xbmc_password=None, delete_lossless_files=0, growl_enabled=0, growl_onsnatch=0, growl_host=None, growl_password=None, prowl_enabled=0, prowl_onsnatch=0, prowl_keys=None, prowl_priority=0, xbmc_enabled=0, xbmc_host=None, xbmc_username=None, xbmc_password=None,
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, 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,
@@ -1302,7 +1304,7 @@ class WebInterface(object):
headphones.AUTOWANT_MANUALLY_ADDED = autowant_manually_added headphones.AUTOWANT_MANUALLY_ADDED = autowant_manually_added
headphones.KEEP_TORRENT_FILES = keep_torrent_files headphones.KEEP_TORRENT_FILES = keep_torrent_files
headphones.PREFER_TORRENTS = int(prefer_torrents) headphones.PREFER_TORRENTS = int(prefer_torrents)
headphones.OPEN_MAGNET_LINKS = open_magnet_links headphones.MAGNET_LINKS = int(magnet_links)
headphones.INTERFACE = interface headphones.INTERFACE = interface
headphones.LOG_DIR = log_dir headphones.LOG_DIR = log_dir
headphones.CACHE_DIR = cache_dir headphones.CACHE_DIR = cache_dir