Change improve management of Transmission config/Search/Torrent Search "Downloaded files location".

This commit is contained in:
JackDandy 2016-03-09 11:16:02 +00:00
parent 944064d92d
commit 3bc0823670
8 changed files with 129 additions and 135 deletions

View file

@ -39,6 +39,7 @@
* Fix alternative unicode show names from breaking search
* Change show update, set shows with newly added airdate or existing episodes with future or never dates, to "Wanted"
* Fix rare NameParser case where numeric episode name was parsed as episode number
* Change improve management of Transmission config/Search/Torrent Search "Downloaded files location"
### 0.11.7 (2016-03-06 12:30:00 UTC)

View file

@ -489,8 +489,9 @@
<span class="component-title" id="directory_title">Downloaded files location</span>
<span class="component-desc">
<input type="text" name="torrent_path" id="torrent_path" value="$sickbeard.TORRENT_PATH" class="form-control input-sm input350">
<p class="clear-left note">where <span id="torrent_client">the torrent client</span> will save downloaded files (blank for client default)
<span id="path_synology"> <b>note:</b> the destination has to be a shared folder for Synology DS</span></p>
<p class="clear-left note">where <span id="torrent_client">the torrent client</span> will save downloaded files <span id="path_blank">(blank for client default)</span>
<span id="path_synology"> <b>note:</b> the destination has to be a shared folder for Synology DS</span>
<span id="path_transmission" class="red-text"> (v2.92 and newer <em>cannot</em> be blank)</span></p>
</span>
</label>
</div>

View file

@ -57,6 +57,8 @@ $(document).ready(function(){
torrent_seed_time_option = '#torrent_seed_time_option',
torrent_high_bandwidth_option = '#torrent_high_bandwidth_option',
torrent_label_option = '#torrent_label_option',
path_blank = '#path_blank',
path_transmission = '#path_transmission',
path_synology = '#path_synology',
torrent_paused_option = '#torrent_paused_option';
@ -71,6 +73,8 @@ $(document).ready(function(){
$(torrent_seed_time_option).hide();
$(torrent_high_bandwidth_option).hide();
$(torrent_label_option).show();
$(path_blank).show();
$(path_transmission).hide();
$(path_synology).hide();
$(torrent_paused_option).show();
@ -83,6 +87,8 @@ $(document).ready(function(){
$(torrent_high_bandwidth_option).show();
$(torrent_label_option).hide();
//$('#directory_title').text(client + directory);
$(path_blank).hide();
$(path_transmission).show();
} else if ('deluge' == selectedProvider){
client = 'Deluge';
$(torrent_verify_cert_option).show();

View file

@ -25,130 +25,134 @@ class GenericClient(object):
self.session = requests.session()
self.session.auth = (self.username, self.password)
def _request(self, method='get', params={}, data=None, files=None):
response = None
def _request(self, method='get', params=None, data=None, files=None, **kwargs):
params = params or {}
if time.time() > self.last_time + 1800 or not self.auth:
self.last_time = time.time()
self._get_auth()
logger.log(
self.name + u': Requested a ' + method.upper() +
' connection to url ' + self.url + ' with Params= ' + str(params) +
' Data=' + str(data if data else 'None')[0:99] +
('...' if len(data if data else 'None') > 200 else ''),
'%s: Requested a %s connection to url %s with Params= %s' % (self.name, method.upper(), self.url, params) +
' Data= ' + ('None' if not data else '%s%s' % (data[0:99], ('', '...')[200 < len(data)])) +
' Json= ' + ('None' if not kwargs.get('json') else '%s%s' %
(str(kwargs.get('json'))[0:99],
('', '...')[200 < len(str(kwargs.get('json')))])),
logger.DEBUG
)
logger.log(
self.name + u': Requested a ' + method.upper() +
' connection to url ' + self.url + ' with Params= ' + str(params) +
((' Data=' + str(data)[0:100] + ('...' if len(data) > 100 else ''))
if data is not None else ''),
'%s: Requested a %s connection to url %s with Params= %s' % (self.name, method.upper(), self.url, params) +
('' if not data else ' Data= %s%s' % (data[0:100], ('', '...')[100 < len(data)])) +
('' if not kwargs.get('json') else ' Json= %s%s' % (str(kwargs.get('json'))[0:100],
('', '...')[100 < len(str(kwargs.get('json')))])),
logger.DEBUG
)
if not self.auth:
logger.log(self.name + u': Authentication Failed', logger.ERROR)
logger.log('%s: Authentication Failed' % self.name, logger.ERROR)
return False
try:
response = self.session.__getattribute__(method)(self.url, params=params, data=data, files=files,
timeout=120, verify=False)
timeout=120, verify=False, **kwargs)
except requests.exceptions.ConnectionError as e:
logger.log(self.name + u': Unable to connect ' + ex(e), logger.ERROR)
logger.log('%s: Unable to connect %s' % (self.name, ex(e)), logger.ERROR)
return False
except (requests.exceptions.MissingSchema, requests.exceptions.InvalidURL):
logger.log(self.name + u': Invalid Host', logger.ERROR)
logger.log('%s: Invalid Host' % self.name, logger.ERROR)
return False
except requests.exceptions.HTTPError as e:
logger.log(self.name + u': Invalid HTTP Request ' + ex(e), logger.ERROR)
logger.log('%s: Invalid HTTP Request %s' % (self.name, ex(e)), logger.ERROR)
return False
except requests.exceptions.Timeout as e:
logger.log(self.name + u': Connection Timeout ' + ex(e), logger.ERROR)
logger.log('%s: Connection Timeout %s' % (self.name, ex(e)), logger.ERROR)
return False
except Exception as e:
logger.log(self.name + u': Unknown exception raised when sending torrent to ' + self.name + ': ' + ex(e),
logger.log('%s: Unknown exception raised when sending torrent to %s: %s' % (self.name, self.name, ex(e)),
logger.ERROR)
return False
if response.status_code == 401:
logger.log(self.name + u': Invalid Username or Password, check your config', logger.ERROR)
if 401 == response.status_code:
logger.log('%s: Invalid Username or Password, check your config' % self.name, logger.ERROR)
return False
if response.status_code in http_error_code.keys():
logger.log(self.name + u': ' + http_error_code[response.status_code], logger.DEBUG)
logger.log('%s: %s' % (self.name, http_error_code[response.status_code]), logger.DEBUG)
return False
logger.log(self.name + u': Response to ' + method.upper() + ' request is ' + response.text, logger.DEBUG)
logger.log('%s: Response to %s request is %s' % (self.name, method.upper(), response.text), logger.DEBUG)
return response
def _get_auth(self):
'''
"""
This should be overridden and should return the auth_id needed for the client
'''
"""
return None
def _add_torrent_uri(self, result):
'''
"""
This should be overridden should return the True/False from the client
when a torrent is added via url (magnet or .torrent link)
'''
"""
return False
def _add_torrent_file(self, result):
'''
"""
This should be overridden should return the True/False from the client
when a torrent is added via result.content (only .torrent file)
'''
"""
return False
def _set_torrent_label(self, result):
'''
"""
This should be overridden should return the True/False from the client
when a torrent is set with label
'''
"""
return True
def _set_torrent_ratio(self, result):
'''
"""
This should be overridden should return the True/False from the client
when a torrent is set with ratio
'''
"""
return True
def _set_torrent_seed_time(self, result):
'''
"""
This should be overridden should return the True/False from the client
when a torrent is set with a seed time
'''
"""
return True
def _set_torrent_priority(self, result):
'''
"""
This should be overriden should return the True/False from the client
when a torrent is set with result.priority (-1 = low, 0 = normal, 1 = high)
'''
"""
return True
def _set_torrent_path(self, torrent_path):
'''
"""
This should be overridden should return the True/False from the client
when a torrent is set with path
'''
"""
return True
def _set_torrent_pause(self, result):
'''
"""
This should be overridden should return the True/False from the client
when a torrent is set with pause
'''
"""
return True
def _get_torrent_hash(self, result):
@staticmethod
def _get_torrent_hash(result):
if result.url.startswith('magnet'):
result.hash = re.findall('urn:btih:([\w]{32,40})', result.url)[0]
if len(result.hash) == 32:
if 32 == len(result.hash):
result.hash = b16encode(b32decode(result.hash)).lower()
else:
info = bdecode(result.content)['info']
@ -156,14 +160,14 @@ class GenericClient(object):
return result
def sendTORRENT(self, result):
def send_torrent(self, result):
r_code = False
logger.log(u'Calling ' + self.name + ' Client', logger.DEBUG)
logger.log('Calling %s Client' % self.name, logger.DEBUG)
if not self._get_auth():
logger.log(self.name + u': Authentication Failed', logger.ERROR)
logger.log('%s: Authentication Failed' % self.name, logger.ERROR)
return r_code
try:
@ -178,52 +182,51 @@ class GenericClient(object):
r_code = self._add_torrent_file(result)
if not r_code:
logger.log(self.name + u': Unable to send Torrent: Return code undefined', logger.ERROR)
logger.log('%s: Unable to send Torrent: Return code undefined' % self.name, logger.ERROR)
return False
if not self._set_torrent_pause(result):
logger.log(self.name + u': Unable to set the pause for Torrent', logger.ERROR)
logger.log('%s: Unable to set the pause for Torrent' % self.name, logger.ERROR)
if not self._set_torrent_label(result):
logger.log(self.name + u': Unable to set the label for Torrent', logger.ERROR)
logger.log('%s: Unable to set the label for Torrent' % self.name, logger.ERROR)
if not self._set_torrent_ratio(result):
logger.log(self.name + u': Unable to set the ratio for Torrent', logger.ERROR)
logger.log('%s: Unable to set the ratio for Torrent' % self.name, logger.ERROR)
if not self._set_torrent_seed_time(result):
logger.log(self.name + u': Unable to set the seed time for Torrent', logger.ERROR)
logger.log('%s: Unable to set the seed time for Torrent' % self.name, logger.ERROR)
if not self._set_torrent_path(result):
logger.log(self.name + u': Unable to set the path for Torrent', logger.ERROR)
logger.log('%s: Unable to set the path for Torrent' % self.name, logger.ERROR)
if result.priority != 0 and not self._set_torrent_priority(result):
logger.log(self.name + u': Unable to set priority for Torrent', logger.ERROR)
if 0 != result.priority and not self._set_torrent_priority(result):
logger.log('%s: Unable to set priority for Torrent' % self.name, logger.ERROR)
except Exception as e:
logger.log(self.name + u': Failed Sending Torrent: ' + result.name + ' - ' + result.hash, logger.ERROR)
logger.log(self.name + u': Exception raised when sending torrent: ' + ex(e), logger.DEBUG)
logger.log('%s: Failed sending torrent: %s - %s' % (self.name, result.name, result.hash), logger.ERROR)
logger.log('%s: Exception raised when sending torrent: %s' % (self.name, ex(e)), logger.DEBUG)
return r_code
return r_code
def testAuthentication(self):
response = None
def test_authentication(self):
try:
response = self.session.get(self.url, timeout=120, verify=False)
if response.status_code == 401:
return False, 'Error: Invalid ' + self.name + ' Username or Password, check your config!'
if 401 == response.status_code:
return False, 'Error: Invalid %s Username or Password, check your config!' % self.name
except requests.exceptions.ConnectionError:
return False, 'Error: ' + self.name + ' Connection Error'
return False, 'Error: %s Connection Error' % self.name
except (requests.exceptions.MissingSchema, requests.exceptions.InvalidURL):
return False, 'Error: Invalid ' + self.name + ' host'
return False, 'Error: Invalid %s host' % self.name
try:
authenticated = self._get_auth()
# FIXME: This test is redundant
if authenticated and self.auth:
return True, 'Success: Connected and Authenticated'
else:
return False, 'Error: Unable to get ' + self.name + ' Authentication, check your config!'
return False, 'Error: Unable to get %s Authentication, check your config!' % self.name
except Exception:
return False, 'Error: Unable to connect to ' + self.name
return False, 'Error: Unable to connect to %s' % self.name

View file

@ -145,7 +145,7 @@ class rTorrentAPI(GenericClient):
return True
def testAuthentication(self):
def test_authentication(self):
try:
self._get_auth()

View file

@ -17,7 +17,6 @@
# along with SickGear. If not, see <http://www.gnu.org/licenses/>.
import re
import json
from base64 import b64encode
import sickbeard
@ -31,93 +30,82 @@ class TransmissionAPI(GenericClient):
super(TransmissionAPI, self).__init__('Transmission', host, username, password)
self.url = self.host + 'transmission/rpc'
self.blankable, self.download_dir = None, None
def _get_auth(self):
post_data = json.dumps({'method': 'session-get', })
try:
response = self.session.post(self.url, data=post_data.encode('utf-8'), timeout=120,
verify=sickbeard.TORRENT_VERIFY_CERT)
self.auth = re.search('X-Transmission-Session-Id:\s*(\w+)', response.text).group(1)
response = self.session.post(self.url, json={'method': 'session-get'},
timeout=120, verify=sickbeard.TORRENT_VERIFY_CERT)
self.auth = re.search(r'(?i)X-Transmission-Session-Id:\s*(\w+)', response.text).group(1)
except:
return None
self.session.headers.update({'x-transmission-session-id': self.auth})
#Validating Transmission authorization
post_data = json.dumps({'arguments': {},
'method': 'session-get',
})
self._request(method='post', data=post_data)
# Validating Transmission authorization
response = self._request(method='post', json={'method': 'session-get', 'arguments': {}})
try:
resp = response.json()
self.blankable = 14386 >= int(re.findall(r'.*[(](\d+)', resp.get('arguments', {}).get('version', '(0)'))[0])
self.download_dir = resp.get('arguments', {}).get('download-dir', '')
except:
pass
return self.auth
def _add_torrent_uri(self, result):
arguments = {'filename': result.url,
'paused': 1 if sickbeard.TORRENT_PAUSED else 0,
'download-dir': sickbeard.TORRENT_PATH
}
post_data = json.dumps({'arguments': arguments,
'method': 'torrent-add',
})
response = self._request(method='post', data=post_data)
return response.json()['result'] == 'success'
return self._add_torrent({'filename': result.url})
def _add_torrent_file(self, result):
arguments = {'metainfo': b64encode(result.content),
'paused': 1 if sickbeard.TORRENT_PAUSED else 0,
'download-dir': sickbeard.TORRENT_PATH
}
post_data = json.dumps({'arguments': arguments,
'method': 'torrent-add',
})
response = self._request(method='post', data=post_data)
return self._add_torrent({'metainfo': b64encode(result.content)})
return response.json()['result'] == 'success'
def _add_torrent(self, t_object):
download_dir = None
if sickbeard.TORRENT_PATH or self.blankable:
download_dir = sickbeard.TORRENT_PATH
elif self.download_dir:
download_dir = self.download_dir
else:
logger.log('Path required for Transmission Downloaded files location', logger.ERROR)
if not download_dir and not self.blankable:
return False
t_object.update({'paused': (0, 1)[sickbeard.TORRENT_PAUSED], 'download-dir': download_dir})
response = self._request(method='post', json={'method': 'torrent-add', 'arguments': t_object})
return 'success' == response.json().get('result', '')
def _set_torrent_ratio(self, result):
ratio = None
if result.ratio:
ratio = result.ratio
mode = 0
ratio, mode = (result.ratio, None)[not result.ratio], 0
if ratio:
if float(ratio) == -1:
ratio = 0
mode = 2
elif float(ratio) >= 0:
ratio = float(ratio)
mode = 1 # Stop seeding at seedRatioLimit
if -1 == float(ratio):
ratio, mode = 0, 2
elif 0 <= float(ratio):
ratio, mode = float(ratio), 1 # Stop seeding at seedRatioLimit
arguments = {'ids': [result.hash],
'seedRatioLimit': ratio,
'seedRatioMode': mode
}
post_data = json.dumps({'arguments': arguments,
'method': 'torrent-set',
})
response = self._request(method='post', data=post_data)
response = self._request(method='post', json={
'method': 'torrent-set',
'arguments': {'ids': [result.hash], 'seedRatioLimit': ratio, 'seedRatioMode': mode}})
return response.json()['result'] == 'success'
return 'success' == response.json().get('result', '')
def _set_torrent_seed_time(self, result):
if result.provider.seed_time or (sickbeard.TORRENT_SEED_TIME and sickbeard.TORRENT_SEED_TIME != -1):
if result.provider.seed_time or (sickbeard.TORRENT_SEED_TIME and -1 != sickbeard.TORRENT_SEED_TIME):
seed_time = result.provider.seed_time or sickbeard.TORRENT_SEED_TIME
arguments = {'ids': [result.hash],
'seedIdleLimit': int(seed_time) * 60,
'seedIdleMode': 1}
post_data = json.dumps({'arguments': arguments,
'method': 'torrent-set'})
response = self._request(method='post', data=post_data)
response = self._request(method='post', json={
'method': 'torrent-set',
'arguments': {'ids': [result.hash], 'seedIdleLimit': int(seed_time) * 60, 'seedIdleMode': 1}})
return response.json()['result'] == 'success'
return 'success' == response.json().get('result', '')
else:
return True
@ -125,9 +113,9 @@ class TransmissionAPI(GenericClient):
arguments = {'ids': [result.hash]}
if result.priority == -1:
if -1 == result.priority:
arguments['priority-low'] = []
elif result.priority == 1:
elif 1 == result.priority:
# set high priority for all files in torrent
arguments['priority-high'] = []
# move torrent to the top if the queue
@ -137,14 +125,9 @@ class TransmissionAPI(GenericClient):
else:
arguments['priority-normal'] = []
post_data = json.dumps({
'arguments': arguments,
'method': 'torrent-set',
response = self._request(method='post', json={'method': 'torrent-set', 'arguments': arguments})
})
response = self._request(method='post', data=post_data)
return response.json()['result'] == 'success'
return 'success' == response.json().get('result', '')
api = TransmissionAPI()

View file

@ -139,7 +139,7 @@ def snatch_episode(result, end_status=SNATCHED):
return False
# Snatches torrent with client
client = clients.getClientIstance(sickbeard.TORRENT_METHOD)()
dl_result = client.sendTORRENT(result)
dl_result = client.send_torrent(result)
else:
logger.log(u'Unknown result type, unable to download it', logger.ERROR)
dl_result = False

View file

@ -676,7 +676,7 @@ class Home(MainHandler):
client = clients.getClientIstance(torrent_method)
connection, accesMsg = client(host, username, password).testAuthentication()
connection, accesMsg = client(host, username, password).test_authentication()
return accesMsg