mirror of
https://github.com/clinton-hall/nzbToMedia.git
synced 2025-08-21 05:43:16 -07:00
Update transmissionrpc to 0.11
Also updates: - six-1.12.0
This commit is contained in:
parent
79011dbbc1
commit
30a1789809
7 changed files with 394 additions and 456 deletions
|
@ -2,25 +2,25 @@
|
||||||
# Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com>
|
# Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com>
|
||||||
# Licensed under the MIT license.
|
# Licensed under the MIT license.
|
||||||
|
|
||||||
|
import re, time, operator, warnings, os
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import operator
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import time
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
from six import PY3, integer_types, iteritems, string_types
|
from transmissionrpc.constants import DEFAULT_PORT, DEFAULT_TIMEOUT
|
||||||
from six.moves.urllib_parse import urlparse
|
from transmissionrpc.error import TransmissionError, HTTPHandlerError
|
||||||
from six.moves.urllib_request import urlopen
|
from transmissionrpc.utils import LOGGER, get_arguments, make_rpc_name, argument_value_convert, rpc_bool
|
||||||
|
from transmissionrpc.httphandler import DefaultHTTPHandler
|
||||||
|
from transmissionrpc.torrent import Torrent
|
||||||
|
from transmissionrpc.session import Session
|
||||||
|
|
||||||
from .constants import DEFAULT_PORT, DEFAULT_TIMEOUT
|
from six import PY3, integer_types, string_types, iteritems
|
||||||
from .error import HTTPHandlerError, TransmissionError
|
|
||||||
from .httphandler import DefaultHTTPHandler
|
|
||||||
from .session import Session
|
|
||||||
from .torrent import Torrent
|
|
||||||
from .utils import LOGGER, argument_value_convert, get_arguments, make_rpc_name, rpc_bool
|
|
||||||
|
|
||||||
|
if PY3:
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
from urllib.request import urlopen
|
||||||
|
else:
|
||||||
|
from urlparse import urlparse
|
||||||
|
from urllib2 import urlopen
|
||||||
|
|
||||||
def debug_httperror(error):
|
def debug_httperror(error):
|
||||||
"""
|
"""
|
||||||
|
@ -45,7 +45,6 @@ def debug_httperror(error):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def parse_torrent_id(arg):
|
def parse_torrent_id(arg):
|
||||||
"""Parse an torrent id or torrent hashString."""
|
"""Parse an torrent id or torrent hashString."""
|
||||||
torrent_id = None
|
torrent_id = None
|
||||||
|
@ -59,7 +58,7 @@ def parse_torrent_id(arg):
|
||||||
elif isinstance(arg, string_types):
|
elif isinstance(arg, string_types):
|
||||||
try:
|
try:
|
||||||
torrent_id = int(arg)
|
torrent_id = int(arg)
|
||||||
if torrent_id >= 2 ** 31:
|
if torrent_id >= 2**31:
|
||||||
torrent_id = None
|
torrent_id = None
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
pass
|
pass
|
||||||
|
@ -72,7 +71,6 @@ def parse_torrent_id(arg):
|
||||||
pass
|
pass
|
||||||
return torrent_id
|
return torrent_id
|
||||||
|
|
||||||
|
|
||||||
def parse_torrent_ids(args):
|
def parse_torrent_ids(args):
|
||||||
"""
|
"""
|
||||||
Take things and make them valid torrent identifiers
|
Take things and make them valid torrent identifiers
|
||||||
|
@ -100,20 +98,19 @@ def parse_torrent_ids(args):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
if not addition:
|
if not addition:
|
||||||
raise ValueError('Invalid torrent id, {item!r}'.format(item=item))
|
raise ValueError('Invalid torrent id, \"%s\"' % item)
|
||||||
ids.extend(addition)
|
ids.extend(addition)
|
||||||
elif isinstance(args, (list, tuple)):
|
elif isinstance(args, (list, tuple)):
|
||||||
for item in args:
|
for item in args:
|
||||||
ids.extend(parse_torrent_ids(item))
|
ids.extend(parse_torrent_ids(item))
|
||||||
else:
|
else:
|
||||||
torrent_id = parse_torrent_id(args)
|
torrent_id = parse_torrent_id(args)
|
||||||
if torrent_id is None:
|
if torrent_id == None:
|
||||||
raise ValueError('Invalid torrent id')
|
raise ValueError('Invalid torrent id')
|
||||||
else:
|
else:
|
||||||
ids = [torrent_id]
|
ids = [torrent_id]
|
||||||
return ids
|
return ids
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Torrent ids
|
Torrent ids
|
||||||
|
|
||||||
|
@ -128,27 +125,26 @@ possible to provide a argument called ``timeout``. Timeout is only effective
|
||||||
when using Python 2.6 or later and the default timeout is 30 seconds.
|
when using Python 2.6 or later and the default timeout is 30 seconds.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Client(object):
|
class Client(object):
|
||||||
"""
|
"""
|
||||||
Client is the class handling the Transmission JSON-RPC client protocol.
|
Client is the class handling the Transmission JSON-RPC client protocol.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, address='localhost', port=DEFAULT_PORT, user=None, password=None, http_handler=None,
|
def __init__(self, address='localhost', port=DEFAULT_PORT, user=None, password=None, http_handler=None, timeout=None):
|
||||||
timeout=None):
|
|
||||||
if isinstance(timeout, (integer_types, float)):
|
if isinstance(timeout, (integer_types, float)):
|
||||||
self._query_timeout = float(timeout)
|
self._query_timeout = float(timeout)
|
||||||
else:
|
else:
|
||||||
self._query_timeout = DEFAULT_TIMEOUT
|
self._query_timeout = DEFAULT_TIMEOUT
|
||||||
urlo = urlparse(address)
|
urlo = urlparse(address)
|
||||||
if not urlo.scheme:
|
if urlo.scheme == '':
|
||||||
self.url = 'http://{host}:{port}/transmission/rpc/'.format(host=address, port=port)
|
base_url = 'http://' + address + ':' + str(port)
|
||||||
|
self.url = base_url + '/transmission/rpc'
|
||||||
else:
|
else:
|
||||||
if urlo.port:
|
if urlo.port:
|
||||||
self.url = '{url.scheme}://{url.hostname}:{url.port}{url.path}'.format(url=urlo)
|
self.url = urlo.scheme + '://' + urlo.hostname + ':' + str(urlo.port) + urlo.path
|
||||||
else:
|
else:
|
||||||
self.url = '{url.scheme}://{url.hostname}{url.path}'.format(url=urlo)
|
self.url = urlo.scheme + '://' + urlo.hostname + urlo.path
|
||||||
LOGGER.info('Using custom URL {url!r}.'.format(url=self.url))
|
LOGGER.info('Using custom URL "' + self.url + '".')
|
||||||
if urlo.username and urlo.password:
|
if urlo.username and urlo.password:
|
||||||
user = urlo.username
|
user = urlo.username
|
||||||
password = urlo.password
|
password = urlo.password
|
||||||
|
@ -204,8 +200,7 @@ class Client(object):
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
timeout = self._query_timeout
|
timeout = self._query_timeout
|
||||||
while True:
|
while True:
|
||||||
LOGGER.debug(
|
LOGGER.debug(json.dumps({'url': self.url, 'headers': headers, 'query': query, 'timeout': timeout}, indent=2))
|
||||||
json.dumps({'url': self.url, 'headers': headers, 'query': query, 'timeout': timeout}, indent=2))
|
|
||||||
try:
|
try:
|
||||||
result = self.http_handler.request(self.url, query, headers, timeout)
|
result = self.http_handler.request(self.url, query, headers, timeout)
|
||||||
break
|
break
|
||||||
|
@ -245,25 +240,26 @@ class Client(object):
|
||||||
elif require_ids:
|
elif require_ids:
|
||||||
raise ValueError('request require ids')
|
raise ValueError('request require ids')
|
||||||
|
|
||||||
query = json.dumps({'tag': self._sequence, 'method': method, 'arguments': arguments})
|
query = json.dumps({'tag': self._sequence, 'method': method
|
||||||
|
, 'arguments': arguments})
|
||||||
self._sequence += 1
|
self._sequence += 1
|
||||||
start = time.time()
|
start = time.time()
|
||||||
http_data = self._http_query(query, timeout)
|
http_data = self._http_query(query, timeout)
|
||||||
elapsed = time.time() - start
|
elapsed = time.time() - start
|
||||||
LOGGER.info('http request took {time:.3f} s'.format(time=elapsed))
|
LOGGER.info('http request took %.3f s' % (elapsed))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = json.loads(http_data)
|
data = json.loads(http_data)
|
||||||
except ValueError as error:
|
except ValueError as error:
|
||||||
LOGGER.error('Error: {msg}'.format(msg=error))
|
LOGGER.error('Error: ' + str(error))
|
||||||
LOGGER.error('Request: {request!r}'.format(request=query))
|
LOGGER.error('Request: \"%s\"' % (query))
|
||||||
LOGGER.error('HTTP data: {data!r}'.format(data=http_data))
|
LOGGER.error('HTTP data: \"%s\"' % (http_data))
|
||||||
raise
|
raise
|
||||||
|
|
||||||
LOGGER.debug(json.dumps(data, indent=2))
|
LOGGER.debug(json.dumps(data, indent=2))
|
||||||
if 'result' in data:
|
if 'result' in data:
|
||||||
if data['result'] != 'success':
|
if data['result'] != 'success':
|
||||||
raise TransmissionError('Query failed with result {result!r}.'.format(result=data['result']))
|
raise TransmissionError('Query failed with result \"%s\".' % (data['result']))
|
||||||
else:
|
else:
|
||||||
raise TransmissionError('Query failed without result.')
|
raise TransmissionError('Query failed without result.')
|
||||||
|
|
||||||
|
@ -347,9 +343,8 @@ class Client(object):
|
||||||
Add a warning to the log if the Transmission RPC version is lower then the provided version.
|
Add a warning to the log if the Transmission RPC version is lower then the provided version.
|
||||||
"""
|
"""
|
||||||
if self.rpc_version < version:
|
if self.rpc_version < version:
|
||||||
LOGGER.warning('Using feature not supported by server. '
|
LOGGER.warning('Using feature not supported by server. RPC version for server %d, feature introduced in %d.'
|
||||||
'RPC version for server {x}, feature introduced in {y}.'.format
|
% (self.rpc_version, version))
|
||||||
(x=self.rpc_version, y=version))
|
|
||||||
|
|
||||||
def add_torrent(self, torrent, timeout=None, **kwargs):
|
def add_torrent(self, torrent, timeout=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -409,8 +404,11 @@ class Client(object):
|
||||||
pass
|
pass
|
||||||
if might_be_base64:
|
if might_be_base64:
|
||||||
torrent_data = torrent
|
torrent_data = torrent
|
||||||
|
args = {}
|
||||||
args = {'metainfo': torrent_data} if torrent_data else {'filename': torrent}
|
if torrent_data:
|
||||||
|
args = {'metainfo': torrent_data}
|
||||||
|
else:
|
||||||
|
args = {'filename': torrent}
|
||||||
for key, value in iteritems(kwargs):
|
for key, value in iteritems(kwargs):
|
||||||
argument = make_rpc_name(key)
|
argument = make_rpc_name(key)
|
||||||
(arg, val) = argument_value_convert('torrent-add', argument, value, self.rpc_version)
|
(arg, val) = argument_value_convert('torrent-add', argument, value, self.rpc_version)
|
||||||
|
@ -474,7 +472,7 @@ class Client(object):
|
||||||
"""
|
"""
|
||||||
self._rpc_version_warning(3)
|
self._rpc_version_warning(3)
|
||||||
self._request('torrent-remove',
|
self._request('torrent-remove',
|
||||||
{'delete-local-data': rpc_bool(delete_data)}, ids, True, timeout=timeout)
|
{'delete-local-data':rpc_bool(delete_data)}, ids, True, timeout=timeout)
|
||||||
|
|
||||||
def remove(self, ids, delete_data=False, timeout=None):
|
def remove(self, ids, delete_data=False, timeout=None):
|
||||||
"""
|
"""
|
||||||
|
@ -604,34 +602,34 @@ class Client(object):
|
||||||
the new methods. list returns a dictionary indexed by torrent id.
|
the new methods. list returns a dictionary indexed by torrent id.
|
||||||
"""
|
"""
|
||||||
warnings.warn('list has been deprecated, please use get_torrent or get_torrents instead.', DeprecationWarning)
|
warnings.warn('list has been deprecated, please use get_torrent or get_torrents instead.', DeprecationWarning)
|
||||||
fields = ['id', 'hashString', 'name', 'sizeWhenDone', 'leftUntilDone',
|
fields = ['id', 'hashString', 'name', 'sizeWhenDone', 'leftUntilDone'
|
||||||
'eta', 'status', 'rateUpload', 'rateDownload', 'uploadedEver',
|
, 'eta', 'status', 'rateUpload', 'rateDownload', 'uploadedEver'
|
||||||
'downloadedEver', 'uploadRatio', 'queuePosition']
|
, 'downloadedEver', 'uploadRatio', 'queuePosition']
|
||||||
return self._request('torrent-get', {'fields': fields}, timeout=timeout)
|
return self._request('torrent-get', {'fields': fields}, timeout=timeout)
|
||||||
|
|
||||||
def get_files(self, ids=None, timeout=None):
|
def get_files(self, ids=None, timeout=None):
|
||||||
"""
|
"""
|
||||||
Get list of files for provided torrent id(s). If ids is empty,
|
Get list of files for provided torrent id(s). If ids is empty,
|
||||||
information for all torrents are fetched. This function returns a dictionary
|
information for all torrents are fetched. This function returns a dictionary
|
||||||
for each requested torrent id holding the information about the files.
|
for each requested torrent id holding the information about the files.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
{
|
{
|
||||||
<torrent id>: {
|
<torrent id>: {
|
||||||
<file id>: {
|
<file id>: {
|
||||||
'name': <file name>,
|
'name': <file name>,
|
||||||
'size': <file size in bytes>,
|
'size': <file size in bytes>,
|
||||||
'completed': <bytes completed>,
|
'completed': <bytes completed>,
|
||||||
'priority': <priority ('high'|'normal'|'low')>,
|
'priority': <priority ('high'|'normal'|'low')>,
|
||||||
'selected': <selected for download (True|False)>
|
'selected': <selected for download (True|False)>
|
||||||
}
|
}
|
||||||
|
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
fields = ['id', 'name', 'hashString', 'files', 'priorities', 'wanted']
|
fields = ['id', 'name', 'hashString', 'files', 'priorities', 'wanted']
|
||||||
request_result = self._request('torrent-get', {'fields': fields}, ids, timeout=timeout)
|
request_result = self._request('torrent-get', {'fields': fields}, ids, timeout=timeout)
|
||||||
|
@ -643,22 +641,22 @@ class Client(object):
|
||||||
def set_files(self, items, timeout=None):
|
def set_files(self, items, timeout=None):
|
||||||
"""
|
"""
|
||||||
Set file properties. Takes a dictionary with similar contents as the result
|
Set file properties. Takes a dictionary with similar contents as the result
|
||||||
of `get_files`.
|
of `get_files`.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
{
|
{
|
||||||
<torrent id>: {
|
<torrent id>: {
|
||||||
<file id>: {
|
<file id>: {
|
||||||
'priority': <priority ('high'|'normal'|'low')>,
|
'priority': <priority ('high'|'normal'|'low')>,
|
||||||
'selected': <selected for download (True|False)>
|
'selected': <selected for download (True|False)>
|
||||||
}
|
}
|
||||||
|
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
if not isinstance(items, dict):
|
if not isinstance(items, dict):
|
||||||
raise ValueError('Invalid file description')
|
raise ValueError('Invalid file description')
|
||||||
|
@ -701,8 +699,8 @@ class Client(object):
|
||||||
|
|
||||||
def change_torrent(self, ids, timeout=None, **kwargs):
|
def change_torrent(self, ids, timeout=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Change torrent parameters for the torrent(s) with the supplied id's. The
|
Change torrent parameters for the torrent(s) with the supplied id's. The
|
||||||
parameters are:
|
parameters are:
|
||||||
|
|
||||||
============================ ===== =============== =======================================================================================
|
============================ ===== =============== =======================================================================================
|
||||||
Argument RPC Replaced by Description
|
Argument RPC Replaced by Description
|
||||||
|
@ -734,13 +732,13 @@ class Client(object):
|
||||||
``uploadLimited`` 5 - Enable upload speed limiter.
|
``uploadLimited`` 5 - Enable upload speed limiter.
|
||||||
============================ ===== =============== =======================================================================================
|
============================ ===== =============== =======================================================================================
|
||||||
|
|
||||||
.. NOTE::
|
.. NOTE::
|
||||||
transmissionrpc will try to automatically fix argument errors.
|
transmissionrpc will try to automatically fix argument errors.
|
||||||
"""
|
"""
|
||||||
args = {}
|
args = {}
|
||||||
for key, value in iteritems(kwargs):
|
for key, value in iteritems(kwargs):
|
||||||
argument = make_rpc_name(key)
|
argument = make_rpc_name(key)
|
||||||
(arg, val) = argument_value_convert('torrent-set', argument, value, self.rpc_version)
|
(arg, val) = argument_value_convert('torrent-set' , argument, value, self.rpc_version)
|
||||||
args[arg] = val
|
args[arg] = val
|
||||||
|
|
||||||
if len(args) > 0:
|
if len(args) > 0:
|
||||||
|
@ -801,7 +799,7 @@ class Client(object):
|
||||||
raise ValueError("Target name cannot contain a path delimiter")
|
raise ValueError("Target name cannot contain a path delimiter")
|
||||||
args = {'path': location, 'name': name}
|
args = {'path': location, 'name': name}
|
||||||
result = self._request('torrent-rename-path', args, torrent_id, True, timeout=timeout)
|
result = self._request('torrent-rename-path', args, torrent_id, True, timeout=timeout)
|
||||||
return result['path'], result['name']
|
return (result['path'], result['name'])
|
||||||
|
|
||||||
def queue_top(self, ids, timeout=None):
|
def queue_top(self, ids, timeout=None):
|
||||||
"""Move transfer to the top of the queue."""
|
"""Move transfer to the top of the queue."""
|
||||||
|
@ -886,14 +884,14 @@ class Client(object):
|
||||||
================================ ===== ================= ==========================================================================================================================
|
================================ ===== ================= ==========================================================================================================================
|
||||||
|
|
||||||
.. NOTE::
|
.. NOTE::
|
||||||
transmissionrpc will try to automatically fix argument errors.
|
transmissionrpc will try to automatically fix argument errors.
|
||||||
"""
|
"""
|
||||||
args = {}
|
args = {}
|
||||||
for key, value in iteritems(kwargs):
|
for key, value in iteritems(kwargs):
|
||||||
if key == 'encryption' and value not in ['required', 'preferred', 'tolerated']:
|
if key == 'encryption' and value not in ['required', 'preferred', 'tolerated']:
|
||||||
raise ValueError('Invalid encryption value')
|
raise ValueError('Invalid encryption value')
|
||||||
argument = make_rpc_name(key)
|
argument = make_rpc_name(key)
|
||||||
(arg, val) = argument_value_convert('session-set', argument, value, self.rpc_version)
|
(arg, val) = argument_value_convert('session-set' , argument, value, self.rpc_version)
|
||||||
args[arg] = val
|
args[arg] = val
|
||||||
if len(args) > 0:
|
if len(args) > 0:
|
||||||
self._request('session-set', args, timeout=timeout)
|
self._request('session-set', args, timeout=timeout)
|
||||||
|
|
|
@ -3,13 +3,11 @@
|
||||||
# Licensed under the MIT license.
|
# Licensed under the MIT license.
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from six import iteritems
|
from six import iteritems
|
||||||
|
|
||||||
LOGGER = logging.getLogger('transmissionrpc')
|
LOGGER = logging.getLogger('transmissionrpc')
|
||||||
LOGGER.setLevel(logging.ERROR)
|
LOGGER.setLevel(logging.ERROR)
|
||||||
|
|
||||||
|
|
||||||
def mirror_dict(source):
|
def mirror_dict(source):
|
||||||
"""
|
"""
|
||||||
Creates a dictionary with all values as keys and all keys as values.
|
Creates a dictionary with all values as keys and all keys as values.
|
||||||
|
@ -17,39 +15,38 @@ def mirror_dict(source):
|
||||||
source.update(dict((value, key) for key, value in iteritems(source)))
|
source.update(dict((value, key) for key, value in iteritems(source)))
|
||||||
return source
|
return source
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_PORT = 9091
|
DEFAULT_PORT = 9091
|
||||||
|
|
||||||
DEFAULT_TIMEOUT = 30.0
|
DEFAULT_TIMEOUT = 30.0
|
||||||
|
|
||||||
TR_PRI_LOW = -1
|
TR_PRI_LOW = -1
|
||||||
TR_PRI_NORMAL = 0
|
TR_PRI_NORMAL = 0
|
||||||
TR_PRI_HIGH = 1
|
TR_PRI_HIGH = 1
|
||||||
|
|
||||||
PRIORITY = mirror_dict({
|
PRIORITY = mirror_dict({
|
||||||
'low': TR_PRI_LOW,
|
'low' : TR_PRI_LOW,
|
||||||
'normal': TR_PRI_NORMAL,
|
'normal' : TR_PRI_NORMAL,
|
||||||
'high': TR_PRI_HIGH
|
'high' : TR_PRI_HIGH
|
||||||
})
|
})
|
||||||
|
|
||||||
TR_RATIOLIMIT_GLOBAL = 0 # follow the global settings
|
TR_RATIOLIMIT_GLOBAL = 0 # follow the global settings
|
||||||
TR_RATIOLIMIT_SINGLE = 1 # override the global settings, seeding until a certain ratio
|
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
|
TR_RATIOLIMIT_UNLIMITED = 2 # override the global settings, seeding regardless of ratio
|
||||||
|
|
||||||
RATIO_LIMIT = mirror_dict({
|
RATIO_LIMIT = mirror_dict({
|
||||||
'global': TR_RATIOLIMIT_GLOBAL,
|
'global' : TR_RATIOLIMIT_GLOBAL,
|
||||||
'single': TR_RATIOLIMIT_SINGLE,
|
'single' : TR_RATIOLIMIT_SINGLE,
|
||||||
'unlimited': TR_RATIOLIMIT_UNLIMITED
|
'unlimited' : TR_RATIOLIMIT_UNLIMITED
|
||||||
})
|
})
|
||||||
|
|
||||||
TR_IDLELIMIT_GLOBAL = 0 # follow the global settings
|
TR_IDLELIMIT_GLOBAL = 0 # follow the global settings
|
||||||
TR_IDLELIMIT_SINGLE = 1 # override the global settings, seeding until a certain idle time
|
TR_IDLELIMIT_SINGLE = 1 # override the global settings, seeding until a certain idle time
|
||||||
TR_IDLELIMIT_UNLIMITED = 2 # override the global settings, seeding regardless of activity
|
TR_IDLELIMIT_UNLIMITED = 2 # override the global settings, seeding regardless of activity
|
||||||
|
|
||||||
IDLE_LIMIT = mirror_dict({
|
IDLE_LIMIT = mirror_dict({
|
||||||
'global': TR_RATIOLIMIT_GLOBAL,
|
'global' : TR_RATIOLIMIT_GLOBAL,
|
||||||
'single': TR_RATIOLIMIT_SINGLE,
|
'single' : TR_RATIOLIMIT_SINGLE,
|
||||||
'unlimited': TR_RATIOLIMIT_UNLIMITED
|
'unlimited' : TR_RATIOLIMIT_UNLIMITED
|
||||||
})
|
})
|
||||||
|
|
||||||
# A note on argument maps
|
# A note on argument maps
|
||||||
|
@ -63,266 +60,236 @@ IDLE_LIMIT = mirror_dict({
|
||||||
|
|
||||||
# Arguments for torrent methods
|
# Arguments for torrent methods
|
||||||
TORRENT_ARGS = {
|
TORRENT_ARGS = {
|
||||||
'get': {
|
'get' : {
|
||||||
'activityDate': ('number', 1, None, None, None, 'Last time of upload or download activity.'),
|
'activityDate': ('number', 1, None, None, None, 'Last time of upload or download activity.'),
|
||||||
'addedDate': ('number', 1, None, None, None, 'The date when this torrent was first added.'),
|
'addedDate': ('number', 1, None, None, None, 'The date when this torrent was first added.'),
|
||||||
'announceResponse': ('string', 1, 7, None, None, 'The announce message from the tracker.'),
|
'announceResponse': ('string', 1, 7, None, None, 'The announce message from the tracker.'),
|
||||||
'announceURL': ('string', 1, 7, None, None, 'Current announce URL.'),
|
'announceURL': ('string', 1, 7, None, None, 'Current announce URL.'),
|
||||||
'bandwidthPriority': ('number', 5, None, None, None, 'Bandwidth priority. Low (-1), Normal (0) or High (1).'),
|
'bandwidthPriority': ('number', 5, None, None, None, 'Bandwidth priority. Low (-1), Normal (0) or High (1).'),
|
||||||
'comment': ('string', 1, None, None, None, 'Torrent comment.'),
|
'comment': ('string', 1, None, None, None, 'Torrent comment.'),
|
||||||
'corruptEver': ('number', 1, None, None, None, 'Number of bytes of corrupt data downloaded.'),
|
'corruptEver': ('number', 1, None, None, None, 'Number of bytes of corrupt data downloaded.'),
|
||||||
'creator': ('string', 1, None, None, None, 'Torrent creator.'),
|
'creator': ('string', 1, None, None, None, 'Torrent creator.'),
|
||||||
'dateCreated': ('number', 1, None, None, None, 'Torrent creation date.'),
|
'dateCreated': ('number', 1, None, None, None, 'Torrent creation date.'),
|
||||||
'desiredAvailable': ('number', 1, None, None, None, 'Number of bytes avalable and left to be downloaded.'),
|
'desiredAvailable': ('number', 1, None, None, None, 'Number of bytes avalable and left to be downloaded.'),
|
||||||
'doneDate': ('number', 1, None, None, None, 'The date when the torrent finished downloading.'),
|
'doneDate': ('number', 1, None, None, None, 'The date when the torrent finished downloading.'),
|
||||||
'downloadDir': ('string', 4, None, None, None, 'The directory path where the torrent is downloaded to.'),
|
'downloadDir': ('string', 4, None, None, None, 'The directory path where the torrent is downloaded to.'),
|
||||||
'downloadedEver': ('number', 1, None, None, None, 'Number of bytes of good data downloaded.'),
|
'downloadedEver': ('number', 1, None, None, None, 'Number of bytes of good data downloaded.'),
|
||||||
'downloaders': ('number', 4, 7, None, None, 'Number of downloaders.'),
|
'downloaders': ('number', 4, 7, None, None, 'Number of downloaders.'),
|
||||||
'downloadLimit': ('number', 1, None, None, None, 'Download limit in Kbps.'),
|
'downloadLimit': ('number', 1, None, None, None, 'Download limit in Kbps.'),
|
||||||
'downloadLimited': ('boolean', 5, None, None, None, 'Download limit is enabled'),
|
'downloadLimited': ('boolean', 5, None, None, None, 'Download limit is enabled'),
|
||||||
'downloadLimitMode': (
|
'downloadLimitMode': ('number', 1, 5, None, None, 'Download limit mode. 0 means global, 1 means signle, 2 unlimited.'),
|
||||||
'number', 1, 5, None, None, 'Download limit mode. 0 means global, 1 means signle, 2 unlimited.'),
|
'error': ('number', 1, None, None, None, 'Kind of error. 0 means OK, 1 means tracker warning, 2 means tracker error, 3 means local error.'),
|
||||||
'error': ('number', 1, None, None, None,
|
'errorString': ('number', 1, None, None, None, 'Error message.'),
|
||||||
'Kind of error. 0 means OK, 1 means tracker warning, 2 means tracker error, 3 means local error.'),
|
'eta': ('number', 1, None, None, None, 'Estimated number of seconds left when downloading or seeding. -1 means not available and -2 means unknown.'),
|
||||||
'errorString': ('number', 1, None, None, None, 'Error message.'),
|
'etaIdle': ('number', 15, None, None, None, 'Estimated number of seconds left until the idle time limit is reached. -1 means not available and -2 means unknown.'),
|
||||||
'eta': ('number', 1, None, None, None,
|
'files': ('array', 1, None, None, None, 'Array of file object containing key, bytesCompleted, length and name.'),
|
||||||
'Estimated number of seconds left when downloading or seeding. -1 means not available and -2 means unknown.'),
|
'fileStats': ('array', 5, None, None, None, 'Aray of file statistics containing bytesCompleted, wanted and priority.'),
|
||||||
'etaIdle': ('number', 15, None, None, None,
|
'hashString': ('string', 1, None, None, None, 'Hashstring unique for the torrent even between sessions.'),
|
||||||
'Estimated number of seconds left until the idle time limit is reached. -1 means not available and -2 means unknown.'),
|
'haveUnchecked': ('number', 1, None, None, None, 'Number of bytes of partial pieces.'),
|
||||||
'files': (
|
'haveValid': ('number', 1, None, None, None, 'Number of bytes of checksum verified data.'),
|
||||||
'array', 1, None, None, None, 'Array of file object containing key, bytesCompleted, length and name.'),
|
'honorsSessionLimits': ('boolean', 5, None, None, None, 'True if session upload limits are honored'),
|
||||||
'fileStats': (
|
'id': ('number', 1, None, None, None, 'Session unique torrent id.'),
|
||||||
'array', 5, None, None, None, 'Aray of file statistics containing bytesCompleted, wanted and priority.'),
|
'isFinished': ('boolean', 9, None, None, None, 'True if the torrent is finished. Downloaded and seeded.'),
|
||||||
'hashString': ('string', 1, None, None, None, 'Hashstring unique for the torrent even between sessions.'),
|
'isPrivate': ('boolean', 1, None, None, None, 'True if the torrent is private.'),
|
||||||
'haveUnchecked': ('number', 1, None, None, None, 'Number of bytes of partial pieces.'),
|
'isStalled': ('boolean', 14, None, None, None, 'True if the torrent has stalled (been idle for a long time).'),
|
||||||
'haveValid': ('number', 1, None, None, None, 'Number of bytes of checksum verified data.'),
|
'lastAnnounceTime': ('number', 1, 7, None, None, 'The time of the last announcement.'),
|
||||||
'honorsSessionLimits': ('boolean', 5, None, None, None, 'True if session upload limits are honored'),
|
'lastScrapeTime': ('number', 1, 7, None, None, 'The time af the last successful scrape.'),
|
||||||
'id': ('number', 1, None, None, None, 'Session unique torrent id.'),
|
'leechers': ('number', 1, 7, None, None, 'Number of leechers.'),
|
||||||
'isFinished': ('boolean', 9, None, None, None, 'True if the torrent is finished. Downloaded and seeded.'),
|
'leftUntilDone': ('number', 1, None, None, None, 'Number of bytes left until the download is done.'),
|
||||||
'isPrivate': ('boolean', 1, None, None, None, 'True if the torrent is private.'),
|
'magnetLink': ('string', 7, None, None, None, 'The magnet link for this torrent.'),
|
||||||
'isStalled': ('boolean', 14, None, None, None, 'True if the torrent has stalled (been idle for a long time).'),
|
'manualAnnounceTime': ('number', 1, None, None, None, 'The time until you manually ask for more peers.'),
|
||||||
'lastAnnounceTime': ('number', 1, 7, None, None, 'The time of the last announcement.'),
|
'maxConnectedPeers': ('number', 1, None, None, None, 'Maximum of connected peers.'),
|
||||||
'lastScrapeTime': ('number', 1, 7, None, None, 'The time af the last successful scrape.'),
|
'metadataPercentComplete': ('number', 7, None, None, None, 'Download progress of metadata. 0.0 to 1.0.'),
|
||||||
'leechers': ('number', 1, 7, None, None, 'Number of leechers.'),
|
'name': ('string', 1, None, None, None, 'Torrent name.'),
|
||||||
'leftUntilDone': ('number', 1, None, None, None, 'Number of bytes left until the download is done.'),
|
'nextAnnounceTime': ('number', 1, 7, None, None, 'Next announce time.'),
|
||||||
'magnetLink': ('string', 7, None, None, None, 'The magnet link for this torrent.'),
|
'nextScrapeTime': ('number', 1, 7, None, None, 'Next scrape time.'),
|
||||||
'manualAnnounceTime': ('number', 1, None, None, None, 'The time until you manually ask for more peers.'),
|
'peer-limit': ('number', 5, None, None, None, 'Maximum number of peers.'),
|
||||||
'maxConnectedPeers': ('number', 1, None, None, None, 'Maximum of connected peers.'),
|
'peers': ('array', 2, None, None, None, 'Array of peer objects.'),
|
||||||
'metadataPercentComplete': ('number', 7, None, None, None, 'Download progress of metadata. 0.0 to 1.0.'),
|
'peersConnected': ('number', 1, None, None, None, 'Number of peers we are connected to.'),
|
||||||
'name': ('string', 1, None, None, None, 'Torrent name.'),
|
'peersFrom': ('object', 1, None, None, None, 'Object containing download peers counts for different peer types.'),
|
||||||
'nextAnnounceTime': ('number', 1, 7, None, None, 'Next announce time.'),
|
'peersGettingFromUs': ('number', 1, None, None, None, 'Number of peers we are sending data to.'),
|
||||||
'nextScrapeTime': ('number', 1, 7, None, None, 'Next scrape time.'),
|
'peersKnown': ('number', 1, 13, None, None, 'Number of peers that the tracker knows.'),
|
||||||
'peer-limit': ('number', 5, None, None, None, 'Maximum number of peers.'),
|
'peersSendingToUs': ('number', 1, None, None, None, 'Number of peers sending to us'),
|
||||||
'peers': ('array', 2, None, None, None, 'Array of peer objects.'),
|
'percentDone': ('double', 5, None, None, None, 'Download progress of selected files. 0.0 to 1.0.'),
|
||||||
'peersConnected': ('number', 1, None, None, None, 'Number of peers we are connected to.'),
|
'pieces': ('string', 5, None, None, None, 'String with base64 encoded bitfield indicating finished pieces.'),
|
||||||
'peersFrom': (
|
'pieceCount': ('number', 1, None, None, None, 'Number of pieces.'),
|
||||||
'object', 1, None, None, None, 'Object containing download peers counts for different peer types.'),
|
'pieceSize': ('number', 1, None, None, None, 'Number of bytes in a piece.'),
|
||||||
'peersGettingFromUs': ('number', 1, None, None, None, 'Number of peers we are sending data to.'),
|
'priorities': ('array', 1, None, None, None, 'Array of file priorities.'),
|
||||||
'peersKnown': ('number', 1, 13, None, None, 'Number of peers that the tracker knows.'),
|
'queuePosition': ('number', 14, None, None, None, 'The queue position.'),
|
||||||
'peersSendingToUs': ('number', 1, None, None, None, 'Number of peers sending to us'),
|
'rateDownload': ('number', 1, None, None, None, 'Download rate in bps.'),
|
||||||
'percentDone': ('double', 5, None, None, None, 'Download progress of selected files. 0.0 to 1.0.'),
|
'rateUpload': ('number', 1, None, None, None, 'Upload rate in bps.'),
|
||||||
'pieces': ('string', 5, None, None, None, 'String with base64 encoded bitfield indicating finished pieces.'),
|
'recheckProgress': ('double', 1, None, None, None, 'Progress of recheck. 0.0 to 1.0.'),
|
||||||
'pieceCount': ('number', 1, None, None, None, 'Number of pieces.'),
|
'secondsDownloading': ('number', 15, None, None, None, ''),
|
||||||
'pieceSize': ('number', 1, None, None, None, 'Number of bytes in a piece.'),
|
'secondsSeeding': ('number', 15, None, None, None, ''),
|
||||||
'priorities': ('array', 1, None, None, None, 'Array of file priorities.'),
|
'scrapeResponse': ('string', 1, 7, None, None, 'Scrape response message.'),
|
||||||
'queuePosition': ('number', 14, None, None, None, 'The queue position.'),
|
'scrapeURL': ('string', 1, 7, None, None, 'Current scrape URL'),
|
||||||
'rateDownload': ('number', 1, None, None, None, 'Download rate in bps.'),
|
'seeders': ('number', 1, 7, None, None, 'Number of seeders reported by the tracker.'),
|
||||||
'rateUpload': ('number', 1, None, None, None, 'Upload rate in bps.'),
|
'seedIdleLimit': ('number', 10, None, None, None, 'Idle limit in minutes.'),
|
||||||
'recheckProgress': ('double', 1, None, None, None, 'Progress of recheck. 0.0 to 1.0.'),
|
'seedIdleMode': ('number', 10, None, None, None, 'Use global (0), torrent (1), or unlimited (2) limit.'),
|
||||||
'secondsDownloading': ('number', 15, None, None, None, ''),
|
'seedRatioLimit': ('double', 5, None, None, None, 'Seed ratio limit.'),
|
||||||
'secondsSeeding': ('number', 15, None, None, None, ''),
|
'seedRatioMode': ('number', 5, None, None, None, 'Use global (0), torrent (1), or unlimited (2) limit.'),
|
||||||
'scrapeResponse': ('string', 1, 7, None, None, 'Scrape response message.'),
|
'sizeWhenDone': ('number', 1, None, None, None, 'Size of the torrent download in bytes.'),
|
||||||
'scrapeURL': ('string', 1, 7, None, None, 'Current scrape URL'),
|
'startDate': ('number', 1, None, None, None, 'The date when the torrent was last started.'),
|
||||||
'seeders': ('number', 1, 7, None, None, 'Number of seeders reported by the tracker.'),
|
'status': ('number', 1, None, None, None, 'Current status, see source'),
|
||||||
'seedIdleLimit': ('number', 10, None, None, None, 'Idle limit in minutes.'),
|
'swarmSpeed': ('number', 1, 7, None, None, 'Estimated speed in Kbps in the swarm.'),
|
||||||
'seedIdleMode': ('number', 10, None, None, None, 'Use global (0), torrent (1), or unlimited (2) limit.'),
|
'timesCompleted': ('number', 1, 7, None, None, 'Number of successful downloads reported by the tracker.'),
|
||||||
'seedRatioLimit': ('double', 5, None, None, None, 'Seed ratio limit.'),
|
'trackers': ('array', 1, None, None, None, 'Array of tracker objects.'),
|
||||||
'seedRatioMode': ('number', 5, None, None, None, 'Use global (0), torrent (1), or unlimited (2) limit.'),
|
'trackerStats': ('object', 7, None, None, None, 'Array of object containing tracker statistics.'),
|
||||||
'sizeWhenDone': ('number', 1, None, None, None, 'Size of the torrent download in bytes.'),
|
'totalSize': ('number', 1, None, None, None, 'Total size of the torrent in bytes'),
|
||||||
'startDate': ('number', 1, None, None, None, 'The date when the torrent was last started.'),
|
'torrentFile': ('string', 5, None, None, None, 'Path to .torrent file.'),
|
||||||
'status': ('number', 1, None, None, None, 'Current status, see source'),
|
'uploadedEver': ('number', 1, None, None, None, 'Number of bytes uploaded, ever.'),
|
||||||
'swarmSpeed': ('number', 1, 7, None, None, 'Estimated speed in Kbps in the swarm.'),
|
'uploadLimit': ('number', 1, None, None, None, 'Upload limit in Kbps'),
|
||||||
'timesCompleted': ('number', 1, 7, None, None, 'Number of successful downloads reported by the tracker.'),
|
'uploadLimitMode': ('number', 1, 5, None, None, 'Upload limit mode. 0 means global, 1 means signle, 2 unlimited.'),
|
||||||
'trackers': ('array', 1, None, None, None, 'Array of tracker objects.'),
|
'uploadLimited': ('boolean', 5, None, None, None, 'Upload limit enabled.'),
|
||||||
'trackerStats': ('object', 7, None, None, None, 'Array of object containing tracker statistics.'),
|
'uploadRatio': ('double', 1, None, None, None, 'Seed ratio.'),
|
||||||
'totalSize': ('number', 1, None, None, None, 'Total size of the torrent in bytes'),
|
'wanted': ('array', 1, None, None, None, 'Array of booleans indicated wanted files.'),
|
||||||
'torrentFile': ('string', 5, None, None, None, 'Path to .torrent file.'),
|
'webseeds': ('array', 1, None, None, None, 'Array of webseeds objects'),
|
||||||
'uploadedEver': ('number', 1, None, None, None, 'Number of bytes uploaded, ever.'),
|
'webseedsSendingToUs': ('number', 1, None, None, None, 'Number of webseeds seeding to us.'),
|
||||||
'uploadLimit': ('number', 1, None, None, None, 'Upload limit in Kbps'),
|
|
||||||
'uploadLimitMode': (
|
|
||||||
'number', 1, 5, None, None, 'Upload limit mode. 0 means global, 1 means signle, 2 unlimited.'),
|
|
||||||
'uploadLimited': ('boolean', 5, None, None, None, 'Upload limit enabled.'),
|
|
||||||
'uploadRatio': ('double', 1, None, None, None, 'Seed ratio.'),
|
|
||||||
'wanted': ('array', 1, None, None, None, 'Array of booleans indicated wanted files.'),
|
|
||||||
'webseeds': ('array', 1, None, None, None, 'Array of webseeds objects'),
|
|
||||||
'webseedsSendingToUs': ('number', 1, None, None, None, 'Number of webseeds seeding to us.'),
|
|
||||||
},
|
},
|
||||||
'set': {
|
'set': {
|
||||||
'bandwidthPriority': ('number', 5, None, None, None, 'Priority for this transfer.'),
|
'bandwidthPriority': ('number', 5, None, None, None, 'Priority for this transfer.'),
|
||||||
'downloadLimit': ('number', 5, None, 'speed-limit-down', None, 'Set the speed limit for download in Kib/s.'),
|
'downloadLimit': ('number', 5, None, 'speed-limit-down', None, 'Set the speed limit for download in Kib/s.'),
|
||||||
'downloadLimited': ('boolean', 5, None, 'speed-limit-down-enabled', None, 'Enable download speed limiter.'),
|
'downloadLimited': ('boolean', 5, None, 'speed-limit-down-enabled', None, 'Enable download speed limiter.'),
|
||||||
'files-wanted': ('array', 1, None, None, None, "A list of file id's that should be downloaded."),
|
'files-wanted': ('array', 1, None, None, None, "A list of file id's that should be downloaded."),
|
||||||
'files-unwanted': ('array', 1, None, None, None, "A list of file id's that shouldn't be downloaded."),
|
'files-unwanted': ('array', 1, None, None, None, "A list of file id's that shouldn't be downloaded."),
|
||||||
'honorsSessionLimits': ('boolean', 5, None, None, None,
|
'honorsSessionLimits': ('boolean', 5, None, None, None, "Enables or disables the transfer to honour the upload limit set in the session."),
|
||||||
"Enables or disables the transfer to honour the upload limit set in the session."),
|
'location': ('array', 1, None, None, None, 'Local download location.'),
|
||||||
'location': ('array', 1, None, None, None, 'Local download location.'),
|
'peer-limit': ('number', 1, None, None, None, 'The peer limit for the torrents.'),
|
||||||
'peer-limit': ('number', 1, None, None, None, 'The peer limit for the torrents.'),
|
'priority-high': ('array', 1, None, None, None, "A list of file id's that should have high priority."),
|
||||||
'priority-high': ('array', 1, None, None, None, "A list of file id's that should have high priority."),
|
'priority-low': ('array', 1, None, None, None, "A list of file id's that should have normal priority."),
|
||||||
'priority-low': ('array', 1, None, None, None, "A list of file id's that should have normal priority."),
|
'priority-normal': ('array', 1, None, None, None, "A list of file id's that should have low priority."),
|
||||||
'priority-normal': ('array', 1, None, None, None, "A list of file id's that should have low priority."),
|
'queuePosition': ('number', 14, None, None, None, 'Position of this transfer in its queue.'),
|
||||||
'queuePosition': ('number', 14, None, None, None, 'Position of this transfer in its queue.'),
|
'seedIdleLimit': ('number', 10, None, None, None, 'Seed inactivity limit in minutes.'),
|
||||||
'seedIdleLimit': ('number', 10, None, None, None, 'Seed inactivity limit in minutes.'),
|
'seedIdleMode': ('number', 10, None, None, None, 'Seed inactivity mode. 0 = Use session limit, 1 = Use transfer limit, 2 = Disable limit.'),
|
||||||
'seedIdleMode': ('number', 10, None, None, None,
|
'seedRatioLimit': ('double', 5, None, None, None, 'Seeding ratio.'),
|
||||||
'Seed inactivity mode. 0 = Use session limit, 1 = Use transfer limit, 2 = Disable limit.'),
|
'seedRatioMode': ('number', 5, None, None, None, 'Which ratio to use. 0 = Use session limit, 1 = Use transfer limit, 2 = Disable limit.'),
|
||||||
'seedRatioLimit': ('double', 5, None, None, None, 'Seeding ratio.'),
|
'speed-limit-down': ('number', 1, 5, None, 'downloadLimit', 'Set the speed limit for download in Kib/s.'),
|
||||||
'seedRatioMode': ('number', 5, None, None, None,
|
'speed-limit-down-enabled': ('boolean', 1, 5, None, 'downloadLimited', 'Enable download speed limiter.'),
|
||||||
'Which ratio to use. 0 = Use session limit, 1 = Use transfer limit, 2 = Disable limit.'),
|
'speed-limit-up': ('number', 1, 5, None, 'uploadLimit', 'Set the speed limit for upload in Kib/s.'),
|
||||||
'speed-limit-down': ('number', 1, 5, None, 'downloadLimit', 'Set the speed limit for download in Kib/s.'),
|
'speed-limit-up-enabled': ('boolean', 1, 5, None, 'uploadLimited', 'Enable upload speed limiter.'),
|
||||||
'speed-limit-down-enabled': ('boolean', 1, 5, None, 'downloadLimited', 'Enable download speed limiter.'),
|
'trackerAdd': ('array', 10, None, None, None, 'Array of string with announce URLs to add.'),
|
||||||
'speed-limit-up': ('number', 1, 5, None, 'uploadLimit', 'Set the speed limit for upload in Kib/s.'),
|
'trackerRemove': ('array', 10, None, None, None, 'Array of ids of trackers to remove.'),
|
||||||
'speed-limit-up-enabled': ('boolean', 1, 5, None, 'uploadLimited', 'Enable upload speed limiter.'),
|
'trackerReplace': ('array', 10, None, None, None, 'Array of (id, url) tuples where the announce URL should be replaced.'),
|
||||||
'trackerAdd': ('array', 10, None, None, None, 'Array of string with announce URLs to add.'),
|
'uploadLimit': ('number', 5, None, 'speed-limit-up', None, 'Set the speed limit for upload in Kib/s.'),
|
||||||
'trackerRemove': ('array', 10, None, None, None, 'Array of ids of trackers to remove.'),
|
'uploadLimited': ('boolean', 5, None, 'speed-limit-up-enabled', None, 'Enable upload speed limiter.'),
|
||||||
'trackerReplace': (
|
|
||||||
'array', 10, None, None, None, 'Array of (id, url) tuples where the announce URL should be replaced.'),
|
|
||||||
'uploadLimit': ('number', 5, None, 'speed-limit-up', None, 'Set the speed limit for upload in Kib/s.'),
|
|
||||||
'uploadLimited': ('boolean', 5, None, 'speed-limit-up-enabled', None, 'Enable upload speed limiter.'),
|
|
||||||
},
|
},
|
||||||
'add': {
|
'add': {
|
||||||
'bandwidthPriority': ('number', 8, None, None, None, 'Priority for this transfer.'),
|
'bandwidthPriority': ('number', 8, None, None, None, 'Priority for this transfer.'),
|
||||||
'download-dir': (
|
'download-dir': ('string', 1, None, None, None, 'The directory where the downloaded contents will be saved in.'),
|
||||||
'string', 1, None, None, None, 'The directory where the downloaded contents will be saved in.'),
|
'cookies': ('string', 13, None, None, None, 'One or more HTTP cookie(s).'),
|
||||||
'cookies': ('string', 13, None, None, None, 'One or more HTTP cookie(s).'),
|
'filename': ('string', 1, None, None, None, "A file path or URL to a torrent file or a magnet link."),
|
||||||
'filename': ('string', 1, None, None, None, "A file path or URL to a torrent file or a magnet link."),
|
'files-wanted': ('array', 1, None, None, None, "A list of file id's that should be downloaded."),
|
||||||
'files-wanted': ('array', 1, None, None, None, "A list of file id's that should be downloaded."),
|
'files-unwanted': ('array', 1, None, None, None, "A list of file id's that shouldn't be downloaded."),
|
||||||
'files-unwanted': ('array', 1, None, None, None, "A list of file id's that shouldn't be downloaded."),
|
'metainfo': ('string', 1, None, None, None, 'The content of a torrent file, base64 encoded.'),
|
||||||
'metainfo': ('string', 1, None, None, None, 'The content of a torrent file, base64 encoded.'),
|
'paused': ('boolean', 1, None, None, None, 'If True, does not start the transfer when added.'),
|
||||||
'paused': ('boolean', 1, None, None, None, 'If True, does not start the transfer when added.'),
|
'peer-limit': ('number', 1, None, None, None, 'Maximum number of peers allowed.'),
|
||||||
'peer-limit': ('number', 1, None, None, None, 'Maximum number of peers allowed.'),
|
'priority-high': ('array', 1, None, None, None, "A list of file id's that should have high priority."),
|
||||||
'priority-high': ('array', 1, None, None, None, "A list of file id's that should have high priority."),
|
'priority-low': ('array', 1, None, None, None, "A list of file id's that should have low priority."),
|
||||||
'priority-low': ('array', 1, None, None, None, "A list of file id's that should have low priority."),
|
'priority-normal': ('array', 1, None, None, None, "A list of file id's that should have normal priority."),
|
||||||
'priority-normal': ('array', 1, None, None, None, "A list of file id's that should have normal priority."),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Arguments for session methods
|
# Arguments for session methods
|
||||||
SESSION_ARGS = {
|
SESSION_ARGS = {
|
||||||
'get': {
|
'get': {
|
||||||
"alt-speed-down": ('number', 5, None, None, None, 'Alternate session download speed limit (in Kib/s).'),
|
"alt-speed-down": ('number', 5, None, None, None, 'Alternate session download speed limit (in Kib/s).'),
|
||||||
"alt-speed-enabled": (
|
"alt-speed-enabled": ('boolean', 5, None, None, None, 'True if alternate global download speed limiter is ebabled.'),
|
||||||
'boolean', 5, None, None, None, 'True if alternate global download speed limiter is ebabled.'),
|
"alt-speed-time-begin": ('number', 5, None, None, None, 'Time when alternate speeds should be enabled. Minutes after midnight.'),
|
||||||
"alt-speed-time-begin": (
|
"alt-speed-time-enabled": ('boolean', 5, None, None, None, 'True if alternate speeds scheduling is enabled.'),
|
||||||
'number', 5, None, None, None, 'Time when alternate speeds should be enabled. Minutes after midnight.'),
|
"alt-speed-time-end": ('number', 5, None, None, None, 'Time when alternate speeds should be disabled. Minutes after midnight.'),
|
||||||
"alt-speed-time-enabled": ('boolean', 5, None, None, None, 'True if alternate speeds scheduling is enabled.'),
|
"alt-speed-time-day": ('number', 5, None, None, None, 'Days alternate speeds scheduling is enabled.'),
|
||||||
"alt-speed-time-end": (
|
"alt-speed-up": ('number', 5, None, None, None, 'Alternate session upload speed limit (in Kib/s)'),
|
||||||
'number', 5, None, None, None, 'Time when alternate speeds should be disabled. Minutes after midnight.'),
|
"blocklist-enabled": ('boolean', 5, None, None, None, 'True when blocklist is enabled.'),
|
||||||
"alt-speed-time-day": ('number', 5, None, None, None, 'Days alternate speeds scheduling is enabled.'),
|
"blocklist-size": ('number', 5, None, None, None, 'Number of rules in the blocklist'),
|
||||||
"alt-speed-up": ('number', 5, None, None, None, 'Alternate session upload speed limit (in Kib/s)'),
|
"blocklist-url": ('string', 11, None, None, None, 'Location of the block list. Updated with blocklist-update.'),
|
||||||
"blocklist-enabled": ('boolean', 5, None, None, None, 'True when blocklist is enabled.'),
|
"cache-size-mb": ('number', 10, None, None, None, 'The maximum size of the disk cache in MB'),
|
||||||
"blocklist-size": ('number', 5, None, None, None, 'Number of rules in the blocklist'),
|
"config-dir": ('string', 8, None, None, None, 'location of transmissions configuration directory'),
|
||||||
"blocklist-url": ('string', 11, None, None, None, 'Location of the block list. Updated with blocklist-update.'),
|
"dht-enabled": ('boolean', 6, None, None, None, 'True if DHT enabled.'),
|
||||||
"cache-size-mb": ('number', 10, None, None, None, 'The maximum size of the disk cache in MB'),
|
"download-dir": ('string', 1, None, None, None, 'The download directory.'),
|
||||||
"config-dir": ('string', 8, None, None, None, 'location of transmissions configuration directory'),
|
"download-dir-free-space": ('number', 12, None, None, None, 'Free space in the download directory, in bytes'),
|
||||||
"dht-enabled": ('boolean', 6, None, None, None, 'True if DHT enabled.'),
|
"download-queue-size": ('number', 14, None, None, None, 'Number of slots in the download queue.'),
|
||||||
"download-dir": ('string', 1, None, None, None, 'The download directory.'),
|
"download-queue-enabled": ('boolean', 14, None, None, None, 'True if the download queue is enabled.'),
|
||||||
"download-dir-free-space": ('number', 12, None, None, None, 'Free space in the download directory, in bytes'),
|
"encryption": ('string', 1, None, None, None, 'Encryption mode, one of ``required``, ``preferred`` or ``tolerated``.'),
|
||||||
"download-queue-size": ('number', 14, None, None, None, 'Number of slots in the download queue.'),
|
"idle-seeding-limit": ('number', 10, None, None, None, 'Seed inactivity limit in minutes.'),
|
||||||
"download-queue-enabled": ('boolean', 14, None, None, None, 'True if the download queue is enabled.'),
|
"idle-seeding-limit-enabled": ('boolean', 10, None, None, None, 'True if the seed activity limit is enabled.'),
|
||||||
"encryption": (
|
"incomplete-dir": ('string', 7, None, None, None, 'The path to the directory for incomplete torrent transfer data.'),
|
||||||
'string', 1, None, None, None, 'Encryption mode, one of ``required``, ``preferred`` or ``tolerated``.'),
|
"incomplete-dir-enabled": ('boolean', 7, None, None, None, 'True if the incomplete dir is enabled.'),
|
||||||
"idle-seeding-limit": ('number', 10, None, None, None, 'Seed inactivity limit in minutes.'),
|
"lpd-enabled": ('boolean', 9, None, None, None, 'True if local peer discovery is enabled.'),
|
||||||
"idle-seeding-limit-enabled": ('boolean', 10, None, None, None, 'True if the seed activity limit is enabled.'),
|
"peer-limit": ('number', 1, 5, None, 'peer-limit-global', 'Maximum number of peers.'),
|
||||||
"incomplete-dir": (
|
"peer-limit-global": ('number', 5, None, 'peer-limit', None, 'Maximum number of peers.'),
|
||||||
'string', 7, None, None, None, 'The path to the directory for incomplete torrent transfer data.'),
|
"peer-limit-per-torrent": ('number', 5, None, None, None, 'Maximum number of peers per transfer.'),
|
||||||
"incomplete-dir-enabled": ('boolean', 7, None, None, None, 'True if the incomplete dir is enabled.'),
|
"pex-allowed": ('boolean', 1, 5, None, 'pex-enabled', 'True if PEX is allowed.'),
|
||||||
"lpd-enabled": ('boolean', 9, None, None, None, 'True if local peer discovery is enabled.'),
|
"pex-enabled": ('boolean', 5, None, 'pex-allowed', None, 'True if PEX is enabled.'),
|
||||||
"peer-limit": ('number', 1, 5, None, 'peer-limit-global', 'Maximum number of peers.'),
|
"port": ('number', 1, 5, None, 'peer-port', 'Peer port.'),
|
||||||
"peer-limit-global": ('number', 5, None, 'peer-limit', None, 'Maximum number of peers.'),
|
"peer-port": ('number', 5, None, 'port', None, 'Peer port.'),
|
||||||
"peer-limit-per-torrent": ('number', 5, None, None, None, 'Maximum number of peers per transfer.'),
|
"peer-port-random-on-start": ('boolean', 5, None, None, None, 'Enables randomized peer port on start of Transmission.'),
|
||||||
"pex-allowed": ('boolean', 1, 5, None, 'pex-enabled', 'True if PEX is allowed.'),
|
"port-forwarding-enabled": ('boolean', 1, None, None, None, 'True if port forwarding is enabled.'),
|
||||||
"pex-enabled": ('boolean', 5, None, 'pex-allowed', None, 'True if PEX is enabled.'),
|
"queue-stalled-minutes": ('number', 14, None, None, None, 'Number of minutes of idle that marks a transfer as stalled.'),
|
||||||
"port": ('number', 1, 5, None, 'peer-port', 'Peer port.'),
|
"queue-stalled-enabled": ('boolean', 14, None, None, None, 'True if stalled tracking of transfers is enabled.'),
|
||||||
"peer-port": ('number', 5, None, 'port', None, 'Peer port.'),
|
"rename-partial-files": ('boolean', 8, None, None, None, 'True if ".part" is appended to incomplete files'),
|
||||||
"peer-port-random-on-start": (
|
"rpc-version": ('number', 4, None, None, None, 'Transmission RPC API Version.'),
|
||||||
'boolean', 5, None, None, None, 'Enables randomized peer port on start of Transmission.'),
|
"rpc-version-minimum": ('number', 4, None, None, None, 'Minimum accepted RPC API Version.'),
|
||||||
"port-forwarding-enabled": ('boolean', 1, None, None, None, 'True if port forwarding is enabled.'),
|
"script-torrent-done-enabled": ('boolean', 9, None, None, None, 'True if the done script is enabled.'),
|
||||||
"queue-stalled-minutes": (
|
"script-torrent-done-filename": ('string', 9, None, None, None, 'Filename of the script to run when the transfer is done.'),
|
||||||
'number', 14, None, None, None, 'Number of minutes of idle that marks a transfer as stalled.'),
|
"seedRatioLimit": ('double', 5, None, None, None, 'Seed ratio limit. 1.0 means 1:1 download and upload ratio.'),
|
||||||
"queue-stalled-enabled": ('boolean', 14, None, None, None, 'True if stalled tracking of transfers is enabled.'),
|
"seedRatioLimited": ('boolean', 5, None, None, None, 'True if seed ration limit is enabled.'),
|
||||||
"rename-partial-files": ('boolean', 8, None, None, None, 'True if ".part" is appended to incomplete files'),
|
"seed-queue-size": ('number', 14, None, None, None, 'Number of slots in the upload queue.'),
|
||||||
"rpc-version": ('number', 4, None, None, None, 'Transmission RPC API Version.'),
|
"seed-queue-enabled": ('boolean', 14, None, None, None, 'True if upload queue is enabled.'),
|
||||||
"rpc-version-minimum": ('number', 4, None, None, None, 'Minimum accepted RPC API Version.'),
|
"speed-limit-down": ('number', 1, None, None, None, 'Download speed limit (in Kib/s).'),
|
||||||
"script-torrent-done-enabled": ('boolean', 9, None, None, None, 'True if the done script is enabled.'),
|
"speed-limit-down-enabled": ('boolean', 1, None, None, None, 'True if the download speed is limited.'),
|
||||||
"script-torrent-done-filename": (
|
"speed-limit-up": ('number', 1, None, None, None, 'Upload speed limit (in Kib/s).'),
|
||||||
'string', 9, None, None, None, 'Filename of the script to run when the transfer is done.'),
|
"speed-limit-up-enabled": ('boolean', 1, None, None, None, 'True if the upload speed is limited.'),
|
||||||
"seedRatioLimit": ('double', 5, None, None, None, 'Seed ratio limit. 1.0 means 1:1 download and upload ratio.'),
|
"start-added-torrents": ('boolean', 9, None, None, None, 'When true uploaded torrents will start right away.'),
|
||||||
"seedRatioLimited": ('boolean', 5, None, None, None, 'True if seed ration limit is enabled.'),
|
"trash-original-torrent-files": ('boolean', 9, None, None, None, 'When true added .torrent files will be deleted.'),
|
||||||
"seed-queue-size": ('number', 14, None, None, None, 'Number of slots in the upload queue.'),
|
'units': ('object', 10, None, None, None, 'An object containing units for size and speed.'),
|
||||||
"seed-queue-enabled": ('boolean', 14, None, None, None, 'True if upload queue is enabled.'),
|
'utp-enabled': ('boolean', 13, None, None, None, 'True if Micro Transport Protocol (UTP) is enabled.'),
|
||||||
"speed-limit-down": ('number', 1, None, None, None, 'Download speed limit (in Kib/s).'),
|
"version": ('string', 3, None, None, None, 'Transmission version.'),
|
||||||
"speed-limit-down-enabled": ('boolean', 1, None, None, None, 'True if the download speed is limited.'),
|
|
||||||
"speed-limit-up": ('number', 1, None, None, None, 'Upload speed limit (in Kib/s).'),
|
|
||||||
"speed-limit-up-enabled": ('boolean', 1, None, None, None, 'True if the upload speed is limited.'),
|
|
||||||
"start-added-torrents": ('boolean', 9, None, None, None, 'When true uploaded torrents will start right away.'),
|
|
||||||
"trash-original-torrent-files": (
|
|
||||||
'boolean', 9, None, None, None, 'When true added .torrent files will be deleted.'),
|
|
||||||
'units': ('object', 10, None, None, None, 'An object containing units for size and speed.'),
|
|
||||||
'utp-enabled': ('boolean', 13, None, None, None, 'True if Micro Transport Protocol (UTP) is enabled.'),
|
|
||||||
"version": ('string', 3, None, None, None, 'Transmission version.'),
|
|
||||||
},
|
},
|
||||||
'set': {
|
'set': {
|
||||||
"alt-speed-down": ('number', 5, None, None, None, 'Alternate session download speed limit (in Kib/s).'),
|
"alt-speed-down": ('number', 5, None, None, None, 'Alternate session download speed limit (in Kib/s).'),
|
||||||
"alt-speed-enabled": ('boolean', 5, None, None, None, 'Enables alternate global download speed limiter.'),
|
"alt-speed-enabled": ('boolean', 5, None, None, None, 'Enables alternate global download speed limiter.'),
|
||||||
"alt-speed-time-begin": (
|
"alt-speed-time-begin": ('number', 5, None, None, None, 'Time when alternate speeds should be enabled. Minutes after midnight.'),
|
||||||
'number', 5, None, None, None, 'Time when alternate speeds should be enabled. Minutes after midnight.'),
|
"alt-speed-time-enabled": ('boolean', 5, None, None, None, 'Enables alternate speeds scheduling.'),
|
||||||
"alt-speed-time-enabled": ('boolean', 5, None, None, None, 'Enables alternate speeds scheduling.'),
|
"alt-speed-time-end": ('number', 5, None, None, None, 'Time when alternate speeds should be disabled. Minutes after midnight.'),
|
||||||
"alt-speed-time-end": (
|
"alt-speed-time-day": ('number', 5, None, None, None, 'Enables alternate speeds scheduling these days.'),
|
||||||
'number', 5, None, None, None, 'Time when alternate speeds should be disabled. Minutes after midnight.'),
|
"alt-speed-up": ('number', 5, None, None, None, 'Alternate session upload speed limit (in Kib/s).'),
|
||||||
"alt-speed-time-day": ('number', 5, None, None, None, 'Enables alternate speeds scheduling these days.'),
|
"blocklist-enabled": ('boolean', 5, None, None, None, 'Enables the block list'),
|
||||||
"alt-speed-up": ('number', 5, None, None, None, 'Alternate session upload speed limit (in Kib/s).'),
|
"blocklist-url": ('string', 11, None, None, None, 'Location of the block list. Updated with blocklist-update.'),
|
||||||
"blocklist-enabled": ('boolean', 5, None, None, None, 'Enables the block list'),
|
"cache-size-mb": ('number', 10, None, None, None, 'The maximum size of the disk cache in MB'),
|
||||||
"blocklist-url": ('string', 11, None, None, None, 'Location of the block list. Updated with blocklist-update.'),
|
"dht-enabled": ('boolean', 6, None, None, None, 'Enables DHT.'),
|
||||||
"cache-size-mb": ('number', 10, None, None, None, 'The maximum size of the disk cache in MB'),
|
"download-dir": ('string', 1, None, None, None, 'Set the session download directory.'),
|
||||||
"dht-enabled": ('boolean', 6, None, None, None, 'Enables DHT.'),
|
"download-queue-size": ('number', 14, None, None, None, 'Number of slots in the download queue.'),
|
||||||
"download-dir": ('string', 1, None, None, None, 'Set the session download directory.'),
|
"download-queue-enabled": ('boolean', 14, None, None, None, 'Enables download queue.'),
|
||||||
"download-queue-size": ('number', 14, None, None, None, 'Number of slots in the download queue.'),
|
"encryption": ('string', 1, None, None, None, 'Set the session encryption mode, one of ``required``, ``preferred`` or ``tolerated``.'),
|
||||||
"download-queue-enabled": ('boolean', 14, None, None, None, 'Enables download queue.'),
|
"idle-seeding-limit": ('number', 10, None, None, None, 'The default seed inactivity limit in minutes.'),
|
||||||
"encryption": ('string', 1, None, None, None,
|
"idle-seeding-limit-enabled": ('boolean', 10, None, None, None, 'Enables the default seed inactivity limit'),
|
||||||
'Set the session encryption mode, one of ``required``, ``preferred`` or ``tolerated``.'),
|
"incomplete-dir": ('string', 7, None, None, None, 'The path to the directory of incomplete transfer data.'),
|
||||||
"idle-seeding-limit": ('number', 10, None, None, None, 'The default seed inactivity limit in minutes.'),
|
"incomplete-dir-enabled": ('boolean', 7, None, None, None, 'Enables the incomplete transfer data directory. Otherwise data for incomplete transfers are stored in the download target.'),
|
||||||
"idle-seeding-limit-enabled": ('boolean', 10, None, None, None, 'Enables the default seed inactivity limit'),
|
"lpd-enabled": ('boolean', 9, None, None, None, 'Enables local peer discovery for public torrents.'),
|
||||||
"incomplete-dir": ('string', 7, None, None, None, 'The path to the directory of incomplete transfer data.'),
|
"peer-limit": ('number', 1, 5, None, 'peer-limit-global', 'Maximum number of peers.'),
|
||||||
"incomplete-dir-enabled": ('boolean', 7, None, None, None,
|
"peer-limit-global": ('number', 5, None, 'peer-limit', None, 'Maximum number of peers.'),
|
||||||
'Enables the incomplete transfer data directory. Otherwise data for incomplete transfers are stored in the download target.'),
|
"peer-limit-per-torrent": ('number', 5, None, None, None, 'Maximum number of peers per transfer.'),
|
||||||
"lpd-enabled": ('boolean', 9, None, None, None, 'Enables local peer discovery for public torrents.'),
|
"pex-allowed": ('boolean', 1, 5, None, 'pex-enabled', 'Allowing PEX in public torrents.'),
|
||||||
"peer-limit": ('number', 1, 5, None, 'peer-limit-global', 'Maximum number of peers.'),
|
"pex-enabled": ('boolean', 5, None, 'pex-allowed', None, 'Allowing PEX in public torrents.'),
|
||||||
"peer-limit-global": ('number', 5, None, 'peer-limit', None, 'Maximum number of peers.'),
|
"port": ('number', 1, 5, None, 'peer-port', 'Peer port.'),
|
||||||
"peer-limit-per-torrent": ('number', 5, None, None, None, 'Maximum number of peers per transfer.'),
|
"peer-port": ('number', 5, None, 'port', None, 'Peer port.'),
|
||||||
"pex-allowed": ('boolean', 1, 5, None, 'pex-enabled', 'Allowing PEX in public torrents.'),
|
"peer-port-random-on-start": ('boolean', 5, None, None, None, 'Enables randomized peer port on start of Transmission.'),
|
||||||
"pex-enabled": ('boolean', 5, None, 'pex-allowed', None, 'Allowing PEX in public torrents.'),
|
"port-forwarding-enabled": ('boolean', 1, None, None, None, 'Enables port forwarding.'),
|
||||||
"port": ('number', 1, 5, None, 'peer-port', 'Peer port.'),
|
"rename-partial-files": ('boolean', 8, None, None, None, 'Appends ".part" to incomplete files'),
|
||||||
"peer-port": ('number', 5, None, 'port', None, 'Peer port.'),
|
"queue-stalled-minutes": ('number', 14, None, None, None, 'Number of minutes of idle that marks a transfer as stalled.'),
|
||||||
"peer-port-random-on-start": (
|
"queue-stalled-enabled": ('boolean', 14, None, None, None, 'Enable tracking of stalled transfers.'),
|
||||||
'boolean', 5, None, None, None, 'Enables randomized peer port on start of Transmission.'),
|
"script-torrent-done-enabled": ('boolean', 9, None, None, None, 'Whether or not to call the "done" script.'),
|
||||||
"port-forwarding-enabled": ('boolean', 1, None, None, None, 'Enables port forwarding.'),
|
"script-torrent-done-filename": ('string', 9, None, None, None, 'Filename of the script to run when the transfer is done.'),
|
||||||
"rename-partial-files": ('boolean', 8, None, None, None, 'Appends ".part" to incomplete files'),
|
"seed-queue-size": ('number', 14, None, None, None, 'Number of slots in the upload queue.'),
|
||||||
"queue-stalled-minutes": (
|
"seed-queue-enabled": ('boolean', 14, None, None, None, 'Enables upload queue.'),
|
||||||
'number', 14, None, None, None, 'Number of minutes of idle that marks a transfer as stalled.'),
|
"seedRatioLimit": ('double', 5, None, None, None, 'Seed ratio limit. 1.0 means 1:1 download and upload ratio.'),
|
||||||
"queue-stalled-enabled": ('boolean', 14, None, None, None, 'Enable tracking of stalled transfers.'),
|
"seedRatioLimited": ('boolean', 5, None, None, None, 'Enables seed ration limit.'),
|
||||||
"script-torrent-done-enabled": ('boolean', 9, None, None, None, 'Whether or not to call the "done" script.'),
|
"speed-limit-down": ('number', 1, None, None, None, 'Download speed limit (in Kib/s).'),
|
||||||
"script-torrent-done-filename": (
|
"speed-limit-down-enabled": ('boolean', 1, None, None, None, 'Enables download speed limiting.'),
|
||||||
'string', 9, None, None, None, 'Filename of the script to run when the transfer is done.'),
|
"speed-limit-up": ('number', 1, None, None, None, 'Upload speed limit (in Kib/s).'),
|
||||||
"seed-queue-size": ('number', 14, None, None, None, 'Number of slots in the upload queue.'),
|
"speed-limit-up-enabled": ('boolean', 1, None, None, None, 'Enables upload speed limiting.'),
|
||||||
"seed-queue-enabled": ('boolean', 14, None, None, None, 'Enables upload queue.'),
|
"start-added-torrents": ('boolean', 9, None, None, None, 'Added torrents will be started right away.'),
|
||||||
"seedRatioLimit": ('double', 5, None, None, None, 'Seed ratio limit. 1.0 means 1:1 download and upload ratio.'),
|
"trash-original-torrent-files": ('boolean', 9, None, None, None, 'The .torrent file of added torrents will be deleted.'),
|
||||||
"seedRatioLimited": ('boolean', 5, None, None, None, 'Enables seed ration limit.'),
|
'utp-enabled': ('boolean', 13, None, None, None, 'Enables Micro Transport Protocol (UTP).'),
|
||||||
"speed-limit-down": ('number', 1, None, None, None, 'Download speed limit (in Kib/s).'),
|
|
||||||
"speed-limit-down-enabled": ('boolean', 1, None, None, None, 'Enables download speed limiting.'),
|
|
||||||
"speed-limit-up": ('number', 1, None, None, None, 'Upload speed limit (in Kib/s).'),
|
|
||||||
"speed-limit-up-enabled": ('boolean', 1, None, None, None, 'Enables upload speed limiting.'),
|
|
||||||
"start-added-torrents": ('boolean', 9, None, None, None, 'Added torrents will be started right away.'),
|
|
||||||
"trash-original-torrent-files": (
|
|
||||||
'boolean', 9, None, None, None, 'The .torrent file of added torrents will be deleted.'),
|
|
||||||
'utp-enabled': ('boolean', 13, None, None, None, 'Enables Micro Transport Protocol (UTP).'),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,13 @@
|
||||||
# Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com>
|
# Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com>
|
||||||
# Licensed under the MIT license.
|
# Licensed under the MIT license.
|
||||||
|
|
||||||
from six import integer_types, string_types
|
from six import string_types, integer_types
|
||||||
|
|
||||||
|
|
||||||
class TransmissionError(Exception):
|
class TransmissionError(Exception):
|
||||||
"""
|
"""
|
||||||
This exception is raised when there has occurred an error related to
|
This exception is raised when there has occurred an error related to
|
||||||
communication with Transmission. It is a subclass of Exception.
|
communication with Transmission. It is a subclass of Exception.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, message='', original=None):
|
def __init__(self, message='', original=None):
|
||||||
Exception.__init__(self)
|
Exception.__init__(self)
|
||||||
self.message = message
|
self.message = message
|
||||||
|
@ -19,17 +17,15 @@ class TransmissionError(Exception):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if self.original:
|
if self.original:
|
||||||
original_name = type(self.original).__name__
|
original_name = type(self.original).__name__
|
||||||
return '{0} Original exception: {1}, "{2}"'.format(self.message, original_name, str(self.original))
|
return '%s Original exception: %s, "%s"' % (self.message, original_name, str(self.original))
|
||||||
else:
|
else:
|
||||||
return self.message
|
return self.message
|
||||||
|
|
||||||
|
|
||||||
class HTTPHandlerError(Exception):
|
class HTTPHandlerError(Exception):
|
||||||
"""
|
"""
|
||||||
This exception is raised when there has occurred an error related to
|
This exception is raised when there has occurred an error related to
|
||||||
the HTTP handler. It is a subclass of Exception.
|
the HTTP handler. It is a subclass of Exception.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, httpurl=None, httpcode=None, httpmsg=None, httpheaders=None, httpdata=None):
|
def __init__(self, httpurl=None, httpcode=None, httpmsg=None, httpheaders=None, httpdata=None):
|
||||||
Exception.__init__(self)
|
Exception.__init__(self)
|
||||||
self.url = ''
|
self.url = ''
|
||||||
|
@ -49,10 +45,10 @@ class HTTPHandlerError(Exception):
|
||||||
self.data = httpdata
|
self.data = httpdata
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<HTTPHandlerError {0:d}, {1}>'.format(self.code, self.message)
|
return '<HTTPHandlerError %d, %s>' % (self.code, self.message)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return 'HTTPHandlerError {0:d}: {1}'.format(self.code, self.message)
|
return 'HTTPHandlerError %d: %s' % (self.code, self.message)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return 'HTTPHandlerError {0:d}: {1}'.format(self.code, self.message)
|
return 'HTTPHandlerError %d: %s' % (self.code, self.message)
|
||||||
|
|
|
@ -4,24 +4,25 @@
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from six.moves.http_client import BadStatusLine
|
from transmissionrpc.error import HTTPHandlerError
|
||||||
from six.moves.urllib_error import HTTPError, URLError
|
|
||||||
from six.moves.urllib_request import (
|
|
||||||
HTTPBasicAuthHandler,
|
|
||||||
HTTPDigestAuthHandler,
|
|
||||||
HTTPPasswordMgrWithDefaultRealm,
|
|
||||||
Request,
|
|
||||||
build_opener,
|
|
||||||
)
|
|
||||||
|
|
||||||
from .error import HTTPHandlerError
|
from six import PY3
|
||||||
|
|
||||||
|
if PY3:
|
||||||
|
from urllib.request import Request, build_opener, \
|
||||||
|
HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, HTTPDigestAuthHandler
|
||||||
|
from urllib.error import HTTPError, URLError
|
||||||
|
from http.client import BadStatusLine
|
||||||
|
else:
|
||||||
|
from urllib2 import Request, build_opener, \
|
||||||
|
HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, HTTPDigestAuthHandler
|
||||||
|
from urllib2 import HTTPError, URLError
|
||||||
|
from httplib import BadStatusLine
|
||||||
|
|
||||||
class HTTPHandler(object):
|
class HTTPHandler(object):
|
||||||
"""
|
"""
|
||||||
Prototype for HTTP handling.
|
Prototype for HTTP handling.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def set_authentication(self, uri, login, password):
|
def set_authentication(self, uri, login, password):
|
||||||
"""
|
"""
|
||||||
Transmission use basic authentication in earlier versions and digest
|
Transmission use basic authentication in earlier versions and digest
|
||||||
|
@ -44,12 +45,10 @@ class HTTPHandler(object):
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError("Bad HTTPHandler, failed to implement request.")
|
raise NotImplementedError("Bad HTTPHandler, failed to implement request.")
|
||||||
|
|
||||||
|
|
||||||
class DefaultHTTPHandler(HTTPHandler):
|
class DefaultHTTPHandler(HTTPHandler):
|
||||||
"""
|
"""
|
||||||
The default HTTP handler provided with transmissionrpc.
|
The default HTTP handler provided with transmissionrpc.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
HTTPHandler.__init__(self)
|
HTTPHandler.__init__(self)
|
||||||
self.http_opener = build_opener()
|
self.http_opener = build_opener()
|
||||||
|
@ -77,7 +76,7 @@ class DefaultHTTPHandler(HTTPHandler):
|
||||||
if hasattr(error.reason, 'args') and isinstance(error.reason.args, tuple) and len(error.reason.args) == 2:
|
if hasattr(error.reason, 'args') and isinstance(error.reason.args, tuple) and len(error.reason.args) == 2:
|
||||||
raise HTTPHandlerError(httpcode=error.reason.args[0], httpmsg=error.reason.args[1])
|
raise HTTPHandlerError(httpcode=error.reason.args[0], httpmsg=error.reason.args[1])
|
||||||
else:
|
else:
|
||||||
raise HTTPHandlerError(httpmsg='urllib2.URLError: {error.reason}'.format(error=error))
|
raise HTTPHandlerError(httpmsg='urllib2.URLError: %s' % (error.reason))
|
||||||
except BadStatusLine as error:
|
except BadStatusLine as error:
|
||||||
raise HTTPHandlerError(httpmsg='httplib.BadStatusLine: {error.line}'.format(error=error))
|
raise HTTPHandlerError(httpmsg='httplib.BadStatusLine: %s' % (error.line))
|
||||||
return response.read().decode('utf-8')
|
return response.read().decode('utf-8')
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
# Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com>
|
# Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com>
|
||||||
# Licensed under the MIT license.
|
# Licensed under the MIT license.
|
||||||
|
|
||||||
from six import integer_types, iteritems
|
from transmissionrpc.utils import Field
|
||||||
|
|
||||||
from .utils import Field
|
|
||||||
|
|
||||||
|
from six import iteritems, integer_types
|
||||||
|
|
||||||
class Session(object):
|
class Session(object):
|
||||||
"""
|
"""
|
||||||
|
@ -27,12 +26,12 @@ class Session(object):
|
||||||
try:
|
try:
|
||||||
return self._fields[name].value
|
return self._fields[name].value
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise AttributeError('No attribute {0}'.format(name))
|
raise AttributeError('No attribute %s' % name)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
text = ''
|
text = ''
|
||||||
for key in sorted(self._fields.keys()):
|
for key in sorted(self._fields.keys()):
|
||||||
text += "{0:32}: {1}\n".format(key[-32:], self._fields[key].value)
|
text += "% 32s: %s\n" % (key[-32:], self._fields[key].value)
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def _update_fields(self, other):
|
def _update_fields(self, other):
|
||||||
|
|
|
@ -2,27 +2,25 @@
|
||||||
# Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com>
|
# Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com>
|
||||||
# Licensed under the MIT license.
|
# Licensed under the MIT license.
|
||||||
|
|
||||||
import datetime
|
import sys, datetime
|
||||||
import sys
|
|
||||||
|
|
||||||
from six import integer_types, iteritems, string_types, text_type
|
from transmissionrpc.constants import PRIORITY, RATIO_LIMIT, IDLE_LIMIT
|
||||||
|
from transmissionrpc.utils import Field, format_timedelta
|
||||||
|
|
||||||
from .constants import IDLE_LIMIT, PRIORITY, RATIO_LIMIT
|
from six import integer_types, string_types, text_type, iteritems
|
||||||
from .utils import Field, format_timedelta
|
|
||||||
|
|
||||||
|
|
||||||
def get_status_old(code):
|
def get_status_old(code):
|
||||||
"""Get the torrent status using old status codes"""
|
"""Get the torrent status using old status codes"""
|
||||||
mapping = {
|
mapping = {
|
||||||
(1 << 0): 'check pending',
|
(1<<0): 'check pending',
|
||||||
(1 << 1): 'checking',
|
(1<<1): 'checking',
|
||||||
(1 << 2): 'downloading',
|
(1<<2): 'downloading',
|
||||||
(1 << 3): 'seeding',
|
(1<<3): 'seeding',
|
||||||
(1 << 4): 'stopped',
|
(1<<4): 'stopped',
|
||||||
}
|
}
|
||||||
return mapping[code]
|
return mapping[code]
|
||||||
|
|
||||||
|
|
||||||
def get_status_new(code):
|
def get_status_new(code):
|
||||||
"""Get the torrent status using new status codes"""
|
"""Get the torrent status using new status codes"""
|
||||||
mapping = {
|
mapping = {
|
||||||
|
@ -36,7 +34,6 @@ def get_status_new(code):
|
||||||
}
|
}
|
||||||
return mapping[code]
|
return mapping[code]
|
||||||
|
|
||||||
|
|
||||||
class Torrent(object):
|
class Torrent(object):
|
||||||
"""
|
"""
|
||||||
Torrent is a class holding the data received from Transmission regarding a bittorrent transfer.
|
Torrent is a class holding the data received from Transmission regarding a bittorrent transfer.
|
||||||
|
@ -74,14 +71,14 @@ class Torrent(object):
|
||||||
tid = self._fields['id'].value
|
tid = self._fields['id'].value
|
||||||
name = self._get_name_string()
|
name = self._get_name_string()
|
||||||
if isinstance(name, str):
|
if isinstance(name, str):
|
||||||
return '<Torrent {0:d} \"{1}\">'.format(tid, name)
|
return '<Torrent %d \"%s\">' % (tid, name)
|
||||||
else:
|
else:
|
||||||
return '<Torrent {0:d}>'.format(tid)
|
return '<Torrent %d>' % (tid)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
name = self._get_name_string()
|
name = self._get_name_string()
|
||||||
if isinstance(name, str):
|
if isinstance(name, str):
|
||||||
return 'Torrent \"{0}\"'.format(name)
|
return 'Torrent \"%s\"' % (name)
|
||||||
else:
|
else:
|
||||||
return 'Torrent'
|
return 'Torrent'
|
||||||
|
|
||||||
|
@ -92,7 +89,7 @@ class Torrent(object):
|
||||||
try:
|
try:
|
||||||
return self._fields[name].value
|
return self._fields[name].value
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise AttributeError('No attribute {0}'.format(name))
|
raise AttributeError('No attribute %s' % name)
|
||||||
|
|
||||||
def _rpc_version(self):
|
def _rpc_version(self):
|
||||||
"""Get the Transmission RPC API version."""
|
"""Get the Transmission RPC API version."""
|
||||||
|
@ -102,9 +99,8 @@ class Torrent(object):
|
||||||
|
|
||||||
def _dirty_fields(self):
|
def _dirty_fields(self):
|
||||||
"""Enumerate changed fields"""
|
"""Enumerate changed fields"""
|
||||||
outgoing_keys = ['bandwidthPriority', 'downloadLimit', 'downloadLimited', 'peer_limit', 'queuePosition',
|
outgoing_keys = ['bandwidthPriority', 'downloadLimit', 'downloadLimited', 'peer_limit', 'queuePosition'
|
||||||
'seedIdleLimit', 'seedIdleMode', 'seedRatioLimit', 'seedRatioMode', 'uploadLimit',
|
, 'seedIdleLimit', 'seedIdleMode', 'seedRatioLimit', 'seedRatioMode', 'uploadLimit', 'uploadLimited']
|
||||||
'uploadLimited']
|
|
||||||
fields = []
|
fields = []
|
||||||
for key in outgoing_keys:
|
for key in outgoing_keys:
|
||||||
if key in self._fields and self._fields[key].dirty:
|
if key in self._fields and self._fields[key].dirty:
|
||||||
|
@ -125,6 +121,7 @@ class Torrent(object):
|
||||||
"""
|
"""
|
||||||
Update the torrent data from a Transmission JSON-RPC arguments dictionary
|
Update the torrent data from a Transmission JSON-RPC arguments dictionary
|
||||||
"""
|
"""
|
||||||
|
fields = None
|
||||||
if isinstance(other, dict):
|
if isinstance(other, dict):
|
||||||
for key, value in iteritems(other):
|
for key, value in iteritems(other):
|
||||||
self._fields[key.replace('-', '_')] = Field(value, False)
|
self._fields[key.replace('-', '_')] = Field(value, False)
|
||||||
|
@ -267,14 +264,13 @@ class Torrent(object):
|
||||||
self._fields['downloadLimited'] = Field(True, True)
|
self._fields['downloadLimited'] = Field(True, True)
|
||||||
self._fields['downloadLimit'] = Field(limit, True)
|
self._fields['downloadLimit'] = Field(limit, True)
|
||||||
self._push()
|
self._push()
|
||||||
elif limit is None:
|
elif limit == None:
|
||||||
self._fields['downloadLimited'] = Field(False, True)
|
self._fields['downloadLimited'] = Field(False, True)
|
||||||
self._push()
|
self._push()
|
||||||
else:
|
else:
|
||||||
raise ValueError("Not a valid limit")
|
raise ValueError("Not a valid limit")
|
||||||
|
|
||||||
download_limit = property(_get_download_limit, _set_download_limit, None,
|
download_limit = property(_get_download_limit, _set_download_limit, None, "Download limit in Kbps or None. This is a mutator.")
|
||||||
"Download limit in Kbps or None. This is a mutator.")
|
|
||||||
|
|
||||||
def _get_peer_limit(self):
|
def _get_peer_limit(self):
|
||||||
"""
|
"""
|
||||||
|
@ -311,7 +307,7 @@ class Torrent(object):
|
||||||
self._push()
|
self._push()
|
||||||
|
|
||||||
priority = property(_get_priority, _set_priority, None
|
priority = property(_get_priority, _set_priority, None
|
||||||
, "Bandwidth priority as string. Can be one of 'low', 'normal', 'high'. This is a mutator.")
|
, "Bandwidth priority as string. Can be one of 'low', 'normal', 'high'. This is a mutator.")
|
||||||
|
|
||||||
def _get_seed_idle_limit(self):
|
def _get_seed_idle_limit(self):
|
||||||
"""
|
"""
|
||||||
|
@ -330,7 +326,7 @@ class Torrent(object):
|
||||||
raise ValueError("Not a valid limit")
|
raise ValueError("Not a valid limit")
|
||||||
|
|
||||||
seed_idle_limit = property(_get_seed_idle_limit, _set_seed_idle_limit, None
|
seed_idle_limit = property(_get_seed_idle_limit, _set_seed_idle_limit, None
|
||||||
, "Torrent seed idle limit in minutes. Also see seed_idle_mode. This is a mutator.")
|
, "Torrent seed idle limit in minutes. Also see seed_idle_mode. This is a mutator.")
|
||||||
|
|
||||||
def _get_seed_idle_mode(self):
|
def _get_seed_idle_mode(self):
|
||||||
"""
|
"""
|
||||||
|
@ -349,7 +345,7 @@ class Torrent(object):
|
||||||
raise ValueError("Not a valid limit")
|
raise ValueError("Not a valid limit")
|
||||||
|
|
||||||
seed_idle_mode = property(_get_seed_idle_mode, _set_seed_idle_mode, None,
|
seed_idle_mode = property(_get_seed_idle_mode, _set_seed_idle_mode, None,
|
||||||
"""
|
"""
|
||||||
Seed idle mode as string. Can be one of 'global', 'single' or 'unlimited'.
|
Seed idle mode as string. Can be one of 'global', 'single' or 'unlimited'.
|
||||||
|
|
||||||
* global, use session seed idle limit.
|
* global, use session seed idle limit.
|
||||||
|
@ -358,7 +354,7 @@ class Torrent(object):
|
||||||
|
|
||||||
This is a mutator.
|
This is a mutator.
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
def _get_seed_ratio_limit(self):
|
def _get_seed_ratio_limit(self):
|
||||||
"""
|
"""
|
||||||
|
@ -377,7 +373,7 @@ class Torrent(object):
|
||||||
raise ValueError("Not a valid limit")
|
raise ValueError("Not a valid limit")
|
||||||
|
|
||||||
seed_ratio_limit = property(_get_seed_ratio_limit, _set_seed_ratio_limit, None
|
seed_ratio_limit = property(_get_seed_ratio_limit, _set_seed_ratio_limit, None
|
||||||
, "Torrent seed ratio limit as float. Also see seed_ratio_mode. This is a mutator.")
|
, "Torrent seed ratio limit as float. Also see seed_ratio_mode. This is a mutator.")
|
||||||
|
|
||||||
def _get_seed_ratio_mode(self):
|
def _get_seed_ratio_mode(self):
|
||||||
"""
|
"""
|
||||||
|
@ -396,7 +392,7 @@ class Torrent(object):
|
||||||
raise ValueError("Not a valid limit")
|
raise ValueError("Not a valid limit")
|
||||||
|
|
||||||
seed_ratio_mode = property(_get_seed_ratio_mode, _set_seed_ratio_mode, None,
|
seed_ratio_mode = property(_get_seed_ratio_mode, _set_seed_ratio_mode, None,
|
||||||
"""
|
"""
|
||||||
Seed ratio mode as string. Can be one of 'global', 'single' or 'unlimited'.
|
Seed ratio mode as string. Can be one of 'global', 'single' or 'unlimited'.
|
||||||
|
|
||||||
* global, use session seed ratio limit.
|
* global, use session seed ratio limit.
|
||||||
|
@ -405,7 +401,7 @@ class Torrent(object):
|
||||||
|
|
||||||
This is a mutator.
|
This is a mutator.
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
def _get_upload_limit(self):
|
def _get_upload_limit(self):
|
||||||
"""
|
"""
|
||||||
|
@ -426,14 +422,13 @@ class Torrent(object):
|
||||||
self._fields['uploadLimited'] = Field(True, True)
|
self._fields['uploadLimited'] = Field(True, True)
|
||||||
self._fields['uploadLimit'] = Field(limit, True)
|
self._fields['uploadLimit'] = Field(limit, True)
|
||||||
self._push()
|
self._push()
|
||||||
elif limit is None:
|
elif limit == None:
|
||||||
self._fields['uploadLimited'] = Field(False, True)
|
self._fields['uploadLimited'] = Field(False, True)
|
||||||
self._push()
|
self._push()
|
||||||
else:
|
else:
|
||||||
raise ValueError("Not a valid limit")
|
raise ValueError("Not a valid limit")
|
||||||
|
|
||||||
upload_limit = property(_get_upload_limit, _set_upload_limit, None,
|
upload_limit = property(_get_upload_limit, _set_upload_limit, None, "Upload limit in Kbps or None. This is a mutator.")
|
||||||
"Upload limit in Kbps or None. This is a mutator.")
|
|
||||||
|
|
||||||
def _get_queue_position(self):
|
def _get_queue_position(self):
|
||||||
"""Get the queue position for this torrent."""
|
"""Get the queue position for this torrent."""
|
||||||
|
|
|
@ -2,19 +2,15 @@
|
||||||
# Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com>
|
# Copyright (c) 2008-2013 Erik Svensson <erik.public@gmail.com>
|
||||||
# Licensed under the MIT license.
|
# Licensed under the MIT license.
|
||||||
|
|
||||||
import datetime
|
import socket, datetime, logging
|
||||||
import logging
|
|
||||||
import socket
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
import transmissionrpc.constants as constants
|
||||||
|
from transmissionrpc.constants import LOGGER
|
||||||
|
|
||||||
from six import iteritems, string_types
|
from six import string_types, iteritems
|
||||||
|
|
||||||
from . import constants
|
|
||||||
from .constants import LOGGER
|
|
||||||
|
|
||||||
UNITS = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB']
|
UNITS = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB']
|
||||||
|
|
||||||
|
|
||||||
def format_size(size):
|
def format_size(size):
|
||||||
"""
|
"""
|
||||||
Format byte size into IEC prefixes, B, KiB, MiB ...
|
Format byte size into IEC prefixes, B, KiB, MiB ...
|
||||||
|
@ -24,16 +20,14 @@ def format_size(size):
|
||||||
while size >= 1024.0 and i < len(UNITS):
|
while size >= 1024.0 and i < len(UNITS):
|
||||||
i += 1
|
i += 1
|
||||||
size /= 1024.0
|
size /= 1024.0
|
||||||
return size, UNITS[i]
|
return (size, UNITS[i])
|
||||||
|
|
||||||
|
|
||||||
def format_speed(size):
|
def format_speed(size):
|
||||||
"""
|
"""
|
||||||
Format bytes per second speed into IEC prefixes, B/s, KiB/s, MiB/s ...
|
Format bytes per second speed into IEC prefixes, B/s, KiB/s, MiB/s ...
|
||||||
"""
|
"""
|
||||||
(size, unit) = format_size(size)
|
(size, unit) = format_size(size)
|
||||||
return size, '{unit}/s'.format(unit=unit)
|
return (size, unit + '/s')
|
||||||
|
|
||||||
|
|
||||||
def format_timedelta(delta):
|
def format_timedelta(delta):
|
||||||
"""
|
"""
|
||||||
|
@ -41,8 +35,7 @@ def format_timedelta(delta):
|
||||||
"""
|
"""
|
||||||
minutes, seconds = divmod(delta.seconds, 60)
|
minutes, seconds = divmod(delta.seconds, 60)
|
||||||
hours, minutes = divmod(minutes, 60)
|
hours, minutes = divmod(minutes, 60)
|
||||||
return '{0:d} {1:02d}:{2:02d}:{3:02d}'.format(delta.days, hours, minutes, seconds)
|
return '%d %02d:%02d:%02d' % (delta.days, hours, minutes, seconds)
|
||||||
|
|
||||||
|
|
||||||
def format_timestamp(timestamp, utc=False):
|
def format_timestamp(timestamp, utc=False):
|
||||||
"""
|
"""
|
||||||
|
@ -57,14 +50,12 @@ def format_timestamp(timestamp, utc=False):
|
||||||
else:
|
else:
|
||||||
return '-'
|
return '-'
|
||||||
|
|
||||||
|
|
||||||
class INetAddressError(Exception):
|
class INetAddressError(Exception):
|
||||||
"""
|
"""
|
||||||
Error parsing / generating a internet address.
|
Error parsing / generating a internet address.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def inet_address(address, default_port, default_address='localhost'):
|
def inet_address(address, default_port, default_address='localhost'):
|
||||||
"""
|
"""
|
||||||
Parse internet address.
|
Parse internet address.
|
||||||
|
@ -81,19 +72,18 @@ def inet_address(address, default_port, default_address='localhost'):
|
||||||
try:
|
try:
|
||||||
port = int(addr[1])
|
port = int(addr[1])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise INetAddressError('Invalid address "{0}".'.format(address))
|
raise INetAddressError('Invalid address "%s".' % address)
|
||||||
if len(addr[0]) == 0:
|
if len(addr[0]) == 0:
|
||||||
addr = default_address
|
addr = default_address
|
||||||
else:
|
else:
|
||||||
addr = addr[0]
|
addr = addr[0]
|
||||||
else:
|
else:
|
||||||
raise INetAddressError('Invalid address "{0}".'.format(address))
|
raise INetAddressError('Invalid address "%s".' % address)
|
||||||
try:
|
try:
|
||||||
socket.getaddrinfo(addr, port, socket.AF_INET, socket.SOCK_STREAM)
|
socket.getaddrinfo(addr, port, socket.AF_INET, socket.SOCK_STREAM)
|
||||||
except socket.gaierror:
|
except socket.gaierror:
|
||||||
raise INetAddressError('Cannot look up address "{0}".'.format(address))
|
raise INetAddressError('Cannot look up address "%s".' % address)
|
||||||
return addr, port
|
return (addr, port)
|
||||||
|
|
||||||
|
|
||||||
def rpc_bool(arg):
|
def rpc_bool(arg):
|
||||||
"""
|
"""
|
||||||
|
@ -106,31 +96,27 @@ def rpc_bool(arg):
|
||||||
arg = arg.lower() in ['true', 'yes']
|
arg = arg.lower() in ['true', 'yes']
|
||||||
return 1 if bool(arg) else 0
|
return 1 if bool(arg) else 0
|
||||||
|
|
||||||
|
|
||||||
TR_TYPE_MAP = {
|
TR_TYPE_MAP = {
|
||||||
'number': int,
|
'number' : int,
|
||||||
'string': str,
|
'string' : str,
|
||||||
'double': float,
|
'double': float,
|
||||||
'boolean': rpc_bool,
|
'boolean' : rpc_bool,
|
||||||
'array': list,
|
'array': list,
|
||||||
'object': dict
|
'object': dict
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def make_python_name(name):
|
def make_python_name(name):
|
||||||
"""
|
"""
|
||||||
Convert Transmission RPC name to python compatible name.
|
Convert Transmission RPC name to python compatible name.
|
||||||
"""
|
"""
|
||||||
return name.replace('-', '_')
|
return name.replace('-', '_')
|
||||||
|
|
||||||
|
|
||||||
def make_rpc_name(name):
|
def make_rpc_name(name):
|
||||||
"""
|
"""
|
||||||
Convert python compatible name to Transmission RPC name.
|
Convert python compatible name to Transmission RPC name.
|
||||||
"""
|
"""
|
||||||
return name.replace('_', '-')
|
return name.replace('_', '-')
|
||||||
|
|
||||||
|
|
||||||
def argument_value_convert(method, argument, value, rpc_version):
|
def argument_value_convert(method, argument, value, rpc_version):
|
||||||
"""
|
"""
|
||||||
Check and fix Transmission RPC issues with regards to methods, arguments and values.
|
Check and fix Transmission RPC issues with regards to methods, arguments and values.
|
||||||
|
@ -140,7 +126,7 @@ def argument_value_convert(method, argument, value, rpc_version):
|
||||||
elif method in ('session-get', 'session-set'):
|
elif method in ('session-get', 'session-set'):
|
||||||
args = constants.SESSION_ARGS[method[-3:]]
|
args = constants.SESSION_ARGS[method[-3:]]
|
||||||
else:
|
else:
|
||||||
return ValueError('Method "{0}" not supported'.format(method))
|
return ValueError('Method "%s" not supported' % (method))
|
||||||
if argument in args:
|
if argument in args:
|
||||||
info = args[argument]
|
info = args[argument]
|
||||||
invalid_version = True
|
invalid_version = True
|
||||||
|
@ -156,18 +142,19 @@ def argument_value_convert(method, argument, value, rpc_version):
|
||||||
if invalid_version:
|
if invalid_version:
|
||||||
if replacement:
|
if replacement:
|
||||||
LOGGER.warning(
|
LOGGER.warning(
|
||||||
'Replacing requested argument "{0}" with "{1}".'.format(argument, replacement))
|
'Replacing requested argument "%s" with "%s".'
|
||||||
|
% (argument, replacement))
|
||||||
argument = replacement
|
argument = replacement
|
||||||
info = args[argument]
|
info = args[argument]
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
'Method "{0}" Argument "{1}" does not exist in version {2:d}.'.format(method, argument, rpc_version))
|
'Method "%s" Argument "%s" does not exist in version %d.'
|
||||||
return argument, TR_TYPE_MAP[info[0]](value)
|
% (method, argument, rpc_version))
|
||||||
|
return (argument, TR_TYPE_MAP[info[0]](value))
|
||||||
else:
|
else:
|
||||||
raise ValueError('Argument "%s" does not exists for method "%s".',
|
raise ValueError('Argument "%s" does not exists for method "%s".',
|
||||||
(argument, method))
|
(argument, method))
|
||||||
|
|
||||||
|
|
||||||
def get_arguments(method, rpc_version):
|
def get_arguments(method, rpc_version):
|
||||||
"""
|
"""
|
||||||
Get arguments for method in specified Transmission RPC version.
|
Get arguments for method in specified Transmission RPC version.
|
||||||
|
@ -177,7 +164,7 @@ def get_arguments(method, rpc_version):
|
||||||
elif method in ('session-get', 'session-set'):
|
elif method in ('session-get', 'session-set'):
|
||||||
args = constants.SESSION_ARGS[method[-3:]]
|
args = constants.SESSION_ARGS[method[-3:]]
|
||||||
else:
|
else:
|
||||||
return ValueError('Method "{0}" not supported'.format(method))
|
return ValueError('Method "%s" not supported' % (method))
|
||||||
accessible = []
|
accessible = []
|
||||||
for argument, info in iteritems(args):
|
for argument, info in iteritems(args):
|
||||||
valid_version = True
|
valid_version = True
|
||||||
|
@ -189,7 +176,6 @@ def get_arguments(method, rpc_version):
|
||||||
accessible.append(argument)
|
accessible.append(argument)
|
||||||
return accessible
|
return accessible
|
||||||
|
|
||||||
|
|
||||||
def add_stdout_logger(level='debug'):
|
def add_stdout_logger(level='debug'):
|
||||||
"""
|
"""
|
||||||
Add a stdout target for the transmissionrpc logging.
|
Add a stdout target for the transmissionrpc logging.
|
||||||
|
@ -204,7 +190,6 @@ def add_stdout_logger(level='debug'):
|
||||||
loghandler.setLevel(loglevel)
|
loghandler.setLevel(loglevel)
|
||||||
trpc_logger.addHandler(loghandler)
|
trpc_logger.addHandler(loghandler)
|
||||||
|
|
||||||
|
|
||||||
def add_file_logger(filepath, level='debug'):
|
def add_file_logger(filepath, level='debug'):
|
||||||
"""
|
"""
|
||||||
Add a stdout target for the transmissionrpc logging.
|
Add a stdout target for the transmissionrpc logging.
|
||||||
|
@ -219,5 +204,4 @@ def add_file_logger(filepath, level='debug'):
|
||||||
loghandler.setLevel(loglevel)
|
loghandler.setLevel(loglevel)
|
||||||
trpc_logger.addHandler(loghandler)
|
trpc_logger.addHandler(loghandler)
|
||||||
|
|
||||||
|
|
||||||
Field = namedtuple('Field', ['value', 'dirty'])
|
Field = namedtuple('Field', ['value', 'dirty'])
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue