From 05c41460c2d0eab8585c4e4c8e3b194196815b49 Mon Sep 17 00:00:00 2001 From: mano3m Date: Sun, 5 Jan 2014 12:38:41 +0100 Subject: [PATCH 1/5] Downloader cleanHost Extend the use of clean host (add more checks and features) and make the settings more dummy proof. --- couchpotato/core/downloaders/deluge/main.py | 4 +-- couchpotato/core/downloaders/nzbget/main.py | 15 +++++----- .../core/downloaders/nzbvortex/__init__.py | 10 ++++++- .../core/downloaders/nzbvortex/main.py | 2 +- .../core/downloaders/rtorrent/__init__.py | 29 ++++++++++++++++--- couchpotato/core/downloaders/rtorrent/main.py | 10 +++---- .../core/downloaders/sabnzbd/__init__.py | 7 +++++ couchpotato/core/downloaders/sabnzbd/main.py | 2 +- couchpotato/core/downloaders/synology/main.py | 3 +- .../core/downloaders/transmission/main.py | 6 ++-- couchpotato/core/downloaders/utorrent/main.py | 4 +-- couchpotato/core/helpers/variable.py | 20 +++++++++---- 12 files changed, 79 insertions(+), 33 deletions(-) diff --git a/couchpotato/core/downloaders/deluge/main.py b/couchpotato/core/downloaders/deluge/main.py index 7ca24292..4cd90c43 100644 --- a/couchpotato/core/downloaders/deluge/main.py +++ b/couchpotato/core/downloaders/deluge/main.py @@ -2,7 +2,7 @@ from base64 import b64encode, b16encode, b32decode from bencode import bencode as benc, bdecode from couchpotato.core.downloaders.base import Downloader, ReleaseDownloadList from couchpotato.core.helpers.encoding import isInt, sp -from couchpotato.core.helpers.variable import tryFloat +from couchpotato.core.helpers.variable import tryFloat, cleanHost from couchpotato.core.logger import CPLog from datetime import timedelta from hashlib import sha1 @@ -22,7 +22,7 @@ class Deluge(Downloader): def connect(self): # Load host from config and split out port. - host = self.conf('host').split(':') + 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 diff --git a/couchpotato/core/downloaders/nzbget/main.py b/couchpotato/core/downloaders/nzbget/main.py index 2dc6cfcb..a05fb118 100644 --- a/couchpotato/core/downloaders/nzbget/main.py +++ b/couchpotato/core/downloaders/nzbget/main.py @@ -1,7 +1,7 @@ from base64 import standard_b64encode from couchpotato.core.downloaders.base import Downloader, ReleaseDownloadList from couchpotato.core.helpers.encoding import ss, sp -from couchpotato.core.helpers.variable import tryInt, md5 +from couchpotato.core.helpers.variable import tryInt, md5, cleanHost from couchpotato.core.logger import CPLog from datetime import timedelta import re @@ -17,7 +17,7 @@ class NZBGet(Downloader): protocol = ['nzb'] - url = '%(protocol)s://%(username)s:%(password)s@%(host)s/xmlrpc' + rpc = 'xmlrpc' def download(self, data = None, media = None, filedata = None): if not media: media = {} @@ -29,10 +29,11 @@ class NZBGet(Downloader): log.info('Sending "%s" to NZBGet.', data.get('name')) - url = self.url % {'protocol': 'https' if self.conf('ssl') else 'http', 'host': self.conf('host'), 'username': self.conf('username'), 'password': self.conf('password')} nzb_name = ss('%s.nzb' % self.createNzbName(data, media)) + 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 drop off %s.' % nzb_name): log.debug('Successfully connected to NZBGet') @@ -71,9 +72,9 @@ class NZBGet(Downloader): log.debug('Checking NZBGet download status.') - url = self.url % {'protocol': 'https' if self.conf('ssl') else 'http', 'host': self.conf('host'), 'username': self.conf('username'), 'password': self.conf('password')} - + 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 check status'): log.debug('Successfully connected to NZBGet') @@ -157,9 +158,9 @@ class NZBGet(Downloader): log.info('%s failed downloading, deleting...', release_download['name']) - url = self.url % {'host': self.conf('host'), 'username': self.conf('username'), 'password': self.conf('password')} - + 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 delete some history'): log.debug('Successfully connected to NZBGet') diff --git a/couchpotato/core/downloaders/nzbvortex/__init__.py b/couchpotato/core/downloaders/nzbvortex/__init__.py index 3b95698e..3087d75b 100644 --- a/couchpotato/core/downloaders/nzbvortex/__init__.py +++ b/couchpotato/core/downloaders/nzbvortex/__init__.py @@ -22,7 +22,15 @@ config = [{ }, { 'name': 'host', - 'default': 'https://localhost:4321', + 'default': 'localhost:4321', + 'description': 'Hostname with port. Usually localhost:4321', + }, + { + 'name': 'ssl', + 'default': 1, + 'type': 'bool', + 'advanced': True, + 'description': 'Use HyperText Transfer Protocol Secure, or https', }, { 'name': 'api_key', diff --git a/couchpotato/core/downloaders/nzbvortex/main.py b/couchpotato/core/downloaders/nzbvortex/main.py index 02256576..d2615bfd 100644 --- a/couchpotato/core/downloaders/nzbvortex/main.py +++ b/couchpotato/core/downloaders/nzbvortex/main.py @@ -116,7 +116,7 @@ class NZBVortex(Downloader): params = tryUrlencode(parameters) - url = cleanHost(self.conf('host')) + 'api/' + call + url = cleanHost(self.conf('host'), ssl = self.conf('ssl')) + 'api/' + call try: data = self.urlopen('%s?%s' % (url, params), *args, **kwargs) diff --git a/couchpotato/core/downloaders/rtorrent/__init__.py b/couchpotato/core/downloaders/rtorrent/__init__.py index 684ea45e..dbef6e6f 100755 --- a/couchpotato/core/downloaders/rtorrent/__init__.py +++ b/couchpotato/core/downloaders/rtorrent/__init__.py @@ -20,11 +20,32 @@ config = [{ 'type': 'enabler', 'radio_group': 'torrent', }, +# @RuudBurger: How do I migrate this? +# { +# 'name': 'url', +# 'default': 'http://localhost:80/RPC2', +# 'description': 'XML-RPC Endpoint URI. Usually scgi://localhost:5000 ' +# 'or http://localhost:80/RPC2' +# }, { - 'name': 'url', - 'default': 'http://localhost:80/RPC2', - 'description': 'XML-RPC Endpoint URI. Usually scgi://localhost:5000 ' - 'or http://localhost:80/RPC2' + 'name': 'host', + 'default': 'localhost:80', + 'description': 'Hostname with port or XML-RPC Endpoint URI. Usually scgi://localhost:5000 ' + 'or localhost:80' + }, + { + 'name': 'ssl', + 'default': 0, + 'type': 'bool', + 'advanced': True, + 'description': 'Use HyperText Transfer Protocol Secure, or https', + }, + { + 'name': 'rpc_url', + 'type': 'string', + 'default': 'RPC2', + 'advanced': True, + 'description': 'Change if you don\'t run rTorrent RPC at the default url.', }, { 'name': 'username', diff --git a/couchpotato/core/downloaders/rtorrent/main.py b/couchpotato/core/downloaders/rtorrent/main.py index 926bb415..5cf4da22 100755 --- a/couchpotato/core/downloaders/rtorrent/main.py +++ b/couchpotato/core/downloaders/rtorrent/main.py @@ -2,6 +2,7 @@ from base64 import b16encode, b32decode from bencode import bencode, bdecode from couchpotato.core.downloaders.base import Downloader, ReleaseDownloadList from couchpotato.core.helpers.encoding import sp +from couchpotato.core.helpers.variable import cleanHost from couchpotato.core.logger import CPLog from datetime import timedelta from hashlib import sha1 @@ -22,19 +23,16 @@ class rTorrent(Downloader): if self.rt is not None: return self.rt - # Ensure url is set - if not self.conf('url'): - log.error('Config properties are not filled in correctly, url is missing.') - return False + url = cleanHost(self.conf('host'), protocol = True, ssl = self.conf('ssl')) + '/' + self.conf('rpc_url').strip('/ ') + '/' if self.conf('username') and self.conf('password'): self.rt = RTorrent( - self.conf('url'), + url, self.conf('username'), self.conf('password') ) else: - self.rt = RTorrent(self.conf('url')) + self.rt = RTorrent(url) return self.rt diff --git a/couchpotato/core/downloaders/sabnzbd/__init__.py b/couchpotato/core/downloaders/sabnzbd/__init__.py index 48692dae..1edbbebf 100644 --- a/couchpotato/core/downloaders/sabnzbd/__init__.py +++ b/couchpotato/core/downloaders/sabnzbd/__init__.py @@ -24,6 +24,13 @@ config = [{ 'name': 'host', 'default': 'localhost:8080', }, + { + 'name': 'ssl', + 'default': 0, + 'type': 'bool', + 'advanced': True, + 'description': 'Use HyperText Transfer Protocol Secure, or https', + }, { 'name': 'api_key', 'label': 'Api Key', diff --git a/couchpotato/core/downloaders/sabnzbd/main.py b/couchpotato/core/downloaders/sabnzbd/main.py index 0519cf62..1d9073ff 100644 --- a/couchpotato/core/downloaders/sabnzbd/main.py +++ b/couchpotato/core/downloaders/sabnzbd/main.py @@ -165,7 +165,7 @@ class Sabnzbd(Downloader): def call(self, request_params, use_json = True, **kwargs): - url = cleanHost(self.conf('host')) + 'api?' + tryUrlencode(mergeDicts(request_params, { + url = cleanHost(self.conf('host'), ssl = self.conf('ssl')) + 'api?' + tryUrlencode(mergeDicts(request_params, { 'apikey': self.conf('api_key'), 'output': 'json' })) diff --git a/couchpotato/core/downloaders/synology/main.py b/couchpotato/core/downloaders/synology/main.py index 74bc449e..7299fa81 100644 --- a/couchpotato/core/downloaders/synology/main.py +++ b/couchpotato/core/downloaders/synology/main.py @@ -1,5 +1,6 @@ from couchpotato.core.downloaders.base import Downloader from couchpotato.core.helpers.encoding import isInt +from couchpotato.core.helpers.variable import cleanHost from couchpotato.core.logger import CPLog import json import requests @@ -21,7 +22,7 @@ class Synology(Downloader): log.error('Sending "%s" (%s) to Synology.', (data['name'], data['protocol'])) # Load host from config and split out port. - host = self.conf('host').split(':') + 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 diff --git a/couchpotato/core/downloaders/transmission/main.py b/couchpotato/core/downloaders/transmission/main.py index 66cceb2f..62f2d33e 100644 --- a/couchpotato/core/downloaders/transmission/main.py +++ b/couchpotato/core/downloaders/transmission/main.py @@ -1,7 +1,7 @@ from base64 import b64encode from couchpotato.core.downloaders.base import Downloader, ReleaseDownloadList from couchpotato.core.helpers.encoding import isInt, sp -from couchpotato.core.helpers.variable import tryInt, tryFloat +from couchpotato.core.helpers.variable import tryInt, tryFloat, cleanHost from couchpotato.core.logger import CPLog from datetime import timedelta import httplib @@ -21,13 +21,13 @@ class Transmission(Downloader): def connect(self): # Load host from config and split out port. - host = self.conf('host').split(':') + 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: - self.trpc = TransmissionRPC(host[0], port = host[1], rpc_url = self.conf('rpc_url'), 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 diff --git a/couchpotato/core/downloaders/utorrent/main.py b/couchpotato/core/downloaders/utorrent/main.py index 77cf2f96..89f75ccf 100644 --- a/couchpotato/core/downloaders/utorrent/main.py +++ b/couchpotato/core/downloaders/utorrent/main.py @@ -2,7 +2,7 @@ from base64 import b16encode, b32decode from bencode import bencode as benc, bdecode 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 +from couchpotato.core.helpers.variable import tryInt, tryFloat, cleanHost from couchpotato.core.logger import CPLog from datetime import timedelta from hashlib import sha1 @@ -37,7 +37,7 @@ class uTorrent(Downloader): def connect(self): # Load host from config and split out port. - host = self.conf('host').split(':') + 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 diff --git a/couchpotato/core/helpers/variable.py b/couchpotato/core/helpers/variable.py index 0b1ca9df..859d2572 100644 --- a/couchpotato/core/helpers/variable.py +++ b/couchpotato/core/helpers/variable.py @@ -118,12 +118,22 @@ def isLocalIP(ip): def getExt(filename): return os.path.splitext(filename)[1][1:] -def cleanHost(host): - if not host.startswith(('http://', 'https://')): - host = 'http://' + host +def cleanHost(host, protocol = True, ssl = False, username = None, password = None): - host = host.rstrip('/') - host += '/' + if not '://' in host and protocol: + host = 'https://' if ssl else 'http://' + host + + if not protocol: + host = host.split('://', 1)[-1] + + if protocol and username and password: + login = '%s:%s@' % (username, password) + if not login in host: + host.replace('://', '://' + login, 1) + + host = host.rstrip('/ ') + if protocol: + host += '/' return host From 3bb44f8d9f9305521a6a02b952fd9242bef7a499 Mon Sep 17 00:00:00 2001 From: mano3m Date: Mon, 13 Jan 2014 23:14:18 +0100 Subject: [PATCH 2/5] Migrate rTorrent options --- couchpotato/core/downloaders/rtorrent/main.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/couchpotato/core/downloaders/rtorrent/main.py b/couchpotato/core/downloaders/rtorrent/main.py index 5cf4da22..7dc6abbf 100755 --- a/couchpotato/core/downloaders/rtorrent/main.py +++ b/couchpotato/core/downloaders/rtorrent/main.py @@ -1,6 +1,7 @@ from base64 import b16encode, b32decode from bencode import bencode, bdecode from couchpotato.core.downloaders.base import Downloader, ReleaseDownloadList +from couchpotato.core.event import fireEvent from couchpotato.core.helpers.encoding import sp from couchpotato.core.helpers.variable import cleanHost from couchpotato.core.logger import CPLog @@ -18,6 +19,15 @@ class rTorrent(Downloader): protocol = ['torrent', 'torrent_magnet'] rt = None + # Migration url to host options + def __init__(self): + super(rTorrent, self).__init__() + if self.conf('url'): + self.conf('ssl', value = (self.conf('url').split('://')[0].strip() == 'https')) + self.conf('host', value = self.conf('url').split('://')[-1].split('/')[0].strip()) + self.conf('rpc_url', value = self.conf('url').split('://')[-1].split('/',1)[1].strip('/ ')) + self.conf('url', value = '') + def connect(self): # Already connected? if self.rt is not None: From 72457d8d10165097c05ab1ae9394ef2af4f3cdd5 Mon Sep 17 00:00:00 2001 From: mano3m Date: Mon, 13 Jan 2014 23:15:10 +0100 Subject: [PATCH 3/5] Log with system encoding --- couchpotato/runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/couchpotato/runner.py b/couchpotato/runner.py index 610fff8b..36d43564 100644 --- a/couchpotato/runner.py +++ b/couchpotato/runner.py @@ -168,7 +168,7 @@ def runCouchPotato(options, base_path, args, data_dir = None, log_dir = None, En logger.addHandler(hdlr) # To file - hdlr2 = handlers.RotatingFileHandler(Env.get('log_path'), 'a', 500000, 10) + hdlr2 = handlers.RotatingFileHandler(Env.get('log_path'), 'a', 500000, 10, encoding = Env.get('encoding')) hdlr2.setFormatter(formatter) logger.addHandler(hdlr2) From 894e419f4068915765d960fb3514596b1fdda47f Mon Sep 17 00:00:00 2001 From: Ruud Date: Wed, 15 Jan 2014 21:08:19 +0100 Subject: [PATCH 4/5] Allow config delete --- couchpotato/core/downloaders/rtorrent/main.py | 31 +++++++++++++------ couchpotato/core/plugins/base.py | 7 +++-- couchpotato/core/settings/__init__.py | 3 ++ 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/couchpotato/core/downloaders/rtorrent/main.py b/couchpotato/core/downloaders/rtorrent/main.py index 7dc6abbf..92a21772 100755 --- a/couchpotato/core/downloaders/rtorrent/main.py +++ b/couchpotato/core/downloaders/rtorrent/main.py @@ -1,9 +1,9 @@ from base64 import b16encode, b32decode from bencode import bencode, bdecode from couchpotato.core.downloaders.base import Downloader, ReleaseDownloadList -from couchpotato.core.event import fireEvent +from couchpotato.core.event import fireEvent, addEvent from couchpotato.core.helpers.encoding import sp -from couchpotato.core.helpers.variable import cleanHost +from couchpotato.core.helpers.variable import cleanHost, splitString from couchpotato.core.logger import CPLog from datetime import timedelta from hashlib import sha1 @@ -22,11 +22,24 @@ class rTorrent(Downloader): # Migration url to host options def __init__(self): super(rTorrent, self).__init__() - if self.conf('url'): - self.conf('ssl', value = (self.conf('url').split('://')[0].strip() == 'https')) - self.conf('host', value = self.conf('url').split('://')[-1].split('/')[0].strip()) - self.conf('rpc_url', value = self.conf('url').split('://')[-1].split('/',1)[1].strip('/ ')) - self.conf('url', value = '') + + addEvent('app.load', self.migrate) + + def migrate(self): + + url = self.conf('url') + if url: + print url + + url = 'http://localhost:8080/RPC2teasd/asdasd//' + host_split = splitString(url.split('://')[-1], split_on = '/') + + self.conf('ssl', value = url.startswith('https')) + self.conf('host', value = host_split[0].strip()) + self.conf('rpc_url', value = '/'.join(host_split[1:])) + + self.deleteConf('url') + #self.conf('url', value = '') def connect(self): # Already connected? @@ -167,14 +180,14 @@ class rTorrent(Downloader): torrent_files = [] for file_item in torrent.get_files(): torrent_files.append(sp(os.path.join(torrent.directory, file_item.path))) - + status = 'busy' if torrent.complete: if torrent.active: status = 'seeding' else: status = 'completed' - + release_downloads.append({ 'id': torrent.info_hash, 'name': torrent.name, diff --git a/couchpotato/core/plugins/base.py b/couchpotato/core/plugins/base.py index 588a2030..0296af50 100644 --- a/couchpotato/core/plugins/base.py +++ b/couchpotato/core/plugins/base.py @@ -52,8 +52,11 @@ class Plugin(object): self.registerStatic(inspect.getfile(self.__class__)) def conf(self, attr, value = None, default = None, section = None): - class_name = self.getName().lower().split(':') - return Env.setting(attr, section = section if section else class_name[0].lower(), value = value, default = default) + class_name = self.getName().lower().split(':')[0].lower() + return Env.setting(attr, section = section if section else class_name, value = value, default = default) + + def deleteConf(self, attr): + return Env._settings.delete(attr, section = self.getName().lower().split(':')[0].lower()) def getName(self): return self._class_name or self.__class__.__name__ diff --git a/couchpotato/core/settings/__init__.py b/couchpotato/core/settings/__init__.py index 61d982f2..e2c82117 100644 --- a/couchpotato/core/settings/__init__.py +++ b/couchpotato/core/settings/__init__.py @@ -110,6 +110,9 @@ class Settings(object): except: return default + def delete(self, option = '', section = 'core'): + self.p.remove_option(section, option) + def getEnabler(self, section, option): return self.getBool(section, option) From 81949b9cad4df067f1892fd268d5437ec984122a Mon Sep 17 00:00:00 2001 From: Ruud Date: Wed, 15 Jan 2014 21:10:06 +0100 Subject: [PATCH 5/5] Remove prints and actually save deletion --- couchpotato/core/downloaders/rtorrent/main.py | 2 -- couchpotato/core/settings/__init__.py | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/couchpotato/core/downloaders/rtorrent/main.py b/couchpotato/core/downloaders/rtorrent/main.py index 92a21772..410bb573 100755 --- a/couchpotato/core/downloaders/rtorrent/main.py +++ b/couchpotato/core/downloaders/rtorrent/main.py @@ -29,7 +29,6 @@ class rTorrent(Downloader): url = self.conf('url') if url: - print url url = 'http://localhost:8080/RPC2teasd/asdasd//' host_split = splitString(url.split('://')[-1], split_on = '/') @@ -39,7 +38,6 @@ class rTorrent(Downloader): self.conf('rpc_url', value = '/'.join(host_split[1:])) self.deleteConf('url') - #self.conf('url', value = '') def connect(self): # Already connected? diff --git a/couchpotato/core/settings/__init__.py b/couchpotato/core/settings/__init__.py index e2c82117..85dc7a8f 100644 --- a/couchpotato/core/settings/__init__.py +++ b/couchpotato/core/settings/__init__.py @@ -112,6 +112,7 @@ class Settings(object): def delete(self, option = '', section = 'core'): self.p.remove_option(section, option) + self.save() def getEnabler(self, section, option): return self.getBool(section, option)