Standardized checking snatched

This commit is contained in:
Ruud
2012-09-28 13:10:58 +02:00
parent 151b100573
commit ce0bf7b51a
5 changed files with 169 additions and 156 deletions
+4 -23
View File
@@ -1,10 +1,7 @@
from base64 import b32decode, b16encode
from couchpotato.core.event import addEvent
from couchpotato.core.helpers.encoding import toSafeString
from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin
from couchpotato.environment import Env
import os
import random
import re
@@ -23,34 +20,18 @@ class Downloader(Plugin):
def __init__(self):
addEvent('download', self.download)
addEvent('download.status', self.getDownloadStatus)
addEvent('download.remove', self.remove)
addEvent('download.status', self.getAllDownloadStatus)
addEvent('download.remove_failed', self.removeFailed)
def download(self, data = {}, movie = {}, manual = False, filedata = None):
pass
def getDownloadStatus(self, data = {}, movie = {}):
def getAllDownloadStatus(self):
return False
def remove(self, name = {}, nzo_id = {}):
def removeFailed(self, name = {}, nzo_id = {}):
return False
def createNzbName(self, data, movie):
tag = self.cpTag(movie)
return '%s%s' % (toSafeString(data.get('name')[:127 - len(tag)]), tag)
def createFileName(self, data, filedata, movie):
name = os.path.join(self.createNzbName(data, movie))
if data.get('type') == 'nzb' and 'DOCTYPE nzb' not in filedata and '</nzb>' not in filedata:
return '%s.%s' % (name, 'rar')
return '%s.%s' % (name, data.get('type'))
def cpTag(self, movie):
if Env.setting('enabled', 'renamer'):
return '.cp(' + movie['library'].get('identifier') + ')' if movie['library'].get('identifier') else ''
return ''
def isCorrectType(self, item_type):
is_correct = item_type in self.type
+70 -64
View File
@@ -1,6 +1,6 @@
from couchpotato.core.downloaders.base import Downloader
from couchpotato.core.helpers.encoding import tryUrlencode
from couchpotato.core.helpers.variable import cleanHost
from couchpotato.core.helpers.variable import cleanHost, mergeDicts
from couchpotato.core.logger import CPLog
import json
import traceback
@@ -63,86 +63,92 @@ class Sabnzbd(Downloader):
log.error("Unknown error: " + result[:40])
return False
def getDownloadStatus(self, data = {}, movie = {}):
if self.isDisabled(manual = True) or not self.isCorrectType(data.get('type')):
return
log.info('Checking SABnzbd download status.')
# Go through Queue
params = {
'apikey': self.conf('api_key'),
'mode': 'queue',
'output': 'json'
}
url = cleanHost(self.conf('host')) + "api?" + tryUrlencode(params)
try:
sab = self.urlopen(url, timeout = 60, show_error = False)
except:
log.error('Failed checking status: %s', traceback.format_exc())
def getAllDownloadStatus(self):
if self.isDisabled(manual = False):
return False
log.debug('Checking SABnzbd download status.')
# Go through Queue
try:
queue = json.loads(sab)
queue = self.call({
'mode': 'queue',
})
except:
log.debug("Result text from SAB: " + sab[:40])
log.error('Failed parsing json status: %s', traceback.format_exc())
log.error('Failed getting queue: %s', traceback.format_exc())
return False
# Go through history items
params = {
'apikey': self.conf('api_key'),
'mode': 'history',
'limit': 15,
'output': 'json'
}
url = cleanHost(self.conf('host')) + "api?" + tryUrlencode(params)
try:
sab = self.urlopen(url, timeout = 60, show_error = False)
history = self.call({
'mode': 'history',
'limit': 15,
})
except:
log.error('Failed getting history: %s', traceback.format_exc())
log.error('Failed getting history json: %s', traceback.format_exc())
return False
try:
history = json.loads(sab)
except:
log.debug("Result text from SAB: " + sab[:40])
log.error('Failed parsing history json: %s', traceback.format_exc())
statuses = []
# 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,
})
# Get old releases
for item in history.get('slots', []):
status = 'busy'
if item['status'] == 'Failed' or (item['status'] == 'Completed' and item['fail_message'].strip()):
status = 'failed'
elif item['status'] == 'Completed':
status = 'completed'
statuses.append({
'id': item['nzo_id'],
'name': item['name'],
'status': status,
'original_status': item['status'],
'timeleft': 0,
})
return statuses
def removeFailed(self, item):
if not self.conf('delete_failed', default = True):
return False
return queue, history
log.info('%s failed downloading, deleting...', item['name'])
def remove(self, name = {}, nzo_id = {}):
# Delete failed download
if self.conf('delete_failed', default = True):
log.info('%s failed downloading, deleting...', name)
params = {
'apikey': self.conf('api_key'),
try:
self.call({
'mode': 'history',
'name': 'delete',
'del_files': '1',
'value': nzo_id
}
url = cleanHost(self.conf('host')) + "api?" + tryUrlencode(params)
'value': item['id']
}, use_json = False)
except:
log.error('Failed deleting: %s', traceback.format_exc())
return False
try:
sab = self.urlopen(url, timeout = 60, show_error = False)
except:
log.error('Failed deleting: %s', traceback.format_exc())
return False
return True
result = sab.strip()
if not result:
log.error("SABnzbd didn't return anything.")
def call(self, params, use_json = True):
url = cleanHost(self.conf('host')) + "api?" + tryUrlencode(mergeDicts(params, {
'apikey': self.conf('api_key'),
'output': 'json'
}))
data = self.urlopen(url, timeout = 60, show_error = False)
if use_json:
return json.loads(data)[params['mode']]
else:
return data
log.debug("Result text from SAB: " + result[:40])
if result == "ok":
log.info('SabNZBd deleted failed release %s successfully.', name)
elif result == "Missing authentication":
log.error("Incorrect username/password or API?.")
else:
log.error("Unknown error: " + result[:40])
return
+10 -2
View File
@@ -118,8 +118,16 @@ def getTitle(library_dict):
try:
return library_dict['titles'][0]['title']
except:
log.error('Could not get title for %s', library_dict['identifier'])
return None
try:
for title in library_dict.titles:
if title.default:
return title.title
except:
log.error('Could not get title for %s', library_dict.identifier)
return None
log.error('Could not get title for %s', library_dict['identifier'])
return None
except:
log.error('Could not get title for library item: %s', library_dict)
return None
+18 -1
View File
@@ -1,7 +1,8 @@
from StringIO import StringIO
from couchpotato import addView
from couchpotato.core.event import fireEvent, addEvent
from couchpotato.core.helpers.encoding import tryUrlencode, simplifyString, ss
from couchpotato.core.helpers.encoding import tryUrlencode, simplifyString, ss, \
toSafeString
from couchpotato.core.helpers.variable import getExt
from couchpotato.core.logger import CPLog
from couchpotato.environment import Env
@@ -245,6 +246,22 @@ class Plugin(object):
Env.get('cache').set(cache_key, value, timeout)
return value
def createNzbName(self, data, movie):
tag = self.cpTag(movie)
return '%s%s' % (toSafeString(data.get('name')[:127 - len(tag)]), tag)
def createFileName(self, data, filedata, movie):
name = os.path.join(self.createNzbName(data, movie))
if data.get('type') == 'nzb' and 'DOCTYPE nzb' not in filedata and '</nzb>' not in filedata:
return '%s.%s' % (name, 'rar')
return '%s.%s' % (name, data.get('type'))
def cpTag(self, movie):
if Env.setting('enabled', 'renamer'):
return '.cp(' + movie['library'].get('identifier') + ')' if movie['library'].get('identifier') else ''
return ''
def isDisabled(self):
return not self.isEnabled()
+67 -66
View File
@@ -20,6 +20,7 @@ log = CPLog(__name__)
class Renamer(Plugin):
renaming_started = False
checking_snatched = False
def __init__(self):
@@ -33,6 +34,7 @@ class Renamer(Plugin):
addEvent('app.load', self.scan)
fireEvent('schedule.interval', 'renamer.check_snatched', self.checkSnatched, minutes = self.conf('run_every'))
fireEvent('schedule.interval', 'renamer.check_snatched_forced', self.scan, hours = 2)
def scanView(self):
@@ -495,6 +497,11 @@ class Renamer(Plugin):
loge('Couldn\'t remove empty directory %s: %s', (folder, traceback.format_exc()))
def checkSnatched(self):
if self.checking_snatched:
log.debug('Already checking snatched')
self.checking_snatched = True
snatched_status = fireEvent('status.get', 'snatched', single = True)
ignored_status = fireEvent('status.get', 'ignored', single = True)
failed_status = fireEvent('status.get', 'failed', single = True)
@@ -504,81 +511,75 @@ class Renamer(Plugin):
db = get_session()
rels = db.query(Release).filter_by(status_id = snatched_status.get('id')).all()
scan_required = False
if rels:
self.checking_snatched = True
log.debug('Checking status snatched releases...')
# get queue and history (once) from SABnzbd
queue, history = fireEvent('download.status', data = {}, movie = {}, single = True)
scan_required = False
for rel in rels:
# Get current selected title
default_title = ''
for title in rel.movie.library.titles:
if title.default: default_title = title.title
# Check if movie has already completed and is manage tab (legacy db correction)
if rel.movie.status_id == done_status.get('id'):
log.debug('Found a completed movie with a snatched release : %s. Setting release status to ignored...' , default_title)
rel.status_id = ignored_status.get('id')
db.commit()
continue
item = {}
for info in rel.info:
item[info.identifier] = info.value
movie_dict = fireEvent('movie.get', rel.movie_id, single = True)
# check status
nzbname = self.createNzbName(item, movie_dict)
try:
for slot in queue['queue']['slots']:
log.debug('Found %s in SabNZBd queue, which is %s, with %s left', (slot['filename'], slot['status'], slot['timeleft']))
if slot['filename'] == nzbname:
downloadstatus =['status'].lower()
except:
log.debug('No items in queue: %s', (traceback.format_exc()))
try:
for slot in history['history']['slots']:
log.debug('Found %s in SabNZBd history, which has %s', (slot['name'], slot['status']))
if slot['name'] == nzbname:
# Note: if post process even if failed is on in SabNZBd, it will complete with a fail message
if slot['status'] == 'Failed' or (slot['status'] == 'Completed' and slot['fail_message'].strip()):
# Delete failed download
rel_remove = fireEvent('download.remove', name = slot['name'], nzo_id = slot['nzo_id'], single = True)
downloadstatus = 'failed'
else:
downloadstatus = slot['status'].lower()
except:
log.debug('No items in history: %s', (traceback.format_exc()))
if not downloadstatus:
statuses = fireEvent('download.status', merge = True)
if not statuses:
log.debug('Download status functionality is not implemented for active downloaders.')
scan_required = True
else:
log.debug('Download status: %s' , downloadstatus)
if downloadstatus == 'failed':
if self.conf('next_on_failed'):
fireEvent('searcher.try_next_release', movie_id = rel.movie_id)
else:
rel.status_id = failed_status.get('id')
try:
for rel in rels:
rel_dict = rel.to_dict({'info': {}})
# Get current selected title
default_title = getTitle(rel.movie.library)
# Check if movie has already completed and is manage tab (legacy db correction)
if rel.movie.status_id == done_status.get('id'):
log.debug('Found a completed movie with a snatched release : %s. Setting release status to ignored...' , default_title)
rel.status_id = ignored_status.get('id')
db.commit()
continue
movie_dict = fireEvent('movie.get', rel.movie_id, single = True)
# check status
nzbname = self.createNzbName(rel_dict['info'], movie_dict)
found = False
for item in statuses:
if item['name'] == nzbname:
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))
if item['status'] == 'busy':
pass
elif item['status'] == 'failed':
if item['delete']:
fireEvent('download.remove_failed', item, single = True)
if self.conf('next_on_failed'):
fireEvent('searcher.try_next_release', movie_id = rel.movie_id)
else:
rel.status_id = failed_status.get('id')
db.commit()
elif item['status'] == 'completed':
log.info('Download of %s completed!', item['name'])
scan_required = True
found = True
break
if not found:
log.info('%s not found in downloaders', nzbname)
rel.status_id = ignored_status.get('id')
db.commit()
log.info('Download of %s failed.', item['name'])
if self.conf('next_on_failed'):
fireEvent('searcher.try_next_release', movie_id = rel.movie_id)
elif downloadstatus == 'completed':
log.info('Download of %s completed!', item['name'])
scan_required = True
except:
log.error('Failed checking for release in downloader: %s', traceback.format_exc())
elif downloadstatus == 'not_found':
log.info('%s not found in downloaders', item['name'])
rel.status_id = ignored_status.get('id')
db.commit()
# Note that Queued, Downloading, Paused, Repair and Unpackimg are also available as status for SabNZBd
if scan_required:
fireEvent('renamer.scan')
self.checking_snatched = False
return True