Added 'test connection' button for downloaders
This commit is contained in:
@@ -49,6 +49,7 @@ class ClientScript(Plugin):
|
|||||||
'scripts/page/settings.js',
|
'scripts/page/settings.js',
|
||||||
'scripts/page/about.js',
|
'scripts/page/about.js',
|
||||||
'scripts/page/manage.js',
|
'scripts/page/manage.js',
|
||||||
|
'scripts/misc/downloaders.js',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from base64 import b32decode, b16encode
|
from base64 import b32decode, b16encode
|
||||||
|
from couchpotato.api import addApiView
|
||||||
from couchpotato.core.event import addEvent
|
from couchpotato.core.event import addEvent
|
||||||
from couchpotato.core.helpers.variable import mergeDicts
|
from couchpotato.core.helpers.variable import mergeDicts
|
||||||
from couchpotato.core.logger import CPLog
|
from couchpotato.core.logger import CPLog
|
||||||
@@ -14,6 +15,7 @@ class Downloader(Provider):
|
|||||||
protocol = []
|
protocol = []
|
||||||
http_time_between_calls = 0
|
http_time_between_calls = 0
|
||||||
status_support = True
|
status_support = True
|
||||||
|
testable = False
|
||||||
|
|
||||||
torrent_sources = [
|
torrent_sources = [
|
||||||
'http://torrage.com/torrent/%s.torrent',
|
'http://torrage.com/torrent/%s.torrent',
|
||||||
@@ -42,6 +44,8 @@ class Downloader(Provider):
|
|||||||
addEvent('download.remove_failed', self._removeFailed)
|
addEvent('download.remove_failed', self._removeFailed)
|
||||||
addEvent('download.pause', self._pause)
|
addEvent('download.pause', self._pause)
|
||||||
addEvent('download.process_complete', self._processComplete)
|
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):
|
def getEnabledProtocol(self):
|
||||||
for download_protocol in self.protocol:
|
for download_protocol in self.protocol:
|
||||||
@@ -158,6 +162,15 @@ class Downloader(Provider):
|
|||||||
(d_manual and manual or d_manual is False) and \
|
(d_manual and manual or d_manual is False) and \
|
||||||
(not data or self.isCorrectProtocol(data.get('protocol')))
|
(not data or self.isCorrectProtocol(data.get('protocol')))
|
||||||
|
|
||||||
|
def isTestable(self):
|
||||||
|
return {'success': self.testable}
|
||||||
|
|
||||||
|
def _test(self):
|
||||||
|
return {'success': self.test()}
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
return False
|
||||||
|
|
||||||
def _pause(self, release_download, pause = True):
|
def _pause(self, release_download, pause = True):
|
||||||
if self.isDisabled(manual = True, data = {}):
|
if self.isDisabled(manual = True, data = {}):
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -19,19 +19,25 @@ class Deluge(Downloader):
|
|||||||
protocol = ['torrent', 'torrent_magnet']
|
protocol = ['torrent', 'torrent_magnet']
|
||||||
log = CPLog(__name__)
|
log = CPLog(__name__)
|
||||||
drpc = None
|
drpc = None
|
||||||
|
testable = True
|
||||||
|
|
||||||
def connect(self):
|
def connect(self, reconnect = False):
|
||||||
# Load host from config and split out port.
|
# Load host from config and split out port.
|
||||||
host = cleanHost(self.conf('host'), protocol = False).split(':')
|
host = cleanHost(self.conf('host'), protocol = False).split(':')
|
||||||
if not isInt(host[1]):
|
if not isInt(host[1]):
|
||||||
log.error('Config properties are not filled in correctly, port is missing.')
|
log.error('Config properties are not filled in correctly, port is missing.')
|
||||||
return False
|
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'))
|
self.drpc = DelugeRPC(host[0], port = host[1], username = self.conf('username'), password = self.conf('password'))
|
||||||
|
|
||||||
return self.drpc
|
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):
|
def download(self, data = None, media = None, filedata = None):
|
||||||
if not media: media = {}
|
if not media: media = {}
|
||||||
if not data: data = {}
|
if not data: data = {}
|
||||||
@@ -178,6 +184,13 @@ class DelugeRPC(object):
|
|||||||
self.client = DelugeClient()
|
self.client = DelugeClient()
|
||||||
self.client.connect(self.host, int(self.port), self.username, self.password)
|
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):
|
def add_torrent_magnet(self, torrent, options):
|
||||||
torrent_id = False
|
torrent_id = False
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -18,6 +18,28 @@ class NZBGet(Downloader):
|
|||||||
protocol = ['nzb']
|
protocol = ['nzb']
|
||||||
|
|
||||||
rpc = 'xmlrpc'
|
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):
|
def download(self, data = None, media = None, filedata = None):
|
||||||
if not media: media = {}
|
if not media: media = {}
|
||||||
|
|||||||
@@ -24,6 +24,15 @@ class NZBVortex(Downloader):
|
|||||||
protocol = ['nzb']
|
protocol = ['nzb']
|
||||||
api_level = None
|
api_level = None
|
||||||
session_id = 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):
|
def download(self, data = None, media = None, filedata = None):
|
||||||
if not media: media = {}
|
if not media: media = {}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class rTorrent(Downloader):
|
|||||||
|
|
||||||
protocol = ['torrent', 'torrent_magnet']
|
protocol = ['torrent', 'torrent_magnet']
|
||||||
rt = None
|
rt = None
|
||||||
|
testable = True
|
||||||
|
|
||||||
# Migration url to host options
|
# Migration url to host options
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -37,9 +38,9 @@ class rTorrent(Downloader):
|
|||||||
|
|
||||||
self.deleteConf('url')
|
self.deleteConf('url')
|
||||||
|
|
||||||
def connect(self):
|
def connect(self, reconnect = False):
|
||||||
# Already connected?
|
# Already connected?
|
||||||
if self.rt is not None:
|
if not reconnect and self.rt is not None:
|
||||||
return self.rt
|
return self.rt
|
||||||
|
|
||||||
url = cleanHost(self.conf('host'), protocol = True, ssl = self.conf('ssl')) + '/' + self.conf('rpc_url').strip('/ ') + '/'
|
url = cleanHost(self.conf('host'), protocol = True, ssl = self.conf('ssl')) + '/' + self.conf('rpc_url').strip('/ ') + '/'
|
||||||
@@ -53,8 +54,16 @@ class rTorrent(Downloader):
|
|||||||
else:
|
else:
|
||||||
self.rt = RTorrent(url)
|
self.rt = RTorrent(url)
|
||||||
|
|
||||||
|
if not self.rt.test_connection():
|
||||||
|
self.rt = None
|
||||||
|
|
||||||
return self.rt
|
return self.rt
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
if not self.connect(True):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def _update_provider_group(self, name, data):
|
def _update_provider_group(self, name, data):
|
||||||
if data.get('seed_time'):
|
if data.get('seed_time'):
|
||||||
log.info('seeding time ignored, not supported')
|
log.info('seeding time ignored, not supported')
|
||||||
|
|||||||
@@ -15,6 +15,17 @@ log = CPLog(__name__)
|
|||||||
class Sabnzbd(Downloader):
|
class Sabnzbd(Downloader):
|
||||||
|
|
||||||
protocol = ['nzb']
|
protocol = ['nzb']
|
||||||
|
testable = True
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
try:
|
||||||
|
sab_data = self.call({
|
||||||
|
'mode': 'version',
|
||||||
|
})
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return bool(sab_data)
|
||||||
|
|
||||||
def download(self, data = None, media = None, filedata = None):
|
def download(self, data = None, media = None, filedata = None):
|
||||||
if not media: media = {}
|
if not media: media = {}
|
||||||
|
|||||||
@@ -13,6 +13,17 @@ class Synology(Downloader):
|
|||||||
|
|
||||||
protocol = ['nzb', 'torrent', 'torrent_magnet']
|
protocol = ['nzb', 'torrent', 'torrent_magnet']
|
||||||
status_support = False
|
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):
|
def download(self, data = None, media = None, filedata = None):
|
||||||
if not media: media = {}
|
if not media: media = {}
|
||||||
@@ -147,3 +158,6 @@ class SynologyRPC(object):
|
|||||||
self._logout()
|
self._logout()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
return bool(self._login())
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class Transmission(Downloader):
|
|||||||
protocol = ['torrent', 'torrent_magnet']
|
protocol = ['torrent', 'torrent_magnet']
|
||||||
log = CPLog(__name__)
|
log = CPLog(__name__)
|
||||||
trpc = None
|
trpc = None
|
||||||
|
testable = True
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
# Load host from config and split out port.
|
# Load host from config and split out port.
|
||||||
@@ -26,11 +27,16 @@ class Transmission(Downloader):
|
|||||||
log.error('Config properties are not filled in correctly, port is missing.')
|
log.error('Config properties are not filled in correctly, port is missing.')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not self.trpc:
|
if not (self.trpc and self.trpc.get_session()):
|
||||||
self.trpc = TransmissionRPC(host[0], port = host[1], rpc_url = self.conf('rpc_url').strip('/ '), username = self.conf('username'), password = self.conf('password'))
|
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
|
return self.trpc
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
if self.connect() and self.trpc.get_session():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def download(self, data = None, media = None, filedata = None):
|
def download(self, data = None, media = None, filedata = None):
|
||||||
if not media: media = {}
|
if not media: media = {}
|
||||||
if not data: data = {}
|
if not data: data = {}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from base64 import b16encode, b32decode
|
from base64 import b16encode, b32decode
|
||||||
from bencode import bencode as benc, bdecode
|
from bencode import bencode as benc, bdecode
|
||||||
|
from couchpotato.api import addApiView
|
||||||
from couchpotato.core.downloaders.base import Downloader, ReleaseDownloadList
|
from couchpotato.core.downloaders.base import Downloader, ReleaseDownloadList
|
||||||
from couchpotato.core.helpers.encoding import isInt, ss, sp
|
from couchpotato.core.helpers.encoding import isInt, ss, sp
|
||||||
from couchpotato.core.helpers.variable import tryInt, tryFloat, cleanHost
|
from couchpotato.core.helpers.variable import tryInt, tryFloat, cleanHost
|
||||||
@@ -24,6 +25,7 @@ class uTorrent(Downloader):
|
|||||||
|
|
||||||
protocol = ['torrent', 'torrent_magnet']
|
protocol = ['torrent', 'torrent_magnet']
|
||||||
utorrent_api = None
|
utorrent_api = None
|
||||||
|
testable = True
|
||||||
status_flags = {
|
status_flags = {
|
||||||
'STARTED' : 1,
|
'STARTED' : 1,
|
||||||
'CHECKING' : 2,
|
'CHECKING' : 2,
|
||||||
@@ -46,6 +48,11 @@ class uTorrent(Downloader):
|
|||||||
|
|
||||||
return self.utorrent_api
|
return self.utorrent_api
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
if self.connect() and self.utorrent_api.get_status():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def download(self, data = None, media = None, filedata = None):
|
def download(self, data = None, media = None, filedata = None):
|
||||||
if not media: media = {}
|
if not media: media = {}
|
||||||
if not data: data = {}
|
if not data: data = {}
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
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 message = new Element('span.failed', {
|
||||||
|
'text': 'Connection failed. Check logs for details.'
|
||||||
|
}).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();
|
||||||
@@ -98,6 +98,13 @@ class RTorrent:
|
|||||||
"Error: Minimum rTorrent version required is {0}".format(
|
"Error: Minimum rTorrent version required is {0}".format(
|
||||||
MIN_RTORRENT_VERSION_STR)
|
MIN_RTORRENT_VERSION_STR)
|
||||||
|
|
||||||
|
def test_connection(self):
|
||||||
|
try:
|
||||||
|
self._verify_conn()
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def _meets_version_requirement(self):
|
def _meets_version_requirement(self):
|
||||||
return self._get_client_version_tuple() >= MIN_RTORRENT_VERSION
|
return self._get_client_version_tuple() >= MIN_RTORRENT_VERSION
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user