Merge pull request #834 from JackDandy/feature/ChangeRt

Change update rTorrent systems.
This commit is contained in:
JackDandy 2016-12-07 16:49:11 +00:00 committed by GitHub
commit 2c6016234f
11 changed files with 162 additions and 122 deletions

View file

@ -199,6 +199,7 @@
* Change refresh page when torrent providers are enabled/disabled
* Change only display Search Settings/"Usenet retention" if Search NZBs is enabled
* Change sab API request to prevent naming mismatch
* Change update rTorrent systems
[develop changelog]
* Change send nzb data to NZBGet for Anizb instead of url

View file

@ -17,10 +17,16 @@
# 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 urllib
try:
import urllib.parse as urlparser
except ImportError:
import urllib as urlparser
import os.path
import time
import xmlrpclib
try:
import xmlrpc.client as xmlrpclib
except ImportError:
import xmlrpclib
from rtorrent.common import find_torrent, \
is_valid_port, convert_version_tuple_to_str
@ -53,7 +59,7 @@ class RTorrent:
self.username = username
self.password = password
self.schema = urllib.splittype(uri)[0]
self.schema = urlparser.splittype(uri)[0]
if sp:
self.sp = sp
@ -210,34 +216,36 @@ class RTorrent:
# load magnet
getattr(p, func_name)(magneturl)
t = None
if verify_load:
MAX_RETRIES = 3
max_retries = 3
i = 0
while i < MAX_RETRIES:
for torrent in self.get_torrents():
if torrent.info_hash != info_hash:
while i < max_retries:
for t in self.get_torrents():
if t.info_hash != info_hash:
continue
time.sleep(1)
i += 1
# Resolve magnet to torrent
torrent.start()
if t:
# Resolve magnet to torrent
t.start()
assert info_hash in [t.info_hash for t in self.torrents],\
"Adding torrent was unsuccessful."
assert info_hash in [t.info_hash for t in self.torrents],\
"Adding torrent was unsuccessful."
MAX_RETRIES = 3
i = 0
while i < MAX_RETRIES:
for torrent in self.get_torrents():
if torrent.info_hash == info_hash:
if str(info_hash) not in str(torrent.name) :
time.sleep(1)
i += 1
max_retries = 3
i = 0
while i < max_retries:
for t in self.get_torrents():
if t.info_hash == info_hash:
if str(info_hash) not in str(t.name) :
time.sleep(1)
i += 1
return(torrent)
return t
def load_torrent(self, torrent, start=False, verbose=False, verify_load=True):
def load_torrent(self, torrent, start=False, verbose=False, verify_load=True, verify_retries=3):
"""
Loads torrent into rTorrent (with various enhancements)
@ -282,9 +290,8 @@ class RTorrent:
getattr(p, func_name)(torrent)
if verify_load:
MAX_RETRIES = 3
i = 0
while i < MAX_RETRIES:
while i < verify_retries:
self.get_torrents()
if info_hash in [t.info_hash for t in self.torrents]:
break

View file

@ -267,7 +267,7 @@ def _encode_dict(data):
def encode(data):
if isinstance(data, bool):
return False
elif isinstance(data, int):
elif isinstance(data, (int, long)):
return _encode_int(data)
elif isinstance(data, bytes):
return _encode_string(data)

View file

@ -77,7 +77,7 @@ class TorrentParser():
self.file_type = "file"
self._raw_torrent = open(self.torrent, "rb").read()
# url?
elif re.search("^(http|ftp):\/\/", self.torrent, re.I):
elif re.search("^(http|ftp)s?:\/\/", self.torrent, re.I):
self.file_type = "url"
self._raw_torrent = urlopen(self.torrent).read()
@ -90,10 +90,10 @@ class TorrentParser():
def _calc_info_hash(self):
self.info_hash = None
if "info" in self._torrent_decoded.keys():
info_encoded = bencode.encode(self._torrent_decoded["info"])
info_encoded = bencode.encode(self._torrent_decoded["info"])
if info_encoded:
self.info_hash = hashlib.sha1(info_encoded).hexdigest().upper()
if info_encoded:
self.info_hash = hashlib.sha1(info_encoded).hexdigest().upper()
return(self.info_hash)

View file

@ -22,7 +22,10 @@
from base64 import encodestring
import string
import xmlrpclib
try:
import xmlrpc.client as xmlrpclib
except:
import xmlrpclib
class BasicAuthTransport(xmlrpclib.Transport):

View file

@ -80,12 +80,25 @@
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
# OF THIS SOFTWARE.
from __future__ import print_function
import httplib
try:
import http.client as httplib
except ImportError:
import httplib
import re
import socket
import urllib
import xmlrpclib
import sys
try:
import urllib.parse as urlparser
except ImportError:
import urllib as urlparser
try:
import xmlrpc.client as xmlrpclib
except:
import xmlrpclib
import errno
@ -96,7 +109,7 @@ class SCGITransport(xmlrpclib.Transport):
for i in (0, 1):
try:
return self.single_request(host, handler, request_body, verbose)
except socket.error, e:
except socket.error as e:
if i or e.errno not in (errno.ECONNRESET, errno.ECONNABORTED, errno.EPIPE):
raise
except httplib.BadStatusLine: #close after we sent request
@ -105,8 +118,8 @@ class SCGITransport(xmlrpclib.Transport):
def single_request(self, host, handler, request_body, verbose=0):
# Add SCGI headers to the request.
headers = {'CONTENT_LENGTH': str(len(request_body)), 'SCGI': '1'}
header = '\x00'.join(('%s\x00%s' % item for item in headers.iteritems())) + '\x00'
headers = [('CONTENT_LENGTH', str(len(request_body))), ('SCGI', '1')]
header = '\x00'.join(['%s\x00%s' % (key, value) for key, value in headers]) + '\x00'
header = '%d:%s' % (len(header), header)
request_body = '%s,%s' % (header, request_body)
@ -114,7 +127,7 @@ class SCGITransport(xmlrpclib.Transport):
try:
if host:
host, port = urllib.splitport(host)
host, port = urlparser.splitport(host)
addrinfo = socket.getaddrinfo(host, int(port), socket.AF_INET,
socket.SOCK_STREAM)
sock = socket.socket(*addrinfo[0][:3])
@ -125,7 +138,10 @@ class SCGITransport(xmlrpclib.Transport):
self.verbose = verbose
sock.send(request_body)
if sys.version_info[0] > 2:
sock.send(bytes(request_body, "utf-8"))
else:
sock.send(request_body)
return self.parse_response(sock.makefile())
finally:
if sock:
@ -142,11 +158,17 @@ class SCGITransport(xmlrpclib.Transport):
response_body += data
# Remove SCGI headers from the response.
response_header, response_body = re.split(r'\n\s*?\n', response_body,
maxsplit=1)
if self.verbose:
print 'body:', repr(response_body)
print('body:', repr(response_body))
try:
response_header, response_body = re.split(r'\n\s*?\n', response_body,
maxsplit=1)
except ValueError:
print("error in response: %s", response_body)
p.close()
u.close()
p.feed(response_body)
p.close()
@ -157,10 +179,10 @@ class SCGITransport(xmlrpclib.Transport):
class SCGIServerProxy(xmlrpclib.ServerProxy):
def __init__(self, uri, transport=None, encoding=None, verbose=False,
allow_none=False, use_datetime=False):
type, uri = urllib.splittype(uri)
type, uri = urlparser.splittype(uri)
if type not in ('scgi'):
raise IOError('unsupported XML-RPC protocol')
self.__host, self.__handler = urllib.splithost(uri)
self.__host, self.__handler = urlparser.splithost(uri)
if not self.__handler:
self.__handler = '/'

View file

@ -338,6 +338,24 @@ class Torrent:
else:
return p.view.set_not_visible(self.info_hash, view)
def add_tracker(self, group, tracker):
"""
Add tracker to torrent
@param group: The group to add the tracker to
@type group: int
@param tracker: The tracker url
@type tracker: str
@return: if successful, 0
@rtype: int
"""
m = rtorrent.rpc.Multicall(self)
self.multicall_add(m, "d.tracker.insert", group, tracker)
return (m.call()[-1])
############################################################################
# CUSTOM METHODS (Not part of the official rTorrent API)
##########################################################################

View file

@ -67,6 +67,21 @@ class Tracker:
multicall.call()
def append_tracker(self, tracker):
"""
Append tracker to current tracker group
@param tracker: The tracker url
@type tracker: str
@return: if successful, 0
@rtype: int
"""
m = rtorrent.rpc.Multicall(self)
self.multicall_add(m, "d.tracker.insert", self.index, tracker)
return (m.call()[-1])
methods = [
# RETRIEVERS
Method(Tracker, 'is_enabled', 't.is_enabled', boolean=True),

View file

@ -228,6 +228,6 @@ class GenericClient(object):
# FIXME: This test is redundant
if authenticated and self.auth:
return True, 'Success: Connected and Authenticated'
return False, 'Error: Unable to get %s Authentication, check your config!' % self.name
return False, 'Error: Unable to get %s authentication, check your config!' % self.name
except (StandardError, Exception):
return False, 'Error: Unable to connect to %s' % self.name

View file

@ -16,100 +16,74 @@
# You should have received a copy of the GNU General Public License
# along with SickGear. If not, see <http://www.gnu.org/licenses/>.
import sickbeard
import xmlrpclib
from sickbeard import helpers, TORRENT_LABEL, TORRENT_PATH
from sickbeard.clients.generic import GenericClient
from lib.rtorrent import RTorrent
class rTorrentAPI(GenericClient):
class RtorrentAPI(GenericClient):
def __init__(self, host=None, username=None, password=None):
super(rTorrentAPI, self).__init__('rTorrent', host, username, password)
if host and host.startswith('scgi:') and any([username, password]):
username = password = None
super(RtorrentAPI, self).__init__('rTorrent', host, username, password)
# self.url = self.host
def _get_auth(self):
self.auth = None
if self.auth is not None:
return self.auth
if not self.host:
return
if self.username and self.password:
self.auth = RTorrent(self.host, self.username, self.password)
else:
self.auth = RTorrent(self.host, None, None, True)
if self.host:
try:
if self.host and self.host.startswith('scgi:') and any([self.username, self.password]):
self.username = self.password = None
self.auth = RTorrent(self.host, self.username, self.password, True)
except (AssertionError, xmlrpclib.ProtocolError) as e:
pass
return self.auth
def _add_torrent_uri(self, result):
def _add_torrent(self, cmd, **kwargs):
torrent = None
if not self.auth:
return False
if self.auth:
try:
# Send magnet to rTorrent
if 'file' == cmd:
torrent = self.auth.load_torrent(kwargs['file'])
elif 'magnet' == cmd:
torrent = self.auth.load_magnet(kwargs['url'], kwargs['btih'])
if not result:
return False
if torrent:
try:
# Send magnet to rTorrent
torrent = self.auth.load_magnet(result.url, result.hash)
if TORRENT_LABEL:
torrent.set_custom(1, TORRENT_LABEL)
if not torrent:
return False
if TORRENT_PATH:
torrent.set_directory(TORRENT_PATH)
# Set label
if sickbeard.TORRENT_LABEL:
torrent.set_custom(1, sickbeard.TORRENT_LABEL)
torrent.start()
if sickbeard.TORRENT_PATH:
torrent.set_directory(sickbeard.TORRENT_PATH)
except (StandardError, Exception) as e:
pass
# Start torrent
torrent.start()
return True
except:
return False
return any([torrent])
def _add_torrent_file(self, result):
if not self.auth:
return False
if result:
return self._add_torrent('file', file=result.content)
return False
if not result:
return False
def _add_torrent_uri(self, result):
# group_name = 'sb_test' ##### Use provider instead of _test
# if not self._set_torrent_ratio(group_name):
# return False
if result:
return self._add_torrent('magnet', uri=result.url, btih=result.hash)
return False
# Send request to rTorrent
try:
# Send torrent to rTorrent
torrent = self.auth.load_torrent(result.content)
if not torrent:
return False
# Set label
if sickbeard.TORRENT_LABEL:
torrent.set_custom(1, sickbeard.TORRENT_LABEL)
if sickbeard.TORRENT_PATH:
torrent.set_directory(sickbeard.TORRENT_PATH)
# Set Ratio Group
# torrent.set_visible(group_name)
# Start torrent
torrent.start()
return True
except:
return False
def _set_torrent_ratio(self, name):
#def _set_torrent_ratio(self, name):
# if not name:
# return False
@ -143,18 +117,18 @@ class rTorrentAPI(GenericClient):
# except:
# return False
return True
# return True
def test_authentication(self):
try:
self._get_auth()
if self.auth is not None:
return True, 'Success: Connected and Authenticated'
else:
return False, 'Error: Unable to get ' + self.name + ' Authentication, check your config!'
except Exception:
return False, 'Error: Unable to connect to ' + self.name
if None is self.auth:
return False, 'Error: Unable to get %s authentication, check your config!' % self.name
return True, 'Success: Connected and Authenticated'
except (StandardError, Exception):
return False, 'Error: Unable to connect to %s' % self.name
api = rTorrentAPI()
api = RtorrentAPI()

View file

@ -55,7 +55,7 @@ class FreshOnTVProvider(generic.TorrentProvider):
post_params={'form_tmpl': True},
failed_msg=(lambda y=None: 'DDoS protection by CloudFlare' in y and
u'Unable to login to %s due to CloudFlare DDoS javascript check' or
'Username does not exist' in x and
'Username does not exist' in y and
u'Invalid username or password for %s. Check settings' or
u'Failed to authenticate or parse a response from %s, abort provider'))