From f5344ab63764f83e37ba926b05162b3abeb8c61c Mon Sep 17 00:00:00 2001 From: Frank Fenton Date: Thu, 20 Sep 2012 01:14:22 +1000 Subject: [PATCH] Add uTorrent downloader --- couchpotato/core/downloaders/utorrent/__init__.py | 54 ++++++++++ couchpotato/core/downloaders/utorrent/main.py | 125 ++++++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 couchpotato/core/downloaders/utorrent/__init__.py create mode 100644 couchpotato/core/downloaders/utorrent/main.py diff --git a/couchpotato/core/downloaders/utorrent/__init__.py b/couchpotato/core/downloaders/utorrent/__init__.py new file mode 100644 index 0000000..88ceaf7 --- /dev/null +++ b/couchpotato/core/downloaders/utorrent/__init__.py @@ -0,0 +1,54 @@ +from .main import uTorrent + +def start(): + return uTorrent() + +config = [{ + 'name': 'utorrent', + 'groups': [ + { + 'tab': 'downloaders', + 'name': 'utorrent', + 'label': 'uTorrent', + 'description': 'Send torrents to uTorrent.', + 'wizard': True, + 'options': [ + { + 'name': 'enabled', + 'default': 0, + 'type': 'enabler', + 'radio_group': 'torrent', + }, + { + 'name': 'host', + 'default': 'localhost:8000', + 'description': 'Hostname with port. Usually localhost:8000', + }, + { + 'name': 'username', + }, + { + 'name': 'password', + 'type': 'password', + }, + { + 'name': 'label', + 'description': 'Label to add torrent as.', + }, + { + 'name': 'paused', + 'type': 'bool', + 'default': False, + 'description': 'Add the torrent paused.', + }, + { + 'name': 'manual', + 'default': 0, + 'type': 'bool', + 'advanced': True, + 'description': 'Disable this downloader for automated searches, but use it when I manually send a release.', + }, + ], + } + ], +}] diff --git a/couchpotato/core/downloaders/utorrent/main.py b/couchpotato/core/downloaders/utorrent/main.py new file mode 100644 index 0000000..92320db --- /dev/null +++ b/couchpotato/core/downloaders/utorrent/main.py @@ -0,0 +1,125 @@ +from base64 import b64encode +from couchpotato.core.downloaders.base import Downloader +from couchpotato.core.helpers.encoding import isInt +from couchpotato.core.logger import CPLog +import httplib +import json +import os.path +import re +import urllib +import urllib2 +import time +import cookielib + +log = CPLog(__name__) + + +class uTorrent(Downloader): + + type = ['torrent_magnet'] + utAPI = None + + def download(self, data, movie, manual = False, filedata = None): + + if self.isDisabled(manual) or not self.isCorrectType(data.get('type')): + return + + log.debug('Sending "%s" (%s) to uTorrent.', (data.get('name'), data.get('type'))) + + # Load host from config and split out port. + host = self.conf('host').split(':') + if not isInt(host[1]): + log.error('Config properties are not filled in correctly, port is missing.') + return False + + torrent_params = {} + if self.conf('label'): + torrent_params['label'] = self.conf('label') + + if not filedata and data.get('type') == 'torrent': + log.error('Failed sending torrent, no data') + return False + + torrent_hash = re.findall('urn:btih:([\w]{32,40})', data.get('url'))[0] + # Send request to uTorrent + try: + if not self.utAPI: + self.utAPI = uTorrentAPI(host[0], port = host[1], username = self.conf('username'), password = self.conf('password')) + self.utAPI.add_torrent_uri(data.get('url')) + + # Change settings of added torrents + self.utAPI.set_torrent(torrent_hash, torrent_params) + if self.conf('paused', default = 0): + self.utAPI.pause_torrent(torrent_hash) + return True + except Exception, err: + log.error('Failed to change settings for transfer: %s', err) + return False + + +class uTorrentAPI(object): + + def __init__(self, host = 'localhost', port = 8000, username = None, password = None): + + super(uTorrentAPI, self).__init__() + + self.url = 'http://' + host + ':' + str(port) + '/gui/' + self.token = '' + self.last_time = time.time() + cookies = cookielib.CookieJar() + self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies)) + self.opener.addheaders = [('User-agent', 'couchpotato-utorrent-client/1.0')] + if username and password: + password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() + password_manager.add_password(realm = None, uri = self.url, user = username, passwd = password) + self.opener.add_handler(urllib2.HTTPBasicAuthHandler(password_manager)) + self.opener.add_handler(urllib2.HTTPDigestAuthHandler(password_manager)) + elif username or password: + log.debug('User or password missing, not using authentication.') + self.token = self.get_token() + + def _request(self, action): + if time.time() > self.last_time + 1800: + self.last_time = time.time() + self.token = self.get_token() + request = urllib2.Request(self.url + "?token=" + self.token + "&" + action) + try: + open_request = self.opener.open(request) + response = open_request.read() + log.debug('response: %s', response) + if response: + log.debug('uTorrent action successfull') + return response + else: + log.debug('Unknown failure sending command to uTorrent. Return text is: %s', response) + return False + except httplib.InvalidURL, err: + log.error('Invalid uTorrent host, check your config %s', err) + return False + except urllib2.HTTPError, err: + if err.code == 401: + log.error('Invalid uTorrent Username or Password, check your config') + return False + else: + log.error('uTorrent HTTPError: %s', err) + except urllib2.URLError, err: + log.error('Unable to connect to uTorrent %s', err) + + def get_token(self): + request = self.opener.open(self.url+"token.html") + token = re.findall("(.*?)