diff --git a/data/interfaces/default/config.html b/data/interfaces/default/config.html index 9ba9f2aa..14254619 100644 --- a/data/interfaces/default/config.html +++ b/data/interfaces/default/config.html @@ -392,6 +392,12 @@ Usually http://localhost:8112 (requires WebUI plugin) +
+ + + Path to the certificate file. Make sure to use a valid certificate ("Issued To" field must match + hostname). +
diff --git a/headphones/config.py b/headphones/config.py index dd1ae9b6..a4dc5d27 100644 --- a/headphones/config.py +++ b/headphones/config.py @@ -68,6 +68,7 @@ _CONFIG_DEFINITIONS = { 'CUSTOMUSER': (str, 'General', ''), 'DELETE_LOSSLESS_FILES': (int, 'General', 1), 'DELUGE_HOST': (str, 'Deluge', ''), + 'DELUGE_CERT': (str, 'Deluge', ''), 'DELUGE_PASSWORD': (str, 'Deluge', ''), 'DELUGE_LABEL': (str, 'Deluge', ''), 'DELUGE_DONE_DIRECTORY': (str, 'Deluge', ''), diff --git a/headphones/deluge.py b/headphones/deluge.py index 5f79d29e..8d283ffa 100644 --- a/headphones/deluge.py +++ b/headphones/deluge.py @@ -48,6 +48,7 @@ import traceback delugeweb_auth = {} delugeweb_url = '' +deluge_verify_cert = False def addTorrent(link, data=None): @@ -158,14 +159,16 @@ def getTorrentFolder(result): ["total_done"] ], "id": 22}) - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) result['total_done'] = json.loads(response.text)['result']['total_done'] tries = 0 while result['total_done'] == 0 and tries < 10: tries += 1 time.sleep(5) - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) result['total_done'] = json.loads(response.text)['result']['total_done'] post_data = json.dumps({"method": "web.get_torrent_status", @@ -183,7 +186,8 @@ def getTorrentFolder(result): ], "id": 23}) - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) result['save_path'] = json.loads(response.text)['result']['save_path'] result['name'] = json.loads(response.text)['result']['name'] @@ -198,30 +202,47 @@ def removeTorrent(torrentid, remove_data=False): if not any(delugeweb_auth): _get_auth() - result = False - post_data = json.dumps({"method": "core.remove_torrent", - "params": [ - torrentid, - remove_data - ], - "id": 25}) - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) - result = json.loads(response.text)['result'] + try: + result = False + post_data = json.dumps({"method": "core.remove_torrent", + "params": [ + torrentid, + remove_data + ], + "id": 25}) + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) + result = json.loads(response.text)['result'] - return result + return result + except Exception as e: + logger.error('Deluge: Removing torrent failed: %s' % str(e)) + formatted_lines = traceback.format_exc().splitlines() + logger.error('; '.join(formatted_lines)) + return None def _get_auth(): logger.debug('Deluge: Authenticating...') - global delugeweb_auth, delugeweb_url + global delugeweb_auth, delugeweb_url, deluge_verify_cert delugeweb_auth = {} delugeweb_host = headphones.CONFIG.DELUGE_HOST + delugeweb_cert = headphones.CONFIG.DELUGE_CERT delugeweb_password = headphones.CONFIG.DELUGE_PASSWORD + logger.debug('Deluge: Using password %s***%s' % (delugeweb_password[0], delugeweb_password[-1])) if not delugeweb_host.startswith('http'): delugeweb_host = 'http://%s' % delugeweb_host + if delugeweb_cert is None or delugeweb_cert.strip() == '': + deluge_verify_cert = False + logger.debug('Deluge: No SSL certificate configured') + else: + deluge_verify_cert = delugeweb_cert + delugeweb_host = delugeweb_host.replace('http:', 'https:') + logger.debug('Deluge: Using certificate %s, host is now %s' % (deluge_verify_cert, delugeweb_host)) + if delugeweb_host.endswith('/'): delugeweb_host = delugeweb_host[:-1] @@ -231,33 +252,47 @@ def _get_auth(): "params": [delugeweb_password], "id": 1}) try: - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) - # , verify=TORRENT_VERIFY_CERT) - except Exception: + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) + except Exception as e: + logger.error('Deluge: Authentication failed: %s' % str(e)) + formatted_lines = traceback.format_exc().splitlines() + logger.error('; '.join(formatted_lines)) return None auth = json.loads(response.text)["result"] + auth_error = json.loads(response.text)["error"] + logger.debug('Deluge: Authentication result: %s, Error: %s' % (auth, auth_error)) delugeweb_auth = response.cookies + logger.debug('Deluge: Authentication cookies: %s' % str(delugeweb_auth.get_dict())) post_data = json.dumps({"method": "web.connected", "params": [], "id": 10}) try: - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) - # , verify=TORRENT_VERIFY_CERT) - except Exception: + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) + except Exception as e: + logger.error('Deluge: Authentication failed: %s' % str(e)) + formatted_lines = traceback.format_exc().splitlines() + logger.error('; '.join(formatted_lines)) return None connected = json.loads(response.text)['result'] + connected_error = json.loads(response.text)['error'] + logger.debug('Deluge: Connection result: %s, Error: %s' % (connected, connected_error)) if not connected: post_data = json.dumps({"method": "web.get_hosts", "params": [], "id": 11}) try: - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) - # , verify=TORRENT_VERIFY_CERT) - except Exception: + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) + except Exception as e: + logger.error('Deluge: Authentication failed: %s' % str(e)) + formatted_lines = traceback.format_exc().splitlines() + logger.error('; '.join(formatted_lines)) return None delugeweb_hosts = json.loads(response.text)['result'] @@ -270,9 +305,12 @@ def _get_auth(): "id": 11}) try: - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) - # , verify=TORRENT_VERIFY_CERT) - except Exception: + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) + except Exception as e: + logger.error('Deluge: Authentication failed: %s' % str(e)) + formatted_lines = traceback.format_exc().splitlines() + logger.error('; '.join(formatted_lines)) return None post_data = json.dumps({"method": "web.connected", @@ -280,9 +318,12 @@ def _get_auth(): "id": 10}) try: - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) - # , verify=TORRENT_VERIFY_CERT) - except Exception: + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) + except Exception as e: + logger.error('Deluge: Authentication failed: %s' % str(e)) + formatted_lines = traceback.format_exc().splitlines() + logger.error('; '.join(formatted_lines)) return None connected = json.loads(response.text)['result'] @@ -302,12 +343,16 @@ def _add_torrent_magnet(result): post_data = json.dumps({"method": "core.add_torrent_magnet", "params": [result['url'], {}], "id": 2}) - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) result['hash'] = json.loads(response.text)['result'] logger.debug('Deluge: Response was %s' % str(json.loads(response.text)['result'])) return json.loads(response.text)['result'] except Exception as e: logger.error('Deluge: Adding torrent magnet failed: %s' % str(e)) + formatted_lines = traceback.format_exc().splitlines() + logger.error('; '.join(formatted_lines)) + return None ''' def _add_torrent_url(result): @@ -318,7 +363,8 @@ def _add_torrent_url(result): post_data = json.dumps({"method": "web.download_torrent_from_url", "params": [result['url'], {}], "id": 2}) - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) result['hash'] = json.loads(response.text)['result'] logger.debug('Deluge: Response was %s' % str(json.loads(response.text)['result'])) return json.loads(response.text)['result'] @@ -336,7 +382,8 @@ def _add_torrent_file(result): post_data = json.dumps({"method": "core.add_torrent_file", "params": [result['name'] + '.torrent', b64encode(result['content'].encode('utf8')), {}], "id": 2}) - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) result['hash'] = json.loads(response.text)['result'] logger.debug('Deluge: Response was %s' % str(json.loads(response.text)['result'])) return json.loads(response.text)['result'] @@ -344,6 +391,7 @@ def _add_torrent_file(result): logger.error('Deluge: Adding torrent file failed: %s' % str(e)) formatted_lines = traceback.format_exc().splitlines() logger.error('; '.join(formatted_lines)) + return None def setTorrentLabel(result): @@ -361,7 +409,8 @@ def setTorrentLabel(result): post_data = json.dumps({"method": 'label.get_labels', "params": [], "id": 3}) - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) labels = json.loads(response.text)['result'] if labels is not None: @@ -371,7 +420,8 @@ def setTorrentLabel(result): post_data = json.dumps({"method": 'label.add', "params": [label], "id": 4}) - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) logger.debug('Deluge: %s label added to Deluge' % label) except Exception as e: logger.error('Deluge: Setting label failed: %s' % str(e)) @@ -382,7 +432,8 @@ def setTorrentLabel(result): post_data = json.dumps({"method": 'label.set_torrent', "params": [result['hash'], label], "id": 5}) - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) logger.debug('Deluge: %s label added to torrent' % label) else: logger.debug('Deluge: Label plugin not detected') @@ -400,19 +451,27 @@ def setSeedRatio(result): if result['ratio']: ratio = result['ratio'] - if ratio: - post_data = json.dumps({"method": "core.set_torrent_stop_at_ratio", - "params": [result['hash'], True], - "id": 5}) - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) - post_data = json.dumps({"method": "core.set_torrent_stop_ratio", - "params": [result['hash'], float(ratio)], - "id": 6}) - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) + try: + if ratio: + post_data = json.dumps({"method": "core.set_torrent_stop_at_ratio", + "params": [result['hash'], True], + "id": 5}) + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) + post_data = json.dumps({"method": "core.set_torrent_stop_ratio", + "params": [result['hash'], float(ratio)], + "id": 6}) + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) - return not json.loads(response.text)['error'] + return not json.loads(response.text)['error'] - return True + return True + except Exception as e: + logger.error('Deluge: Setting seed ratio failed: %s' % str(e)) + formatted_lines = traceback.format_exc().splitlines() + logger.error('; '.join(formatted_lines)) + return None def setTorrentPath(result): @@ -420,28 +479,36 @@ def setTorrentPath(result): if not any(delugeweb_auth): _get_auth() - if headphones.CONFIG.DELUGE_DONE_DIRECTORY or headphones.CONFIG.DOWNLOAD_TORRENT_DIR: - post_data = json.dumps({"method": "core.set_torrent_move_completed", - "params": [result['hash'], True], - "id": 7}) - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) + try: + if headphones.CONFIG.DELUGE_DONE_DIRECTORY or headphones.CONFIG.DOWNLOAD_TORRENT_DIR: + post_data = json.dumps({"method": "core.set_torrent_move_completed", + "params": [result['hash'], True], + "id": 7}) + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) - if headphones.CONFIG.DELUGE_DONE_DIRECTORY: - move_to = headphones.CONFIG.DELUGE_DONE_DIRECTORY - else: - move_to = headphones.CONFIG.DOWNLOAD_TORRENT_DIR + if headphones.CONFIG.DELUGE_DONE_DIRECTORY: + move_to = headphones.CONFIG.DELUGE_DONE_DIRECTORY + else: + move_to = headphones.CONFIG.DOWNLOAD_TORRENT_DIR - if not os.path.exists(move_to): - logger.debug('Deluge: %s directory doesn\'t exist, let\'s create it' % move_to) - os.makedirs(move_to) - post_data = json.dumps({"method": "core.set_torrent_move_completed_path", - "params": [result['hash'], move_to], - "id": 8}) - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) + if not os.path.exists(move_to): + logger.debug('Deluge: %s directory doesn\'t exist, let\'s create it' % move_to) + os.makedirs(move_to) + post_data = json.dumps({"method": "core.set_torrent_move_completed_path", + "params": [result['hash'], move_to], + "id": 8}) + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) - return not json.loads(response.text)['error'] + return not json.loads(response.text)['error'] - return True + return True + except Exception as e: + logger.error('Deluge: Setting torrent move-to directory failed: %s' % str(e)) + formatted_lines = traceback.format_exc().splitlines() + logger.error('; '.join(formatted_lines)) + return None def setTorrentPause(result): @@ -449,12 +516,19 @@ def setTorrentPause(result): if not any(delugeweb_auth): _get_auth() - if headphones.CONFIG.DELUGE_PAUSED: - post_data = json.dumps({"method": "core.pause_torrent", - "params": [[result['hash']]], - "id": 9}) - response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth) + try: + if headphones.CONFIG.DELUGE_PAUSED: + post_data = json.dumps({"method": "core.pause_torrent", + "params": [[result['hash']]], + "id": 9}) + response = requests.post(delugeweb_url, data=post_data.encode('utf-8'), cookies=delugeweb_auth, + verify=deluge_verify_cert) - return not json.loads(response.text)['error'] + return not json.loads(response.text)['error'] - return True + return True + except Exception as e: + logger.error('Deluge: Setting torrent paused failed: %s' % str(e)) + formatted_lines = traceback.format_exc().splitlines() + logger.error('; '.join(formatted_lines)) + return None diff --git a/headphones/webserve.py b/headphones/webserve.py index 741a37f4..d22f0185 100644 --- a/headphones/webserve.py +++ b/headphones/webserve.py @@ -1157,6 +1157,7 @@ class WebInterface(object): "transmission_username": headphones.CONFIG.TRANSMISSION_USERNAME, "transmission_password": headphones.CONFIG.TRANSMISSION_PASSWORD, "deluge_host": headphones.CONFIG.DELUGE_HOST, + "deluge_cert": headphones.CONFIG.DELUGE_CERT, "deluge_password": headphones.CONFIG.DELUGE_PASSWORD, "deluge_label": headphones.CONFIG.DELUGE_LABEL, "deluge_done_directory": headphones.CONFIG.DELUGE_DONE_DIRECTORY,