mylar/lib/rtorrent/connection.py

166 lines
5.1 KiB
Python
Raw Permalink Normal View History

FIX:(#1466) When post-processing if filename did not have issue year or volume, would error, IMP:(#1418) Separate copy/move/hardlink/symlink option for Story arcs, IMP:(#1417) Added story arc format folder to story arc options - can now specify folder format for story arc naming, IMP:(#1374) Added rtorrent_authentication to config.ini allowing user to specify digest/basic authentication, as well as the rpc_url (rtorrent_rpc_url) and ssl (rtorrent_ssl). Rtorrent_host no longer requires protocol in field, IMP: Instead of hitting the intermediary/32P site to get the torrent group, will now retain specific id for torrent group to speed up searches, FIX: (#1472) Fixed some problems with series being searched against 32P which had special characters and would return no results, FIX: Added some specific exception catches when attempting to retrieve search results for nzb providers, FIX: Fixed publisher retaining problem for story arcs (note story arcs will have to be refreshed), FIX: Fixed a problem with the pull-list matching up to the correct series when the issue was an annual for a given series with the alt_pull 2 method (would create an invalid link on the Wanted tab), IMP:(#1470) Added config.ini option to specify folder-formatting for weekly folder numbering, 0=YYYY-WN, 1=YYYY-MM-DD, IMP: (#1471) Added quick check to ensure that newznab host entries do not contain leading/trailing spaces and will strip accordingly, FIX:(#1476) Annuals now have option to add to reading list via the series detail page, IMP: Fixed password fields to allow for special characters within password, IMP: Weekly pull will now correctly show status for previous/future weeks for watchlisted series, IMP: Download option on pullist will work for previous weeks, FIX: Fixed some issues with one-off and story arc post-processing using different file operations, FIX: Fixed error when performing an 'Force Update Active Comics' from the Manage tab (or the scheduled updating of all active comics), IMP: Storyarc issues that are not on watchlist will now retain value for volume to help when searching and file-checking/post-processing, FIX:(#1473) Changed pullist dates on pullist page to unicode to allow for non-English presentation
2016-12-02 17:45:49 +00:00
import logging
import urllib
from rtorrent.common import convert_version_tuple_to_str, join_uri, update_uri
from rtorrent.lib.xmlrpc.clients.http import HTTPServerProxy
from rtorrent.lib.xmlrpc.clients.scgi import SCGIServerProxy
from rtorrent.lib.xmlrpc.transports.basic_auth import BasicAuthTransport
try:
from requests.packages.urllib3 import disable_warnings
disable_warnings()
except ImportError:
print 'Unable to disable warnings for non-https authentication.'
# Try import requests transport (optional)
try:
from rtorrent.lib.xmlrpc.transports.requests_ import RequestsTransport
except ImportError:
RequestsTransport = None
MIN_RTORRENT_VERSION = (0, 8, 1)
MIN_RTORRENT_VERSION_STR = convert_version_tuple_to_str(MIN_RTORRENT_VERSION)
log = logging.getLogger(__name__)
class Connection(object):
def __init__(self, uri, auth=None, verify_ssl=True, sp=None, sp_kwargs=None):
self.auth = auth
self.verify_ssl = verify_ssl
# Transform + Parse URI
self.uri = self._transform_uri(uri)
self.scheme = urllib.splittype(self.uri)[0]
# Construct RPC Client
self.sp = self._get_sp(self.scheme, sp)
self.sp_kwargs = sp_kwargs or {}
self._client = None
self._client_version_tuple = ()
self._rpc_methods = []
@property
def client(self):
if self._client is None:
# Construct new client
self._client = self.connect()
# Return client
return self._client
def connect(self):
log.debug('Connecting to server: %r', self.uri)
if self.auth:
# Construct server proxy with authentication transport
return self.sp(self.uri, transport=self._construct_transport(), **self.sp_kwargs)
# Construct plain server proxy
return self.sp(self.uri, **self.sp_kwargs)
def test(self):
try:
self.verify()
except:
return False
return True
def verify(self):
# check for rpc methods that should be available
assert "system.client_version" in self._get_rpc_methods(), "Required RPC method not available."
assert "system.library_version" in self._get_rpc_methods(), "Required RPC method not available."
# minimum rTorrent version check
assert self._meets_version_requirement() is True,\
"Error: Minimum rTorrent version required is {0}".format(MIN_RTORRENT_VERSION_STR)
#
# Private methods
#
def _construct_transport(self):
# Ensure "auth" parameter is valid
if type(self.auth) is not tuple or len(self.auth) != 3:
raise ValueError('Invalid "auth" parameter format')
# Construct transport with authentication details
method, _, _ = self.auth
secure = self.scheme == 'https'
log.debug('Constructing transport for scheme: %r, authentication method: %r', self.scheme, method)
# Use requests transport (if available)
if RequestsTransport and method in ['basic', 'digest']:
return RequestsTransport(
secure, self.auth,
verify_ssl=self.verify_ssl
)
# Use basic authentication transport
if method == 'basic':
return BasicAuthTransport(secure, self.auth)
# Unsupported authentication method
if method == 'digest':
raise Exception('Digest authentication requires the "requests" library')
raise NotImplementedError('Unknown authentication method: %r' % method)
def _get_client_version_tuple(self):
if not self._client_version_tuple:
if not hasattr(self, "client_version"):
setattr(self, "client_version", self.client.system.client_version())
rtver = getattr(self, "client_version")
self._client_version_tuple = tuple([int(i) for i in rtver.split(".")])
return self._client_version_tuple
def _get_rpc_methods(self):
""" Get list of raw RPC commands
@return: raw RPC commands
@rtype: list
"""
return(self._rpc_methods or self._update_rpc_methods())
@staticmethod
def _get_sp(scheme, sp):
if sp:
return sp
if scheme in ['http', 'https']:
return HTTPServerProxy
if scheme == 'scgi':
return SCGIServerProxy
raise NotImplementedError()
def _meets_version_requirement(self):
return self._get_client_version_tuple() >= MIN_RTORRENT_VERSION
@staticmethod
def _transform_uri(uri):
scheme = urllib.splittype(uri)[0]
if scheme == 'httprpc' or scheme.startswith('httprpc+'):
# Try find HTTPRPC transport (token after '+' in 'httprpc+https'), otherwise assume HTTP
transport = scheme[scheme.index('+') + 1:] if '+' in scheme else 'http'
# Transform URI with new path and scheme
uri = join_uri(uri, 'plugins/httprpc/action.php', construct=False)
return update_uri(uri, scheme=transport)
return uri
def _update_rpc_methods(self):
self._rpc_methods = self.client.system.listMethods()
return self._rpc_methods