mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-03 18:03:37 +00:00
Merge pull request #834 from JackDandy/feature/ChangeRt
Change update rTorrent systems.
This commit is contained in:
commit
2c6016234f
11 changed files with 162 additions and 122 deletions
|
@ -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
|
||||
|
|
|
@ -17,9 +17,15 @@
|
|||
# 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
|
||||
try:
|
||||
import xmlrpc.client as xmlrpclib
|
||||
except ImportError:
|
||||
import xmlrpclib
|
||||
|
||||
from rtorrent.common import find_torrent, \
|
||||
|
@ -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
|
||||
|
||||
if t:
|
||||
# Resolve magnet to torrent
|
||||
torrent.start()
|
||||
t.start()
|
||||
|
||||
assert info_hash in [t.info_hash for t in self.torrents],\
|
||||
"Adding torrent was unsuccessful."
|
||||
|
||||
MAX_RETRIES = 3
|
||||
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) :
|
||||
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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
|
||||
from base64 import encodestring
|
||||
import string
|
||||
try:
|
||||
import xmlrpc.client as xmlrpclib
|
||||
except:
|
||||
import xmlrpclib
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
try:
|
||||
import http.client as httplib
|
||||
except ImportError:
|
||||
import httplib
|
||||
import re
|
||||
import socket
|
||||
import urllib
|
||||
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,6 +138,9 @@ class SCGITransport(xmlrpclib.Transport):
|
|||
|
||||
self.verbose = verbose
|
||||
|
||||
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:
|
||||
|
@ -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 = '/'
|
||||
|
||||
|
|
|
@ -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)
|
||||
##########################################################################
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
||||
if not self.auth:
|
||||
return False
|
||||
|
||||
if not result:
|
||||
return False
|
||||
def _add_torrent(self, cmd, **kwargs):
|
||||
torrent = None
|
||||
|
||||
if self.auth:
|
||||
try:
|
||||
# Send magnet to rTorrent
|
||||
torrent = self.auth.load_magnet(result.url, result.hash)
|
||||
if 'file' == cmd:
|
||||
torrent = self.auth.load_torrent(kwargs['file'])
|
||||
elif 'magnet' == cmd:
|
||||
torrent = self.auth.load_magnet(kwargs['url'], kwargs['btih'])
|
||||
|
||||
if not torrent:
|
||||
return False
|
||||
if torrent:
|
||||
|
||||
# Set label
|
||||
if sickbeard.TORRENT_LABEL:
|
||||
torrent.set_custom(1, sickbeard.TORRENT_LABEL)
|
||||
if TORRENT_LABEL:
|
||||
torrent.set_custom(1, TORRENT_LABEL)
|
||||
|
||||
if sickbeard.TORRENT_PATH:
|
||||
torrent.set_directory(sickbeard.TORRENT_PATH)
|
||||
if TORRENT_PATH:
|
||||
torrent.set_directory(TORRENT_PATH)
|
||||
|
||||
# Start torrent
|
||||
torrent.start()
|
||||
|
||||
return True
|
||||
except (StandardError, Exception) as e:
|
||||
pass
|
||||
|
||||
except:
|
||||
return False
|
||||
return any([torrent])
|
||||
|
||||
def _add_torrent_file(self, result):
|
||||
|
||||
if not self.auth:
|
||||
if result:
|
||||
return self._add_torrent('file', file=result.content)
|
||||
return False
|
||||
|
||||
if not result:
|
||||
def _add_torrent_uri(self, result):
|
||||
|
||||
if result:
|
||||
return self._add_torrent('magnet', uri=result.url, btih=result.hash)
|
||||
return False
|
||||
|
||||
# group_name = 'sb_test' ##### Use provider instead of _test
|
||||
# if not self._set_torrent_ratio(group_name):
|
||||
# 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:
|
||||
if None is self.auth:
|
||||
return False, 'Error: Unable to get %s authentication, check your config!' % self.name
|
||||
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
|
||||
|
||||
except (StandardError, Exception):
|
||||
return False, 'Error: Unable to connect to %s' % self.name
|
||||
|
||||
|
||||
api = rTorrentAPI()
|
||||
api = RtorrentAPI()
|
||||
|
|
|
@ -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'))
|
||||
|
||||
|
|
Loading…
Reference in a new issue