Browse Source

Merge pull request #2878 from fuzeman/feature/rtorrent/httprpc

[rtorrent] HTTP-RPC support
pull/2897/head
Ruud Burger 11 years ago
parent
commit
4d8338e829
  1. 6
      couchpotato/core/downloaders/rtorrent/__init__.py
  2. 12
      couchpotato/core/downloaders/rtorrent/main.py
  3. 27
      libs/rtorrent/__init__.py
  4. 67
      libs/rtorrent/common.py

6
couchpotato/core/downloaders/rtorrent/__init__.py

@ -31,8 +31,8 @@ config = [{
{
'name': 'host',
'default': 'localhost:80',
'description': 'Hostname with port or XML-RPC Endpoint URI. Usually <strong>scgi://localhost:5000</strong> '
'or <strong>localhost:80</strong>'
'description': 'RPC Communication URI. Usually <strong>scgi://localhost:5000</strong>, '
'<strong>httprpc://localhost/rutorrent</strong> or <strong>localhost:80</strong>'
},
{
'name': 'ssl',
@ -46,7 +46,7 @@ config = [{
'type': 'string',
'default': 'RPC2',
'advanced': True,
'description': 'Change if you don\'t run rTorrent RPC at the default url.',
'description': 'Change if your RPC mount is at a different path.',
},
{
'name': 'username',

12
couchpotato/core/downloaders/rtorrent/main.py

@ -1,14 +1,15 @@
from base64 import b16encode, b32decode
from bencode import bencode, bdecode
from couchpotato.core.downloaders.base import Downloader, ReleaseDownloadList
from couchpotato.core.event import fireEvent, addEvent
from couchpotato.core.helpers.encoding import sp
from couchpotato.core.helpers.variable import cleanHost, splitString
from couchpotato.core.logger import CPLog
from base64 import b16encode, b32decode
from bencode import bencode, bdecode
from datetime import timedelta
from hashlib import sha1
from rtorrent import RTorrent
from rtorrent.err import MethodError
from urlparse import urlparse
import os
log = CPLog(__name__)
@ -51,7 +52,12 @@ class rTorrent(Downloader):
if self.rt is not None:
return self.rt
url = cleanHost(self.conf('host'), protocol = True, ssl = self.conf('ssl')) + self.conf('rpc_url')
url = cleanHost(self.conf('host'), protocol = True, ssl = self.conf('ssl'))
parsed = urlparse(url)
# rpc_url is only used on http/https scgi pass-through
if parsed.scheme in ['http', 'https']:
url += self.conf('rpc_url')
if self.conf('username') and self.conf('password'):
self.rt = RTorrent(

27
libs/rtorrent/__init__.py

@ -22,8 +22,8 @@ import os.path
import time
import xmlrpclib
from rtorrent.common import find_torrent, \
is_valid_port, convert_version_tuple_to_str
from rtorrent.common import find_torrent, join_uri, \
update_uri, is_valid_port, convert_version_tuple_to_str
from rtorrent.lib.torrentparser import TorrentParser
from rtorrent.lib.xmlrpc.http import HTTPServerProxy
from rtorrent.lib.xmlrpc.scgi import SCGIServerProxy
@ -48,18 +48,18 @@ class RTorrent:
def __init__(self, uri, username=None, password=None,
verify=False, sp=None, sp_kwargs=None):
self.uri = uri # : From X{__init__(self, url)}
self.uri = self._transform_uri(uri) # : From X{__init__(self, url)}
self.username = username
self.password = password
self.schema = urllib.splittype(uri)[0]
self.scheme = urllib.splittype(self.uri)[0]
if sp:
self.sp = sp
elif self.schema in ['http', 'https']:
elif self.scheme in ['http', 'https']:
self.sp = HTTPServerProxy
elif self.schema == 'scgi':
elif self.scheme == 'scgi':
self.sp = SCGIServerProxy
else:
raise NotImplementedError()
@ -74,10 +74,23 @@ class RTorrent:
if verify is True:
self._verify_conn()
def _transform_uri(self, 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 _get_conn(self):
"""Get ServerProxy instance"""
if self.username is not None and self.password is not None:
if self.schema == 'scgi':
if self.scheme == 'scgi':
raise NotImplementedError()
return self.sp(

67
libs/rtorrent/common.py

@ -17,7 +17,8 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import urlparse
import os
from rtorrent.compat import is_py3
@ -84,3 +85,67 @@ def safe_repr(fmt, *args, **kwargs):
return out.encode("utf-8")
else:
return fmt.format(*args, **kwargs)
def split_path(path):
fragments = path.split('/')
if len(fragments) == 1:
return fragments
if not fragments[-1]:
return fragments[:-1]
return fragments
def join_path(base, path):
# Return if we have a new absolute path
if os.path.isabs(path):
return path
# non-absolute base encountered
if base and not os.path.isabs(base):
raise NotImplementedError()
return '/'.join(split_path(base) + split_path(path))
def join_uri(base, uri, construct=True):
p_uri = urlparse.urlparse(uri)
# Return if there is nothing to join
if not p_uri.path:
return base
scheme, netloc, path, params, query, fragment = urlparse.urlparse(base)
# Switch to 'uri' parts
_, _, _, params, query, fragment = p_uri
path = join_path(path, p_uri.path)
result = urlparse.ParseResult(scheme, netloc, path, params, query, fragment)
if not construct:
return result
# Construct from parts
return urlparse.urlunparse(result)
def update_uri(uri, construct=True, **kwargs):
if isinstance(uri, urlparse.ParseResult):
uri = dict(uri._asdict())
if type(uri) is not dict:
raise ValueError("Unknown URI type")
uri.update(kwargs)
result = urlparse.ParseResult(**uri)
if not construct:
return result
return urlparse.urlunparse(result)

Loading…
Cancel
Save