From 5eb21488c1327e993b26e431b35e730d3c90866d Mon Sep 17 00:00:00 2001 From: Correl Roush Date: Thu, 27 May 2010 23:31:51 -0400 Subject: [PATCH] Cleanup --- .../lib/transmissionrpc-0.3-python2.4.patch | 80 --- .../transmissionrpc-0.3-python2.4/__init__.py | 10 - .../constants.py | 230 ------- .../transmission.py | 606 ----------------- .../transmissionrpc-0.3-python2.4/utils.py | 138 ---- resources/lib/transmissionrpc-0.3/__init__.py | 10 - .../lib/transmissionrpc-0.3/constants.py | 230 ------- .../lib/transmissionrpc-0.3/transmission.py | 605 ----------------- resources/lib/transmissionrpc-0.3/utils.py | 135 ---- resources/lib/transmissionrpc-0.4/__init__.py | 10 - .../lib/transmissionrpc-0.4/constants.py | 234 ------- .../lib/transmissionrpc-0.4/transmission.py | 628 ------------------ resources/lib/transmissionrpc-0.4/utils.py | 138 ---- 13 files changed, 3054 deletions(-) delete mode 100644 resources/lib/transmissionrpc-0.3-python2.4.patch delete mode 100644 resources/lib/transmissionrpc-0.3-python2.4/__init__.py delete mode 100755 resources/lib/transmissionrpc-0.3-python2.4/constants.py delete mode 100755 resources/lib/transmissionrpc-0.3-python2.4/transmission.py delete mode 100644 resources/lib/transmissionrpc-0.3-python2.4/utils.py delete mode 100644 resources/lib/transmissionrpc-0.3/__init__.py delete mode 100755 resources/lib/transmissionrpc-0.3/constants.py delete mode 100755 resources/lib/transmissionrpc-0.3/transmission.py delete mode 100644 resources/lib/transmissionrpc-0.3/utils.py delete mode 100755 resources/lib/transmissionrpc-0.4/__init__.py delete mode 100755 resources/lib/transmissionrpc-0.4/constants.py delete mode 100755 resources/lib/transmissionrpc-0.4/transmission.py delete mode 100644 resources/lib/transmissionrpc-0.4/utils.py diff --git a/resources/lib/transmissionrpc-0.3-python2.4.patch b/resources/lib/transmissionrpc-0.3-python2.4.patch deleted file mode 100644 index d9b84d4..0000000 --- a/resources/lib/transmissionrpc-0.3-python2.4.patch +++ /dev/null @@ -1,80 +0,0 @@ -diff -rupN transmissionrpc-0.3/transmission.py transmissionrpc/transmission.py ---- transmissionrpc-0.3/transmission.py 2009-12-10 16:39:33.134130829 -0500 -+++ transmissionrpc/transmission.py 2009-12-10 16:45:37.385258836 -0500 -@@ -69,7 +69,7 @@ class Torrent(object): - wanted = self.fields['wanted'] - index = 1 - for item in zip(indicies, files, priorities, wanted): -- selected = True if item[3] else False -+ selected = bool(item[3]) - priority = PRIORITY[item[2]] - result[item[0]] = { - 'selected': selected, -@@ -252,29 +252,30 @@ class Client(object): - while True: - error_data = "" - try: -- self._debug_request(request) -- socket.setdefaulttimeout(10) -- if (sys.version_info[0] == 2 and sys.version_info[1] > 5) or sys.version_info[0] > 2: -- response = urllib2.urlopen(request, timeout=60) -- else: -- response = urllib2.urlopen(request) -- break -- except urllib2.HTTPError, error: -- error_data = error.read() -- if error.code == 409: -- logger.info('Server responded with 409, trying to set session-id.') -- if request_count > 1: -- raise TransmissionError('Session ID negotiation failed.', error) -- if 'X-Transmission-Session-Id' in error.headers: -- self.sessionid = error.headers['X-Transmission-Session-Id'] -- request.add_header('X-Transmission-Session-Id', self.sessionid) -+ try: -+ self._debug_request(request) -+ socket.setdefaulttimeout(10) -+ if (sys.version_info[0] == 2 and sys.version_info[1] > 5) or sys.version_info[0] > 2: -+ response = urllib2.urlopen(request, timeout=60) - else: -- raise TransmissionError('Unknown conflict.', error) -- except urllib2.URLError, error: -- raise TransmissionError('Failed to connect to daemon.', error) -- except httplib.BadStatusLine, error: -- if (request_count > 1): -- raise TransmissionError('Failed to request %s "%s".' % (self.url, query), error) -+ response = urllib2.urlopen(request) -+ break -+ except urllib2.HTTPError, error: -+ error_data = error.read() -+ if error.code == 409: -+ logger.info('Server responded with 409, trying to set session-id.') -+ if request_count > 1: -+ raise TransmissionError('Session ID negotiation failed.', error) -+ if 'X-Transmission-Session-Id' in error.headers: -+ self.sessionid = error.headers['X-Transmission-Session-Id'] -+ request.add_header('X-Transmission-Session-Id', self.sessionid) -+ else: -+ raise TransmissionError('Unknown conflict.', error) -+ except urllib2.URLError, error: -+ raise TransmissionError('Failed to connect to daemon.', error) -+ except httplib.BadStatusLine, error: -+ if (request_count > 1): -+ raise TransmissionError('Failed to request %s "%s".' % (self.url, query), error) - finally: - if error_data: - self._debug_response(error, error_data) -diff -rupN transmissionrpc-0.3/utils.py transmissionrpc/utils.py ---- transmissionrpc-0.3/utils.py 2009-12-10 16:39:33.134130829 -0500 -+++ transmissionrpc/utils.py 2009-12-10 16:45:37.386133947 -0500 -@@ -64,7 +64,10 @@ def rpc_bool(arg): - arg = bool(int(arg)) - except: - arg = arg.lower() in [u'true', u'yes'] -- return 1 if bool(arg) else 0 -+ if bool(arg): -+ return 1 -+ else: -+ return 0 - - TR_TYPE_MAP = { - 'number' : int, diff --git a/resources/lib/transmissionrpc-0.3-python2.4/__init__.py b/resources/lib/transmissionrpc-0.3-python2.4/__init__.py deleted file mode 100644 index f4afa02..0000000 --- a/resources/lib/transmissionrpc-0.3-python2.4/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# 2008-08, Erik Svensson - -from constants import * -from transmission import TransmissionError, Torrent, Session, Client - -__author__ = u'Erik Svensson ' -__version__ = u'0.3' -__copyright__ = u'Copyright (c) 2008 Erik Svensson' -__license__ = u'MIT' diff --git a/resources/lib/transmissionrpc-0.3-python2.4/constants.py b/resources/lib/transmissionrpc-0.3-python2.4/constants.py deleted file mode 100755 index 96ccc01..0000000 --- a/resources/lib/transmissionrpc-0.3-python2.4/constants.py +++ /dev/null @@ -1,230 +0,0 @@ -# -*- coding: utf-8 -*- -# 2008-07, Erik Svensson - -import logging - -logger = logging.getLogger('transmissionrpc') -logger.setLevel(logging.ERROR) - -def mirror_dict(d): - d.update(dict((v, k) for k, v in d.iteritems())) - return d - -DEFAULT_PORT = 9091 - -TR_STATUS_CHECK_WAIT = (1<<0) -TR_STATUS_CHECK = (1<<1) -TR_STATUS_DOWNLOAD = (1<<2) -TR_STATUS_SEED = (1<<3) -TR_STATUS_STOPPED = (1<<4) - -STATUS = mirror_dict({ - 'check pending' : TR_STATUS_CHECK_WAIT, - 'checking' : TR_STATUS_CHECK, - 'downloading' : TR_STATUS_DOWNLOAD, - 'seeding' : TR_STATUS_SEED, - 'stopped' : TR_STATUS_STOPPED, -}) - -TR_PRI_LOW = -1 -TR_PRI_NORMAL = 0 -TR_PRI_HIGH = 1 - -PRIORITY = mirror_dict({ - 'low' : TR_PRI_LOW, - 'normal' : TR_PRI_NORMAL, - 'high' : TR_PRI_HIGH -}) - -TR_RATIOLIMIT_GLOBAL = 0 # follow the global settings -TR_RATIOLIMIT_SINGLE = 1 # override the global settings, seeding until a certain ratio -TR_RATIOLIMIT_UNLIMITED = 2 # override the global settings, seeding regardless of ratio - -RATIO_LIMIT = mirror_dict({ - 'global' : TR_RATIOLIMIT_GLOBAL, - 'single' : TR_RATIOLIMIT_SINGLE, - 'unlimeted' : TR_RATIOLIMIT_UNLIMITED -}) - -# A note on argument maps -# These maps are used to verify *-set methods. The information is structured in -# a tree. -# set +- - [, , , , ] -# | +- - [, , , , ] -# | -# get +- - [, , , , ] -# +- - [, , , , ] - -# Arguments for torrent methods -TORRENT_ARGS = { - 'get' : { - 'activityDate': ('number', 1, None, None, None), - 'addedDate': ('number', 1, None, None, None), - 'announceResponse': ('string', 1, None, None, None), - 'announceURL': ('string', 1, None, None, None), - 'bandwidthPriority': ('number', 5, None, None, None), - 'comment': ('string', 1, None, None, None), - 'corruptEver': ('number', 1, None, None, None), - 'creator': ('string', 1, None, None, None), - 'dateCreated': ('number', 1, None, None, None), - 'desiredAvailable': ('number', 1, None, None, None), - 'doneDate': ('number', 1, None, None, None), - 'downloadDir': ('string', 4, None, None, None), - 'downloadedEver': ('number', 1, None, None, None), - 'downloaders': ('number', 4, None, None, None), - 'downloadLimit': ('number', 1, None, None, None), - 'downloadLimited': ('boolean', 5, None, None, None), - 'downloadLimitMode': ('number', 1, 5, None, None), - 'error': ('number', 1, None, None, None), - 'errorString': ('number', 1, None, None, None), - 'eta': ('number', 1, None, None, None), - 'files': ('array', 1, None, None, None), - 'fileStats': ('array', 5, None, None, None), - 'hashString': ('string', 1, None, None, None), - 'haveUnchecked': ('number', 1, None, None, None), - 'haveValid': ('number', 1, None, None, None), - 'honorsSessionLimits': ('boolean', 5, None, None, None), - 'id': ('number', 1, None, None, None), - 'isPrivate': ('boolean', 1, None, None, None), - 'lastAnnounceTime': ('number', 1, None, None, None), - 'lastScrapeTime': ('number', 1, None, None, None), - 'leechers': ('number', 1, None, None, None), - 'leftUntilDone': ('number', 1, None, None, None), - 'manualAnnounceTime': ('number', 1, None, None, None), - 'maxConnectedPeers': ('number', 1, None, None, None), - 'name': ('string', 1, None, None, None), - 'nextAnnounceTime': ('number', 1, None, None, None), - 'nextScrapeTime': ('number', 1, None, None, None), - 'peer-limit': ('number', 5, None, None, None), - 'peers': ('array', 2, None, None, None), - 'peersConnected': ('number', 1, None, None, None), - 'peersFrom': ('object', 1, None, None, None), - 'peersGettingFromUs': ('number', 1, None, None, None), - 'peersKnown': ('number', 1, None, None, None), - 'peersSendingToUs': ('number', 1, None, None, None), - 'percentDone': ('double', 5, None, None, None), - 'pieces': ('string', 5, None, None, None), - 'pieceCount': ('number', 1, None, None, None), - 'pieceSize': ('number', 1, None, None, None), - 'priorities': ('array', 1, None, None, None), - 'rateDownload': ('number', 1, None, None, None), - 'rateUpload': ('number', 1, None, None, None), - 'recheckProgress': ('double', 1, None, None, None), - 'scrapeResponse': ('string', 1, None, None, None), - 'scrapeURL': ('string', 1, None, None, None), - 'seeders': ('number', 1, None, None, None), - 'seedRatioLimit': ('double', 5, None, None, None), - 'seedRatioMode': ('number', 5, None, None, None), - 'sizeWhenDone': ('number', 1, None, None, None), - 'startDate': ('number', 1, None, None, None), - 'status': ('number', 1, None, None, None), - 'swarmSpeed': ('number', 1, None, None, None), - 'timesCompleted': ('number', 1, None, None, None), - 'trackers': ('array', 1, None, None, None), - 'totalSize': ('number', 1, None, None, None), - 'torrentFile': ('string', 5, None, None, None), - 'uploadedEver': ('number', 1, None, None, None), - 'uploadLimit': ('number', 1, None, None, None), - 'uploadLimitMode': ('number', 1, 5, None, None), - 'uploadLimited': ('boolean', 5, None, None, None), - 'uploadRatio': ('double', 1, None, None, None), - 'wanted': ('array', 1, None, None, None), - 'webseeds': ('array', 1, None, None, None), - 'webseedsSendingToUs': ('number', 1, None, None, None), - }, - 'set': { - 'bandwidthPriority': ('number', 5, None, None, None), - 'downloadLimit': ('number', 5, None, 'speed-limit-down', None), - 'downloadLimited': ('boolean', 5, None, 'speed-limit-down-enabled', None), - 'files-wanted': ('array', 1, None, None, None), - 'files-unwanted': ('array', 1, None, None, None), - 'honorsSessionLimits': ('boolean', 5, None, None, None), - 'ids': ('array', 1, None, None, None), - 'peer-limit': ('number', 1, None, None, None), - 'priority-high': ('array', 1, None, None, None), - 'priority-low': ('array', 1, None, None, None), - 'priority-normal': ('array', 1, None, None, None), - 'seedRatioLimit': ('double', 5, None, None, None), - 'seedRatioMode': ('number', 5, None, None, None), - 'speed-limit-down': ('number', 1, 5, None, 'downloadLimit'), - 'speed-limit-down-enabled': ('boolean', 1, 5, None, 'downloadLimited'), - 'speed-limit-up': ('number', 1, 5, None, 'uploadLimit'), - 'speed-limit-up-enabled': ('boolean', 1, 5, None, 'uploadLimited'), - 'uploadLimit': ('number', 5, None, 'speed-limit-up', None), - 'uploadLimited': ('boolean', 5, None, 'speed-limit-up-enabled', None), - }, - 'add': { - 'download-dir': ('string', 1, None, None, None), - 'filename': ('string', 1, None, None, None), - 'files-wanted': ('array', 1, None, None, None), - 'files-unwanted': ('array', 1, None, None, None), - 'metainfo': ('string', 1, None, None, None), - 'paused': ('boolean', 1, None, None, None), - 'peer-limit': ('number', 1, None, None, None), - 'priority-high': ('array', 1, None, None, None), - 'priority-low': ('array', 1, None, None, None), - 'priority-normal': ('array', 1, None, None, None), - } -} - -# Arguments for session methods -SESSION_ARGS = { - 'get': { - "alt-speed-down": ('number', 5, None, None, None), - "alt-speed-enabled": ('boolean', 5, None, None, None), - "alt-speed-time-begin": ('number', 5, None, None, None), - "alt-speed-time-enabled": ('boolean', 5, None, None, None), - "alt-speed-time-end": ('number', 5, None, None, None), - "alt-speed-time-day": ('number', 5, None, None, None), - "alt-speed-up": ('number', 5, None, None, None), - "blocklist-enabled": ('boolean', 5, None, None, None), - "blocklist-size": ('number', 5, None, None, None), - "encryption": ('string', 1, None, None, None), - "download-dir": ('string', 1, None, None, None), - "peer-limit": ('number', 1, 5, None, None), - "peer-limit-global": ('number', 5, None, None, None), - "peer-limit-per-torrent": ('number', 5, None, None, None), - "pex-allowed": ('boolean', 1, 5, None, None), - "pex-enabled": ('boolean', 5, None, None, None), - "port": ('number', 1, 5, None, None), - "peer-port": ('number', 5, None, None, None), - "peer-port-random-on-start": ('boolean', 5, None, None, None), - "port-forwarding-enabled": ('boolean', 1, None, None, None), - "rpc-version": ('number', 4, None, None, None), - "rpc-version-minimum": ('number', 4, None, None, None), - "seedRatioLimit": ('double', 5, None, None, None), - "seedRatioLimited": ('boolean', 5, None, None, None), - "speed-limit-down": ('number', 1, None, None, None), - "speed-limit-down-enabled": ('boolean', 1, None, None, None), - "speed-limit-up": ('number', 1, None, None, None), - "speed-limit-up-enabled": ('boolean', 1, None, None, None), - "version": ('string', 3, None, None, None), - }, - 'set': { - "alt-speed-down": ('number', 5, None, None, None), - "alt-speed-enabled": ('boolean', 5, None, None, None), - "alt-speed-time-begin": ('number', 5, None, None, None), - "alt-speed-time-enabled": ('boolean', 5, None, None, None), - "alt-speed-time-end": ('number', 5, None, None, None), - "alt-speed-time-day": ('number', 5, None, None, None), - "alt-speed-up": ('number', 5, None, None, None), - "blocklist-enabled": ('boolean', 5, None, None, None), - "encryption": ('string', 1, None, None, None), - "download-dir": ('string', 1, None, None, None), - "peer-limit": ('number', 1, 5, None, 'peer-limit-global'), - "peer-limit-global": ('number', 5, None, 'peer-limit', None), - "peer-limit-per-torrent": ('number', 5, None, None, None), - "pex-allowed": ('boolean', 1, 5, None, 'pex-enabled'), - "pex-enabled": ('boolean', 5, None, 'pex-allowed', None), - "port": ('number', 1, 5, None, 'peer-port'), - "peer-port": ('number', 5, None, 'port', None), - "peer-port-random-on-start": ('boolean', 5, None, None, None), - "port-forwarding-enabled": ('boolean', 1, None, None, None), - "seedRatioLimit": ('double', 5, None, None, None), - "seedRatioLimited": ('boolean', 5, None, None, None), - "speed-limit-down": ('number', 1, None, None, None), - "speed-limit-down-enabled": ('boolean', 1, None, None, None), - "speed-limit-up": ('number', 1, None, None, None), - "speed-limit-up-enabled": ('boolean', 1, None, None, None), - }, -} diff --git a/resources/lib/transmissionrpc-0.3-python2.4/transmission.py b/resources/lib/transmissionrpc-0.3-python2.4/transmission.py deleted file mode 100755 index fb3867d..0000000 --- a/resources/lib/transmissionrpc-0.3-python2.4/transmission.py +++ /dev/null @@ -1,606 +0,0 @@ -# -*- coding: utf-8 -*- -# 2008-07, Erik Svensson - -import sys, os, time, datetime -import re -import httplib, urllib2, base64, socket - -try: - import json -except ImportError: - import simplejson as json - -from constants import * -from utils import * - -class TransmissionError(Exception): - def __init__(self, message='', original=None): - Exception.__init__(self, message) - self.message = message - self.original = original - - def __str__(self): - if self.original: - original_name = type(self.original).__name__ - return '%s Original exception: %s, "%s"' % (self.message, original_name, self.original.args) - else: - return self.args - -class Torrent(object): - """ - Torrent is a class holding the data raceived from Transmission regarding a bittorrent transfer. - All fetched torrent fields are accessable through this class using attributes. - This class has a few convenience properties using the torrent data. - """ - - def __init__(self, fields): - if 'id' not in fields: - raise ValueError('Torrent requires an id') - self.fields = {} - self.update(fields) - - def __repr__(self): - return '' % (self.fields['id'], self.fields['name']) - - def __str__(self): - return 'torrent %s' % self.fields['name'] - - def update(self, other): - """Update the torrent data from a Transmission arguments dictinary""" - fields = None - if isinstance(other, dict): - fields = other - elif isinstance(other, Torrent): - fields = other.fields - else: - raise ValueError('Cannot update with supplied data') - for k, v in fields.iteritems(): - self.fields[k.replace('-', '_')] = v - - def files(self): - """ - Get list of files for this torrent. This function returns a dictionary with file information for each file. - """ - result = {} - if 'files' in self.fields: - indicies = xrange(len(self.fields['files'])) - files = self.fields['files'] - priorities = self.fields['priorities'] - wanted = self.fields['wanted'] - index = 1 - for item in zip(indicies, files, priorities, wanted): - selected = bool(item[3]) - priority = PRIORITY[item[2]] - result[item[0]] = { - 'selected': selected, - 'priority': priority, - 'size': item[1]['length'], - 'name': item[1]['name'], - 'completed': item[1]['bytesCompleted']} - return result - - def __getattr__(self, name): - try: - return self.fields[name] - except KeyError, e: - raise AttributeError('No attribute %s' % name) - - @property - def status(self): - """Get the status as string.""" - return STATUS[self.fields['status']] - - @property - def progress(self): - """Get the download progress in percent as float.""" - try: - return 100.0 * (self.fields['sizeWhenDone'] - self.fields['leftUntilDone']) / float(self.fields['sizeWhenDone']) - except ZeroDivisionError: - return 0.0 - - @property - def ratio(self): - """Get the upload/download ratio.""" - try: - return self.fields['uploadedEver'] / float(self.fields['downloadedEver']) - except ZeroDivisionError: - return 0.0 - - @property - def eta(self): - """Get the "eta" as datetime.timedelta.""" - eta = self.fields['eta'] - if eta >= 0: - return datetime.timedelta(seconds=eta) - else: - ValueError('eta not valid') - - @property - def date_active(self): - """Get the attribute "activityDate" as datetime.datetime.""" - return datetime.datetime.fromtimestamp(self.fields['activityDate']) - - @property - def date_added(self): - """Get the attribute "addedDate" as datetime.datetime.""" - return datetime.datetime.fromtimestamp(self.fields['addedDate']) - - @property - def date_started(self): - """Get the attribute "startDate" as datetime.datetime.""" - return datetime.datetime.fromtimestamp(self.fields['startDate']) - - @property - def date_done(self): - """Get the attribute "doneDate" as datetime.datetime.""" - return datetime.datetime.fromtimestamp(self.fields['doneDate']) - - def format_eta(self): - """Returns the attribute "eta" formatted as a string.""" - eta = self.fields['eta'] - if eta == -1: - return 'not available' - elif eta == -2: - return 'unknown' - else: - return format_timedelta(self.eta) - -class Session(object): - """ - Session is a class holding the session data for a Transmission daemon. - - Access the session field can be done through attributes. - The attributes available are the same as the session arguments in the - Transmission RPC specification, but with underscore instead of hypen. - ``download-dir`` -> ``download_dir``. - """ - - def __init__(self, fields={}): - self.fields = {} - self.update(fields) - - def update(self, other): - """Update the session data from a session arguments dictinary""" - - fields = None - if isinstance(other, dict): - fields = other - elif isinstance(other, Session): - fields = other.fields - else: - raise ValueError('Cannot update with supplied data') - - for k, v in fields.iteritems(): - self.fields[k.replace('-', '_')] = v - - def __getattr__(self, name): - try: - return self.fields[name] - except KeyError, e: - raise AttributeError('No attribute %s' % name) - - def __str__(self): - text = '' - for k, v in self.fields.iteritems(): - text += "% 32s: %s\n" % (k[-32:], v) - return text - -class Client(object): - """ - This is it. This class implements the json-RPC protocol to communicate with Transmission. - """ - - def __init__(self, address='localhost', port=DEFAULT_PORT, user=None, password=None): - base_url = 'http://' + address + ':' + str(port) - self.url = base_url + '/transmission/rpc' - if user and password: - password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() - password_manager.add_password(realm=None, uri=self.url, user=user, passwd=password) - opener = urllib2.build_opener( - urllib2.HTTPBasicAuthHandler(password_manager) - , urllib2.HTTPDigestAuthHandler(password_manager) - ) - urllib2.install_opener(opener) - elif user or password: - logger.warning('Either user or password missing, not using authentication.') - self._sequence = 0 - self.session = Session() - self.sessionid = 0 - self.protocol_version = None - self.get_session() - self.torrent_get_arguments = get_arguments('torrent-get' - , self.rpc_version) - - def _debug_request(self, request): - logger.debug( - json.dumps( - { - 'request': { - 'url': request.get_full_url(), - 'request-headers': dict(request.header_items()), - 'request-data': json.loads(request.data), - } - }, - indent=2 - ) - ) - - def _debug_response(self, response, response_data): - try: - response_data = json.loads(response_data) - except: - pass - logger.debug( - json.dumps( - { - 'response': { - 'url': response.url, - 'code': response.code, - 'msg': response.msg, - 'headers': dict(response.headers), - 'data': response_data, - } - }, - indent=2 - ) - ) - - def _http_query(self, query): - headers = {'X-Transmission-Session-Id': self.sessionid} - request = urllib2.Request(self.url, query, headers) - request_count = 0 - while True: - error_data = "" - try: - try: - self._debug_request(request) - socket.setdefaulttimeout(10) - if (sys.version_info[0] == 2 and sys.version_info[1] > 5) or sys.version_info[0] > 2: - response = urllib2.urlopen(request, timeout=60) - else: - response = urllib2.urlopen(request) - break - except urllib2.HTTPError, error: - error_data = error.read() - if error.code == 409: - logger.info('Server responded with 409, trying to set session-id.') - if request_count > 1: - raise TransmissionError('Session ID negotiation failed.', error) - if 'X-Transmission-Session-Id' in error.headers: - self.sessionid = error.headers['X-Transmission-Session-Id'] - request.add_header('X-Transmission-Session-Id', self.sessionid) - else: - raise TransmissionError('Unknown conflict.', error) - except urllib2.URLError, error: - raise TransmissionError('Failed to connect to daemon.', error) - except httplib.BadStatusLine, error: - if (request_count > 1): - raise TransmissionError('Failed to request %s "%s".' % (self.url, query), error) - finally: - if error_data: - self._debug_response(error, error_data) - request_count = request_count + 1 - result = response.read() - self._debug_response(response, result) - return result - - def _request(self, method, arguments={}, ids=[], require_ids = False): - """Send json-rpc request to Transmission using http POST""" - - if not isinstance(method, (str, unicode)): - raise ValueError('request takes method as string') - if not isinstance(arguments, dict): - raise ValueError('request takes arguments as dict') - ids = self._format_ids(ids) - if len(ids) > 0: - arguments['ids'] = ids - elif require_ids: - raise ValueError('request require ids') - - query = json.dumps({'tag': self._sequence, 'method': method - , 'arguments': arguments}) - logger.info(query) - self._sequence += 1 - start = time.time() - http_data = self._http_query(query) - elapsed = time.time() - start - logger.info('http request took %.3f s' % (elapsed)) - - try: - data = json.loads(http_data) - except ValueError, e: - logger.error('Error: ' + str(e)) - logger.error('Request: \"%s\"' % (query)) - logger.error('HTTP data: \"%s\"' % (http_data)) - raise - - logger.info(json.dumps(data, indent=2)) - - if data['result'] != 'success': - raise TransmissionError('Query failed with result \"%s\"' - % data['result']) - - results = {} - if method == 'torrent-get': - for item in data['arguments']['torrents']: - results[item['id']] = Torrent(item) - if self.protocol_version == 2 and 'peers' not in item: - self.protocol_version = 1 - elif method == 'torrent-add': - item = data['arguments']['torrent-added'] - results[item['id']] = Torrent(item) - elif method == 'session-get': - self._update_session(data['arguments']) - elif method == 'session-stats': - # older versions of T has the return data in "session-stats" - if 'session-stats' in data['arguments']: - self._update_session(data['arguments']['session-stats']) - else: - self._update_session(data['arguments']) - elif method in ('port-test', 'blocklist-update'): - results = data['arguments'] - else: - return None - - return results - - def _format_ids(self, args): - """Take things and make them valid torrent identifiers""" - ids = [] - - if isinstance(args, (int, long)): - ids.append(args) - elif isinstance(args, (str, unicode)): - for item in re.split(u'[ ,]+', args): - if len(item) == 0: - continue - addition = None - try: - # handle index - addition = [int(item)] - except ValueError: - pass - if not addition: - # handle hashes - try: - int(item, 16) - addition = [item] - except: - pass - if not addition: - # handle index ranges i.e. 5:10 - match = re.match(u'^(\d+):(\d+)$', item) - if match: - try: - idx_from = int(match.group(1)) - idx_to = int(match.group(2)) - addition = range(idx_from, idx_to + 1) - except: - pass - if not addition: - raise ValueError(u'Invalid torrent id, \"%s\"' % item) - ids.extend(addition) - elif isinstance(args, (list)): - for item in args: - ids.extend(self._format_ids(item)) - else: - raise ValueError(u'Invalid torrent id') - return ids - - def _update_session(self, data): - self.session.update(data) - - @property - def rpc_version(self): - if self.protocol_version == None: - if hasattr(self.session, 'rpc_version'): - self.protocol_version = self.session.rpc_version - elif hasattr(self.session, 'version'): - self.protocol_version = 3 - else: - self.protocol_version = 2 - return self.protocol_version - - def _rpc_version_warning(self, version): - if self.rpc_version < version: - logger.warning('Using feature not supported by server. RPC version for server %d, feature introduced in %d.' % (self.rpc_version, version)) - - def add(self, data, **kwargs): - """ - Add torrent to transfers list. Takes a base64 encoded .torrent file in data. - Additional arguments are: - - * `paused`, boolean, Whether to pause the transfer on add. - * `download_dir`, path, The directory where the downloaded - contents will be saved in. - * `peer_limit`, number, Limits the number of peers for this - transfer. - * `files_unwanted`, - * `files_wanted`, - * `priority_high`, - * `priority_low`, - * `priority_normal`, - """ - args = {'metainfo': data} - for key, value in kwargs.iteritems(): - argument = make_rpc_name(key) - (arg, val) = argument_value_convert('torrent-add', - argument, value, self.rpc_version) - args[arg] = val - return self._request('torrent-add', args) - - def add_url(self, torrent_url, **kwargs): - """ - Add torrent to transfers list. Takes a url to a .torrent file. - Additional arguments are: - - * `paused`, boolean, Whether to pause the transfer on add. - * `download_dir`, path, The directory where the downloaded - contents will be saved in. - * `peer_limit`, number, Limits the number of peers for this - transfer. - * `files_unwanted`, - * `files_wanted`, - * `priority_high`, - * `priority_low`, - * `priority_normal`, - """ - torrent_file = None - if os.path.exists(torrent_url): - torrent_file = open(torrent_url, 'r') - else: - try: - torrent_file = urllib2.urlopen(torrent_url) - except: - torrent_file = None - - if not torrent_file: - raise TransmissionError('File does not exist.') - - torrent_data = base64.b64encode(torrent_file.read()) - return self.add(torrent_data, **kwargs) - - def remove(self, ids, delete_data=False): - """ - remove torrent(s) with provided id(s). Local data is removed if - delete_data is True, otherwise not. - """ - self._rpc_version_warning(3) - self._request('torrent-remove', - {'delete-local-data':rpc_bool(delete_data)}, ids, True) - - def start(self, ids): - """start torrent(s) with provided id(s)""" - self._request('torrent-start', {}, ids, True) - - def stop(self, ids): - """stop torrent(s) with provided id(s)""" - self._request('torrent-stop', {}, ids, True) - - def verify(self, ids): - """verify torrent(s) with provided id(s)""" - self._request('torrent-verify', {}, ids, True) - - def reannounce(self, ids): - """reannounce torrent(s) with provided id(s)""" - self._rpc_version_warning(5) - self._request('torrent-reannounce', {}, ids, True) - - def info(self, ids=[], arguments={}): - """Get detailed information for torrent(s) with provided id(s).""" - if not arguments: - arguments = self.torrent_get_arguments - return self._request('torrent-get', {'fields': arguments}, ids) - - def get_files(self, ids=[]): - """ - Get list of files for provided torrent id(s). - This function returns a dictonary for each requested torrent id holding - the information about the files. - """ - fields = ['id', 'name', 'hashString', 'files', 'priorities', 'wanted'] - request_result = self._request('torrent-get', {'fields': fields}, ids) - result = {} - for id, torrent in request_result.iteritems(): - result[id] = torrent.files() - return result - - def set_files(self, items): - """ - Set file properties. Takes a dictonary with similar contents as the - result of get_files. - """ - if not isinstance(items, dict): - raise ValueError('Invalid file description') - for tid, files in items.iteritems(): - if not isinstance(files, dict): - continue - wanted = [] - unwanted = [] - priority_high = [] - priority_normal = [] - priority_low = [] - for fid, file in files.iteritems(): - if not isinstance(file, dict): - continue - if 'selected' in file and file['selected']: - wanted.append(fid) - else: - unwanted.append(fid) - if 'priority' in file: - if file['priority'] == 'high': - priority_high.append(fid) - elif file['priority'] == 'normal': - priority_normal.append(fid) - elif file['priority'] == 'low': - priority_low.append(fid) - self.change([tid], files_wanted = wanted - , files_unwanted = unwanted - , priority_high = priority_high - , priority_normal = priority_normal - , priority_low = priority_low) - - def list(self): - """list all torrents""" - fields = ['id', 'hashString', 'name', 'sizeWhenDone', 'leftUntilDone' - , 'eta', 'status', 'rateUpload', 'rateDownload', 'uploadedEver' - , 'downloadedEver'] - return self._request('torrent-get', {'fields': fields}) - - def change(self, ids, **kwargs): - """ - Change torrent parameters. This is the list of parameters that. - """ - args = {} - for key, value in kwargs.iteritems(): - argument = make_rpc_name(key) - (arg, val) = argument_value_convert('torrent-set' - , argument, value, self.rpc_version) - args[arg] = val - - if len(args) > 0: - self._request('torrent-set', args, ids, True) - else: - ValueError("No arguments to set") - - def get_session(self): - """Get session parameters""" - self._request('session-get') - return self.session - - def set_session(self, **kwargs): - """Set session parameters""" - args = {} - for key, value in kwargs.iteritems(): - if key == 'encryption' and value not in ['required', 'preferred', 'tolerated']: - raise ValueError('Invalid encryption value') - argument = make_rpc_name(key) - (arg, val) = argument_value_convert('session-set' - , argument, value, self.rpc_version) - args[arg] = val - if len(args) > 0: - self._request('session-set', args) - - def blocklist_update(self): - """Update block list. Returns the size of the block list.""" - self._rpc_version_warning(5) - result = self._request('blocklist-update') - if 'blocklist-size' in result: - return result['blocklist-size'] - return None - - def port_test(self): - """ - Tests to see if your incoming peer port is accessible from the - outside world. - """ - self._rpc_version_warning(5) - result = self._request('port-test') - if 'port-is-open' in result: - return result['port-is-open'] - return None - - def session_stats(self): - """Get session statistics""" - self._request('session-stats') - return self.session diff --git a/resources/lib/transmissionrpc-0.3-python2.4/utils.py b/resources/lib/transmissionrpc-0.3-python2.4/utils.py deleted file mode 100644 index 3e4099e..0000000 --- a/resources/lib/transmissionrpc-0.3-python2.4/utils.py +++ /dev/null @@ -1,138 +0,0 @@ -# -*- coding: utf-8 -*- -# 2008-07, Erik Svensson - -import socket, datetime -import constants -from constants import logger - -UNITS = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB'] - -def format_size(size): - s = float(size) - i = 0 - while size >= 1024.0 and i < len(UNITS): - i += 1 - size /= 1024.0 - return (size, UNITS[i]) - -def format_speed(size): - (size, unit) = format_size(size) - return (size, unit + '/s') - -def format_timedelta(delta): - minutes, seconds = divmod(delta.seconds, 60) - hours, minutes = divmod(minutes, 60) - return '%d %02d:%02d:%02d' % (delta.days, hours, minutes, seconds) - -def format_timestamp(timestamp): - if timestamp > 0: - dt = datetime.datetime.fromtimestamp(timestamp) - return dt.isoformat(' ') - else: - return '-' - -class INetAddressError(Exception): - pass - -def inet_address(address, default_port, default_address='localhost'): - addr = address.split(':') - if len(addr) == 1: - try: - port = int(addr[0]) - addr = default_address - except: - addr = addr[0] - port = default_port - elif len(addr) == 2: - port = int(addr[1]) - if len(addr[0]) == 0: - addr = default_address - else: - addr = addr[0] - else: - addr = default_address - port = default_port - try: - socket.getaddrinfo(addr, port, socket.AF_INET, socket.SOCK_STREAM) - except socket.gaierror, e: - raise INetAddressError('Cannot look up address "%s".' % address) - return (addr, port) - -def rpc_bool(arg): - if isinstance(arg, (str, unicode)): - try: - arg = bool(int(arg)) - except: - arg = arg.lower() in [u'true', u'yes'] - if bool(arg): - return 1 - else: - return 0 - -TR_TYPE_MAP = { - 'number' : int, - 'string' : str, - 'double': float, - 'boolean' : rpc_bool, - 'array': list, - 'object': dict -} - -def make_python_name(name): - return name.replace('-', '_') - -def make_rpc_name(name): - return name.replace('_', '-') - -def argument_value_convert(method, argument, value, rpc_version): - if method in ('torrent-add', 'torrent-get', 'torrent-set'): - args = constants.TORRENT_ARGS[method[-3:]] - elif method in ('session-get', 'session-set'): - args = constants.SESSION_ARGS[method[-3:]] - else: - return ValueError('Method "%s" not supported' % (method)) - if argument in args: - info = args[argument] - invalid_version = True - while invalid_version: - invalid_version = False - replacement = None - if rpc_version < info[1]: - invalid_version = True - replacement = info[3] - if info[2] and info[2] <= rpc_version: - invalid_version = True - replacement = info[4] - if invalid_version: - if replacement: - logger.warning( - 'Replacing requested argument "%s" with "%s".' - % (argument, replacement)) - argument = replacement - info = args[argument] - else: - raise ValueError( - 'Method "%s" Argument "%s" does not exist in version %d.' - % (method, argument, rpc_version)) - return (argument, TR_TYPE_MAP[info[0]](value)) - else: - raise ValueError('Argument "%s" does not exists for method "%s".', - (argument, method)) - -def get_arguments(method, rpc_version): - if method in ('torrent-add', 'torrent-get', 'torrent-set'): - args = constants.TORRENT_ARGS[method[-3:]] - elif method in ('session-get', 'session-set'): - args = constants.SESSION_ARGS[method[-3:]] - else: - return ValueError('Method "%s" not supported' % (method)) - accessible = [] - for argument, info in args.iteritems(): - valid_version = True - if rpc_version < info[1]: - valid_version = False - if info[2] and info[2] <= rpc_version: - valid_version = False - if valid_version: - accessible.append(argument) - return accessible diff --git a/resources/lib/transmissionrpc-0.3/__init__.py b/resources/lib/transmissionrpc-0.3/__init__.py deleted file mode 100644 index f4afa02..0000000 --- a/resources/lib/transmissionrpc-0.3/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# 2008-08, Erik Svensson - -from constants import * -from transmission import TransmissionError, Torrent, Session, Client - -__author__ = u'Erik Svensson ' -__version__ = u'0.3' -__copyright__ = u'Copyright (c) 2008 Erik Svensson' -__license__ = u'MIT' diff --git a/resources/lib/transmissionrpc-0.3/constants.py b/resources/lib/transmissionrpc-0.3/constants.py deleted file mode 100755 index 96ccc01..0000000 --- a/resources/lib/transmissionrpc-0.3/constants.py +++ /dev/null @@ -1,230 +0,0 @@ -# -*- coding: utf-8 -*- -# 2008-07, Erik Svensson - -import logging - -logger = logging.getLogger('transmissionrpc') -logger.setLevel(logging.ERROR) - -def mirror_dict(d): - d.update(dict((v, k) for k, v in d.iteritems())) - return d - -DEFAULT_PORT = 9091 - -TR_STATUS_CHECK_WAIT = (1<<0) -TR_STATUS_CHECK = (1<<1) -TR_STATUS_DOWNLOAD = (1<<2) -TR_STATUS_SEED = (1<<3) -TR_STATUS_STOPPED = (1<<4) - -STATUS = mirror_dict({ - 'check pending' : TR_STATUS_CHECK_WAIT, - 'checking' : TR_STATUS_CHECK, - 'downloading' : TR_STATUS_DOWNLOAD, - 'seeding' : TR_STATUS_SEED, - 'stopped' : TR_STATUS_STOPPED, -}) - -TR_PRI_LOW = -1 -TR_PRI_NORMAL = 0 -TR_PRI_HIGH = 1 - -PRIORITY = mirror_dict({ - 'low' : TR_PRI_LOW, - 'normal' : TR_PRI_NORMAL, - 'high' : TR_PRI_HIGH -}) - -TR_RATIOLIMIT_GLOBAL = 0 # follow the global settings -TR_RATIOLIMIT_SINGLE = 1 # override the global settings, seeding until a certain ratio -TR_RATIOLIMIT_UNLIMITED = 2 # override the global settings, seeding regardless of ratio - -RATIO_LIMIT = mirror_dict({ - 'global' : TR_RATIOLIMIT_GLOBAL, - 'single' : TR_RATIOLIMIT_SINGLE, - 'unlimeted' : TR_RATIOLIMIT_UNLIMITED -}) - -# A note on argument maps -# These maps are used to verify *-set methods. The information is structured in -# a tree. -# set +- - [, , , , ] -# | +- - [, , , , ] -# | -# get +- - [, , , , ] -# +- - [, , , , ] - -# Arguments for torrent methods -TORRENT_ARGS = { - 'get' : { - 'activityDate': ('number', 1, None, None, None), - 'addedDate': ('number', 1, None, None, None), - 'announceResponse': ('string', 1, None, None, None), - 'announceURL': ('string', 1, None, None, None), - 'bandwidthPriority': ('number', 5, None, None, None), - 'comment': ('string', 1, None, None, None), - 'corruptEver': ('number', 1, None, None, None), - 'creator': ('string', 1, None, None, None), - 'dateCreated': ('number', 1, None, None, None), - 'desiredAvailable': ('number', 1, None, None, None), - 'doneDate': ('number', 1, None, None, None), - 'downloadDir': ('string', 4, None, None, None), - 'downloadedEver': ('number', 1, None, None, None), - 'downloaders': ('number', 4, None, None, None), - 'downloadLimit': ('number', 1, None, None, None), - 'downloadLimited': ('boolean', 5, None, None, None), - 'downloadLimitMode': ('number', 1, 5, None, None), - 'error': ('number', 1, None, None, None), - 'errorString': ('number', 1, None, None, None), - 'eta': ('number', 1, None, None, None), - 'files': ('array', 1, None, None, None), - 'fileStats': ('array', 5, None, None, None), - 'hashString': ('string', 1, None, None, None), - 'haveUnchecked': ('number', 1, None, None, None), - 'haveValid': ('number', 1, None, None, None), - 'honorsSessionLimits': ('boolean', 5, None, None, None), - 'id': ('number', 1, None, None, None), - 'isPrivate': ('boolean', 1, None, None, None), - 'lastAnnounceTime': ('number', 1, None, None, None), - 'lastScrapeTime': ('number', 1, None, None, None), - 'leechers': ('number', 1, None, None, None), - 'leftUntilDone': ('number', 1, None, None, None), - 'manualAnnounceTime': ('number', 1, None, None, None), - 'maxConnectedPeers': ('number', 1, None, None, None), - 'name': ('string', 1, None, None, None), - 'nextAnnounceTime': ('number', 1, None, None, None), - 'nextScrapeTime': ('number', 1, None, None, None), - 'peer-limit': ('number', 5, None, None, None), - 'peers': ('array', 2, None, None, None), - 'peersConnected': ('number', 1, None, None, None), - 'peersFrom': ('object', 1, None, None, None), - 'peersGettingFromUs': ('number', 1, None, None, None), - 'peersKnown': ('number', 1, None, None, None), - 'peersSendingToUs': ('number', 1, None, None, None), - 'percentDone': ('double', 5, None, None, None), - 'pieces': ('string', 5, None, None, None), - 'pieceCount': ('number', 1, None, None, None), - 'pieceSize': ('number', 1, None, None, None), - 'priorities': ('array', 1, None, None, None), - 'rateDownload': ('number', 1, None, None, None), - 'rateUpload': ('number', 1, None, None, None), - 'recheckProgress': ('double', 1, None, None, None), - 'scrapeResponse': ('string', 1, None, None, None), - 'scrapeURL': ('string', 1, None, None, None), - 'seeders': ('number', 1, None, None, None), - 'seedRatioLimit': ('double', 5, None, None, None), - 'seedRatioMode': ('number', 5, None, None, None), - 'sizeWhenDone': ('number', 1, None, None, None), - 'startDate': ('number', 1, None, None, None), - 'status': ('number', 1, None, None, None), - 'swarmSpeed': ('number', 1, None, None, None), - 'timesCompleted': ('number', 1, None, None, None), - 'trackers': ('array', 1, None, None, None), - 'totalSize': ('number', 1, None, None, None), - 'torrentFile': ('string', 5, None, None, None), - 'uploadedEver': ('number', 1, None, None, None), - 'uploadLimit': ('number', 1, None, None, None), - 'uploadLimitMode': ('number', 1, 5, None, None), - 'uploadLimited': ('boolean', 5, None, None, None), - 'uploadRatio': ('double', 1, None, None, None), - 'wanted': ('array', 1, None, None, None), - 'webseeds': ('array', 1, None, None, None), - 'webseedsSendingToUs': ('number', 1, None, None, None), - }, - 'set': { - 'bandwidthPriority': ('number', 5, None, None, None), - 'downloadLimit': ('number', 5, None, 'speed-limit-down', None), - 'downloadLimited': ('boolean', 5, None, 'speed-limit-down-enabled', None), - 'files-wanted': ('array', 1, None, None, None), - 'files-unwanted': ('array', 1, None, None, None), - 'honorsSessionLimits': ('boolean', 5, None, None, None), - 'ids': ('array', 1, None, None, None), - 'peer-limit': ('number', 1, None, None, None), - 'priority-high': ('array', 1, None, None, None), - 'priority-low': ('array', 1, None, None, None), - 'priority-normal': ('array', 1, None, None, None), - 'seedRatioLimit': ('double', 5, None, None, None), - 'seedRatioMode': ('number', 5, None, None, None), - 'speed-limit-down': ('number', 1, 5, None, 'downloadLimit'), - 'speed-limit-down-enabled': ('boolean', 1, 5, None, 'downloadLimited'), - 'speed-limit-up': ('number', 1, 5, None, 'uploadLimit'), - 'speed-limit-up-enabled': ('boolean', 1, 5, None, 'uploadLimited'), - 'uploadLimit': ('number', 5, None, 'speed-limit-up', None), - 'uploadLimited': ('boolean', 5, None, 'speed-limit-up-enabled', None), - }, - 'add': { - 'download-dir': ('string', 1, None, None, None), - 'filename': ('string', 1, None, None, None), - 'files-wanted': ('array', 1, None, None, None), - 'files-unwanted': ('array', 1, None, None, None), - 'metainfo': ('string', 1, None, None, None), - 'paused': ('boolean', 1, None, None, None), - 'peer-limit': ('number', 1, None, None, None), - 'priority-high': ('array', 1, None, None, None), - 'priority-low': ('array', 1, None, None, None), - 'priority-normal': ('array', 1, None, None, None), - } -} - -# Arguments for session methods -SESSION_ARGS = { - 'get': { - "alt-speed-down": ('number', 5, None, None, None), - "alt-speed-enabled": ('boolean', 5, None, None, None), - "alt-speed-time-begin": ('number', 5, None, None, None), - "alt-speed-time-enabled": ('boolean', 5, None, None, None), - "alt-speed-time-end": ('number', 5, None, None, None), - "alt-speed-time-day": ('number', 5, None, None, None), - "alt-speed-up": ('number', 5, None, None, None), - "blocklist-enabled": ('boolean', 5, None, None, None), - "blocklist-size": ('number', 5, None, None, None), - "encryption": ('string', 1, None, None, None), - "download-dir": ('string', 1, None, None, None), - "peer-limit": ('number', 1, 5, None, None), - "peer-limit-global": ('number', 5, None, None, None), - "peer-limit-per-torrent": ('number', 5, None, None, None), - "pex-allowed": ('boolean', 1, 5, None, None), - "pex-enabled": ('boolean', 5, None, None, None), - "port": ('number', 1, 5, None, None), - "peer-port": ('number', 5, None, None, None), - "peer-port-random-on-start": ('boolean', 5, None, None, None), - "port-forwarding-enabled": ('boolean', 1, None, None, None), - "rpc-version": ('number', 4, None, None, None), - "rpc-version-minimum": ('number', 4, None, None, None), - "seedRatioLimit": ('double', 5, None, None, None), - "seedRatioLimited": ('boolean', 5, None, None, None), - "speed-limit-down": ('number', 1, None, None, None), - "speed-limit-down-enabled": ('boolean', 1, None, None, None), - "speed-limit-up": ('number', 1, None, None, None), - "speed-limit-up-enabled": ('boolean', 1, None, None, None), - "version": ('string', 3, None, None, None), - }, - 'set': { - "alt-speed-down": ('number', 5, None, None, None), - "alt-speed-enabled": ('boolean', 5, None, None, None), - "alt-speed-time-begin": ('number', 5, None, None, None), - "alt-speed-time-enabled": ('boolean', 5, None, None, None), - "alt-speed-time-end": ('number', 5, None, None, None), - "alt-speed-time-day": ('number', 5, None, None, None), - "alt-speed-up": ('number', 5, None, None, None), - "blocklist-enabled": ('boolean', 5, None, None, None), - "encryption": ('string', 1, None, None, None), - "download-dir": ('string', 1, None, None, None), - "peer-limit": ('number', 1, 5, None, 'peer-limit-global'), - "peer-limit-global": ('number', 5, None, 'peer-limit', None), - "peer-limit-per-torrent": ('number', 5, None, None, None), - "pex-allowed": ('boolean', 1, 5, None, 'pex-enabled'), - "pex-enabled": ('boolean', 5, None, 'pex-allowed', None), - "port": ('number', 1, 5, None, 'peer-port'), - "peer-port": ('number', 5, None, 'port', None), - "peer-port-random-on-start": ('boolean', 5, None, None, None), - "port-forwarding-enabled": ('boolean', 1, None, None, None), - "seedRatioLimit": ('double', 5, None, None, None), - "seedRatioLimited": ('boolean', 5, None, None, None), - "speed-limit-down": ('number', 1, None, None, None), - "speed-limit-down-enabled": ('boolean', 1, None, None, None), - "speed-limit-up": ('number', 1, None, None, None), - "speed-limit-up-enabled": ('boolean', 1, None, None, None), - }, -} diff --git a/resources/lib/transmissionrpc-0.3/transmission.py b/resources/lib/transmissionrpc-0.3/transmission.py deleted file mode 100755 index 7a62c19..0000000 --- a/resources/lib/transmissionrpc-0.3/transmission.py +++ /dev/null @@ -1,605 +0,0 @@ -# -*- coding: utf-8 -*- -# 2008-07, Erik Svensson - -import sys, os, time, datetime -import re -import httplib, urllib2, base64, socket - -try: - import json -except ImportError: - import simplejson as json - -from constants import * -from utils import * - -class TransmissionError(Exception): - def __init__(self, message='', original=None): - Exception.__init__(self, message) - self.message = message - self.original = original - - def __str__(self): - if self.original: - original_name = type(self.original).__name__ - return '%s Original exception: %s, "%s"' % (self.message, original_name, self.original.args) - else: - return self.args - -class Torrent(object): - """ - Torrent is a class holding the data raceived from Transmission regarding a bittorrent transfer. - All fetched torrent fields are accessable through this class using attributes. - This class has a few convenience properties using the torrent data. - """ - - def __init__(self, fields): - if 'id' not in fields: - raise ValueError('Torrent requires an id') - self.fields = {} - self.update(fields) - - def __repr__(self): - return '' % (self.fields['id'], self.fields['name']) - - def __str__(self): - return 'torrent %s' % self.fields['name'] - - def update(self, other): - """Update the torrent data from a Transmission arguments dictinary""" - fields = None - if isinstance(other, dict): - fields = other - elif isinstance(other, Torrent): - fields = other.fields - else: - raise ValueError('Cannot update with supplied data') - for k, v in fields.iteritems(): - self.fields[k.replace('-', '_')] = v - - def files(self): - """ - Get list of files for this torrent. This function returns a dictionary with file information for each file. - """ - result = {} - if 'files' in self.fields: - indicies = xrange(len(self.fields['files'])) - files = self.fields['files'] - priorities = self.fields['priorities'] - wanted = self.fields['wanted'] - index = 1 - for item in zip(indicies, files, priorities, wanted): - selected = True if item[3] else False - priority = PRIORITY[item[2]] - result[item[0]] = { - 'selected': selected, - 'priority': priority, - 'size': item[1]['length'], - 'name': item[1]['name'], - 'completed': item[1]['bytesCompleted']} - return result - - def __getattr__(self, name): - try: - return self.fields[name] - except KeyError, e: - raise AttributeError('No attribute %s' % name) - - @property - def status(self): - """Get the status as string.""" - return STATUS[self.fields['status']] - - @property - def progress(self): - """Get the download progress in percent as float.""" - try: - return 100.0 * (self.fields['sizeWhenDone'] - self.fields['leftUntilDone']) / float(self.fields['sizeWhenDone']) - except ZeroDivisionError: - return 0.0 - - @property - def ratio(self): - """Get the upload/download ratio.""" - try: - return self.fields['uploadedEver'] / float(self.fields['downloadedEver']) - except ZeroDivisionError: - return 0.0 - - @property - def eta(self): - """Get the "eta" as datetime.timedelta.""" - eta = self.fields['eta'] - if eta >= 0: - return datetime.timedelta(seconds=eta) - else: - ValueError('eta not valid') - - @property - def date_active(self): - """Get the attribute "activityDate" as datetime.datetime.""" - return datetime.datetime.fromtimestamp(self.fields['activityDate']) - - @property - def date_added(self): - """Get the attribute "addedDate" as datetime.datetime.""" - return datetime.datetime.fromtimestamp(self.fields['addedDate']) - - @property - def date_started(self): - """Get the attribute "startDate" as datetime.datetime.""" - return datetime.datetime.fromtimestamp(self.fields['startDate']) - - @property - def date_done(self): - """Get the attribute "doneDate" as datetime.datetime.""" - return datetime.datetime.fromtimestamp(self.fields['doneDate']) - - def format_eta(self): - """Returns the attribute "eta" formatted as a string.""" - eta = self.fields['eta'] - if eta == -1: - return 'not available' - elif eta == -2: - return 'unknown' - else: - return format_timedelta(self.eta) - -class Session(object): - """ - Session is a class holding the session data for a Transmission daemon. - - Access the session field can be done through attributes. - The attributes available are the same as the session arguments in the - Transmission RPC specification, but with underscore instead of hypen. - ``download-dir`` -> ``download_dir``. - """ - - def __init__(self, fields={}): - self.fields = {} - self.update(fields) - - def update(self, other): - """Update the session data from a session arguments dictinary""" - - fields = None - if isinstance(other, dict): - fields = other - elif isinstance(other, Session): - fields = other.fields - else: - raise ValueError('Cannot update with supplied data') - - for k, v in fields.iteritems(): - self.fields[k.replace('-', '_')] = v - - def __getattr__(self, name): - try: - return self.fields[name] - except KeyError, e: - raise AttributeError('No attribute %s' % name) - - def __str__(self): - text = '' - for k, v in self.fields.iteritems(): - text += "% 32s: %s\n" % (k[-32:], v) - return text - -class Client(object): - """ - This is it. This class implements the json-RPC protocol to communicate with Transmission. - """ - - def __init__(self, address='localhost', port=DEFAULT_PORT, user=None, password=None): - base_url = 'http://' + address + ':' + str(port) - self.url = base_url + '/transmission/rpc' - if user and password: - password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() - password_manager.add_password(realm=None, uri=self.url, user=user, passwd=password) - opener = urllib2.build_opener( - urllib2.HTTPBasicAuthHandler(password_manager) - , urllib2.HTTPDigestAuthHandler(password_manager) - ) - urllib2.install_opener(opener) - elif user or password: - logger.warning('Either user or password missing, not using authentication.') - self._sequence = 0 - self.session = Session() - self.sessionid = 0 - self.protocol_version = None - self.get_session() - self.torrent_get_arguments = get_arguments('torrent-get' - , self.rpc_version) - - def _debug_request(self, request): - logger.debug( - json.dumps( - { - 'request': { - 'url': request.get_full_url(), - 'request-headers': dict(request.header_items()), - 'request-data': json.loads(request.data), - } - }, - indent=2 - ) - ) - - def _debug_response(self, response, response_data): - try: - response_data = json.loads(response_data) - except: - pass - logger.debug( - json.dumps( - { - 'response': { - 'url': response.url, - 'code': response.code, - 'msg': response.msg, - 'headers': dict(response.headers), - 'data': response_data, - } - }, - indent=2 - ) - ) - - def _http_query(self, query): - headers = {'X-Transmission-Session-Id': self.sessionid} - request = urllib2.Request(self.url, query, headers) - request_count = 0 - while True: - error_data = "" - try: - self._debug_request(request) - socket.setdefaulttimeout(10) - if (sys.version_info[0] == 2 and sys.version_info[1] > 5) or sys.version_info[0] > 2: - response = urllib2.urlopen(request, timeout=60) - else: - response = urllib2.urlopen(request) - break - except urllib2.HTTPError, error: - error_data = error.read() - if error.code == 409: - logger.info('Server responded with 409, trying to set session-id.') - if request_count > 1: - raise TransmissionError('Session ID negotiation failed.', error) - if 'X-Transmission-Session-Id' in error.headers: - self.sessionid = error.headers['X-Transmission-Session-Id'] - request.add_header('X-Transmission-Session-Id', self.sessionid) - else: - raise TransmissionError('Unknown conflict.', error) - except urllib2.URLError, error: - raise TransmissionError('Failed to connect to daemon.', error) - except httplib.BadStatusLine, error: - if (request_count > 1): - raise TransmissionError('Failed to request %s "%s".' % (self.url, query), error) - finally: - if error_data: - self._debug_response(error, error_data) - request_count = request_count + 1 - result = response.read() - self._debug_response(response, result) - return result - - def _request(self, method, arguments={}, ids=[], require_ids = False): - """Send json-rpc request to Transmission using http POST""" - - if not isinstance(method, (str, unicode)): - raise ValueError('request takes method as string') - if not isinstance(arguments, dict): - raise ValueError('request takes arguments as dict') - ids = self._format_ids(ids) - if len(ids) > 0: - arguments['ids'] = ids - elif require_ids: - raise ValueError('request require ids') - - query = json.dumps({'tag': self._sequence, 'method': method - , 'arguments': arguments}) - logger.info(query) - self._sequence += 1 - start = time.time() - http_data = self._http_query(query) - elapsed = time.time() - start - logger.info('http request took %.3f s' % (elapsed)) - - try: - data = json.loads(http_data) - except ValueError, e: - logger.error('Error: ' + str(e)) - logger.error('Request: \"%s\"' % (query)) - logger.error('HTTP data: \"%s\"' % (http_data)) - raise - - logger.info(json.dumps(data, indent=2)) - - if data['result'] != 'success': - raise TransmissionError('Query failed with result \"%s\"' - % data['result']) - - results = {} - if method == 'torrent-get': - for item in data['arguments']['torrents']: - results[item['id']] = Torrent(item) - if self.protocol_version == 2 and 'peers' not in item: - self.protocol_version = 1 - elif method == 'torrent-add': - item = data['arguments']['torrent-added'] - results[item['id']] = Torrent(item) - elif method == 'session-get': - self._update_session(data['arguments']) - elif method == 'session-stats': - # older versions of T has the return data in "session-stats" - if 'session-stats' in data['arguments']: - self._update_session(data['arguments']['session-stats']) - else: - self._update_session(data['arguments']) - elif method in ('port-test', 'blocklist-update'): - results = data['arguments'] - else: - return None - - return results - - def _format_ids(self, args): - """Take things and make them valid torrent identifiers""" - ids = [] - - if isinstance(args, (int, long)): - ids.append(args) - elif isinstance(args, (str, unicode)): - for item in re.split(u'[ ,]+', args): - if len(item) == 0: - continue - addition = None - try: - # handle index - addition = [int(item)] - except ValueError: - pass - if not addition: - # handle hashes - try: - int(item, 16) - addition = [item] - except: - pass - if not addition: - # handle index ranges i.e. 5:10 - match = re.match(u'^(\d+):(\d+)$', item) - if match: - try: - idx_from = int(match.group(1)) - idx_to = int(match.group(2)) - addition = range(idx_from, idx_to + 1) - except: - pass - if not addition: - raise ValueError(u'Invalid torrent id, \"%s\"' % item) - ids.extend(addition) - elif isinstance(args, (list)): - for item in args: - ids.extend(self._format_ids(item)) - else: - raise ValueError(u'Invalid torrent id') - return ids - - def _update_session(self, data): - self.session.update(data) - - @property - def rpc_version(self): - if self.protocol_version == None: - if hasattr(self.session, 'rpc_version'): - self.protocol_version = self.session.rpc_version - elif hasattr(self.session, 'version'): - self.protocol_version = 3 - else: - self.protocol_version = 2 - return self.protocol_version - - def _rpc_version_warning(self, version): - if self.rpc_version < version: - logger.warning('Using feature not supported by server. RPC version for server %d, feature introduced in %d.' % (self.rpc_version, version)) - - def add(self, data, **kwargs): - """ - Add torrent to transfers list. Takes a base64 encoded .torrent file in data. - Additional arguments are: - - * `paused`, boolean, Whether to pause the transfer on add. - * `download_dir`, path, The directory where the downloaded - contents will be saved in. - * `peer_limit`, number, Limits the number of peers for this - transfer. - * `files_unwanted`, - * `files_wanted`, - * `priority_high`, - * `priority_low`, - * `priority_normal`, - """ - args = {'metainfo': data} - for key, value in kwargs.iteritems(): - argument = make_rpc_name(key) - (arg, val) = argument_value_convert('torrent-add', - argument, value, self.rpc_version) - args[arg] = val - return self._request('torrent-add', args) - - def add_url(self, torrent_url, **kwargs): - """ - Add torrent to transfers list. Takes a url to a .torrent file. - Additional arguments are: - - * `paused`, boolean, Whether to pause the transfer on add. - * `download_dir`, path, The directory where the downloaded - contents will be saved in. - * `peer_limit`, number, Limits the number of peers for this - transfer. - * `files_unwanted`, - * `files_wanted`, - * `priority_high`, - * `priority_low`, - * `priority_normal`, - """ - torrent_file = None - if os.path.exists(torrent_url): - torrent_file = open(torrent_url, 'r') - else: - try: - torrent_file = urllib2.urlopen(torrent_url) - except: - torrent_file = None - - if not torrent_file: - raise TransmissionError('File does not exist.') - - torrent_data = base64.b64encode(torrent_file.read()) - return self.add(torrent_data, **kwargs) - - def remove(self, ids, delete_data=False): - """ - remove torrent(s) with provided id(s). Local data is removed if - delete_data is True, otherwise not. - """ - self._rpc_version_warning(3) - self._request('torrent-remove', - {'delete-local-data':rpc_bool(delete_data)}, ids, True) - - def start(self, ids): - """start torrent(s) with provided id(s)""" - self._request('torrent-start', {}, ids, True) - - def stop(self, ids): - """stop torrent(s) with provided id(s)""" - self._request('torrent-stop', {}, ids, True) - - def verify(self, ids): - """verify torrent(s) with provided id(s)""" - self._request('torrent-verify', {}, ids, True) - - def reannounce(self, ids): - """reannounce torrent(s) with provided id(s)""" - self._rpc_version_warning(5) - self._request('torrent-reannounce', {}, ids, True) - - def info(self, ids=[], arguments={}): - """Get detailed information for torrent(s) with provided id(s).""" - if not arguments: - arguments = self.torrent_get_arguments - return self._request('torrent-get', {'fields': arguments}, ids) - - def get_files(self, ids=[]): - """ - Get list of files for provided torrent id(s). - This function returns a dictonary for each requested torrent id holding - the information about the files. - """ - fields = ['id', 'name', 'hashString', 'files', 'priorities', 'wanted'] - request_result = self._request('torrent-get', {'fields': fields}, ids) - result = {} - for id, torrent in request_result.iteritems(): - result[id] = torrent.files() - return result - - def set_files(self, items): - """ - Set file properties. Takes a dictonary with similar contents as the - result of get_files. - """ - if not isinstance(items, dict): - raise ValueError('Invalid file description') - for tid, files in items.iteritems(): - if not isinstance(files, dict): - continue - wanted = [] - unwanted = [] - priority_high = [] - priority_normal = [] - priority_low = [] - for fid, file in files.iteritems(): - if not isinstance(file, dict): - continue - if 'selected' in file and file['selected']: - wanted.append(fid) - else: - unwanted.append(fid) - if 'priority' in file: - if file['priority'] == 'high': - priority_high.append(fid) - elif file['priority'] == 'normal': - priority_normal.append(fid) - elif file['priority'] == 'low': - priority_low.append(fid) - self.change([tid], files_wanted = wanted - , files_unwanted = unwanted - , priority_high = priority_high - , priority_normal = priority_normal - , priority_low = priority_low) - - def list(self): - """list all torrents""" - fields = ['id', 'hashString', 'name', 'sizeWhenDone', 'leftUntilDone' - , 'eta', 'status', 'rateUpload', 'rateDownload', 'uploadedEver' - , 'downloadedEver'] - return self._request('torrent-get', {'fields': fields}) - - def change(self, ids, **kwargs): - """ - Change torrent parameters. This is the list of parameters that. - """ - args = {} - for key, value in kwargs.iteritems(): - argument = make_rpc_name(key) - (arg, val) = argument_value_convert('torrent-set' - , argument, value, self.rpc_version) - args[arg] = val - - if len(args) > 0: - self._request('torrent-set', args, ids, True) - else: - ValueError("No arguments to set") - - def get_session(self): - """Get session parameters""" - self._request('session-get') - return self.session - - def set_session(self, **kwargs): - """Set session parameters""" - args = {} - for key, value in kwargs.iteritems(): - if key == 'encryption' and value not in ['required', 'preferred', 'tolerated']: - raise ValueError('Invalid encryption value') - argument = make_rpc_name(key) - (arg, val) = argument_value_convert('session-set' - , argument, value, self.rpc_version) - args[arg] = val - if len(args) > 0: - self._request('session-set', args) - - def blocklist_update(self): - """Update block list. Returns the size of the block list.""" - self._rpc_version_warning(5) - result = self._request('blocklist-update') - if 'blocklist-size' in result: - return result['blocklist-size'] - return None - - def port_test(self): - """ - Tests to see if your incoming peer port is accessible from the - outside world. - """ - self._rpc_version_warning(5) - result = self._request('port-test') - if 'port-is-open' in result: - return result['port-is-open'] - return None - - def session_stats(self): - """Get session statistics""" - self._request('session-stats') - return self.session diff --git a/resources/lib/transmissionrpc-0.3/utils.py b/resources/lib/transmissionrpc-0.3/utils.py deleted file mode 100644 index 5b2b2a0..0000000 --- a/resources/lib/transmissionrpc-0.3/utils.py +++ /dev/null @@ -1,135 +0,0 @@ -# -*- coding: utf-8 -*- -# 2008-07, Erik Svensson - -import socket, datetime -import constants -from constants import logger - -UNITS = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB'] - -def format_size(size): - s = float(size) - i = 0 - while size >= 1024.0 and i < len(UNITS): - i += 1 - size /= 1024.0 - return (size, UNITS[i]) - -def format_speed(size): - (size, unit) = format_size(size) - return (size, unit + '/s') - -def format_timedelta(delta): - minutes, seconds = divmod(delta.seconds, 60) - hours, minutes = divmod(minutes, 60) - return '%d %02d:%02d:%02d' % (delta.days, hours, minutes, seconds) - -def format_timestamp(timestamp): - if timestamp > 0: - dt = datetime.datetime.fromtimestamp(timestamp) - return dt.isoformat(' ') - else: - return '-' - -class INetAddressError(Exception): - pass - -def inet_address(address, default_port, default_address='localhost'): - addr = address.split(':') - if len(addr) == 1: - try: - port = int(addr[0]) - addr = default_address - except: - addr = addr[0] - port = default_port - elif len(addr) == 2: - port = int(addr[1]) - if len(addr[0]) == 0: - addr = default_address - else: - addr = addr[0] - else: - addr = default_address - port = default_port - try: - socket.getaddrinfo(addr, port, socket.AF_INET, socket.SOCK_STREAM) - except socket.gaierror, e: - raise INetAddressError('Cannot look up address "%s".' % address) - return (addr, port) - -def rpc_bool(arg): - if isinstance(arg, (str, unicode)): - try: - arg = bool(int(arg)) - except: - arg = arg.lower() in [u'true', u'yes'] - return 1 if bool(arg) else 0 - -TR_TYPE_MAP = { - 'number' : int, - 'string' : str, - 'double': float, - 'boolean' : rpc_bool, - 'array': list, - 'object': dict -} - -def make_python_name(name): - return name.replace('-', '_') - -def make_rpc_name(name): - return name.replace('_', '-') - -def argument_value_convert(method, argument, value, rpc_version): - if method in ('torrent-add', 'torrent-get', 'torrent-set'): - args = constants.TORRENT_ARGS[method[-3:]] - elif method in ('session-get', 'session-set'): - args = constants.SESSION_ARGS[method[-3:]] - else: - return ValueError('Method "%s" not supported' % (method)) - if argument in args: - info = args[argument] - invalid_version = True - while invalid_version: - invalid_version = False - replacement = None - if rpc_version < info[1]: - invalid_version = True - replacement = info[3] - if info[2] and info[2] <= rpc_version: - invalid_version = True - replacement = info[4] - if invalid_version: - if replacement: - logger.warning( - 'Replacing requested argument "%s" with "%s".' - % (argument, replacement)) - argument = replacement - info = args[argument] - else: - raise ValueError( - 'Method "%s" Argument "%s" does not exist in version %d.' - % (method, argument, rpc_version)) - return (argument, TR_TYPE_MAP[info[0]](value)) - else: - raise ValueError('Argument "%s" does not exists for method "%s".', - (argument, method)) - -def get_arguments(method, rpc_version): - if method in ('torrent-add', 'torrent-get', 'torrent-set'): - args = constants.TORRENT_ARGS[method[-3:]] - elif method in ('session-get', 'session-set'): - args = constants.SESSION_ARGS[method[-3:]] - else: - return ValueError('Method "%s" not supported' % (method)) - accessible = [] - for argument, info in args.iteritems(): - valid_version = True - if rpc_version < info[1]: - valid_version = False - if info[2] and info[2] <= rpc_version: - valid_version = False - if valid_version: - accessible.append(argument) - return accessible diff --git a/resources/lib/transmissionrpc-0.4/__init__.py b/resources/lib/transmissionrpc-0.4/__init__.py deleted file mode 100755 index 5e09d46..0000000 --- a/resources/lib/transmissionrpc-0.4/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# 2008-08, Erik Svensson - -from constants import * -from transmission import TransmissionError, Torrent, Session, Client - -__author__ = u'Erik Svensson ' -__version__ = u'0.4' -__copyright__ = u'Copyright (c) 2009 Erik Svensson' -__license__ = u'MIT' diff --git a/resources/lib/transmissionrpc-0.4/constants.py b/resources/lib/transmissionrpc-0.4/constants.py deleted file mode 100755 index f40cdc6..0000000 --- a/resources/lib/transmissionrpc-0.4/constants.py +++ /dev/null @@ -1,234 +0,0 @@ -# -*- coding: utf-8 -*- -# 2008-07, Erik Svensson - -import logging - -logger = logging.getLogger('transmissionrpc') -logger.setLevel(logging.ERROR) - -def mirror_dict(d): - d.update(dict((v, k) for k, v in d.iteritems())) - return d - -DEFAULT_PORT = 9091 - -DEFAULT_TIMEOUT = 30 - -TR_STATUS_CHECK_WAIT = (1<<0) -TR_STATUS_CHECK = (1<<1) -TR_STATUS_DOWNLOAD = (1<<2) -TR_STATUS_SEED = (1<<3) -TR_STATUS_STOPPED = (1<<4) - -STATUS = mirror_dict({ - 'check pending' : TR_STATUS_CHECK_WAIT, - 'checking' : TR_STATUS_CHECK, - 'downloading' : TR_STATUS_DOWNLOAD, - 'seeding' : TR_STATUS_SEED, - 'stopped' : TR_STATUS_STOPPED, -}) - -TR_PRI_LOW = -1 -TR_PRI_NORMAL = 0 -TR_PRI_HIGH = 1 - -PRIORITY = mirror_dict({ - 'low' : TR_PRI_LOW, - 'normal' : TR_PRI_NORMAL, - 'high' : TR_PRI_HIGH -}) - -TR_RATIOLIMIT_GLOBAL = 0 # follow the global settings -TR_RATIOLIMIT_SINGLE = 1 # override the global settings, seeding until a certain ratio -TR_RATIOLIMIT_UNLIMITED = 2 # override the global settings, seeding regardless of ratio - -RATIO_LIMIT = mirror_dict({ - 'global' : TR_RATIOLIMIT_GLOBAL, - 'single' : TR_RATIOLIMIT_SINGLE, - 'unlimeted' : TR_RATIOLIMIT_UNLIMITED -}) - -# A note on argument maps -# These maps are used to verify *-set methods. The information is structured in -# a tree. -# set +- - [, , , , ] -# | +- - [, , , , ] -# | -# get +- - [, , , , ] -# +- - [, , , , ] - -# Arguments for torrent methods -TORRENT_ARGS = { - 'get' : { - 'activityDate': ('number', 1, None, None, None), - 'addedDate': ('number', 1, None, None, None), - 'announceResponse': ('string', 1, None, None, None), - 'announceURL': ('string', 1, None, None, None), - 'bandwidthPriority': ('number', 5, None, None, None), - 'comment': ('string', 1, None, None, None), - 'corruptEver': ('number', 1, None, None, None), - 'creator': ('string', 1, None, None, None), - 'dateCreated': ('number', 1, None, None, None), - 'desiredAvailable': ('number', 1, None, None, None), - 'doneDate': ('number', 1, None, None, None), - 'downloadDir': ('string', 4, None, None, None), - 'downloadedEver': ('number', 1, None, None, None), - 'downloaders': ('number', 4, None, None, None), - 'downloadLimit': ('number', 1, None, None, None), - 'downloadLimited': ('boolean', 5, None, None, None), - 'downloadLimitMode': ('number', 1, 5, None, None), - 'error': ('number', 1, None, None, None), - 'errorString': ('number', 1, None, None, None), - 'eta': ('number', 1, None, None, None), - 'files': ('array', 1, None, None, None), - 'fileStats': ('array', 5, None, None, None), - 'hashString': ('string', 1, None, None, None), - 'haveUnchecked': ('number', 1, None, None, None), - 'haveValid': ('number', 1, None, None, None), - 'honorsSessionLimits': ('boolean', 5, None, None, None), - 'id': ('number', 1, None, None, None), - 'isPrivate': ('boolean', 1, None, None, None), - 'lastAnnounceTime': ('number', 1, None, None, None), - 'lastScrapeTime': ('number', 1, None, None, None), - 'leechers': ('number', 1, None, None, None), - 'leftUntilDone': ('number', 1, None, None, None), - 'manualAnnounceTime': ('number', 1, None, None, None), - 'maxConnectedPeers': ('number', 1, None, None, None), - 'name': ('string', 1, None, None, None), - 'nextAnnounceTime': ('number', 1, None, None, None), - 'nextScrapeTime': ('number', 1, None, None, None), - 'peer-limit': ('number', 5, None, None, None), - 'peers': ('array', 2, None, None, None), - 'peersConnected': ('number', 1, None, None, None), - 'peersFrom': ('object', 1, None, None, None), - 'peersGettingFromUs': ('number', 1, None, None, None), - 'peersKnown': ('number', 1, None, None, None), - 'peersSendingToUs': ('number', 1, None, None, None), - 'percentDone': ('double', 5, None, None, None), - 'pieces': ('string', 5, None, None, None), - 'pieceCount': ('number', 1, None, None, None), - 'pieceSize': ('number', 1, None, None, None), - 'priorities': ('array', 1, None, None, None), - 'rateDownload': ('number', 1, None, None, None), - 'rateUpload': ('number', 1, None, None, None), - 'recheckProgress': ('double', 1, None, None, None), - 'scrapeResponse': ('string', 1, None, None, None), - 'scrapeURL': ('string', 1, None, None, None), - 'seeders': ('number', 1, None, None, None), - 'seedRatioLimit': ('double', 5, None, None, None), - 'seedRatioMode': ('number', 5, None, None, None), - 'sizeWhenDone': ('number', 1, None, None, None), - 'startDate': ('number', 1, None, None, None), - 'status': ('number', 1, None, None, None), - 'swarmSpeed': ('number', 1, None, None, None), - 'timesCompleted': ('number', 1, None, None, None), - 'trackers': ('array', 1, None, None, None), - 'totalSize': ('number', 1, None, None, None), - 'torrentFile': ('string', 5, None, None, None), - 'uploadedEver': ('number', 1, None, None, None), - 'uploadLimit': ('number', 1, None, None, None), - 'uploadLimitMode': ('number', 1, 5, None, None), - 'uploadLimited': ('boolean', 5, None, None, None), - 'uploadRatio': ('double', 1, None, None, None), - 'wanted': ('array', 1, None, None, None), - 'webseeds': ('array', 1, None, None, None), - 'webseedsSendingToUs': ('number', 1, None, None, None), - }, - 'set': { - 'bandwidthPriority': ('number', 5, None, None, None), - 'downloadLimit': ('number', 5, None, 'speed-limit-down', None), - 'downloadLimited': ('boolean', 5, None, 'speed-limit-down-enabled', None), - 'files-wanted': ('array', 1, None, None, None), - 'files-unwanted': ('array', 1, None, None, None), - 'honorsSessionLimits': ('boolean', 5, None, None, None), - 'ids': ('array', 1, None, None, None), - 'peer-limit': ('number', 1, None, None, None), - 'priority-high': ('array', 1, None, None, None), - 'priority-low': ('array', 1, None, None, None), - 'priority-normal': ('array', 1, None, None, None), - 'seedRatioLimit': ('double', 5, None, None, None), - 'seedRatioMode': ('number', 5, None, None, None), - 'speed-limit-down': ('number', 1, 5, None, 'downloadLimit'), - 'speed-limit-down-enabled': ('boolean', 1, 5, None, 'downloadLimited'), - 'speed-limit-up': ('number', 1, 5, None, 'uploadLimit'), - 'speed-limit-up-enabled': ('boolean', 1, 5, None, 'uploadLimited'), - 'uploadLimit': ('number', 5, None, 'speed-limit-up', None), - 'uploadLimited': ('boolean', 5, None, 'speed-limit-up-enabled', None), - }, - 'add': { - 'download-dir': ('string', 1, None, None, None), - 'filename': ('string', 1, None, None, None), - 'files-wanted': ('array', 1, None, None, None), - 'files-unwanted': ('array', 1, None, None, None), - 'metainfo': ('string', 1, None, None, None), - 'paused': ('boolean', 1, None, None, None), - 'peer-limit': ('number', 1, None, None, None), - 'priority-high': ('array', 1, None, None, None), - 'priority-low': ('array', 1, None, None, None), - 'priority-normal': ('array', 1, None, None, None), - } -} - -# Arguments for session methods -SESSION_ARGS = { - 'get': { - "alt-speed-down": ('number', 5, None, None, None), - "alt-speed-enabled": ('boolean', 5, None, None, None), - "alt-speed-time-begin": ('number', 5, None, None, None), - "alt-speed-time-enabled": ('boolean', 5, None, None, None), - "alt-speed-time-end": ('number', 5, None, None, None), - "alt-speed-time-day": ('number', 5, None, None, None), - "alt-speed-up": ('number', 5, None, None, None), - "blocklist-enabled": ('boolean', 5, None, None, None), - "blocklist-size": ('number', 5, None, None, None), - "dht-enabled": ('boolean', 6, None, None, None), - "download-dir": ('string', 1, None, None, None), - "encryption": ('string', 1, None, None, None), - "peer-limit": ('number', 1, 5, None, None), - "peer-limit-global": ('number', 5, None, None, None), - "peer-limit-per-torrent": ('number', 5, None, None, None), - "pex-allowed": ('boolean', 1, 5, None, None), - "pex-enabled": ('boolean', 5, None, None, None), - "port": ('number', 1, 5, None, None), - "peer-port": ('number', 5, None, None, None), - "peer-port-random-on-start": ('boolean', 5, None, None, None), - "port-forwarding-enabled": ('boolean', 1, None, None, None), - "rpc-version": ('number', 4, None, None, None), - "rpc-version-minimum": ('number', 4, None, None, None), - "seedRatioLimit": ('double', 5, None, None, None), - "seedRatioLimited": ('boolean', 5, None, None, None), - "speed-limit-down": ('number', 1, None, None, None), - "speed-limit-down-enabled": ('boolean', 1, None, None, None), - "speed-limit-up": ('number', 1, None, None, None), - "speed-limit-up-enabled": ('boolean', 1, None, None, None), - "version": ('string', 3, None, None, None), - }, - 'set': { - "alt-speed-down": ('number', 5, None, None, None), - "alt-speed-enabled": ('boolean', 5, None, None, None), - "alt-speed-time-begin": ('number', 5, None, None, None), - "alt-speed-time-enabled": ('boolean', 5, None, None, None), - "alt-speed-time-end": ('number', 5, None, None, None), - "alt-speed-time-day": ('number', 5, None, None, None), - "alt-speed-up": ('number', 5, None, None, None), - "blocklist-enabled": ('boolean', 5, None, None, None), - "dht-enabled": ('boolean', 6, None, None, None), - "download-dir": ('string', 1, None, None, None), - "encryption": ('string', 1, None, None, None), - "peer-limit": ('number', 1, 5, None, 'peer-limit-global'), - "peer-limit-global": ('number', 5, None, 'peer-limit', None), - "peer-limit-per-torrent": ('number', 5, None, None, None), - "pex-allowed": ('boolean', 1, 5, None, 'pex-enabled'), - "pex-enabled": ('boolean', 5, None, 'pex-allowed', None), - "port": ('number', 1, 5, None, 'peer-port'), - "peer-port": ('number', 5, None, 'port', None), - "peer-port-random-on-start": ('boolean', 5, None, None, None), - "port-forwarding-enabled": ('boolean', 1, None, None, None), - "seedRatioLimit": ('double', 5, None, None, None), - "seedRatioLimited": ('boolean', 5, None, None, None), - "speed-limit-down": ('number', 1, None, None, None), - "speed-limit-down-enabled": ('boolean', 1, None, None, None), - "speed-limit-up": ('number', 1, None, None, None), - "speed-limit-up-enabled": ('boolean', 1, None, None, None), - }, -} diff --git a/resources/lib/transmissionrpc-0.4/transmission.py b/resources/lib/transmissionrpc-0.4/transmission.py deleted file mode 100755 index 8723385..0000000 --- a/resources/lib/transmissionrpc-0.4/transmission.py +++ /dev/null @@ -1,628 +0,0 @@ -# -*- coding: utf-8 -*- -# 2008-07, Erik Svensson - -import sys, os, time, datetime -import re -import httplib, urllib2, base64, socket - -try: - import json -except ImportError: - import simplejson as json - -from constants import * -from utils import * - -class TransmissionError(Exception): - def __init__(self, message='', original=None): - Exception.__init__(self, message) - self.message = message - self.original = original - - def __str__(self): - if self.original: - original_name = type(self.original).__name__ - return '%s Original exception: %s, "%s"' % (self.message, original_name, self.original.args) - else: - return self.args - -class Torrent(object): - """ - Torrent is a class holding the data raceived from Transmission regarding a bittorrent transfer. - All fetched torrent fields are accessable through this class using attributes. - This class has a few convenience properties using the torrent data. - """ - - def __init__(self, fields): - if 'id' not in fields: - raise ValueError('Torrent requires an id') - self.fields = {} - self.update(fields) - - def __repr__(self): - return '' % (self.fields['id'], self.fields['name']) - - def __str__(self): - return 'torrent %s' % self.fields['name'] - - def update(self, other): - """Update the torrent data from a Transmission arguments dictinary""" - fields = None - if isinstance(other, dict): - fields = other - elif isinstance(other, Torrent): - fields = other.fields - else: - raise ValueError('Cannot update with supplied data') - for k, v in fields.iteritems(): - self.fields[k.replace('-', '_')] = v - - def files(self): - """ - Get list of files for this torrent. This function returns a dictionary with file information for each file. - """ - result = {} - if 'files' in self.fields: - indicies = xrange(len(self.fields['files'])) - files = self.fields['files'] - priorities = self.fields['priorities'] - wanted = self.fields['wanted'] - index = 1 - for item in zip(indicies, files, priorities, wanted): - selected = bool(item[3]) - priority = PRIORITY[item[2]] - result[item[0]] = { - 'selected': selected, - 'priority': priority, - 'size': item[1]['length'], - 'name': item[1]['name'], - 'completed': item[1]['bytesCompleted']} - return result - - def __getattr__(self, name): - try: - return self.fields[name] - except KeyError, e: - raise AttributeError('No attribute %s' % name) - - @property - def status(self): - """Get the status as string.""" - return STATUS[self.fields['status']] - - @property - def progress(self): - """Get the download progress in percent as float.""" - try: - return 100.0 * (self.fields['sizeWhenDone'] - self.fields['leftUntilDone']) / float(self.fields['sizeWhenDone']) - except ZeroDivisionError: - return 0.0 - - @property - def ratio(self): - """Get the upload/download ratio.""" - try: - return self.fields['uploadedEver'] / float(self.fields['downloadedEver']) - except ZeroDivisionError: - return 0.0 - - @property - def eta(self): - """Get the "eta" as datetime.timedelta.""" - eta = self.fields['eta'] - if eta >= 0: - return datetime.timedelta(seconds=eta) - else: - ValueError('eta not valid') - - @property - def date_active(self): - """Get the attribute "activityDate" as datetime.datetime.""" - return datetime.datetime.fromtimestamp(self.fields['activityDate']) - - @property - def date_added(self): - """Get the attribute "addedDate" as datetime.datetime.""" - return datetime.datetime.fromtimestamp(self.fields['addedDate']) - - @property - def date_started(self): - """Get the attribute "startDate" as datetime.datetime.""" - return datetime.datetime.fromtimestamp(self.fields['startDate']) - - @property - def date_done(self): - """Get the attribute "doneDate" as datetime.datetime.""" - return datetime.datetime.fromtimestamp(self.fields['doneDate']) - - def format_eta(self): - """Returns the attribute "eta" formatted as a string.""" - eta = self.fields['eta'] - if eta == -1: - return 'not available' - elif eta == -2: - return 'unknown' - else: - return format_timedelta(self.eta) - -class Session(object): - """ - Session is a class holding the session data for a Transmission daemon. - - Access the session field can be done through attributes. - The attributes available are the same as the session arguments in the - Transmission RPC specification, but with underscore instead of hypen. - ``download-dir`` -> ``download_dir``. - """ - - def __init__(self, fields={}): - self.fields = {} - self.update(fields) - - def update(self, other): - """Update the session data from a session arguments dictinary""" - - fields = None - if isinstance(other, dict): - fields = other - elif isinstance(other, Session): - fields = other.fields - else: - raise ValueError('Cannot update with supplied data') - - for k, v in fields.iteritems(): - self.fields[k.replace('-', '_')] = v - - def __getattr__(self, name): - try: - return self.fields[name] - except KeyError, e: - raise AttributeError('No attribute %s' % name) - - def __str__(self): - text = '' - for k, v in self.fields.iteritems(): - text += "% 32s: %s\n" % (k[-32:], v) - return text - -class Client(object): - """ - This is it. This class implements the json-RPC protocol to communicate with Transmission. - """ - - def __init__(self, address='localhost', port=DEFAULT_PORT, user=None, password=None): - base_url = 'http://' + address + ':' + str(port) - self.url = base_url + '/transmission/rpc' - if user and password: - password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() - password_manager.add_password(realm=None, uri=self.url, user=user, passwd=password) - opener = urllib2.build_opener( - urllib2.HTTPBasicAuthHandler(password_manager) - , urllib2.HTTPDigestAuthHandler(password_manager) - ) - urllib2.install_opener(opener) - elif user or password: - logger.warning('Either user or password missing, not using authentication.') - self._sequence = 0 - self.session = Session() - self.sessionid = 0 - self.protocol_version = None - self.get_session() - self.torrent_get_arguments = get_arguments('torrent-get' - , self.rpc_version) - - def _debug_request(self, request): - logger.debug( - json.dumps( - { - 'request': { - 'url': request.get_full_url(), - 'request-headers': dict(request.header_items()), - 'request-data': json.loads(request.data), - } - }, - indent=2 - ) - ) - - def _debug_response(self, response, response_data): - try: - response_data = json.loads(response_data) - except: - pass - logger.debug( - json.dumps( - { - 'response': { - 'url': response.url, - 'code': response.code, - 'msg': response.msg, - 'headers': dict(response.headers), - 'data': response_data, - } - }, - indent=2 - ) - ) - - def _http_query(self, query, timeout=DEFAULT_TIMEOUT): - headers = {'X-Transmission-Session-Id': self.sessionid} - request = urllib2.Request(self.url, query, headers) - request_count = 0 - while True: - error_data = "" - try: - try: - self._debug_request(request) - socket.setdefaulttimeout(timeout) # 30 seconds - if (sys.version_info[0] == 2 and sys.version_info[1] > 5) or sys.version_info[0] > 2: - response = urllib2.urlopen(request, timeout=timeout) - else: - response = urllib2.urlopen(request) - break - except urllib2.HTTPError, error: - error_data = error.read() - if error.code == 409: - logger.info('Server responded with 409, trying to set session-id.') - if request_count > 1: - raise TransmissionError('Session ID negotiation failed.', error) - if 'X-Transmission-Session-Id' in error.headers: - self.sessionid = error.headers['X-Transmission-Session-Id'] - request.add_header('X-Transmission-Session-Id', self.sessionid) - else: - raise TransmissionError('Unknown conflict.', error) - except urllib2.URLError, error: - raise TransmissionError('Failed to connect to daemon.', error) - except httplib.BadStatusLine, error: - if (request_count > 1): - raise TransmissionError('Failed to request %s "%s".' % (self.url, query), error) - finally: - if error_data: - self._debug_response(error, error_data) - request_count = request_count + 1 - result = response.read() - self._debug_response(response, result) - return result - - def _request(self, method, arguments={}, ids=[], require_ids=False, timeout=DEFAULT_TIMEOUT): - """Send json-rpc request to Transmission using http POST""" - - if not isinstance(method, (str, unicode)): - raise ValueError('request takes method as string') - if not isinstance(arguments, dict): - raise ValueError('request takes arguments as dict') - ids = self._format_ids(ids) - if len(ids) > 0: - arguments['ids'] = ids - elif require_ids: - raise ValueError('request require ids') - - query = json.dumps({'tag': self._sequence, 'method': method - , 'arguments': arguments}) - logger.info(query) - self._sequence += 1 - start = time.time() - http_data = self._http_query(query, timeout) - elapsed = time.time() - start - logger.info('http request took %.3f s' % (elapsed)) - - try: - data = json.loads(http_data) - except ValueError, e: - logger.error('Error: ' + str(e)) - logger.error('Request: \"%s\"' % (query)) - logger.error('HTTP data: \"%s\"' % (http_data)) - raise - - logger.info(json.dumps(data, indent=2)) - - if data['result'] != 'success': - raise TransmissionError('Query failed with result \"%s\"' - % data['result']) - - results = {} - if method == 'torrent-get': - for item in data['arguments']['torrents']: - results[item['id']] = Torrent(item) - if self.protocol_version == 2 and 'peers' not in item: - self.protocol_version = 1 - elif method == 'torrent-add': - item = data['arguments']['torrent-added'] - results[item['id']] = Torrent(item) - elif method == 'session-get': - self._update_session(data['arguments']) - elif method == 'session-stats': - # older versions of T has the return data in "session-stats" - if 'session-stats' in data['arguments']: - self._update_session(data['arguments']['session-stats']) - else: - self._update_session(data['arguments']) - elif method in ('port-test', 'blocklist-update'): - results = data['arguments'] - else: - return None - - return results - - def _format_ids(self, args): - """Take things and make them valid torrent identifiers""" - ids = [] - - if isinstance(args, (int, long)): - ids.append(args) - elif isinstance(args, (str, unicode)): - for item in re.split(u'[ ,]+', args): - if len(item) == 0: - continue - addition = None - try: - # handle index - addition = [int(item)] - except ValueError: - pass - if not addition: - # handle hashes - try: - int(item, 16) - addition = [item] - except: - pass - if not addition: - # handle index ranges i.e. 5:10 - match = re.match(u'^(\d+):(\d+)$', item) - if match: - try: - idx_from = int(match.group(1)) - idx_to = int(match.group(2)) - addition = range(idx_from, idx_to + 1) - except: - pass - if not addition: - raise ValueError(u'Invalid torrent id, \"%s\"' % item) - ids.extend(addition) - elif isinstance(args, (list)): - for item in args: - ids.extend(self._format_ids(item)) - else: - raise ValueError(u'Invalid torrent id') - return ids - - def _update_session(self, data): - self.session.update(data) - - @property - def rpc_version(self): - if self.protocol_version == None: - if hasattr(self.session, 'rpc_version'): - self.protocol_version = self.session.rpc_version - elif hasattr(self.session, 'version'): - self.protocol_version = 3 - else: - self.protocol_version = 2 - return self.protocol_version - - def _rpc_version_warning(self, version): - if self.rpc_version < version: - logger.warning('Using feature not supported by server. RPC version for server %d, feature introduced in %d.' % (self.rpc_version, version)) - - def add(self, data, timeout=DEFAULT_TIMEOUT, **kwargs): - """ - Add torrent to transfers list. Takes a base64 encoded .torrent file in data. - Additional arguments are: - - * `metainfo`, string, alternate way to pass base64 encoded torrent data - * `filename`, path or url, provide torrent data as a file path or URL. - * `paused`, boolean, Whether to pause the transfer on add. - * `download_dir`, path, The directory where the downloaded - contents will be saved in. - * `peer_limit`, number, Limits the number of peers for this - transfer. - * `files_unwanted`, - * `files_wanted`, - * `priority_high`, - * `priority_low`, - * `priority_normal`, - """ - args = {} - if data: - args = {'metainfo': data} - if 'metainfo' in kwargs: - pass - if 'filename' in kwargs: - pass - else: - raise ValueError('No torrent data or torrent url.') - for key, value in kwargs.iteritems(): - argument = make_rpc_name(key) - (arg, val) = argument_value_convert('torrent-add', - argument, value, self.rpc_version) - args[arg] = val - return self._request('torrent-add', args, timeout=timeout) - - def add_url(self, torrent_url, **kwargs): - """ - Add torrent to transfers list. Takes a url to a .torrent file. - Additional arguments are: - - * `paused`, boolean, Whether to pause the transfer on add. - * `download_dir`, path, The directory where the downloaded - contents will be saved in. - * `peer_limit`, number, Limits the number of peers for this - transfer. - * `files_unwanted`, - * `files_wanted`, - * `priority_high`, - * `priority_low`, - * `priority_normal`, - """ - torrent_file = None - if os.path.exists(torrent_url): - torrent_file = open(torrent_url, 'r') - else: - try: - torrent_file = urllib2.urlopen(torrent_url) - except: - torrent_file = None - - if not torrent_file: - raise TransmissionError('File does not exist.') - - torrent_data = base64.b64encode(torrent_file.read()) - return self.add(torrent_data, **kwargs) - - def remove(self, ids, delete_data=False, timeout=DEFAULT_TIMEOUT): - """ - remove torrent(s) with provided id(s). Local data is removed if - delete_data is True, otherwise not. - """ - self._rpc_version_warning(3) - self._request('torrent-remove', - {'delete-local-data':rpc_bool(delete_data)}, ids, True, timeout=timeout) - - def start(self, ids, timeout=DEFAULT_TIMEOUT): - """start torrent(s) with provided id(s)""" - self._request('torrent-start', {}, ids, True, timeout=timeout) - - def stop(self, ids, timeout=DEFAULT_TIMEOUT): - """stop torrent(s) with provided id(s)""" - self._request('torrent-stop', {}, ids, True, timeout=timeout) - - def verify(self, ids, timeout=DEFAULT_TIMEOUT): - """verify torrent(s) with provided id(s)""" - self._request('torrent-verify', {}, ids, True, timeout=timeout) - - def reannounce(self, ids, timeout=DEFAULT_TIMEOUT): - """reannounce torrent(s) with provided id(s)""" - self._rpc_version_warning(5) - self._request('torrent-reannounce', {}, ids, True, timeout=timeout) - - def info(self, ids=[], arguments={}, timeout=DEFAULT_TIMEOUT): - """Get detailed information for torrent(s) with provided id(s).""" - if not arguments: - arguments = self.torrent_get_arguments - return self._request('torrent-get', {'fields': arguments}, ids, timeout=timeout) - - def get_files(self, ids=[], timeout=DEFAULT_TIMEOUT): - """ - Get list of files for provided torrent id(s). - This function returns a dictonary for each requested torrent id holding - the information about the files. - """ - fields = ['id', 'name', 'hashString', 'files', 'priorities', 'wanted'] - request_result = self._request('torrent-get', {'fields': fields}, ids, timeout=timeout) - result = {} - for id, torrent in request_result.iteritems(): - result[id] = torrent.files() - return result - - def set_files(self, items, timeout=DEFAULT_TIMEOUT): - """ - Set file properties. Takes a dictonary with similar contents as the - result of get_files. - """ - if not isinstance(items, dict): - raise ValueError('Invalid file description') - for tid, files in items.iteritems(): - if not isinstance(files, dict): - continue - wanted = [] - unwanted = [] - priority_high = [] - priority_normal = [] - priority_low = [] - for fid, file in files.iteritems(): - if not isinstance(file, dict): - continue - if 'selected' in file and file['selected']: - wanted.append(fid) - else: - unwanted.append(fid) - if 'priority' in file: - if file['priority'] == 'high': - priority_high.append(fid) - elif file['priority'] == 'normal': - priority_normal.append(fid) - elif file['priority'] == 'low': - priority_low.append(fid) - self.change([tid], files_wanted = wanted - , files_unwanted = unwanted - , priority_high = priority_high - , priority_normal = priority_normal - , priority_low = priority_low, timeout=timeout) - - def list(self, timeout=DEFAULT_TIMEOUT): - """list all torrents""" - fields = ['id', 'hashString', 'name', 'sizeWhenDone', 'leftUntilDone' - , 'eta', 'status', 'rateUpload', 'rateDownload', 'uploadedEver' - , 'downloadedEver'] - return self._request('torrent-get', {'fields': fields}, timeout=timeout) - - def change(self, ids, timeout=DEFAULT_TIMEOUT, **kwargs): - """ - Change torrent parameters. This is the list of parameters that. - """ - args = {} - for key, value in kwargs.iteritems(): - argument = make_rpc_name(key) - (arg, val) = argument_value_convert('torrent-set' - , argument, value, self.rpc_version) - args[arg] = val - - if len(args) > 0: - self._request('torrent-set', args, ids, True, timeout=timeout) - else: - ValueError("No arguments to set") - - def move(self, ids, location, timeout=DEFAULT_TIMEOUT): - """Move torrent data to the new location.""" - self._rpc_version_warning(6) - args = {'location': location, 'move': True} - self._request('torrent-set-location', args, ids, True, timeout=timeout); - - def locate(self, ids, location, timeout=DEFAULT_TIMEOUT): - """Locate torrent data at the location.""" - self._rpc_version_warning(6) - args = {'location': location, 'move': False} - self._request('torrent-set-location', args, ids, True, timeout=timeout); - - def get_session(self, timeout=DEFAULT_TIMEOUT): - """Get session parameters""" - self._request('session-get', timeout=timeout) - return self.session - - def set_session(self, timeout=DEFAULT_TIMEOUT, **kwargs): - """Set session parameters""" - args = {} - for key, value in kwargs.iteritems(): - if key == 'encryption' and value not in ['required', 'preferred', 'tolerated']: - raise ValueError('Invalid encryption value') - argument = make_rpc_name(key) - (arg, val) = argument_value_convert('session-set' - , argument, value, self.rpc_version) - args[arg] = val - if len(args) > 0: - self._request('session-set', args, timeout=timeout) - - def blocklist_update(self, timeout=DEFAULT_TIMEOUT): - """Update block list. Returns the size of the block list.""" - self._rpc_version_warning(5) - result = self._request('blocklist-update', timeout=timeout) - if 'blocklist-size' in result: - return result['blocklist-size'] - return None - - def port_test(self, timeout=DEFAULT_TIMEOUT): - """ - Tests to see if your incoming peer port is accessible from the - outside world. - """ - self._rpc_version_warning(5) - result = self._request('port-test', timeout=timeout) - if 'port-is-open' in result: - return result['port-is-open'] - return None - - def session_stats(self, timeout=DEFAULT_TIMEOUT): - """Get session statistics""" - self._request('session-stats', timeout=timeout) - return self.session diff --git a/resources/lib/transmissionrpc-0.4/utils.py b/resources/lib/transmissionrpc-0.4/utils.py deleted file mode 100644 index 9e61c69..0000000 --- a/resources/lib/transmissionrpc-0.4/utils.py +++ /dev/null @@ -1,138 +0,0 @@ -# -*- coding: utf-8 -*- -# 2008-07, Erik Svensson - -import socket, datetime -import constants -from constants import logger - -UNITS = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB'] - -def format_size(size): - s = float(size) - i = 0 - while size >= 1024.0 and i < len(UNITS): - i += 1 - size /= 1024.0 - return (size, UNITS[i]) - -def format_speed(size): - (size, unit) = format_size(size) - return (size, unit + '/s') - -def format_timedelta(delta): - minutes, seconds = divmod(delta.seconds, 60) - hours, minutes = divmod(minutes, 60) - return '%d %02d:%02d:%02d' % (delta.days, hours, minutes, seconds) - -def format_timestamp(timestamp): - if timestamp > 0: - dt = datetime.datetime.fromtimestamp(timestamp) - return dt.isoformat(' ') - else: - return '-' - -class INetAddressError(Exception): - pass - -def inet_address(address, default_port, default_address='localhost'): - addr = address.split(':') - if len(addr) == 1: - try: - port = int(addr[0]) - addr = default_address - except: - addr = addr[0] - port = default_port - elif len(addr) == 2: - port = int(addr[1]) - if len(addr[0]) == 0: - addr = default_address - else: - addr = addr[0] - else: - addr = default_address - port = default_port - try: - socket.getaddrinfo(addr, port, socket.AF_INET, socket.SOCK_STREAM) - except socket.gaierror, e: - raise INetAddressError('Cannot look up address "%s".' % address) - return (addr, port) - -def rpc_bool(arg): - if isinstance(arg, (str, unicode)): - try: - arg = bool(int(arg)) - except: - arg = arg.lower() in [u'true', u'yes'] - if bool(arg): - return 1 - else: - return 0 - -TR_TYPE_MAP = { - 'number' : int, - 'string' : str, - 'double': float, - 'boolean' : rpc_bool, - 'array': list, - 'object': dict -} - -def make_python_name(name): - return name.replace('-', '_') - -def make_rpc_name(name): - return name.replace('_', '-') - -def argument_value_convert(method, argument, value, rpc_version): - if method in ('torrent-add', 'torrent-get', 'torrent-set'): - args = constants.TORRENT_ARGS[method[-3:]] - elif method in ('session-get', 'session-set'): - args = constants.SESSION_ARGS[method[-3:]] - else: - return ValueError('Method "%s" not supported' % (method)) - if argument in args: - info = args[argument] - invalid_version = True - while invalid_version: - invalid_version = False - replacement = None - if rpc_version < info[1]: - invalid_version = True - replacement = info[3] - if info[2] and info[2] <= rpc_version: - invalid_version = True - replacement = info[4] - if invalid_version: - if replacement: - logger.warning( - 'Replacing requested argument "%s" with "%s".' - % (argument, replacement)) - argument = replacement - info = args[argument] - else: - raise ValueError( - 'Method "%s" Argument "%s" does not exist in version %d.' - % (method, argument, rpc_version)) - return (argument, TR_TYPE_MAP[info[0]](value)) - else: - raise ValueError('Argument "%s" does not exists for method "%s".', - (argument, method)) - -def get_arguments(method, rpc_version): - if method in ('torrent-add', 'torrent-get', 'torrent-set'): - args = constants.TORRENT_ARGS[method[-3:]] - elif method in ('session-get', 'session-set'): - args = constants.SESSION_ARGS[method[-3:]] - else: - return ValueError('Method "%s" not supported' % (method)) - accessible = [] - for argument, info in args.iteritems(): - valid_version = True - if rpc_version < info[1]: - valid_version = False - if info[2] and info[2] <= rpc_version: - valid_version = False - if valid_version: - accessible.append(argument) - return accessible