Standardized checking snatched

This commit is contained in:
Ruud committed 2012-09-28 13:10:58 +02:00
1 parent 151b100573
commit ce0bf7b51a
5 files changed
+143 -130

No files matched your search

+4 -23
View File
@@ -1,10 +1,7 @@
from base64 import b32decode, b16encode from base64 import b32decode, b16encode
from couchpotato.core.event import addEvent from couchpotato.core.event import addEvent
from couchpotato.core.helpers.encoding import toSafeString
from couchpotato.core.logger import CPLog from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin from couchpotato.core.plugins.base import Plugin
from couchpotato.environment import Env
import os
import random import random
import re import re
@@ -23,34 +20,18 @@ class Downloader(Plugin):
def __init__(self): def __init__(self):
addEvent('download', self.download) addEvent('download', self.download)
addEvent('download.status', self.getDownloadStatus) addEvent('download.status', self.getAllDownloadStatus)
addEvent('download.remove', self.remove) addEvent('download.remove_failed', self.removeFailed)
def download(self, data = {}, movie = {}, manual = False, filedata = None): def download(self, data = {}, movie = {}, manual = False, filedata = None):
pass pass
def getDownloadStatus(self, data = {}, movie = {}): def getAllDownloadStatus(self):
return False return False
def remove(self, name = {}, nzo_id = {}): def removeFailed(self, name = {}, nzo_id = {}):
return False 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): def isCorrectType(self, item_type):
is_correct = item_type in self.type is_correct = item_type in self.type
+66 -60
View File
@@ -1,6 +1,6 @@
from couchpotato.core.downloaders.base import Downloader from couchpotato.core.downloaders.base import Downloader
from couchpotato.core.helpers.encoding import tryUrlencode 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 from couchpotato.core.logger import CPLog
import json import json
import traceback import traceback
@@ -63,86 +63,92 @@ class Sabnzbd(Downloader):
log.error("Unknown error: " + result[:40]) log.error("Unknown error: " + result[:40])
return False return False
def getDownloadStatus(self, data = {}, movie = {}): def getAllDownloadStatus(self):
if self.isDisabled(manual = True) or not self.isCorrectType(data.get('type')): if self.isDisabled(manual = False):
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())
return False return False
log.debug('Checking SABnzbd download status.')
# Go through Queue
try: try:
queue = json.loads(sab) queue = self.call({
'mode': 'queue',
})
except: except:
log.debug("Result text from SAB: " + sab[:40]) log.error('Failed getting queue: %s', traceback.format_exc())
log.error('Failed parsing json status: %s', traceback.format_exc())
return False return False
# Go through history items # Go through history items
params = { try:
'apikey': self.conf('api_key'), history = self.call({
'mode': 'history', 'mode': 'history',
'limit': 15, 'limit': 15,
'output': 'json' })
}
url = cleanHost(self.conf('host')) + "api?" + tryUrlencode(params)
try:
sab = self.urlopen(url, timeout = 60, show_error = False)
except: except:
log.error('Failed getting history: %s', traceback.format_exc()) log.error('Failed getting history json: %s', traceback.format_exc())
return False return False
try: statuses = []
history = json.loads(sab)
except: # Get busy releases
log.debug("Result text from SAB: " + sab[:40]) for item in queue.get('slots', []):
log.error('Failed parsing history json: %s', traceback.format_exc()) 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 False
return queue, history log.info('%s failed downloading, deleting...', item['name'])
def remove(self, name = {}, nzo_id = {}): try:
# Delete failed download self.call({
if self.conf('delete_failed', default = True):
log.info('%s failed downloading, deleting...', name)
params = {
'apikey': self.conf('api_key'),
'mode': 'history', 'mode': 'history',
'name': 'delete', 'name': 'delete',
'del_files': '1', 'del_files': '1',
'value': nzo_id 'value': item['id']
} }, use_json = False)
url = cleanHost(self.conf('host')) + "api?" + tryUrlencode(params)
try:
sab = self.urlopen(url, timeout = 60, show_error = False)
except: except:
log.error('Failed deleting: %s', traceback.format_exc()) log.error('Failed deleting: %s', traceback.format_exc())
return False return False
result = sab.strip() return True
if not result:
log.error("SABnzbd didn't return anything.")
log.debug("Result text from SAB: " + result[:40]) def call(self, params, use_json = True):
if result == "ok":
log.info('SabNZBd deleted failed release %s successfully.', name) url = cleanHost(self.conf('host')) + "api?" + tryUrlencode(mergeDicts(params, {
elif result == "Missing authentication": 'apikey': self.conf('api_key'),
log.error("Incorrect username/password or API?.") 'output': 'json'
}))
data = self.urlopen(url, timeout = 60, show_error = False)
if use_json:
return json.loads(data)[params['mode']]
else: else:
log.error("Unknown error: " + result[:40]) return data
return
+8
View File
@@ -118,6 +118,14 @@ def getTitle(library_dict):
try: try:
return library_dict['titles'][0]['title'] return library_dict['titles'][0]['title']
except: except:
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']) log.error('Could not get title for %s', library_dict['identifier'])
return None return None
except: except:
+18 -1
View File
@@ -1,7 +1,8 @@
from StringIO import StringIO from StringIO import StringIO
from couchpotato import addView from couchpotato import addView
from couchpotato.core.event import fireEvent, addEvent 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.helpers.variable import getExt
from couchpotato.core.logger import CPLog from couchpotato.core.logger import CPLog
from couchpotato.environment import Env from couchpotato.environment import Env
@@ -245,6 +246,22 @@ class Plugin(object):
Env.get('cache').set(cache_key, value, timeout) Env.get('cache').set(cache_key, value, timeout)
return value 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): def isDisabled(self):
return not self.isEnabled() return not self.isEnabled()
+47 -46
View File
@@ -20,6 +20,7 @@ log = CPLog(__name__)
class Renamer(Plugin): class Renamer(Plugin):
renaming_started = False renaming_started = False
checking_snatched = False
def __init__(self): def __init__(self):
@@ -33,6 +34,7 @@ class Renamer(Plugin):
addEvent('app.load', self.scan) addEvent('app.load', self.scan)
fireEvent('schedule.interval', 'renamer.check_snatched', self.checkSnatched, minutes = self.conf('run_every')) 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): def scanView(self):
@@ -495,6 +497,11 @@ class Renamer(Plugin):
loge('Couldn\'t remove empty directory %s: %s', (folder, traceback.format_exc())) loge('Couldn\'t remove empty directory %s: %s', (folder, traceback.format_exc()))
def checkSnatched(self): def checkSnatched(self):
if self.checking_snatched:
log.debug('Already checking snatched')
self.checking_snatched = True
snatched_status = fireEvent('status.get', 'snatched', single = True) snatched_status = fireEvent('status.get', 'snatched', single = True)
ignored_status = fireEvent('status.get', 'ignored', single = True) ignored_status = fireEvent('status.get', 'ignored', single = True)
failed_status = fireEvent('status.get', 'failed', single = True) failed_status = fireEvent('status.get', 'failed', single = True)
@@ -504,19 +511,23 @@ class Renamer(Plugin):
db = get_session() db = get_session()
rels = db.query(Release).filter_by(status_id = snatched_status.get('id')).all() rels = db.query(Release).filter_by(status_id = snatched_status.get('id')).all()
if rels:
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 scan_required = False
if rels:
self.checking_snatched = True
log.debug('Checking status snatched releases...')
# get queue and history (once) from SABnzbd
statuses = fireEvent('download.status', merge = True)
if not statuses:
log.debug('Download status functionality is not implemented for active downloaders.')
scan_required = True
try:
for rel in rels: for rel in rels:
rel_dict = rel.to_dict({'info': {}})
# Get current selected title # Get current selected title
default_title = '' default_title = getTitle(rel.movie.library)
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) # Check if movie has already completed and is manage tab (legacy db correction)
if rel.movie.status_id == done_status.get('id'): if rel.movie.status_id == done_status.get('id'):
@@ -525,60 +536,50 @@ class Renamer(Plugin):
db.commit() db.commit()
continue continue
item = {}
for info in rel.info:
item[info.identifier] = info.value
movie_dict = fireEvent('movie.get', rel.movie_id, single = True) movie_dict = fireEvent('movie.get', rel.movie_id, single = True)
# check status # check status
nzbname = self.createNzbName(item, movie_dict) nzbname = self.createNzbName(rel_dict['info'], 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 found = False
rel_remove = fireEvent('download.remove', name = slot['name'], nzo_id = slot['nzo_id'], single = True) for item in statuses:
downloadstatus = 'failed' if item['name'] == nzbname:
else:
downloadstatus = slot['status'].lower()
except:
log.debug('No items in history: %s', (traceback.format_exc()))
if not downloadstatus: timeleft = 'N/A' if item['timeleft'] == -1 else item['timeleft']
log.debug('Download status functionality is not implemented for active downloaders.') log.debug('Found %s: %s, time to go: %s', (item['name'], item['status'].upper(), timeleft))
scan_required = True
else: if item['status'] == 'busy':
log.debug('Download status: %s' , downloadstatus) pass
elif item['status'] == 'failed':
if item['delete']:
fireEvent('download.remove_failed', item, single = True)
if downloadstatus == 'failed':
if self.conf('next_on_failed'): if self.conf('next_on_failed'):
fireEvent('searcher.try_next_release', movie_id = rel.movie_id) fireEvent('searcher.try_next_release', movie_id = rel.movie_id)
else: else:
rel.status_id = failed_status.get('id') rel.status_id = failed_status.get('id')
db.commit() db.commit()
elif item['status'] == 'completed':
log.info('Download of %s failed.', item['name'])
elif downloadstatus == 'completed':
log.info('Download of %s completed!', item['name']) log.info('Download of %s completed!', item['name'])
scan_required = True scan_required = True
elif downloadstatus == 'not_found': found = True
log.info('%s not found in downloaders', item['name']) break
if not found:
log.info('%s not found in downloaders', nzbname)
rel.status_id = ignored_status.get('id') rel.status_id = ignored_status.get('id')
db.commit() db.commit()
# Note that Queued, Downloading, Paused, Repair and Unpackimg are also available as status for SabNZBd if self.conf('next_on_failed'):
fireEvent('searcher.try_next_release', movie_id = rel.movie_id)
except:
log.error('Failed checking for release in downloader: %s', traceback.format_exc())
if scan_required: if scan_required:
fireEvent('renamer.scan') fireEvent('renamer.scan')
self.checking_snatched = False
return True