Try and find release status by ID instead of name. closes #1511

Thanks to @mano3m
This commit is contained in:
Ruud
2013-03-24 19:54:11 +01:00
parent a97570027d
commit b0d556c8eb
9 changed files with 200 additions and 37 deletions
+38
View File
@@ -1,5 +1,6 @@
from base64 import b32decode, b16encode
from couchpotato.core.event import addEvent
from couchpotato.core.helpers.variable import mergeDicts
from couchpotato.core.logger import CPLog
from couchpotato.core.providers.base import Provider
import random
@@ -103,6 +104,12 @@ class Downloader(Provider):
log.error('Failed converting magnet url to torrent: %s', (torrent_hash))
return False
def downloadReturnId(self, download_id):
return {
'downloader': self.getName(),
'id': download_id
}
def isDisabled(self, manual, data):
return not self.isEnabled(manual, data)
@@ -116,3 +123,34 @@ class Downloader(Provider):
return super(Downloader, self).isEnabled() and \
((d_manual and manual) or (d_manual is False)) and \
(not data or self.isCorrectType(data.get('type')))
class StatusList(list):
provider = None
def __init__(self, provider, **kwargs):
self.provider = provider
self.kwargs = kwargs
super(StatusList, self).__init__()
def extend(self, results):
for r in results:
self.append(r)
def append(self, result):
new_result = self.fillResult(result)
super(StatusList, self).append(new_result)
def fillResult(self, result):
defaults = {
'id': 0,
'status': 'busy',
'downloader': self.provider.getName(),
}
return mergeDicts(defaults, result)
@@ -48,6 +48,12 @@ config = [{
'advanced': True,
'description': 'Disable this downloader for automated searches, but use it when I manually send a release.',
},
{
'name': 'delete_failed',
'default': True,
'type': 'bool',
'description': 'Delete a release after the download has failed.',
},
],
}
],
+104 -2
View File
@@ -1,9 +1,11 @@
from base64 import standard_b64encode
from couchpotato.core.downloaders.base import Downloader
from couchpotato.core.downloaders.base import Downloader, StatusList
from couchpotato.core.helpers.encoding import ss
from couchpotato.core.helpers.variable import tryInt
from couchpotato.core.logger import CPLog
from datetime import timedelta
import re
import shutil
import socket
import traceback
import xmlrpclib
@@ -50,7 +52,107 @@ class NZBGet(Downloader):
if xml_response:
log.info('NZB sent successfully to NZBGet')
return True
groups = rpc.listgroups()
nzb_id = [item['NZBID'] for item in groups if item['NZBFilename'] == nzb_name][0]
return self.downloadReturnId(nzb_id)
else:
log.error('NZBGet could not add %s to the queue.', nzb_name)
return False
def getAllDownloadStatus(self):
log.debug('Checking NZBGet download status.')
url = self.url % {'host': self.conf('host'), 'password': self.conf('password')}
rpc = xmlrpclib.ServerProxy(url)
try:
if rpc.writelog('INFO', 'CouchPotato connected to check status'):
log.info('Successfully connected to NZBGet')
else:
log.info('Successfully connected to NZBGet, but unable to send a message')
except socket.error:
log.error('NZBGet is not responding. Please ensure that NZBGet is running and host setting is correct.')
return False
except xmlrpclib.ProtocolError, e:
if e.errcode == 401:
log.error('Password is incorrect.')
else:
log.error('Protocol Error: %s', e)
return False
# Get NZBGet data
try:
status = rpc.status()
groups = rpc.listgroups()
queue = rpc.postqueue(0)
history = rpc.history()
except:
log.error('Failed getting data: %s', traceback.format_exc(1))
return False
statuses = StatusList(self)
for item in groups:
log.debug('Found %s in NZBGet download queue', item['NZBFilename'])
statuses.append({
'id': item['NZBID'],
'name': item['NZBFilename'],
'original_status': 'DOWNLOADING' if item['ActiveDownloads'] > 0 else 'QUEUED',
# Seems to have no native API function for time left. This will return the time left after NZBGet started downloading this item
'timeleft': str(timedelta(seconds = item['RemainingSizeMB'] / status['DownloadRate'] * 2 ^ 20)) if item['ActiveDownloads'] > 0 and not (status['DownloadPaused'] or status['Download2Paused']) else -1,
})
for item in queue:
log.debug('Found %s in NZBGet postprocessing queue', item['NZBFilename'])
statuses.append({
'id': item['NZBID'],
'name': item['NZBFilename'],
'original_status': item['Stage'],
'timeleft': str(timedelta(seconds = 0)) if not status['PostPaused'] else -1,
})
for item in history:
log.debug('Found %s in NZBGet history. ParStatus: %s, ScriptStatus: %s, Log: %s', (item['NZBFilename'] , item['ParStatus'], item['ScriptStatus'] , item['Log']))
statuses.append({
'id': item['NZBID'],
'name': item['NZBFilename'],
'status': 'completed' if item['ParStatus'] == 'SUCCESS' and item['ScriptStatus'] == 'SUCCESS' else 'failed',
'original_status': item['ParStatus'] + ', ' + item['ScriptStatus'],
'timeleft': str(timedelta(seconds = 0)),
})
return statuses
def removeFailed(self, item):
log.info('%s failed downloading, deleting...', item['name'])
url = self.url % {'host': self.conf('host'), 'password': self.conf('password')}
rpc = xmlrpclib.ServerProxy(url)
try:
if rpc.writelog('INFO', 'CouchPotato connected to delete some history'):
log.info('Successfully connected to NZBGet')
else:
log.info('Successfully connected to NZBGet, but unable to send a message')
except socket.error:
log.error('NZBGet is not responding. Please ensure that NZBGet is running and host setting is correct.')
return False
except xmlrpclib.ProtocolError, e:
if e.errcode == 401:
log.error('Password is incorrect.')
else:
log.error('Protocol Error: %s', e)
return False
try:
history = rpc.history()
if rpc.editqueue('HistoryDelete', 0, "", [int(item['id'][len('NZBGet_'):])]):
path = [hist['DestDir'] for hist in history if hist['NZBID'] == item['id']][0]
shutil.rmtree(path, True)
except:
log.error('Failed deleting: %s', traceback.format_exc(0))
return False
return True
@@ -1,5 +1,5 @@
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 tryUrlencode, ss
from couchpotato.core.helpers.variable import cleanHost
from couchpotato.core.logger import CPLog
@@ -29,7 +29,9 @@ class NZBVortex(Downloader):
nzb_filename = self.createFileName(data, filedata, movie)
self.call('nzb/add', params = {'file': (ss(nzb_filename), filedata)}, multipart = True)
return True
raw_statuses = self.call('nzb')
nzb_id = [item['id'] for item in raw_statuses.get('nzbs', []) if item['name'] == nzb_filename][0]
return self.downloadReturnId(nzb_id)
except:
log.error('Something went wrong sending the NZB file: %s', traceback.format_exc())
return False
@@ -38,7 +40,7 @@ class NZBVortex(Downloader):
raw_statuses = self.call('nzb')
statuses = []
statuses = StatusList(self)
for item in raw_statuses.get('nzbs', []):
# Check status
+21 -23
View File
@@ -1,4 +1,4 @@
from couchpotato.core.downloaders.base import Downloader
from couchpotato.core.downloaders.base import Downloader, StatusList
from couchpotato.core.helpers.encoding import tryUrlencode, ss
from couchpotato.core.helpers.variable import cleanHost, mergeDicts
from couchpotato.core.logger import CPLog
@@ -17,8 +17,7 @@ class Sabnzbd(Downloader):
log.info('Sending "%s" to SABnzbd.', data.get('name'))
params = {
'apikey': self.conf('api_key'),
req_params = {
'cat': self.conf('category'),
'mode': 'addurl',
'nzbname': self.createNzbName(data, movie),
@@ -31,17 +30,15 @@ class Sabnzbd(Downloader):
# If it's a .rar, it adds the .rar extension, otherwise it stays .nzb
nzb_filename = self.createFileName(data, filedata, movie)
params['mode'] = 'addfile'
req_params['mode'] = 'addfile'
else:
params['name'] = data.get('url')
url = cleanHost(self.conf('host')) + 'api?' + tryUrlencode(params)
req_params['name'] = data.get('url')
try:
if params.get('mode') is 'addfile':
sab = self.urlopen(url, timeout = 60, params = {'nzbfile': (ss(nzb_filename), filedata)}, multipart = True, show_error = False, headers = {'User-Agent': Env.getIdentifier()})
if req_params.get('mode') is 'addfile':
sab_data = self.call(req_params, params = {'nzbfile': (ss(nzb_filename), filedata)}, multipart = True)
else:
sab = self.urlopen(url, timeout = 60, show_error = False, headers = {'User-Agent': Env.getIdentifier()})
sab_data = self.call(req_params)
except URLError:
log.error('Failed sending release, probably wrong HOST: %s', traceback.format_exc(0))
return False
@@ -49,17 +46,19 @@ class Sabnzbd(Downloader):
log.error('Failed sending release, use API key, NOT the NZB key: %s', traceback.format_exc(0))
return False
result = sab.strip()
if not result:
log.error('SABnzbd didn\'t return anything.')
if sab_data.get('error'):
log.error('Error getting data from SABNZBd: %s', sab_data.get('error'))
return False
log.debug('Result text from SAB: %s', result[:40])
if result[:2] == 'ok':
log.debug('Result from SAB: %s', sab_data)
if sab_data.get('status'):
log.info('NZB sent to SAB successfully.')
return True
if filedata:
return self.downloadReturnId(sab_data.get('nzo_ids')[0])
else:
return True
else:
log.error(result[:40])
log.error(sab_data)
return False
def getAllDownloadStatus(self):
@@ -85,14 +84,13 @@ class Sabnzbd(Downloader):
log.error('Failed getting history json: %s', traceback.format_exc(1))
return False
statuses = []
statuses = StatusList(self)
# Get busy releases
for item in queue.get('slots', []):
statuses.append({
'id': item['nzo_id'],
'name': item['filename'],
'status': 'busy',
'original_status': item['status'],
'timeleft': item['timeleft'] if not queue['paused'] else -1,
})
@@ -133,21 +131,21 @@ class Sabnzbd(Downloader):
return True
def call(self, params, use_json = True):
def call(self, request_params, use_json = True, **kwargs):
url = cleanHost(self.conf('host')) + 'api?' + tryUrlencode(mergeDicts(params, {
url = cleanHost(self.conf('host')) + 'api?' + tryUrlencode(mergeDicts(request_params, {
'apikey': self.conf('api_key'),
'output': 'json'
}))
data = self.urlopen(url, timeout = 60, show_error = False, headers = {'User-Agent': Env.getIdentifier()})
data = self.urlopen(url, timeout = 60, show_error = False, headers = {'User-Agent': Env.getIdentifier()}, **kwargs)
if use_json:
d = json.loads(data)
if d.get('error'):
log.error('Error getting data from SABNZBd: %s', d.get('error'))
return {}
return d[params['mode']]
return d.get(request_params['mode']) or d
else:
return data
@@ -62,7 +62,7 @@ class Transmission(Downloader):
if torrent_params:
trpc.set_torrent(remote_torrent['torrent-added']['hashString'], torrent_params)
return True
return self.downloadReturnId(remote_torrent['torrent-added']['hashString'])
except Exception, err:
log.error('Failed to change settings for transfer: %s', err)
return False
@@ -1,6 +1,6 @@
from base64 import b16encode, b32decode
from bencode import bencode, bdecode
from couchpotato.core.downloaders.base import Downloader
from couchpotato.core.downloaders.base import Downloader, StatusList
from couchpotato.core.helpers.encoding import isInt, ss
from couchpotato.core.logger import CPLog
from hashlib import sha1
@@ -66,7 +66,7 @@ class uTorrent(Downloader):
self.utorrent_api.set_torrent(torrent_hash, torrent_params)
if self.conf('paused', default = 0):
self.utorrent_api.pause_torrent(torrent_hash)
return True
return self.downloadReturnId(torrent_hash)
except Exception, err:
log.error('Failed to send torrent to uTorrent: %s', err)
return False
@@ -103,7 +103,7 @@ class uTorrent(Downloader):
log.debug('Nothing in queue')
return False
statuses = []
statuses = StatusList(self)
# Get torrents
for item in queue.get('torrents', []):
+9 -1
View File
@@ -571,8 +571,16 @@ class Renamer(Plugin):
found = False
for item in statuses:
if item['name'] == nzbname or rel_dict['info']['name'] in item['name'] or getImdb(item['name']) == movie_dict['library']['identifier']:
found_release = False
if rel_dict['info'].get('download_id'):
if item['id'] == rel_dict['info']['download_id'] and item['downloader'] == rel_dict['info']['download_downloader']:
log.debug('Found release by id: %s', item['id'])
found_release = True
else:
if item['name'] == nzbname or rel_dict['info']['name'] in item['name'] or getImdb(item['name']) == movie_dict['library']['identifier']:
found_release = True
if found_release:
timeleft = 'N/A' if item['timeleft'] == -1 else item['timeleft']
log.debug('Found %s: %s, time to go: %s', (item['name'], item['status'].upper(), timeleft))
+13 -4
View File
@@ -285,10 +285,10 @@ class Searcher(Plugin):
if filedata == 'try_next':
return filedata
successful = fireEvent('download', data = data, movie = movie, manual = manual, filedata = filedata, single = True)
if successful:
download_result = fireEvent('download', data = data, movie = movie, manual = manual, filedata = filedata, single = True)
log.debug('Downloader result: %s', download_result)
if download_result:
try:
# Mark release as snatched
db = get_session()
@@ -298,6 +298,15 @@ class Searcher(Plugin):
done_status = fireEvent('status.get', 'done', single = True)
rls.status_id = done_status.get('id') if not renamer_enabled else snatched_status.get('id')
# Save download-id info if returned
if isinstance(download_result, dict):
for key in download_result:
rls_info = ReleaseInfo(
identifier = 'download_%s' % key,
value = toUnicode(download_result.get(key))
)
rls.info.append(rls_info)
db.commit()
log_movie = '%s (%s) in %s' % (getTitle(movie['library']), movie['library']['year'], rls.quality.label)
@@ -333,7 +342,7 @@ class Searcher(Plugin):
return True
log.info('Tried to download, but none of the "%s" downloaders are enabled', (data.get('type', '')))
log.info('Tried to download, but none of the "%s" downloaders are enabled or gave an error', (data.get('type', '')))
return False