Merge branch 'downloaders_test' of git://github.com/mikke89/CouchPotatoServer into mikke89-downloaders_test

Conflicts:
	couchpotato/core/downloaders/rtorrent/main.py
This commit is contained in:
Ruud
2014-02-24 22:07:49 +01:00
12 changed files with 235 additions and 6 deletions

View File

@@ -49,6 +49,7 @@ class ClientScript(Plugin):
'scripts/page/settings.js',
'scripts/page/about.js',
'scripts/page/manage.js',
'scripts/misc/downloaders.js',
],
}

View File

@@ -1,4 +1,5 @@
from base64 import b32decode, b16encode
from couchpotato.api import addApiView
from couchpotato.core.event import addEvent
from couchpotato.core.helpers.variable import mergeDicts
from couchpotato.core.logger import CPLog
@@ -14,6 +15,7 @@ class Downloader(Provider):
protocol = []
http_time_between_calls = 0
status_support = True
testable = False
torrent_sources = [
'http://torrage.com/torrent/%s.torrent',
@@ -42,6 +44,8 @@ class Downloader(Provider):
addEvent('download.remove_failed', self._removeFailed)
addEvent('download.pause', self._pause)
addEvent('download.process_complete', self._processComplete)
addApiView('download.%s.is_testable' % self.getName().lower(), self.isTestable)
addApiView('download.%s.test' % self.getName().lower(), self._test)
def getEnabledProtocol(self):
for download_protocol in self.protocol:
@@ -158,6 +162,18 @@ class Downloader(Provider):
(d_manual and manual or d_manual is False) and \
(not data or self.isCorrectProtocol(data.get('protocol')))
def isTestable(self):
return {'success': self.testable}
def _test(self):
t = self.test()
if isinstance(t,tuple):
return {'success': t[0], 'msg': t[1] }
return {'success': t }
def test(self):
return False
def _pause(self, release_download, pause = True):
if self.isDisabled(manual = True, data = {}):
return

View File

@@ -19,19 +19,25 @@ class Deluge(Downloader):
protocol = ['torrent', 'torrent_magnet']
log = CPLog(__name__)
drpc = None
testable = True
def connect(self):
def connect(self, reconnect = False):
# Load host from config and split out port.
host = cleanHost(self.conf('host'), protocol = False).split(':')
if not isInt(host[1]):
log.error('Config properties are not filled in correctly, port is missing.')
return False
if not self.drpc:
if not self.drpc or reconnect:
self.drpc = DelugeRPC(host[0], port = host[1], username = self.conf('username'), password = self.conf('password'))
return self.drpc
def test(self):
if self.connect(True) and self.drpc.test():
return True
return False
def download(self, data = None, media = None, filedata = None):
if not media: media = {}
if not data: data = {}
@@ -178,6 +184,13 @@ class DelugeRPC(object):
self.client = DelugeClient()
self.client.connect(self.host, int(self.port), self.username, self.password)
def test(self):
try:
self.connect()
except:
return False
return True
def add_torrent_magnet(self, torrent, options):
torrent_id = False
try:

View File

@@ -18,6 +18,28 @@ class NZBGet(Downloader):
protocol = ['nzb']
rpc = 'xmlrpc'
testable = True
def test(self):
url = cleanHost(host = self.conf('host'), ssl = self.conf('ssl'), username = self.conf('username'), password = self.conf('password')) + self.rpc
rpc = xmlrpclib.ServerProxy(url)
try:
if rpc.writelog('INFO', 'CouchPotato connected to test connection'):
log.debug('Successfully connected to NZBGet')
else:
log.info('Successfully connected to NZBGet, but unable to send a message')
except socket.error:
log.error('NZBGet is not responding. Please ensure that NZBGet is running and host setting is correct.')
return False
except xmlrpclib.ProtocolError as e:
if e.errcode == 401:
log.error('Password is incorrect.')
else:
log.error('Protocol Error: %s', e)
return False
return True
def download(self, data = None, media = None, filedata = None):
if not media: media = {}

View File

@@ -24,6 +24,15 @@ class NZBVortex(Downloader):
protocol = ['nzb']
api_level = None
session_id = None
testable = True
def test(self):
try:
login_result = self.login()
except:
return False
return login_result
def download(self, data = None, media = None, filedata = None):
if not media: media = {}

View File

@@ -19,6 +19,8 @@ class rTorrent(Downloader):
protocol = ['torrent', 'torrent_magnet']
rt = None
testable = True
error_msg = ''
# Migration url to host options
def __init__(self):
@@ -49,7 +51,7 @@ class rTorrent(Downloader):
def connect(self):
# Already connected?
if self.rt is not None:
if not reconnect and self.rt is not None:
return self.rt
url = cleanHost(self.conf('host'), protocol = True, ssl = self.conf('ssl'))
@@ -68,9 +70,25 @@ class rTorrent(Downloader):
else:
self.rt = RTorrent(url)
self.error_msg = ''
try:
self.rt._verify_conn()
except AssertionError as e:
self.error_msg = e.message
self.rt = None
return self.rt
def updateProviderGroup(self, name, data):
def test(self):
if self.connect(True):
return True
if self.error_msg:
return False, 'Connection failed: ' + self.error_msg
return False
def _update_provider_group(self, name, data):
if data.get('seed_time'):
log.info('seeding time ignored, not supported')

View File

@@ -15,6 +15,27 @@ log = CPLog(__name__)
class Sabnzbd(Downloader):
protocol = ['nzb']
testable = True
def test(self):
try:
sab_data = self.call({
'mode': 'version',
})
v = sab_data.split('.')
if int(v[0]) == 0 and int(v[1]) < 7:
return False, 'Your Sabnzbd client is too old, please update to newest version.'
# the version check will work even with wrong api key, so we need the next check as well
sab_data = self.call({
'mode': 'qstatus',
})
if not sab_data:
return False
except:
return False
return True
def download(self, data = None, media = None, filedata = None):
if not media: media = {}

View File

@@ -13,6 +13,17 @@ class Synology(Downloader):
protocol = ['nzb', 'torrent', 'torrent_magnet']
status_support = False
testable = True
def test(self):
host = cleanHost(self.conf('host'), protocol = False).split(':')
try:
srpc = SynologyRPC(host[0], host[1], self.conf('username'), self.conf('password'))
test_result = srpc.test()
except:
return False
return test_result
def download(self, data = None, media = None, filedata = None):
if not media: media = {}
@@ -147,3 +158,6 @@ class SynologyRPC(object):
self._logout()
return result
def test(self):
return bool(self._login())

View File

@@ -18,19 +18,25 @@ class Transmission(Downloader):
protocol = ['torrent', 'torrent_magnet']
log = CPLog(__name__)
trpc = None
testable = True
def connect(self):
def connect(self, reconnect = False):
# Load host from config and split out port.
host = cleanHost(self.conf('host'), protocol = False).split(':')
if not isInt(host[1]):
log.error('Config properties are not filled in correctly, port is missing.')
return False
if not self.trpc:
if not self.trpc or reconnect:
self.trpc = TransmissionRPC(host[0], port = host[1], rpc_url = self.conf('rpc_url').strip('/ '), username = self.conf('username'), password = self.conf('password'))
return self.trpc
def test(self):
if self.connect(True) and self.trpc.get_session():
return True
return False
def download(self, data = None, media = None, filedata = None):
if not media: media = {}
if not data: data = {}

View File

@@ -1,5 +1,6 @@
from base64 import b16encode, b32decode
from bencode import bencode as benc, bdecode
from couchpotato.api import addApiView
from couchpotato.core.downloaders.base import Downloader, ReleaseDownloadList
from couchpotato.core.helpers.encoding import isInt, ss, sp
from couchpotato.core.helpers.variable import tryInt, tryFloat, cleanHost
@@ -24,6 +25,7 @@ class uTorrent(Downloader):
protocol = ['torrent', 'torrent_magnet']
utorrent_api = None
testable = True
status_flags = {
'STARTED' : 1,
'CHECKING' : 2,
@@ -46,6 +48,17 @@ class uTorrent(Downloader):
return self.utorrent_api
def test(self):
if self.connect():
build_version = self.utorrent_api.get_build()
if not build_version:
return False
if build_version < 25406: # This build corresponds to version 3.0.0 stable
return False, 'Your uTorrent client is too old, please update to newest version.'
return True
return False
def download(self, data = None, media = None, filedata = None):
if not media: media = {}
if not data: data = {}
@@ -322,3 +335,10 @@ class uTorrentAPI(object):
def get_files(self, hash):
action = 'action=getfiles&hash=%s' % hash
return self._request(action)
def get_build(self):
data = self._request('')
if not data:
return False
response = json.loads(data)
return int(response.get('build'))

View File

@@ -0,0 +1,82 @@
var DownloadersBase = new Class({
Implements: [Events],
initialize: function(){
var self = this;
// Add test buttons to settings page
App.addEvent('load', self.addTestButtons.bind(self));
},
// Downloaders setting tests
addTestButtons: function(){
var self = this;
var setting_page = App.getPage('Settings');
setting_page.addEvent('create', function(){
Object.each(setting_page.tabs.downloaders.groups, self.addTestButton.bind(self))
})
},
addTestButton: function(fieldset, plugin_name){
var self = this,
button_name = self.testButtonName(fieldset);
if(button_name.contains('Downloaders')) return;
Api.request('download.'+plugin_name+'.is_testable', {
'onComplete': function(json){
if(json.success){
// Only add test button if downloader is testable
new Element('.ctrlHolder.test_button').adopt(
new Element('a.button', {
'text': button_name,
'events': {
'click': function(){
var button = fieldset.getElement('.test_button .button');
button.set('text', 'Connecting...');
Api.request('download.'+plugin_name+'.test', {
'onComplete': function(json){
button.set('text', button_name);
if(json.success){
var message = new Element('span.success', {
'text': 'Connection successful'
}).inject(button, 'after')
}
else {
var msg_text = 'Connection failed. Check logs for details.';
if(json.hasOwnProperty('msg')) msg_text = json.msg;
var message = new Element('span.failed', {
'text': msg_text
}).inject(button, 'after')
}
(function(){
message.destroy();
}).delay(3000)
}
});
}
}
})
).inject(fieldset);
}
}
});
},
testButtonName: function(fieldset){
var name = String(fieldset.getElement('h2').innerHTML).substring(0,String(fieldset.getElement('h2').innerHTML).indexOf("<span"));
return 'Test '+name;
},
});
window.Downloaders = new DownloadersBase();

View File

@@ -111,6 +111,13 @@ class RTorrent:
"Error: Minimum rTorrent version required is {0}".format(
MIN_RTORRENT_VERSION_STR)
def test_connection(self):
try:
self._verify_conn()
except:
return False
return True
def _meets_version_requirement(self):
return self._get_client_version_tuple() >= MIN_RTORRENT_VERSION