From 67b0ec5741d327d27afe88783d85fcf2c4c4f204 Mon Sep 17 00:00:00 2001 From: David Runge Date: Sun, 3 Nov 2013 12:30:45 +0100 Subject: First commit --- bin/torrentSort.py | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 bin/torrentSort.py (limited to 'bin/torrentSort.py') diff --git a/bin/torrentSort.py b/bin/torrentSort.py new file mode 100644 index 0000000..e284a88 --- /dev/null +++ b/bin/torrentSort.py @@ -0,0 +1,220 @@ +#! /usr/bin/python +# simple python script to sort torrents +# modifications by xkonni +# - added folder sorting +# - added htdigest authorisation +# - fixed some minor glitches +# +# original version by jonassw from +# http://forum.xbmc.org/showthread.php?t=60749 + +# << DOCUMENTATION +# +# i) lighttpd configuration for htdigest +# server.modules += ( "mod_auth" ) +# auth.backend = "htdigest" +# auth.backend.htdigest.userfile = "/etc/lighttpd/auth" +# auth.debug = 2 +# auth.require = ( "/RPC2" => +# ( +# "method" => "digest", +# "realm" => "REALM", +# "require" => "valid-user" +# ) +# ) +# ii) i recommend starting this with a basic cron job you may find other +# suggestions like when rtorrent finishes hashing, but for me this caused +# lockups when starting rtorrent (as all downloads return hash_ok) +# +# */5 * * * * for i in /mnt/torrent/tv/*; do torrentSort.py $i > /dev/null; done +# +# DOCUMENTATION >> + + +import xmlrpclib, os, sys, re, shutil + + +class HTTPSDigestTransport(xmlrpclib.SafeTransport): + """ +Transport that uses urllib2 so that we can do Digest authentication. +Based upon code at http://bytes.com/topic/python/answers/509382-solution-xml-rpc-over-proxy +""" + + def __init__(self, username, pw, realm, verbose = None, use_datetime=0): + self.__username = username + self.__pw = pw + self.__realm = realm + self.verbose = verbose + self._use_datetime = use_datetime + + def request(self, host, handler, request_body, verbose): + import urllib2 + + url='https://'+host+handler + if verbose or self.verbose: + print "ProxyTransport URL: [%s]"%url + + request = urllib2.Request(url) + request.add_data(request_body) + # Note: 'Host' and 'Content-Length' are added automatically + request.add_header("User-Agent", self.user_agent) + request.add_header("Content-Type", "text/xml") # Important + + # setup digest authentication + authhandler = urllib2.HTTPDigestAuthHandler() + authhandler.add_password(self.__realm, url, self.__username, self.__pw) + opener = urllib2.build_opener(authhandler) + + #proxy_handler=urllib2.ProxyHandler() + #opener=urllib2.build_opener(proxy_handler) + f=opener.open(request) + return(self.parse_response(f)) + + +def adoptionCandidates(basedir, filename): + dirs = filter(lambda x : os.path.isdir(os.path.join(basedir, x)), os.listdir(basedir)) + + #set filename to lowercase for string comparisons + filename=filename.lower() + + ignoredPhrases = ['-','_'] + + candidates = [] + for dir in dirs: + dirParts = dir.split() + score = 0 + requiredScore = 0 + + for part in dirParts: + if ignoredPhrases.count(part) > 0: + continue + requiredScore = requiredScore + 1 + + #force lower case for string comparison. + part=part.lower() + # replace "'" with "" and add word to list + repPart = part.replace('\'','') + if repPart != part: + dirParts.append(repPart) + requiredScore -= 1 + if filename.find(part) >= 0: + score = score + 1 + if score == requiredScore: + candidates.append( (os.path.join(basedir, dir), score) ) + + return candidates + +def getSeasonNumber(filename): + patterns = [ + '.*S(\d+)E(\d+).*', + '.*S(\d+)(\.)?E(\d+).*', # hopefully matches series.s01.e05.avi + '(\d+)x(\d+).*', + '(\d+)(\d+)(\d+).*' + # commented out regex thought below Season was '4' not 14. Def better way of doing that + #top_gear.14x04.720p_hdtv_x264-fov.mkv + #'.*(\d+)x(\d+).*' + ] + + for pattern in patterns: + p = re.compile(pattern, re.I) + g = p.findall(orphanFile) + if len(g) > 0: + season = int(g[0][0]) + return season + return None + + +def getRtorrentId(filename): + downloads = rtorrent.download_list('') + for dl in downloads: + rfile = rtorrent.d.get_base_filename(dl) + if rfile == filename: + return dl + +# << CONFIGURATION +# i) FOLDER SETTINGS +showLocations = ['/mnt/media/tv'] +allowedSourceLocation = '/mnt/media/torrent/complete/tv' + +# ii) CONNECTION SETTINGS +# - using htdigest authorisation +digestTransport = HTTPSDigestTransport("username", "password", "realm") +rtorrent = xmlrpclib.ServerProxy('http://localhost',transport=digestTransport) +# - not using authorisation +# rtorrent = xmlrpclib.ServerProxy('http://localhost') + +# CONFIGURATION >> + +print '--------------- BEGIN ---------------' +orphanFile = sys.argv[1] +if os.path.isdir(orphanFile): + (fpath, fname) = os.path.split(orphanFile) + fname = os.path.relpath(orphanFile, allowedSourceLocation) + +else: + (fpath, fname) = os.path.split(orphanFile) +print 'File path: %s' % fpath +print 'File name: %s' % fname + +candidates = [] + +if not orphanFile.startswith(allowedSourceLocation): + print 'STOP! This file is not located in %s' % allowedSourceLocation + exit() + +print 'Attempting to find a home for file %s' % orphanFile + +for location in showLocations: + candidates.extend(adoptionCandidates(location, fname)) + +candidates.sort(lambda (da, sa), (db, sb): sb-sa) + +if len(candidates) <= 0: + print 'No one wanted this file :(' + exit() + +for (dir, score) in candidates: + print 'Candidate: %s with score %i' % (dir, score) + +print 'Winner is %s with score %i' % candidates[0] + +if os.path.isdir(orphanFile): + finaldir = candidates[0][0] + +else: + # Determine Season and Episode number + season = getSeasonNumber(fname) + if not season: + print 'STOP! Season could not be determined.' + exit() + + print 'Season was determined to be %i' % season + finaldir = os.path.join(candidates[0][0], 'Season %s' % season) + + # Check if season folder is present + if not os.path.isdir(finaldir): + print 'Season dir doesn\'t exist. Creating now' + os.mkdir(finaldir) + + if os.path.isfile(os.path.join(finaldir, fname)): + print 'error: file already exists, exiting' + sys.exit(1) + + print 'Will move file to %s' % finaldir + + +print 'Requesting id from rtorrent' +rid = getRtorrentId(fname) +print '%s was resolved to rtorrent id: %s' % (fname, rid) + +print 'Pausing rtorrent' +rtorrent.d.pause(rid) + +print 'Updating rtorrent' +rtorrent.d.set_directory(rid, finaldir) + +print 'Moving file' +shutil.move(orphanFile, finaldir) + +print 'Resuming rtorrent' +rtorrent.d.resume(rid) -- cgit v1.2.3-54-g00ecf