diff --git a/couchpotato/core/downloaders/deluge/main.py b/couchpotato/core/downloaders/deluge/main.py
index 7ca2429..2d9084b 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
@@ -103,7 +103,12 @@ class Deluge(Downloader):
for torrent_id in queue:
torrent = queue[torrent_id]
- log.debug('name=%s / id=%s / save_path=%s / move_completed_path=%s / hash=%s / progress=%s / state=%s / eta=%s / ratio=%s / stop_ratio=%s / is_seed=%s / is_finished=%s / paused=%s', (torrent['name'], torrent['hash'], torrent['save_path'], torrent['move_completed_path'], torrent['hash'], torrent['progress'], torrent['state'], torrent['eta'], torrent['ratio'], torrent['stop_ratio'], torrent['is_seed'], torrent['is_finished'], torrent['paused']))
+
+ if not 'hash' in torrent:
+ # When given a list of ids, deluge will return an empty item for a non-existant torrent.
+ continue
+
+ log.debug('name=%s / id=%s / save_path=%s / move_on_completed=%s / move_completed_path=%s / hash=%s / progress=%s / state=%s / eta=%s / ratio=%s / stop_ratio=%s / is_seed=%s / is_finished=%s / paused=%s', (torrent['name'], torrent['hash'], torrent['save_path'], torrent['move_on_completed'], torrent['move_completed_path'], torrent['hash'], torrent['progress'], torrent['state'], torrent['eta'], torrent['ratio'], torrent['stop_ratio'], torrent['is_seed'], torrent['is_finished'], torrent['paused']))
# Deluge has no easy way to work out if a torrent is stalled or failing.
#status = 'failed'
@@ -212,7 +217,7 @@ class DelugeRPC(object):
ret = False
try:
self.connect()
- ret = self.client.core.get_torrents_status({'id': ids}, {}).get()
+ ret = self.client.core.get_torrents_status({'id': ids}, ('name', 'hash', 'save_path', 'move_completed_path', 'progress', 'state', 'eta', 'ratio', 'stop_ratio', 'is_seed', 'is_finished', 'paused', 'move_on_completed', 'files')).get()
except Exception, err:
log.error('Failed to get all torrents: %s %s', (err, traceback.format_exc()))
finally:
diff --git a/couchpotato/core/downloaders/nzbget/main.py b/couchpotato/core/downloaders/nzbget/main.py
index 2dc6cfc..a05fb11 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 3b95698..3087d75 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 0225657..d2615bf 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 684ea45..dbef6e6 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 926bb41..5027631 100755
--- a/couchpotato/core/downloaders/rtorrent/main.py
+++ b/couchpotato/core/downloaders/rtorrent/main.py
@@ -1,7 +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, addEvent
from couchpotato.core.helpers.encoding import sp
+from couchpotato.core.helpers.variable import cleanHost, splitString
from couchpotato.core.logger import CPLog
from datetime import timedelta
from hashlib import sha1
@@ -17,24 +19,39 @@ class rTorrent(Downloader):
protocol = ['torrent', 'torrent_magnet']
rt = None
+ # Migration url to host options
+ def __init__(self):
+ super(rTorrent, self).__init__()
+
+ addEvent('app.load', self.migrate)
+
+ def migrate(self):
+
+ url = self.conf('url')
+ if url:
+ 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')
+
def connect(self):
# Already connected?
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
@@ -159,14 +176,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/downloaders/sabnzbd/__init__.py b/couchpotato/core/downloaders/sabnzbd/__init__.py
index 48692da..1edbbeb 100644
--- a/couchpotato/core/downloaders/sabnzbd/__init__.py
+++ b/couchpotato/core/downloaders/sabnzbd/__init__.py
@@ -25,6 +25,13 @@ config = [{
'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',
'description': 'Used for all calls to Sabnzbd.',
diff --git a/couchpotato/core/downloaders/sabnzbd/main.py b/couchpotato/core/downloaders/sabnzbd/main.py
index 0519cf6..1d9073f 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 74bc449..7299fa8 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 620b0d6..d41337f 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 77cf2f9..89f75cc 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 7146f95..0cfaa57 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
diff --git a/couchpotato/core/notifications/xbmc/main.py b/couchpotato/core/notifications/xbmc/main.py
index 759e43c..b53485a 100755
--- a/couchpotato/core/notifications/xbmc/main.py
+++ b/couchpotato/core/notifications/xbmc/main.py
@@ -8,6 +8,7 @@ import socket
import traceback
import urllib
import requests
+from requests.packages.urllib3.exceptions import MaxRetryError
log = CPLog(__name__)
@@ -168,7 +169,7 @@ class XBMC(Notification):
# manually fake expected response array
return [{'result': 'Error'}]
- except requests.exceptions.Timeout:
+ except (MaxRetryError, requests.exceptions.Timeout):
log.info2('Couldn\'t send request to XBMC, assuming it\'s turned off')
return [{'result': 'Error'}]
except:
@@ -203,7 +204,7 @@ class XBMC(Notification):
log.debug('Returned from request %s: %s', (host, response))
return response
- except requests.exceptions.Timeout:
+ except (MaxRetryError, requests.exceptions.Timeout):
log.info2('Couldn\'t send request to XBMC, assuming it\'s turned off')
return []
except:
diff --git a/couchpotato/core/plugins/base.py b/couchpotato/core/plugins/base.py
index 588a203..c7ec517 100644
--- a/couchpotato/core/plugins/base.py
+++ b/couchpotato/core/plugins/base.py
@@ -5,6 +5,8 @@ from couchpotato.core.helpers.variable import getExt, md5, isLocalIP
from couchpotato.core.logger import CPLog
from couchpotato.environment import Env
import requests
+from requests.packages.urllib3 import Timeout
+from requests.packages.urllib3.exceptions import MaxRetryError
from tornado import template
from tornado.web import StaticFileHandler
from urlparse import urlparse
@@ -52,8 +54,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__
@@ -170,9 +175,9 @@ class Plugin(object):
data = response.content if return_raw else response.text
self.http_failed_request[host] = 0
- except IOError:
+ except (IOError, MaxRetryError, Timeout):
if show_error:
- log.error('Failed opening url in %s: %s %s', (self.getName(), url, traceback.format_exc(1)))
+ log.error('Failed opening url in %s: %s %s', (self.getName(), url, traceback.format_exc(0)))
# Save failed requests by hosts
try:
@@ -262,7 +267,7 @@ class Plugin(object):
if not kwargs.get('show_error', True):
raise
- log.error('Failed getting cache: %s', (traceback.format_exc()))
+ log.debug('Failed getting cache: %s', (traceback.format_exc(0)))
return ''
def setCache(self, cache_key, value, timeout = 300):
diff --git a/couchpotato/core/providers/base.py b/couchpotato/core/providers/base.py
index 89967df..e30cc24 100644
--- a/couchpotato/core/providers/base.py
+++ b/couchpotato/core/providers/base.py
@@ -164,7 +164,7 @@ class YarrProvider(Provider):
try:
if not self.login():
log.error('Failed downloading from %s', self.getName())
- return self.urlopen(url)
+ return self.urlopen(url, return_raw = True)
except:
log.error('Failed downloading from %s: %s', (self.getName(), traceback.format_exc()))
@@ -173,7 +173,7 @@ class YarrProvider(Provider):
def download(self, url = '', nzb_id = ''):
try:
- return self.urlopen(url, headers = {'User-Agent': Env.getIdentifier()}, show_error = False)
+ return self.urlopen(url, headers = {'User-Agent': Env.getIdentifier()}, show_error = False, return_raw = True)
except:
log.error('Failed getting nzb from %s: %s', (self.getName(), traceback.format_exc()))
diff --git a/couchpotato/core/settings/__init__.py b/couchpotato/core/settings/__init__.py
index 61d982f..85dc7a8 100644
--- a/couchpotato/core/settings/__init__.py
+++ b/couchpotato/core/settings/__init__.py
@@ -110,6 +110,10 @@ class Settings(object):
except:
return default
+ def delete(self, option = '', section = 'core'):
+ self.p.remove_option(section, option)
+ self.save()
+
def getEnabler(self, section, option):
return self.getBool(section, option)
diff --git a/couchpotato/runner.py b/couchpotato/runner.py
index 610fff8..36d4356 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)