|
|
@ -1,13 +1,15 @@ |
|
|
|
from base64 import b64encode |
|
|
|
from couchpotato.core.downloaders.base import Downloader |
|
|
|
from couchpotato.core.downloaders.base import Downloader, StatusList |
|
|
|
from couchpotato.core.helpers.encoding import isInt |
|
|
|
from couchpotato.core.logger import CPLog |
|
|
|
from couchpotato.environment import Env |
|
|
|
from datetime import timedelta |
|
|
|
import httplib |
|
|
|
import json |
|
|
|
import os.path |
|
|
|
import re |
|
|
|
import traceback |
|
|
|
import urllib2 |
|
|
|
import shutil |
|
|
|
|
|
|
|
log = CPLog(__name__) |
|
|
|
|
|
|
@ -19,7 +21,7 @@ class Transmission(Downloader): |
|
|
|
|
|
|
|
def download(self, data, movie, filedata = None): |
|
|
|
|
|
|
|
log.debug('Sending "%s" (%s) to Transmission.', (data.get('name'), data.get('type'))) |
|
|
|
log.info('Sending "%s" (%s) to Transmission.', (data.get('name'), data.get('type'))) |
|
|
|
|
|
|
|
# Load host from config and split out port. |
|
|
|
host = self.conf('host').split(':') |
|
|
@ -45,7 +47,7 @@ class Transmission(Downloader): |
|
|
|
if self.conf('ratio'): |
|
|
|
torrent_params = { |
|
|
|
'seedRatioLimit': self.conf('ratio'), |
|
|
|
'seedRatioMode': self.conf('ratio') |
|
|
|
'seedRatioMode': self.conf('ratiomode') |
|
|
|
} |
|
|
|
|
|
|
|
if not filedata and data.get('type') == 'torrent': |
|
|
@ -68,11 +70,99 @@ class Transmission(Downloader): |
|
|
|
elif torrent_params: |
|
|
|
trpc.set_torrent(remote_torrent['torrent-added']['hashString'], torrent_params) |
|
|
|
|
|
|
|
log.info('Torrent sent to Transmission successfully.') |
|
|
|
return self.downloadReturnId(remote_torrent['torrent-added']['hashString']) |
|
|
|
except: |
|
|
|
log.error('Failed to change settings for transfer: %s', traceback.format_exc()) |
|
|
|
return False |
|
|
|
|
|
|
|
def getAllDownloadStatus(self): |
|
|
|
|
|
|
|
log.debug('Checking Transmission download status.') |
|
|
|
|
|
|
|
# Load host from config and split out port. |
|
|
|
host = self.conf('host').split(':') |
|
|
|
if not isInt(host[1]): |
|
|
|
log.error('Config properties are not filled in correctly, port is missing.') |
|
|
|
return False |
|
|
|
|
|
|
|
# Go through Queue |
|
|
|
try: |
|
|
|
trpc = TransmissionRPC(host[0], port = host[1], username = self.conf('username'), password = self.conf('password')) |
|
|
|
return_params = { |
|
|
|
'fields': ['id', 'name', 'hashString', 'percentDone', 'status', 'eta', 'isFinished', 'downloadDir', 'uploadRatio'] |
|
|
|
} |
|
|
|
queue = trpc.get_alltorrents(return_params) |
|
|
|
|
|
|
|
except Exception, err: |
|
|
|
log.error('Failed getting queue: %s', err) |
|
|
|
return False |
|
|
|
|
|
|
|
statuses = StatusList(self) |
|
|
|
|
|
|
|
# Get torrents status |
|
|
|
# CouchPotato Status |
|
|
|
#status = 'busy' |
|
|
|
#status = 'failed' |
|
|
|
#status = 'completed' |
|
|
|
# Transmission Status |
|
|
|
#status = 0 => "Torrent is stopped" |
|
|
|
#status = 1 => "Queued to check files" |
|
|
|
#status = 2 => "Checking files" |
|
|
|
#status = 3 => "Queued to download" |
|
|
|
#status = 4 => "Downloading" |
|
|
|
#status = 4 => "Queued to seed" |
|
|
|
#status = 6 => "Seeding" |
|
|
|
#To do : |
|
|
|
# add checking file |
|
|
|
# manage no peer in a range time => fail |
|
|
|
|
|
|
|
for item in queue['torrents']: |
|
|
|
log.debug('name=%s / id=%s / downloadDir=%s / hashString=%s / percentDone=%s / status=%s / eta=%s / uploadRatio=%s / confRatio=%s / isFinished=%s', (item['name'], item['id'], item['downloadDir'], item['hashString'], item['percentDone'], item['status'], item['eta'], item['uploadRatio'], self.conf('ratio'), item['isFinished'] )) |
|
|
|
|
|
|
|
if not os.path.isdir(Env.setting('from', 'renamer')): |
|
|
|
log.debug('Renamer folder has to exist.') |
|
|
|
return |
|
|
|
|
|
|
|
if (item['percentDone'] * 100) >= 100 and (item['status'] == 6 or item['status'] == 0) and item['uploadRatio'] > self.conf('ratio'): |
|
|
|
try: |
|
|
|
trpc.stop_torrent(item['hashString'], {}) |
|
|
|
|
|
|
|
if not os.path.isdir(item['downloadDir']): |
|
|
|
raise Exception('Missing folder: %s' % item['downloadDir']) |
|
|
|
|
|
|
|
else: |
|
|
|
log.info('Moving folder from "%s" to "%s"', (item['downloadDir'], Env.setting('from', 'renamer'))) |
|
|
|
shutil.move(item['downloadDir'], Env.setting('from', 'renamer')) |
|
|
|
|
|
|
|
statuses.append({ |
|
|
|
'id': item['hashString'], |
|
|
|
'name': item['downloadDir'], |
|
|
|
'status': 'completed', |
|
|
|
'original_status': item['status'], |
|
|
|
'timeleft': str(timedelta(seconds = 0)), |
|
|
|
'folder': os.path.join(Env.setting('from', 'renamer'), os.path.basename(item['downloadDir'].rstrip(os.path.sep))), |
|
|
|
}) |
|
|
|
trpc.remove_torrent(item['hashString'], True, {}) |
|
|
|
except Exception, err: |
|
|
|
log.error('Failed to stop and remove torrent "%s" with error: %s', (item['name'], err)) |
|
|
|
statuses.append({ |
|
|
|
'id': item['hashString'], |
|
|
|
'name': item['downloadDir'], |
|
|
|
'status': 'failed', |
|
|
|
'original_status': item['status'], |
|
|
|
'timeleft': str(timedelta(seconds = 0)), |
|
|
|
}) |
|
|
|
else: |
|
|
|
statuses.append({ |
|
|
|
'id': item['hashString'], |
|
|
|
'name': item['downloadDir'], |
|
|
|
'status': 'busy', |
|
|
|
'original_status': item['status'], |
|
|
|
'timeleft': str(timedelta(seconds = item['eta'])), # Is ETA in seconds?? |
|
|
|
}) |
|
|
|
|
|
|
|
return statuses |
|
|
|
|
|
|
|
class TransmissionRPC(object): |
|
|
|
|
|
|
@ -103,6 +193,7 @@ class TransmissionRPC(object): |
|
|
|
try: |
|
|
|
open_request = urllib2.urlopen(request) |
|
|
|
response = json.loads(open_request.read()) |
|
|
|
log.debug('request: %s', json.dumps(ojson)) |
|
|
|
log.debug('response: %s', json.dumps(response)) |
|
|
|
if response['result'] == 'success': |
|
|
|
log.debug('Transmission action successfull') |
|
|
@ -152,3 +243,18 @@ class TransmissionRPC(object): |
|
|
|
arguments['ids'] = torrent_id |
|
|
|
post_data = {'arguments': arguments, 'method': 'torrent-set', 'tag': self.tag} |
|
|
|
return self._request(post_data) |
|
|
|
|
|
|
|
def get_alltorrents(self, arguments): |
|
|
|
post_data = {'arguments': arguments, 'method': 'torrent-get', 'tag': self.tag} |
|
|
|
return self._request(post_data) |
|
|
|
|
|
|
|
def stop_torrent(self, torrent_id, arguments): |
|
|
|
arguments['ids'] = torrent_id |
|
|
|
post_data = {'arguments': arguments, 'method': 'torrent-stop', 'tag': self.tag} |
|
|
|
return self._request(post_data) |
|
|
|
|
|
|
|
def remove_torrent(self, torrent_id, remove_local_data, arguments): |
|
|
|
arguments['ids'] = torrent_id |
|
|
|
arguments['delete-local-data'] = remove_local_data |
|
|
|
post_data = {'arguments': arguments, 'method': 'torrent-remove', 'tag': self.tag} |
|
|
|
return self._request(post_data) |
|
|
|