You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

938 lines
30 KiB

#!/usr/bin/python -OO
# Copyright 2008-2009 The SABnzbd-Team <team@sabnzbd.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
sabnzbd.nzbqueue - nzb queue
"""
import os
import logging
import time
import datetime
import sabnzbd
from sabnzbd.trylist import TryList
from sabnzbd.nzbstuff import NzbObject
from sabnzbd.misc import panic_queue, exit_sab, sanitize_foldername, cat_to_opts
import sabnzbd.database as database
from sabnzbd.decorators import *
from sabnzbd.constants import *
import sabnzbd.cfg as cfg
import sabnzbd.articlecache
import sabnzbd.downloader
import sabnzbd.assembler
from sabnzbd.lang import T, Ta
from sabnzbd.utils import osx
def DeleteLog(name):
if name:
name = name.replace('.nzb', '.log')
try:
os.remove(os.path.join(os.path.dirname(sabnzbd.LOGFILE), name))
except:
pass
#-------------------------------------------------------------------------------
class NzbQueue(TryList):
def __init__(self):
TryList.__init__(self)
self.__downloaded_items = []
self.__top_only = cfg.TOP_ONLY.get()
self.__top_nzo = None
self.__nzo_list = []
self.__nzo_table = {}
self.__auto_sort = cfg.AUTO_SORT.get()
nzo_ids = []
data = sabnzbd.load_data(QUEUE_FILE_NAME, remove = False)
if data:
try:
queue_vers, nzo_ids, self.__downloaded_items = data
if not queue_vers == QUEUE_VERSION:
logging.error(Ta('error-qBad'))
self.__downloaded_items = []
nzo_ids = []
panic_queue(os.path.join(cfg.CACHE_DIR.get_path(),QUEUE_FILE_NAME))
exit_sab(2)
except ValueError:
logging.error(Ta('error-qCorruptFile@1'),
os.path.join(cfg.CACHE_DIR.get_path(), QUEUE_FILE_NAME))
for nzo_id in nzo_ids:
nzo = sabnzbd.load_data(nzo_id, remove = False)
if nzo:
self.add(nzo, save = False)
@synchronized(NZBQUEUE_LOCK)
def save(self):
""" Save queue """
logging.info("Saving queue")
nzo_ids = []
# Aggregate nzo_ids and save each nzo
for nzo in self.__nzo_list:
nzo_ids.append(nzo.nzo_id)
sabnzbd.save_data(nzo, nzo.nzo_id)
sabnzbd.save_data((QUEUE_VERSION, nzo_ids,
self.__downloaded_items), QUEUE_FILE_NAME)
@synchronized(NZBQUEUE_LOCK)
def set_top_only(self, value):
self.__top_only = value
@synchronized(NZBQUEUE_LOCK)
def generate_future(self, msg, pp=None, script=None, cat=None, url=None, priority=NORMAL_PRIORITY, nzbname=None):
""" Create and return a placeholder nzo object """
future_nzo = NzbObject(msg, 0, pp, script, None, True, cat=cat, url=url, priority=priority, nzbname=nzbname, status="Grabbing")
self.add(future_nzo)
return future_nzo
@synchronized(NZBQUEUE_LOCK)
def insert_future(self, future, filename, msgid, data, pp=None, script=None, cat=None, priority=NORMAL_PRIORITY, nzbname=None, nzo_info=None):
""" Refresh a placeholder nzo with an actual nzo """
if nzo_info is None:
nzo_info = {}
nzo_id = future.nzo_id
if nzo_id in self.__nzo_table:
try:
logging.info("Regenerating item: %s", nzo_id)
r, u, d = future.get_repair_opts()
if not r is None:
pp = sabnzbd.opts_to_pp(r, u, d)
scr = future.get_script()
if scr is None:
scr = script
categ = future.get_cat()
if categ is None:
categ = cat
categ, pp, script, priority = cat_to_opts(categ, pp, script, priority)
try:
future.__init__(filename, msgid, pp, scr, nzb=data, futuretype=False, cat=categ, priority=priority, nzbname=nzbname, nzo_info=nzo_info)
future.nzo_id = nzo_id
self.save()
except ValueError:
self.remove(nzo_id, False)
except TypeError:
self.remove(nzo_id, False)
# Make sure the priority is changed now that we know the category
self.set_priority(future.nzo_id, priority)
if self.__auto_sort:
self.sort_by_avg_age()
self.reset_try_list()
except:
logging.error(Ta('error-qAdd@1'), nzo_id)
logging.debug("Traceback: ", exc_info = True)
self.remove(nzo_id, False)
else:
logging.info("Item %s no longer in queue, omitting",
nzo_id)
@synchronized(NZBQUEUE_LOCK)
def change_opts(self, nzo_id, pp):
if nzo_id in self.__nzo_table:
self.__nzo_table[nzo_id].set_opts(pp)
@synchronized(NZBQUEUE_LOCK)
def change_script(self, nzo_id, script):
if nzo_id in self.__nzo_table:
self.__nzo_table[nzo_id].set_script(script)
@synchronized(NZBQUEUE_LOCK)
def change_cat(self, nzo_id, cat):
if nzo_id in self.__nzo_table:
self.__nzo_table[nzo_id].set_cat(cat)
@synchronized(NZBQUEUE_LOCK)
def change_name(self, nzo_id, name):
if nzo_id in self.__nzo_table:
self.__nzo_table[nzo_id].set_name(name)
@synchronized(NZBQUEUE_LOCK)
def get_nzo(self, nzo_id):
if nzo_id in self.__nzo_table:
return self.__nzo_table[nzo_id]
else:
return None
@synchronized(NZBQUEUE_LOCK)
def add(self, nzo, save=True):
sabnzbd.QUEUECOMPLETEACTION_GO = False
# Reset try_lists
nzo.reset_try_list()
self.reset_try_list()
if not nzo.nzo_id:
nzo.nzo_id = sabnzbd.get_new_id('nzo')
if nzo.nzo_id:
nzo.deleted = False
priority = nzo.get_priority()
self.__nzo_table[nzo.nzo_id] = nzo
if priority == TOP_PRIORITY:
#A top priority item (usually a completed download fetching pars)
#is added to the top of the queue
self.__nzo_list.insert(0, nzo)
elif priority == LOW_PRIORITY:
self.__nzo_list.append(nzo)
else:
#for high priority we need to add the item at the bottom
#of any other high priority items above the normal priority
#for normal priority we need to add the item at the bottom
#of the normal priority items above the low priority
if self.__nzo_list:
pos = 0
added = False
for position in self.__nzo_list:
if position.get_priority() < priority:
self.__nzo_list.insert(pos, nzo)
added=True
break
pos+=1
if not added:
#if there are no other items classed as a lower priority
#then it will be added to the bottom of the queue
self.__nzo_list.append(nzo)
else:
#if the queue is empty then simple append the item to the bottom
self.__nzo_list.append(nzo)
if save:
self.save()
if nzo.get_status() not in ('Fetching',):
osx.sendGrowlMsg(T('grwl-nzbadd-title'),nzo.get_filename(),osx.NOTIFICATION['download'])
if self.__auto_sort:
self.sort_by_avg_age()
@synchronized(NZBQUEUE_LOCK)
def remove(self, nzo_id, add_to_history = True, unload=False, save=True, cleanup=True):
if nzo_id in self.__nzo_table:
nzo = self.__nzo_table.pop(nzo_id)
nzo.deleted = True
self.__nzo_list.remove(nzo)
if add_to_history:
# Create the history DB instance
history_db = database.get_history_handle()
# Add the nzo to the database. Only the path, script and time taken is passed
# Other information is obtained from the nzo
history_db.add_history_db(nzo, '', '', 0, '', '')
history_db.close()
elif cleanup:
self.cleanup_nzo(nzo)
sabnzbd.remove_data(nzo_id)
if save:
self.save()
@synchronized(NZBQUEUE_LOCK)
def remove_multiple(self, nzo_ids):
for nzo_id in nzo_ids:
self.remove(nzo_id, add_to_history = False, save = False)
self.save()
@synchronized(NZBQUEUE_LOCK)
def remove_all(self):
lst = []
for nzo_id in self.__nzo_table:
lst.append(nzo_id)
for nzo_id in lst:
nzo = self.__nzo_table.pop(nzo_id)
nzo.deleted = True
self.__nzo_list.remove(nzo)
self.cleanup_nzo(nzo)
sabnzbd.remove_data(nzo_id)
del lst
self.save()
@synchronized(NZBQUEUE_LOCK)
def remove_nzf(self, nzo_id, nzf_id):
if nzo_id in self.__nzo_table:
nzo = self.__nzo_table[nzo_id]
nzf = nzo.get_nzf_by_id(nzf_id)
if nzf:
post_done = nzo.remove_nzf(nzf)
if post_done:
self.remove(nzo_id, add_to_history = False)
@synchronized(NZBQUEUE_LOCK)
def pause_multiple_nzo(self, nzo_ids):
for nzo_id in nzo_ids:
self.pause_nzo(nzo_id)
@synchronized(NZBQUEUE_LOCK)
def pause_nzo(self, nzo_id):
if nzo_id in self.__nzo_table:
nzo = self.__nzo_table[nzo_id]
nzo.pause_nzo()
logging.debug("Paused nzo: %s", nzo_id)
@synchronized(NZBQUEUE_LOCK)
def resume_multiple_nzo(self, nzo_ids):
for nzo_id in nzo_ids:
self.resume_nzo(nzo_id)
@synchronized(NZBQUEUE_LOCK)
def resume_nzo(self, nzo_id):
if nzo_id in self.__nzo_table:
nzo = self.__nzo_table[nzo_id]
nzo.resume_nzo()
logging.debug("Resumed nzo: %s", nzo_id)
@synchronized(NZBQUEUE_LOCK)
def switch(self, item_id_1, item_id_2):
try:
# Allow an index as second parameter, easier for some skins
i = int(item_id_2)
item_id_2 = self.__nzo_list[i].nzo_id
except:
pass
try:
nzo1 = self.__nzo_table[item_id_1]
nzo2 = self.__nzo_table[item_id_2]
except KeyError:
# One or both jobs missing
return (-1, 0)
#get the priorities of the two items
nzo1_priority = nzo1.get_priority()
nzo2_priority = nzo2.get_priority()
try:
#get the item id of the item below to use in priority changing
item_id_3 = self.__nzo_list[i+1].nzo_id
#if there is an item below the id1 and id2 then we need that too
#to determine whether to change the priority
nzo3 = self.__nzo_table[item_id_3]
nzo3_priority = nzo3.get_priority()
#if id1 is surrounded by items of a different priority then change it's pririty to match
if nzo2_priority != nzo1_priority and nzo3_priority != nzo1_priority or nzo2_priority > nzo1_priority:
nzo1.set_priority(nzo2_priority)
except:
nzo1.set_priority(nzo2_priority)
item_id_pos1 = -1
item_id_pos2 = -1
for i in xrange(len(self.__nzo_list)):
if item_id_1 == self.__nzo_list[i].nzo_id:
item_id_pos1 = i
elif item_id_2 == self.__nzo_list[i].nzo_id:
item_id_pos2 = i
if (item_id_pos1 > -1) and (item_id_pos2 > -1):
item = self.__nzo_list[item_id_pos1]
del self.__nzo_list[item_id_pos1]
self.__nzo_list.insert(item_id_pos2, item)
return (item_id_pos2, nzo1.get_priority())
# If moving failed/no movement took place
return (-1, nzo1.get_priority())
@synchronized(NZBQUEUE_LOCK)
def get_position(self, nzb_id):
for i in xrange(len(self.__nzo_list)):
if nzb_id == self.__nzo_list[i].nzo_id:
return i
return -1
@synchronized(NZBQUEUE_LOCK)
def move_up_bulk(self, nzo_id, nzf_ids):
if nzo_id in self.__nzo_table:
self.__nzo_table[nzo_id].move_up_bulk(nzf_ids)
@synchronized(NZBQUEUE_LOCK)
def move_top_bulk(self, nzo_id, nzf_ids):
if nzo_id in self.__nzo_table:
self.__nzo_table[nzo_id].move_top_bulk(nzf_ids)
@synchronized(NZBQUEUE_LOCK)
def move_down_bulk(self, nzo_id, nzf_ids):
if nzo_id in self.__nzo_table:
self.__nzo_table[nzo_id].move_down_bulk(nzf_ids)
@synchronized(NZBQUEUE_LOCK)
def move_bottom_bulk(self, nzo_id, nzf_ids):
if nzo_id in self.__nzo_table:
self.__nzo_table[nzo_id].move_bottom_bulk(nzf_ids)
@synchronized(NZBQUEUE_LOCK)
def sort_by_avg_age(self, reverse=False):
logging.info("Sorting by average date...(reversed:%s)", reverse)
self.__nzo_list = sort_queue_function(self.__nzo_list, _nzo_date_cmp, reverse)
@synchronized(NZBQUEUE_LOCK)
def sort_by_name(self, reverse=False):
logging.info("Sorting by name...(reversed:%s)", reverse)
self.__nzo_list = sort_queue_function(self.__nzo_list, _nzo_name_cmp, reverse)
@synchronized(NZBQUEUE_LOCK)
def sort_by_size(self, reverse=False):
logging.info("Sorting by size...(reversed:%s)", reverse)
self.__nzo_list = sort_queue_function(self.__nzo_list, _nzo_size_cmp, reverse)
@synchronized(NZBQUEUE_LOCK)
def sort_queue(self, field, reverse=False):
if isinstance(reverse, str):
if reverse.lower() == 'desc':
reverse = True
else:
reverse = False
if reverse is None:
reverse = False
if field.lower() == 'name':
self.sort_by_name(reverse)
elif field.lower() == 'size' or field.lower() == 'bytes':
self.sort_by_size(reverse)
elif field.lower() == 'avg_age':
self.sort_by_avg_age(reverse)
else:
logging.debug("Sort: %s not recognised", field)
@synchronized(NZBQUEUE_LOCK)
def set_priority(self, nzo_id, priority):
""" Sets the priority on the nzo and places it in the queue at the approrioate position """
try:
priority = int(priority)
nzo = self.__nzo_table[nzo_id]
nzo_id_pos1 = -1
pos = -1
# Get the current position in the queue
for i in xrange(len(self.__nzo_list)):
if nzo_id == self.__nzo_list[i].nzo_id:
nzo_id_pos1 = i
break
# Don't change priority and order if priority is the same as asked
if priority == self.__nzo_list[nzo_id_pos1].get_priority():
return nzo_id_pos1
nzo.set_priority(priority)
if nzo_id_pos1 != -1:
del self.__nzo_list[nzo_id_pos1]
if priority == TOP_PRIORITY:
#A top priority item (usually a completed download fetching pars)
#is added to the top of the queue
self.__nzo_list.insert(0, nzo)
pos = 0
elif priority == LOW_PRIORITY:
pos = len(self.__nzo_list)
self.__nzo_list.append(nzo)
else:
# for high priority we need to add the item at the bottom
#of any other high priority items above the normal priority
# for normal priority we need to add the item at the bottom
#of the normal priority items above the low priority
if self.__nzo_list:
p = 0
added = False
for position in self.__nzo_list:
if position.get_priority() < priority:
self.__nzo_list.insert(p, nzo)
pos = p
added=True
break
p+=1
if not added:
#if there are no other items classed as a lower priority
#then it will be added to the bottom of the queue
pos = len(self.__nzo_list)
self.__nzo_list.append(nzo)
else:
#if the queue is empty then simple append the item to the bottom
self.__nzo_list.append(nzo)
pos = 0
return pos
except:
return -1
@synchronized(NZBQUEUE_LOCK)
def set_priority_multiple(self, nzo_ids, priority):
try:
n = -1
for nzo_id in nzo_ids:
n = self.set_priority(nzo_id, priority)
return n
except:
return -1
@synchronized(NZBQUEUE_LOCK)
def set_original_dirname(self, nzo_id, name):
try:
if name:
nzo = self.__nzo_table[nzo_id]
name = sanitize_foldername(name)
nzo.set_original_dirname(name)
except:
pass
@synchronized(NZBQUEUE_LOCK)
def reset_try_lists(self, nzf = None, nzo = None):
if nzf:
nzf.reset_try_list()
if nzo:
nzo.reset_try_list()
self.reset_try_list()
@synchronized(NZBQUEUE_LOCK)
def reset_all_try_lists(self):
for nzo in self.__nzo_list:
nzo.reset_all_try_lists()
self.reset_try_list()
@synchronized(NZBQUEUE_LOCK)
def has_articles_for(self, server):
''' Check whether there are any pending articles for the downloader '''
if not self.__nzo_list:
return False
elif self.__top_only:
for nzo in self.__nzo_list:
# Ignore any items that are in a paused or grabbing state
if nzo.get_status() not in ('Paused', 'Grabbing'):
return not nzo.server_in_try_list(server)
else:
return not self.server_in_try_list(server)
@synchronized(NZBQUEUE_LOCK)
def has_forced_items(self):
''' Check if the queue contains any Forced
Priority items to download while paused '''
for nzo in self.__nzo_list:
if nzo.get_priority() == TOP_PRIORITY and nzo.get_status() != 'Paused':
return True
return False
@synchronized(NZBQUEUE_LOCK)
def get_article(self, server):
if self.__top_only:
if self.__nzo_list:
for nzo in self.__nzo_list:
if not nzo.get_status() == 'Paused':
article = nzo.get_article(server)
if article:
return article
else:
for nzo in self.__nzo_list:
# Don't try to get an article if server is in try_list of nzo
if not nzo.server_in_try_list(server) and nzo.get_status() != 'Paused':
article = nzo.get_article(server)
if article:
return article
# No articles for this server, block server (until reset issued)
self.add_to_try_list(server)
@synchronized(NZBQUEUE_LOCK)
def register_article(self, article):
nzf = article.nzf
nzo = nzf.nzo
if nzo.deleted or nzf.deleted:
logging.debug("Discarding article %s, no longer in queue", article.article)
return
file_done, post_done, reset = nzo.remove_article(article)
filename = nzf.get_filename()
if reset:
self.reset_try_list()
if file_done:
if nzo.extra3 is None or time.time() > nzo.extra3:
sabnzbd.save_data(nzo, nzo.nzo_id)
if nzo.extra4 is None:
nzo.extra3 = None
else:
nzo.extra3 = time.time() + nzo.extra4
_type = nzf.get_type()
# Only start decoding if we have a filename and type
if filename and _type:
sabnzbd.assembler.process((nzo, nzf))
else:
logging.warning(Ta('warn-unknownEncoding@1'), filename)
if post_done:
self.remove(nzo.nzo_id, add_to_history=False, cleanup=False)
if not self.__nzo_list:
# Close server connections
if cfg.AUTODISCONNECT.get():
sabnzbd.downloader.disconnect()
# Sets the end-of-queue back on if disabled
# adding an nzb and re-adding for more blocks disables it
if sabnzbd.QUEUECOMPLETEACTION:
sabnzbd.QUEUECOMPLETEACTION_GO = True
# Notify assembler to call postprocessor
sabnzbd.assembler.process((nzo, None))
@synchronized(NZBQUEUE_LOCK)
def queue_info(self, for_cli = False):
bytes_left = 0
bytes = 0
pnfo_list = []
for nzo in self.__nzo_list:
pnfo = nzo.gather_info(for_cli = for_cli)
if nzo.get_status() != 'Paused':
bytes += pnfo[PNFO_BYTES_FIELD]
bytes_left += pnfo[PNFO_BYTES_LEFT_FIELD]
pnfo_list.append(pnfo)
return (bytes, bytes_left, pnfo_list)
@synchronized(NZBQUEUE_LOCK)
def is_empty(self):
empty = True
for nzo in self.__nzo_list:
if not nzo.futuretype:
empty = False
break
return empty
@synchronized(NZBQUEUE_LOCK)
def cleanup_nzo(self, nzo):
nzo.purge_data()
sabnzbd.articlecache.method.purge_articles(nzo.saved_articles)
for hist_item in self.__downloaded_items:
# refresh fields & delete nzo reference
if hist_item.nzo and hist_item.nzo == nzo:
hist_item.cleanup()
logging.debug('%s cleaned up',
nzo.get_dirname())
@synchronized(NZBQUEUE_LOCK)
def debug(self):
return (self.__downloaded_items[:], self.__nzo_list[:],
self.__nzo_table.copy(), self.try_list[:])
def get_urls(self):
""" Return list of future-types needing URL """
lst = []
for nzo_id in self.__nzo_table:
nzo = self.__nzo_table[nzo_id]
url = nzo.get_future()
if nzo.futuretype and url.lower().startswith('http'):
lst.append((url, nzo))
return lst
def get_msgids(self):
""" Return list of future-types needing msgid """
lst = []
for nzo_id in self.__nzo_table:
nzo = self.__nzo_table[nzo_id]
msgid = nzo.get_future()
if nzo.futuretype and (msgid.isdigit() or len(msgid)==5):
lst.append((msgid, nzo))
return lst
def __repr__(self):
return "<NzbQueue>"
#-------------------------------------------------------------------------------
def _nzo_date_cmp(nzo1, nzo2):
avg_date1 = nzo1.get_avg_date()
avg_date2 = nzo2.get_avg_date()
if avg_date1 is None and avg_date2 is None:
return 0
if avg_date1 is None:
avg_date1 = datetime.datetime.now()
elif avg_date2 is None:
avg_date2 = datetime.datetime.now()
return cmp(avg_date1, avg_date2)
def _nzo_name_cmp(nzo1, nzo2):
return cmp(nzo1.get_filename(), nzo2.get_filename())
def _nzo_size_cmp(nzo1, nzo2):
return cmp(nzo1.get_bytes(), nzo2.get_bytes())
def sort_queue_function(nzo_list, method, reverse):
super_high_priority = [nzo for nzo in nzo_list if nzo.get_priority() == TOP_PRIORITY]
high_priority = [nzo for nzo in nzo_list if nzo.get_priority() == HIGH_PRIORITY]
normal_priority = [nzo for nzo in nzo_list if nzo.get_priority() == NORMAL_PRIORITY]
low_priority = [nzo for nzo in nzo_list if nzo.get_priority() == LOW_PRIORITY]
super_high_priority.sort(cmp=method, reverse=reverse)
high_priority.sort(cmp=method, reverse=reverse)
normal_priority.sort(cmp=method, reverse=reverse)
low_priority.sort(cmp=method, reverse=reverse)
new_list = super_high_priority
new_list.extend(high_priority)
new_list.extend(normal_priority)
new_list.extend(low_priority)
# Make sure any left-over jobs enter the new list
for item in nzo_list:
if item not in new_list:
new_list.append(item)
return new_list
#-------------------------------------------------------------------------------
# NZBQ Wrappers
__NZBQ = None # Global pointer to NzbQueue instance
def init():
global __NZBQ
if __NZBQ:
__NZBQ.__init__()
else:
__NZBQ = NzbQueue()
def start():
global __NZBQ
if __NZBQ: __NZBQ.start()
def stop():
global __NZBQ
if __NZBQ:
__NZBQ.stop()
try:
__NZBQ.join()
except:
pass
def debug():
global __NZBQ
if __NZBQ: return __NZBQ.debug()
def move_up_bulk(nzo_id, nzf_ids):
global __NZBQ
if __NZBQ: __NZBQ.move_up_bulk(nzo_id, nzf_ids)
def move_top_bulk(nzo_id, nzf_ids):
global __NZBQ
if __NZBQ: __NZBQ.move_top_bulk(nzo_id, nzf_ids)
def move_down_bulk(nzo_id, nzf_ids):
global __NZBQ
if __NZBQ: __NZBQ.move_down_bulk(nzo_id, nzf_ids)
def move_bottom_bulk(nzo_id, nzf_ids):
global __NZBQ
if __NZBQ: __NZBQ.move_bottom_bulk(nzo_id, nzf_ids)
def remove_nzo(nzo_id, add_to_history = True, unload=False):
global __NZBQ
if __NZBQ: __NZBQ.remove(nzo_id, add_to_history, unload)
def remove_multiple_nzos(nzo_ids):
global __NZBQ
if __NZBQ: __NZBQ.remove_multiple(nzo_ids)
def remove_all_nzo():
global __NZBQ
if __NZBQ: __NZBQ.remove_all()
def remove_nzf(nzo_id, nzf_id):
global __NZBQ
if __NZBQ: __NZBQ.remove_nzf(nzo_id, nzf_id)
def sort_by_avg_age(reverse=False):
global __NZBQ
if __NZBQ: __NZBQ.sort_by_avg_age(reverse)
def sort_by_name(reverse=False):
global __NZBQ
if __NZBQ: __NZBQ.sort_by_name(reverse)
def sort_by_size(reverse=False):
global __NZBQ
if __NZBQ: __NZBQ.sort_by_size(reverse)
def change_opts(nzo_id, pp):
global __NZBQ
if __NZBQ: __NZBQ.change_opts(nzo_id, pp)
def change_script(nzo_id, script):
global __NZBQ
if __NZBQ: __NZBQ.change_script(nzo_id, script)
def change_cat(nzo_id, cat):
global __NZBQ
if __NZBQ: __NZBQ.change_cat(nzo_id, cat)
def change_name(nzo_id, name):
global __NZBQ
if __NZBQ: __NZBQ.change_name(nzo_id, name)
def get_article(host):
global __NZBQ
if __NZBQ: return __NZBQ.get_article(host)
def has_articles():
global __NZBQ
if __NZBQ: return not __NZBQ.is_empty()
def has_articles_for(server):
global __NZBQ
if __NZBQ: return __NZBQ.has_articles_for(server)
def has_forced_items():
global __NZBQ
if __NZBQ: return __NZBQ.has_forced_items()
def register_article(article):
global __NZBQ
if __NZBQ: return __NZBQ.register_article(article)
def switch(nzo_id1, nzo_id2):
global __NZBQ
if __NZBQ:
return __NZBQ.switch(nzo_id1, nzo_id2)
def get_position(nzo_id):
global __NZBQ
if __NZBQ:
return __NZBQ.get_position(nzo_id)
def rename_nzo(nzo_id, name):
global __NZBQ
if __NZBQ: __NZBQ.change_name(nzo_id, name)
def history_info():
global __NZBQ
if __NZBQ: return __NZBQ.history_info()
def queue_info(for_cli = False):
global __NZBQ
if __NZBQ: return __NZBQ.queue_info(for_cli = for_cli)
#def purge_history(job=None):
# global __NZBQ
# if __NZBQ: __NZBQ.purge(job)
#def remove_multiple_history(jobs=None):
# global __NZBQ
# if __NZBQ: __NZBQ.remove_multiple_history(jobs)
def get_msgids():
global __NZBQ
if __NZBQ: return __NZBQ.get_msgids()
def get_urls():
global __NZBQ
if __NZBQ: return __NZBQ.get_urls()
def pause_multiple_nzo(jobs):
global __NZBQ
if __NZBQ: __NZBQ.pause_multiple_nzo(jobs)
def resume_multiple_nzo(jobs):
global __NZBQ
if __NZBQ: __NZBQ.resume_multiple_nzo(jobs)
def cleanup_nzo(nzo):
global __NZBQ
if __NZBQ: __NZBQ.cleanup_nzo(nzo)
def reset_try_lists(nzf = None, nzo = None):
global __NZBQ
if __NZBQ: __NZBQ.reset_try_lists(nzf, nzo)
def reset_all_try_lists():
global __NZBQ
if __NZBQ: __NZBQ.reset_all_try_lists()
def save():
global __NZBQ
if __NZBQ: __NZBQ.save()
def generate_future(msg, pp, script, cat, url, priority, nzbname):
global __NZBQ
if __NZBQ: return __NZBQ.generate_future(msg, pp, script, cat, url, priority, nzbname)
def set_top_only(value):
global __NZBQ
if __NZBQ: __NZBQ.set_top_only(value)
#-------------------------------------------------------------------------------
# Synchronized wrappers
@synchronized_CV
def add_nzo(nzo):
global __NZBQ
if __NZBQ: __NZBQ.add(nzo)
@synchronized_CV
def insert_future_nzo(future_nzo, filename, msgid, data, pp=None, script=None, cat=None, priority=NORMAL_PRIORITY, nzbname=None, nzo_info=None):
global __NZBQ
if nzo_info is None:
nzo_info = {}
if __NZBQ: __NZBQ.insert_future(future_nzo, filename, msgid, data, pp=pp, script=script, cat=cat, priority=priority, nzbname=nzbname, nzo_info=nzo_info)
@synchronized_CV
def set_priority(nzo_id, priority):
global __NZBQ
if __NZBQ:
return __NZBQ.set_priority(nzo_id, priority)
@synchronized_CV
def get_nzo(nzo_id):
global __NZBQ
if __NZBQ:
return __NZBQ.get_nzo(nzo_id)
@synchronized_CV
def set_priority_multiple(nzo_ids, priority):
global __NZBQ
if __NZBQ: return __NZBQ.set_priority_multiple(nzo_ids, priority)
@synchronized_CV
def sort_queue(field, reverse=False):
global __NZBQ
if __NZBQ: __NZBQ.sort_queue(field, reverse)