Implemented Jackett (Custom Torznab) option for Torrent Search Providers

This commit is contained in:
unknown
2015-08-23 11:34:22 -06:00
parent 8c94c9ecbf
commit 61bdab8621
4 changed files with 190 additions and 4 deletions

View File

@@ -516,6 +516,59 @@
<fieldset>
<legend>Torrents</legend>
<fieldset>
<div class="row checkbox left">
<input id="use_torznab" type="checkbox" class="bigcheck" name="use_torznab" value="1" ${config['use_torznab']} /><label for="use_torznab"><span class="option">Jackett / Torznab Providers</span></label>
</div>
<div id="torznab_providers">
<div class="config" id="torznab1">
<div class="row">
<label>Torznab Host</label>
<input type="text" name="torznab_host" value="${config['torznab_host']}" size="30">
<small>e.g. http://localhost:9117/torznab/iptorrents</small>
</div>
<div class="row">
<label>Torznab API</label>
<input type="text" name="torznab_apikey" value="${config['torznab_apikey']}" size="36">
</div>
<div class="row checkbox">
<input id="torznab_enabled" type="checkbox" name="torznab_enabled" value="1" ${config['torznab_enabled']} /><label>Enabled</label>
</div>
</div>
<%
torznab_number = 2
%>
%for torznab in config['extra_torznabs']:
<%
if torznab[2] == '1' or torznab[2] == 1:
torznab_enabled = "checked"
else:
torznab_enabled = ""
%>
<div class="config" id="torznab${torznab_number}">
<div class="row">
<label>Torznab Host</label>
<input type="text" name="torznab_host${torznab_number}" value="${torznab[0]}" size="30">
</div>
<div class="row">
<label>Torznab API</label>
<input type="text" name="Torznab_api${torznab_number}" value="${torznab[1]}" size="36">
</div>
<div class="row checkbox">
<input id="torznab_enabled" type="checkbox" name="torznab_enabled${torznab_number}" value="1" ${torznab_enabled} /><label>Enabled</label>
</div>
<div class="row">
<input type="button" class="remove" id="torznab${torznab_number}" value="Remove ${torznab[0]}">
</div>
</div>
<%
torznab_number += 1
%>
%endfor
<input type="button" value="Add Torznab" class="add_torznab" id="add_torznab" />
</div>
</fieldset>
<fieldset>
<div class="row checkbox left">
<input id="use_piratebay" type="checkbox" class="bigcheck" name="use_piratebay" value="1" ${config['use_piratebay']} /><label for="use_piratebay"><span class="option">The Pirate Bay</span></label>
@@ -2152,11 +2205,18 @@
var deletedNewznabs = 0;
$(".remove").click(function() {
$(".removeNewznab").click(function() {
$(this).parent().parent().remove();
deletedNewznabs = deletedNewznabs + 1;
});
var deletedTorznabs = 0;
$(".removeTorznab").click(function() {
$(this).parent().parent().remove();
deletedTorznabs = deletedTorznabs + 1;
});
$("#modify_extras").click(openExtrasDialog);
$("#include_extras").click(function(){
@@ -2179,7 +2239,7 @@
$("#add_newznab").click(function() {
var intId = $("#newznab_providers > div").size() + deletedNewznabs + 1;
var formfields = $("<div class=\"config\" id=\"newznab" + intId + "\"><div class=\"row\"><label>Newznab Host</label><input type=\"text\" name=\"newznab_host" + intId + "\" size=\"30\"></div><div class=\"row\"><label>Newznab API</label><input type=\"text\" name=\"newznab_api" + intId + "\" size=\"36\"></div><div class=\"row checkbox\"><input type=\"checkbox\" name=\"newznab_enabled" + intId + "\" value=\"1\" checked /><label>Enabled</label></div>");
var removeButton = $("<div class=\"row\"><input type=\"button\" class=\"remove\" value=\"Remove\" /></div>");
var removeButton = $("<div class=\"row\"><input type=\"button\" class=\"removeNewznab\" value=\"Remove\" /></div>");
removeButton.click(function() {
$(this).parent().remove();
deletedNewznabs = deletedNewznabs + 1;
@@ -2190,6 +2250,20 @@
$("#add_newznab").before(formfields);
});
$("#add_torznab").click(function() {
var intId = $("#torznab_providers > div").size() + deletedTorznabs + 1;
var formfields = $("<div class=\"config\" id=\"torznab" + intId + "\"><div class=\"row\"><label>Torznab Host</label><input type=\"text\" name=\"torznab_host" + intId + "\" size=\"30\"></div><div class=\"row\"><label>Torznab API</label><input type=\"text\" name=\"torznab_api" + intId + "\" size=\"36\"></div><div class=\"row checkbox\"><input type=\"checkbox\" name=\"torznab_enabled" + intId + "\" value=\"1\" checked /><label>Enabled</label></div>");
var removeButton = $("<div class=\"row\"><input type=\"button\" class=\"removeTorznab\" value=\"Remove\" /></div>");
removeButton.click(function() {
$(this).parent().remove();
deletedTorznabs = deletedTorznabs + 1;
});
formfields.append(removeButton);
formfields.append("</div>");
$("#add_torznab").before(formfields);
});
$(".hpuser").keyup(function() {
$(".hpuser").val($(this).val());
});
@@ -2206,6 +2280,7 @@
initConfigCheckbox("#use_newznab");
initConfigCheckbox("#use_nzbsorg");
initConfigCheckbox("#use_omgwtfnzbs");
initConfigCheckbox("#use_torznab");
initConfigCheckbox("#use_kat");
initConfigCheckbox("#use_piratebay");
initConfigCheckbox("#use_oldpiratebay");

View File

@@ -81,6 +81,7 @@ _CONFIG_DEFINITIONS = {
'ENCODER_PATH': (str, 'General', ''),
'EXTRAS': (str, 'General', ''),
'EXTRA_NEWZNABS': (list, 'Newznab', ''),
'EXTRA_TORZNABS': (list, 'Torznab', ''),
'FILE_FORMAT': (str, 'General', 'Track Artist - Album [Year] - Title'),
'FILE_PERMISSIONS': (str, 'General', '0644'),
'FILE_UNDERSCORES': (int, 'General', 0),
@@ -140,6 +141,10 @@ _CONFIG_DEFINITIONS = {
'NEWZNAB_APIKEY': (str, 'Newznab', ''),
'NEWZNAB_ENABLED': (int, 'Newznab', 1),
'NEWZNAB_HOST': (str, 'Newznab', ''),
'TORZNAB': (int, 'Torznab', 0),
'TORZNAB_APIKEY': (str, 'Torznab', ''),
'TORZNAB_ENABLED': (int, 'Torznab', 1),
'TORZNAB_HOST': (str, 'Torznab', ''),
'NMA_APIKEY': (str, 'NMA', ''),
'NMA_ENABLED': (int, 'NMA', 0),
'NMA_ONSNATCH': (int, 'NMA', 0),
@@ -351,6 +356,25 @@ class Config(object):
extra_newznabs.append(item)
self.EXTRA_NEWZNABS = extra_newznabs
def get_extra_torznabs(self):
""" Return the extra torznab tuples """
extra_torznabs = list(
itertools.izip(*[itertools.islice(self.EXTRA_TORZNABS, i, None, 3)
for i in range(3)])
)
return extra_torznabs
def clear_extra_torznabs(self):
""" Forget about the configured extra torznabs """
self.EXTRA_TORZNABS = []
def add_extra_torznab(self, torznab):
""" Add a new extra torznab """
extra_torznabs = self.EXTRA_TORZNABS
for item in torznab:
extra_torznabs.append(item)
self.EXTRA_TORZNABS = extra_torznabs
def __getattr__(self, name):
"""
Returns something from the ini unless it is a real property

View File

@@ -228,7 +228,7 @@ def do_sorted_search(album, new, losslessOnly, choose_specific_download=False):
NZB_PROVIDERS = (headphones.CONFIG.HEADPHONES_INDEXER or headphones.CONFIG.NEWZNAB or headphones.CONFIG.NZBSORG or headphones.CONFIG.OMGWTFNZBS)
NZB_DOWNLOADERS = (headphones.CONFIG.SAB_HOST or headphones.CONFIG.BLACKHOLE_DIR or headphones.CONFIG.NZBGET_HOST)
TORRENT_PROVIDERS = (headphones.CONFIG.KAT or headphones.CONFIG.PIRATEBAY or headphones.CONFIG.OLDPIRATEBAY or headphones.CONFIG.MININOVA or headphones.CONFIG.WAFFLES or headphones.CONFIG.RUTRACKER or headphones.CONFIG.WHATCD)
TORRENT_PROVIDERS = (headphones.CONFIG.TORZNAB or headphones.CONFIG.KAT or headphones.CONFIG.PIRATEBAY or headphones.CONFIG.OLDPIRATEBAY or headphones.CONFIG.MININOVA or headphones.CONFIG.WAFFLES or headphones.CONFIG.RUTRACKER or headphones.CONFIG.WHATCD)
results = []
myDB = db.DBConnection()
@@ -1086,6 +1086,68 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None, choose
return proxy_url
if headphones.CONFIG.TORZNAB:
provider = "torznab"
torznab_hosts = []
if headphones.CONFIG.TORZNAB_HOST and headphones.CONFIG.TORZNAB_ENABLED:
torznab_hosts.append((headphones.CONFIG.TORZNAB_HOST, headphones.CONFIG.TORZNAB_APIKEY, headphones.CONFIG.TORZNAB_ENABLED))
for torznab_host in headphones.CONFIG.get_extra_torznabs():
if torznab_host[2] == '1' or torznab_host[2] == 1:
torznab_hosts.append(torznab_host)
if headphones.CONFIG.PREFERRED_QUALITY == 3 or losslessOnly:
categories = "3040"
elif headphones.CONFIG.PREFERRED_QUALITY == 1 or allow_lossless:
categories = "3040,3010"
else:
categories = "3010"
if album['Type'] == 'Other':
categories = "3030"
logger.info("Album type is audiobook/spokenword. Using audiobook category")
for torznab_host in torznab_hosts:
provider = torznab_host[0]
# Request results
logger.info('Parsing results from %s using search term: %s' % (torznab_host[0],term))
headers = {'User-Agent': USER_AGENT}
params = {
"t": "search",
"apikey": torznab_host[1],
"cat": categories,
"maxage": headphones.CONFIG.USENET_RETENTION,
"q": term
}
data = request.request_feed(
url=torznab_host[0] + '/api?',
params=params, headers=headers
)
# Process feed
if data:
if not len(data.entries):
logger.info(u"No results found from %s for %s", torznab_host[0], term)
else:
for item in data.entries:
try:
url = item.link
title = item.title
size = int(item.links[1]['length'])
if all(word.lower() in title.lower() for word in term.split()):
logger.info('Found %s. Size: %s' % (title, helpers.bytes_to_mb(size)))
resultlist.append((title, size, url, provider, 'torrent', True))
else:
logger.info('Skipping %s, not all search term words found' % title)
except Exception as e:
logger.exception("An unknown error occurred trying to parse the feed: %s" % e)
if headphones.CONFIG.KAT:
provider = "Kick Ass Torrents"
ka_term = term.replace("!", "")

View File

@@ -1065,6 +1065,11 @@ class WebInterface(object):
"newznab_apikey": headphones.CONFIG.NEWZNAB_APIKEY,
"newznab_enabled": checked(headphones.CONFIG.NEWZNAB_ENABLED),
"extra_newznabs": headphones.CONFIG.get_extra_newznabs(),
"use_torznab": checked(headphones.CONFIG.TORZNAB),
"torznab_host": headphones.CONFIG.TORZNAB_HOST,
"torznab_apikey": headphones.CONFIG.TORZNAB_APIKEY,
"torznab_enabled": checked(headphones.CONFIG.TORZNAB_ENABLED),
"extra_torznabs": headphones.CONFIG.get_extra_torznabs(),
"use_nzbsorg": checked(headphones.CONFIG.NZBSORG),
"nzbsorg_uid": headphones.CONFIG.NZBSORG_UID,
"nzbsorg_hash": headphones.CONFIG.NZBSORG_HASH,
@@ -1278,7 +1283,7 @@ class WebInterface(object):
# Handle the variable config options. Note - keys with False values aren't getting passed
checked_configs = [
"launch_browser", "enable_https", "api_enabled", "use_blackhole", "headphones_indexer", "use_newznab", "newznab_enabled",
"launch_browser", "enable_https", "api_enabled", "use_blackhole", "headphones_indexer", "use_newznab", "newznab_enabled", "use_torznab", "torznab_enabled",
"use_nzbsorg", "use_omgwtfnzbs", "use_kat", "use_piratebay", "use_oldpiratebay", "use_mininova", "use_waffles", "use_rutracker",
"use_whatcd", "preferred_bitrate_allow_lossless", "detect_bitrate", "ignore_clean_releases", "freeze_db", "cue_split", "move_files",
"rename_files", "correct_metadata", "cleanup_files", "keep_nfo", "add_album_art", "embed_album_art", "embed_lyrics",
@@ -1316,6 +1321,21 @@ class WebInterface(object):
del kwargs[key]
extra_newznabs.append((newznab_host, newznab_api, newznab_enabled))
extra_torznabs = []
for kwarg in [x for x in kwargs if x.startswith('torznab_host')]:
torznab_host_key = kwarg
torznab_number = kwarg[12:]
if len(torznab_number):
torznab_api_key = 'torznab_api' + torznab_number
torznab_enabled_key = 'torznab_enabled' + torznab_number
torznab_host = kwargs.get(torznab_host_key, '')
torznab_api = kwargs.get(torznab_api_key, '')
torznab_enabled = int(kwargs.get(torznab_enabled_key, 0))
for key in [torznab_host_key, torznab_api_key, torznab_enabled_key]:
if key in kwargs:
del kwargs[key]
extra_torznabs.append((torznab_host, torznab_api, torznab_enabled))
# Convert the extras to list then string. Coming in as 0 or 1 (append new extras to the end)
temp_extras_list = []
@@ -1346,6 +1366,11 @@ class WebInterface(object):
for extra_newznab in extra_newznabs:
headphones.CONFIG.add_extra_newznab(extra_newznab)
headphones.CONFIG.clear_extra_torznabs()
headphones.CONFIG.process_kwargs(kwargs)
for extra_torznab in extra_torznabs:
headphones.CONFIG.add_extra_torznab(extra_torznab)
# Sanity checking
if headphones.CONFIG.SEARCH_INTERVAL and headphones.CONFIG.SEARCH_INTERVAL < 360:
logger.info("Search interval too low. Resetting to 6 hour minimum")