Multi Newznab provider support

This commit is contained in:
Ruud committed 2011-08-20 16:29:51 +02:00
1 parent 96822fb5a0
commit dcf8ac7ada
5 files changed
+200 -40

No files matched your search

+25 -24
View File
@@ -2,10 +2,12 @@ from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin from couchpotato.core.plugins.base import Plugin
from couchpotato.environment import Env from couchpotato.environment import Env
from urllib2 import URLError from urllib2 import URLError
from urlparse import urlparse
import math import math
import re import re
import socket import socket
import time import time
import urllib
import urllib2 import urllib2
log = CPLog(__name__) log = CPLog(__name__)
@@ -16,9 +18,9 @@ class Provider(Plugin):
type = None # movie, nzb, torrent, subtitle, trailer type = None # movie, nzb, torrent, subtitle, trailer
time_between_searches = 10 # Default timeout for url requests time_between_searches = 10 # Default timeout for url requests
last_use = 0 last_use = {}
last_available_check = 0 last_available_check = {}
is_available = 0 is_available = {}
def getCache(self, cache_key): def getCache(self, cache_key):
cache = Env.get('cache').get(cache_key) cache = Env.get('cache').get(cache_key)
@@ -35,49 +37,48 @@ class Provider(Plugin):
if Env.get('debug'): return True if Env.get('debug'): return True
now = time.time() now = time.time()
host = urlparse(test_url).hostname
if self.last_available_check < now - 900: if self.last_available_check.get(host) < now - 900:
self.last_available_check = now self.last_available_check[host] = now
try: try:
self.urlopen(test_url, 30) self.urlopen(test_url, 30)
self.is_available = True self.is_available[host] = True
except (IOError, URLError): except (IOError, URLError):
log.error('%s unavailable, trying again in an 15 minutes.' % self.name) log.error('%s unavailable, trying again in an 15 minutes.' % self.name)
self.is_available = False self.is_available[host] = False
return self.is_available return self.is_available[host]
def urlopen(self, url, timeout = 10, username = None, password = None): def urlopen(self, url, timeout = 10, params = {}):
socket.setdefaulttimeout(timeout) socket.setdefaulttimeout(timeout)
self.wait()
host = urlparse(url).hostname
self.wait(host)
try: try:
log.info('Opening url: %s' % url) log.info('Opening url: %s, params: %s' % (url, params))
if username and password: request = urllib2.Request(url, urllib.urlencode(params))
passman = urllib2.HTTPPasswordMgrWithDefaultRealm() data = urllib2.urlopen(request).read()
passman.add_password(None, url, username, password)
authhandler = urllib2.HTTPBasicAuthHandler(passman)
opener = urllib2.build_opener(authhandler)
data = opener.open(url).read()
else:
data = urllib2.urlopen(url).read()
except IOError, e: except IOError, e:
log.error('Failed opening url, %s: %s' % (url, e)) log.error('Failed opening url, %s: %s' % (url, e))
data = '' data = ''
self.last_use = time.time() self.last_use[host] = time.time()
return data return data
def wait(self): def wait(self, host = ''):
now = time.time() now = time.time()
wait = math.ceil(self.last_use - now + self.time_between_searches)
last_use = self.last_use.get(host, 0)
wait = math.ceil(last_use - now + self.time_between_searches)
if wait > 0: if wait > 0:
log.debug('Waiting for %s, %d seconds' % (self.getName(), wait)) log.debug('Waiting for %s, %d seconds' % (self.getName(), wait))
time.sleep(self.last_use - now + self.time_between_searches) time.sleep(last_use - now + self.time_between_searches)
class MovieProvider(Provider): class MovieProvider(Provider):
@@ -9,11 +9,16 @@ config = [{
{ {
'tab': 'providers', 'tab': 'providers',
'name': 'newznab', 'name': 'newznab',
'description': 'Enable multiple NewzNab providers',
'options': [ 'options': [
{ {
'name': 'enabled', 'name': 'enabled',
'type': 'enabler', 'type': 'enabler',
}, },
{
'name': 'use',
'default': '0'
},
{ {
'name': 'host', 'name': 'host',
'default': 'http://nzb.su', 'default': 'http://nzb.su',
@@ -23,7 +28,7 @@ config = [{
'name': 'api_key', 'name': 'api_key',
'default': '', 'default': '',
'label': 'Api Key', 'label': 'Api Key',
'description': 'Can be found after login on the "API" page, bottom left. The string after "&amp;apikey=".', 'description': 'Can be found on your profile page',
}, },
], ],
}, },
+29 -14
View File
@@ -35,26 +35,41 @@ class Newznab(NZBProvider, RSS):
addEvent('provider.nzb.search', self.search) addEvent('provider.nzb.search', self.search)
addEvent('provider.yarr.search', self.search) addEvent('provider.yarr.search', self.search)
def getUrl(self, type): self.registerStatic(__file__)
return cleanHost(self.conf('host')) + 'api?t=' + type
def getUrl(self, host, type):
return cleanHost(host) + 'api?t=' + type
def search(self, movie, quality): def search(self, movie, quality):
uses = str(self.conf('use')).split(',')
hosts = self.conf('host').split(',')
api_keys = self.conf('api_key').split(',')
for nr in range(len(hosts)):
self.singleSearch({
'use': uses[nr],
'host': hosts[nr],
'api_key': api_keys[nr]
}, movie, quality)
def singleSearch(self, host, movie, quality):
results = [] results = []
if self.isDisabled() or not self.isAvailable(self.getUrl(self.urls['search'])): if self.isDisabled(host) or not self.isAvailable(self.getUrl(host['host'], self.urls['search'])):
return results return results
cat_id = self.getCatId(quality['identifier']) cat_id = self.getCatId(quality['identifier'])
arguments = urlencode({ arguments = urlencode({
'imdbid': movie['library']['identifier'].replace('tt', ''), 'imdbid': movie['library']['identifier'].replace('tt', ''),
'cat': cat_id[0], 'cat': cat_id[0],
'apikey': self.conf('api_key'), 'apikey': host['api_key'],
't': self.urls['search'], 't': self.urls['search'],
'extended': 1 'extended': 1
}) })
url = "%s&%s" % (self.getUrl(self.urls['search']), arguments) url = "%s&%s" % (self.getUrl(host['host'], self.urls['search']), arguments)
cache_key = 'newznab.%s.%s' % (movie['library']['identifier'], cat_id[0]) cache_key = 'newznab.%s.%s.%s' % (host['host'], movie['library']['identifier'], cat_id[0])
single_cat = (len(cat_id) == 1 and cat_id[0] != self.cat_backup_id) single_cat = (len(cat_id) == 1 and cat_id[0] != self.cat_backup_id)
try: try:
@@ -91,8 +106,8 @@ class Newznab(NZBProvider, RSS):
'name': self.getTextElement(nzb, "title"), 'name': self.getTextElement(nzb, "title"),
'age': self.calculateAge(int(time.mktime(parse(date).timetuple()))), 'age': self.calculateAge(int(time.mktime(parse(date).timetuple()))),
'size': int(size) / 1024 / 1024, 'size': int(size) / 1024 / 1024,
'url': (self.getUrl(self.urls['download']) % id) + self.getApiExt(), 'url': (self.getUrl(host['host'], self.urls['download']) % id) + self.getApiExt(host),
'detail_url': (self.getUrl(self.urls['detail']) % id) + self.getApiExt(), 'detail_url': (self.getUrl(host['host'], self.urls['detail']) % id) + self.getApiExt(host),
'content': self.getTextElement(nzb, "description"), 'content': self.getTextElement(nzb, "description"),
} }
new['score'] = fireEvent('score.calculate', new, movie, single = True) new['score'] = fireEvent('score.calculate', new, movie, single = True)
@@ -112,11 +127,11 @@ class Newznab(NZBProvider, RSS):
return results return results
def isEnabled(self): def isDisabled(self, host):
return NZBProvider.isEnabled(self) and self.conf('host') and self.conf('api_key') return not self.isEnabled(host)
def getApiExt(self): def isEnabled(self, host):
return '&apikey=%s' % self.conf('api_key') return NZBProvider.isEnabled(self) and host['host'] and host['api_key'] and int(host['use'])
def detailLink(self, id): def getApiExt(self, host):
return self.getUrl(self.detailUrl) % id return '&apikey=%s' % host['api_key']
@@ -0,0 +1,137 @@
var MultipleNewznab = new Class({
input_types: ['use', 'host', 'api_key'],
initialize: function(){
var self = this;
self.items = [];
self.values = [];
self.inputs = {};
App.addEvent('load', self.addSettings.bind(self))
},
addSettings: function(){
var self = this;
self.settings = App.getPage('Settings')
self.settings.addEvent('create', function(){
self.fieldset = self.settings.tabs.providers.content.getElement('.section_newznab');
self.input_types.each(function(name){
self.inputs[name] = self.fieldset.getElement('input[name=newznab['+name+']]');
var values = self.inputs[name].get('value').split(',');
values.each(function(value, nr){
if (!self.values[nr]) self.values[nr] = {};
self.values[nr][name] = value.trim();
});
self.inputs[name].getParent().hide()
});
self.values.each(function(item, nr){
self.createItem(item.use, item.host, item.api_key);
});
new Element('a.nice_button', {
'text': 'Add new NewzNab provider',
'events': {
'click': function(e){
(e).stop();
self.createItem(1, '', '');
}
}
}).inject(self.fieldset.getElement('h2'), 'after');
})
},
createItem: function(use, host, api){
var self = this;
var checkbox = new Element('input[type=checkbox].use.inlay', {
'checked': +use,
'events': {
'click': self.save.bind(self),
'change': self.save.bind(self)
}
})
var item = new Element('div.ctrlHolder').adopt(
checkbox,
new Element('input[type=text].host.inlay', {
'value': host,
'placeholder': 'Host',
'events': {
'keyup': self.save.bind(self),
'change': self.save.bind(self)
}
}),
new Element('input[type=text].api_key.inlay', {
'value': api,
'placeholder': 'Api hash key',
'events': {
'keyup': self.save.bind(self),
'change': self.save.bind(self)
}
}),
new Element('a.icon.delete', {
'text': 'delete',
'events': {
'click': self.deleteItem.bind(self)
}
})
).inject(self.fieldset);
new Form.Check(checkbox, {
'onChange': checkbox.fireEvent.bind(checkbox, 'change')
});
self.items.include(item)
},
save: function(){
var self = this;
var temp = {}
self.items.each(function(item, nr){
self.input_types.each(function(type){
var input = item.getElement('input.'+type);
if(!temp[type]) temp[type] = [];
temp[type][nr] = input.get('type') == 'checkbox' ? +input.get('checked') : input.get('value').trim();
})
});
self.input_types.each(function(name){
self.inputs[name].set('value', temp[name].join(','));
self.inputs[name].fireEvent('change');
});
},
deleteItem: function(e){
var self = this;
(e).stop();
var item = e.target.getParent();
self.items.erase(item);
item.destroy();
self.save();
}
});
window.MNewznab = new MultipleNewznab();
+3 -1
View File
@@ -121,7 +121,9 @@ Page.Settings = new Class({
// Create the group // Create the group
if(!self.tabs[group.tab].groups[group.name]){ if(!self.tabs[group.tab].groups[group.name]){
var group_el = self.createGroup(group).inject(self.tabs[group.tab].content); var group_el = self.createGroup(group)
.inject(self.tabs[group.tab].content)
.addClass('section_'+section_name);
self.tabs[group.tab].groups[group.name] = group_el self.tabs[group.tab].groups[group.name] = group_el
} }