queue sorter

Come up with a useful post-processing script? Share it here!
Post Reply
doubledrat
Release Testers
Release Testers
Posts: 180
Joined: February 20th, 2008, 3:16 pm

queue sorter

Post by doubledrat »

Hi all

I don't know about you, but I generally have a long queue and I don't find the 4 priorities enough to give me the granularity I want, so I wrote this bit of python to sort the queue.  IT WILL ONLY WORK ON V5 as it uses the priority.

THIS IS NOT A POSTPROC SCRIPT.  I run it after I add anything to the queue. (with a 30 sec delay to ensure any nzb I've added has been retrieved and processed - otherwise it is called "fetching..." which is no help!)

Code: Select all

import urllib
import xml.dom.minidom
import re
import time
import os
import sys
import string
import pickle
import operator

from stat import S_ISDIR

##############
# queue sort #
##############

# will sort you SAB queue based on a control file in the following format
# priority category title

# regular expressions are supported.  only the priority is mandatory.  you should have at least all the priorities defined or results will be unpredictable
# this list is evaluated in reverse order.  if an entry in the queue matches the criteria, it is moved to that new position.  as this is done in reverse order
# queue entries can really only be demoted, not promoted.  e.g. in the below example, the
# .*tuck.* entry will never be evaluated for low hdtv or tv shows as the "low hdtv" and "low tv" will match first.  If you want to promote nip tuck
# you will have to make sure that the lower tv lines don't match it by using an excluding regex, something like ^(?:(?!nip.*tuck).)*$ e.g.

#		low .* .*tuck.*     \
#		low hdtv             - will not work
#		low tv              /


#		low .* .*tuck.*                   \
#		low hdtv ^(?:(?!nip.*tuck).)*$     - will work
#		low tv ^(?:(?!nip.*tuck).)*$      /


# you can promote multiple strings with the | character - ^(?:(?!nip.*tuck|including this|or this).)*$

# example file

#		force
#		high
#		high iphone
#		normal
#		normal iphone
#		low
#		low .* .*tuck.*
#		low hdtv ^(?:(?!nip.*tuck).)*$
#		low tv ^(?:(?!nip.*tuck).)*$
#		low .* .*fornicat.*
#		low .* .*30 rock.*
#		low .* .*warehouse.*
#		low .* .*think you can.*
#		low .* .*heroes.*
#		low consoles
#		low usawii
#		low games
#		low iphone
#		low iphone .*uk.*
#		low iphone .*dopey.*
#		low .*tv .*family.*guy.*
#		
################################### change to your own values #####################################

# your SABNZB address
my_SAB="http://192.168.0.3:8080"
# additional SAB parameters to e.g. specify the category, and/or script to run.  see http://sabnzbd.wikidot.com/automation-support
my_SAB_params="&apikey=yourapikey"

# config file
config_file=r"D:\user\sab_priorities.txt"

################################### change to your own values #####################################


#  Change log
# 091205 original version
# 091207 added the ability to use #s to comment the config file.

import glob

pri={"force":2, "high":1, "normal":0, "low":-1}

illegal = r'\/<>?*:;|"'
legal   = r'++{}!@--#`'
translate_table = string.maketrans(illegal, legal)

# read config file in format
# priority category title

w_priority=[]
w_category=[]
w_title=[]
w_order=[]

order=0
fileHandle = open ( config_file, 'r' )
for line in fileHandle:
        line=line.lower()
        # ignore comments
        line=re.sub("\#.*","",line)
        line=line.strip()
        if len(line)>0:
	        cat=".*"
	        tit=".*"
	        try:
	                pri, cat, tit=line.split(" ",2)
	        except:
	                try:
	                        pri, cat=line.split(" ",1)
	                except:
	                        pri=line
	        w_priority.append(pri)
	        w_category.append(cat)
	        w_title.append(tit)
	        w_order.append(order)
#	        print pri, cat, tit, order
	        order+=1
fileHandle.close()

# reverse the order to make the subsequent looping easier
w_priority.reverse()
w_category.reverse()
w_title.reverse()
w_order.reverse()


index=0
q_priority=[]
q_category=[]
q_title=[]
q_jobID=[]
q_new_position=[]

# go through the queue and store the pertinent information

queue=xml.dom.minidom.parse(urllib.urlopen(my_SAB+"/sabnzbd/api?mode=queue&output=xml"+my_SAB_params))
for job in queue.getElementsByTagName("slot"):
	title=job.getElementsByTagName("filename")[0].childNodes[0].data
	title=title.lower()
	itempriority=job.getElementsByTagName("priority")[0].childNodes[0].data
	itempriority=itempriority.lower()
#	print priority, pri[itempriority]
	jobID=job.getElementsByTagName("nzo_id")[0].childNodes[0].data
	category=job.getElementsByTagName("cat")[0].childNodes[0].data
	category=category.lower()
# where in the pecking order should this be?  Go through the desired order in reverse
# when we get a match, that's the position of this item in the new ordered list
	neworder=order-1
	for wpri, wcat, wtit, word in zip(w_priority, w_category, w_title, w_order):
		if re.match(wpri,itempriority) and re.match(wcat, category) and re.match(wtit,title):
			neworder=word
			break
#	print str(index)+","+str(neworder)+","+jobID+","+itempriority+","+category+","+title
	q_new_position.append(neworder)
	q_title.append(title)
	q_jobID.append(jobID)
	index+=1

index-=1
tosort=zip(q_new_position, q_title, q_jobID)
tosort.sort(key=operator.itemgetter(0)) # sort on the first field only
Qpos=0

print "New queue order is -"
print ""
for posn, tit, ID in tosort:
	urllib.urlopen(my_SAB+"/sabnzbd/api?mode=switch&value="+ID+"&value2="+str(Qpos)+my_SAB_params)
	Qpos+=1
	print tit
an example control file -

Code: Select all

# demotion is the name of the game here.  you need tricky regexes to promote an entry!
# expressions are evaluated from the bottom up.  once a match to all 3 attributes is made, that's where the queued item will end up
# regular expressions can be used in any column.  an omitted column defaults to ".*" e.g. 
#     force is the same as force .* .* 
#     high iphone is the same as high iphone .*

# priority category title
force

high
high music
high iphone

normal
normal music
normal iphone

low
low iphone .*uk.*
low iphone .*1\.1.*
low .* .*nip.*tuck.*

# below 2 ignore nip tuck to allow promotion rather than demotion
low hdtv ^(?:(?!nip.*tuck).)*$
low music
low tv ^(?:(?!nip.*tuck).)*$

low .* .*fornicat.*
low .* .*30 rock.*
low .* .*warehouse.*
low .* .*think you can.*
low .* ^lost.*
low .* .*heroes.*
low consoles
low consoles ^(?:(?!guitar).)*$ # guitar to allow promotion rather than demotion

low games
low usawii
low iphone ^(?:(?!uk).)*$             # low iphone but exclude anything with uk in it
low iphone .*1\.[01].*
low iphone .*dopey.*
low .*tv .*family.*guy.*
Last edited by doubledrat on February 13th, 2010, 4:31 am, edited 1 time in total.
rollingeyeball
Release Testers
Release Testers
Posts: 181
Joined: January 30th, 2009, 12:26 pm

Re: queue sorter

Post by rollingeyeball »

I think this is GREAT, but I don't usually have a need for it.
I shall monitor this thread though.

Good work doubledrat!
By the way - Any ideas on how one could automate this to run after adding something to queue?. Just out of curiosity :)
doubledrat
Release Testers
Release Testers
Posts: 180
Joined: February 20th, 2008, 3:16 pm

Re: queue sorter

Post by doubledrat »

well my items get added (mainly) through scripts, so I just call this one after adding something.  not so sure about how you'd do it if adding manually.  just run it manually I guess?
Post Reply