2009-11-02, 23:38
I've made these scripts, and thought I'd share them.
This is the first code I've ever written in Python and it's taken probably 4-5 hour total to make these. I'm a C# coder by trade, so forgive the somewhat C#'ish way of naming things.
They're not pretty, but they work. Someday I might clean them, but until then, maybe they'll be of help to someone.
Also, I didn't bother learning about logging in python, so I just print stuff and >> it to some logfile when I execute the script.
For starters, what does these scripts actually do:
ezrss.py:
Downloads torrents off ezrss.it for shows you've "subscribed" to. Subscription in this case, is defined by the shows you've got a directory for. It can EASILY be modified to use a show-per-line file if you'd rather have that.
adoptFile.py:
Called by rtorrent on hash_done (more on that later), whenever a download is completed.
I'll walk through all your "TV Show Directories", and consider all the directories as "adoption candidates".
It should be safe against i.e. cases like this.
Consider this filename:
Super.Heroes.S01E03.somecrap.avi
Consider these folders:
/TV Shows/Heroes
/TV Shows/Super Heroes
Every word in the directory name must be present in the filename, or it won't be considered a candidate.
However, "Heroes" would be considered a candidate for the file above, but since "Super Heroes" have two matches, that folder will be considered. The winning folder will always be the one with the highest "score".
Now, the code...
First, the script that downloads stuff from EZRSS to rtorrents watch folder:
About this script:
1) The showfolders.list file contains a list of where my TV Shows are stored. I've got two harddrives where I keep those:
/media/data1/TV Shows
/media/data2/TV Shows
Each of these folders contains folders with this typical pattern:
/ShowName/Season [n]
This script assumes you want to subscribe to anything you've got a show for.
If there is a /ShowName/keywords.list, the script will also include these keywords when searching in the RSS feed. I.e. you'd want to include a 720p line in keywords.list for shows you prefer in HD Quality.
Secondly, the script that sorts anything rtorrent completes:
About this:
This is activated by rtorrent from .rtorrent.rc. These are the lines for it:
(post size limit hit)
This is the first code I've ever written in Python and it's taken probably 4-5 hour total to make these. I'm a C# coder by trade, so forgive the somewhat C#'ish way of naming things.
They're not pretty, but they work. Someday I might clean them, but until then, maybe they'll be of help to someone.
Also, I didn't bother learning about logging in python, so I just print stuff and >> it to some logfile when I execute the script.
For starters, what does these scripts actually do:
ezrss.py:
Downloads torrents off ezrss.it for shows you've "subscribed" to. Subscription in this case, is defined by the shows you've got a directory for. It can EASILY be modified to use a show-per-line file if you'd rather have that.
adoptFile.py:
Called by rtorrent on hash_done (more on that later), whenever a download is completed.
I'll walk through all your "TV Show Directories", and consider all the directories as "adoption candidates".
It should be safe against i.e. cases like this.
Consider this filename:
Super.Heroes.S01E03.somecrap.avi
Consider these folders:
/TV Shows/Heroes
/TV Shows/Super Heroes
Every word in the directory name must be present in the filename, or it won't be considered a candidate.
However, "Heroes" would be considered a candidate for the file above, but since "Super Heroes" have two matches, that folder will be considered. The winning folder will always be the one with the highest "score".
Now, the code...
First, the script that downloads stuff from EZRSS to rtorrents watch folder:
Code:
import urllib, os, feedparser
def getDownloadHistory(historyFile):
dh = []
if not os.access(historyFile, os.R_OK):
return dh
f = open(historyFile, 'r')
for line in f:
dh.append(line.replace('\n',''))
f.close()
return dh
def markAsDownloaded(historyFile, url):
f = open(historyFile, 'a')
f.write(url)
f.write('\n')
f.close()
def isShowSubscribed(showname, subscribedShows):
for s in subscribedShows:
parts = s.split()
reqScore = 0
score = 0
for part in parts:
if showname.lower().find(part.lower()) >= 0:
score = score + 1
reqScore = reqScore + 1
isSubscribed = reqScore == score
#print '% scored %i out of %i' % (showname, score, reqScore)
if isSubscribed:
return True
return False
def downloadFile(localDir, remoteFile):
filename = remoteFile.split('/')[-1]
webFile = urllib.urlopen(remoteFile)
localFile = open(localDir + filename, 'w')
localFile.write(webFile.read())
webFile.close()
localFile.close()
def getShowList(showfolderFile):
showfolders = []
f = open(showfolderFile, 'r')
for line in f:
sh = line.replace('\n','')
if len(sh) > 0:
showfolders.append(sh)
shows = []
for showfolder in showfolders:
dirs = filter(lambda x : os.path.isdir(os.path.join(showfolder, x)), os.listdir(showfolder))
for dir in dirs:
show = dir
xkeys = getFolderKeywords(showfolder + '/' + dir)
if(len(xkeys) > 0):
show = show + ' ' + xkeys
shows.append(show)
return shows
f = open(showFile, 'r')
shows = []
for show in f:
shows.append(show.replace('\n',''))
f.close()
return shows
def getFolderKeywords(dir):
xkeys = ''
xfile = dir + '/keywords.list'
if not os.access(xfile, os.R_OK):
return xkeys
f = open(xfile, 'r')
for key in f:
if len(xkeys) > 0:
xkeys = xkeys + ' '
xkeys = xkeys + key.replace('\n', '')
return xkeys
downloadTo = '/home/jonas/torrents/watch/'
historyFile = '/home/jonas/torrentscripts/dltorrents.list'
showfolderFile = '/home/jonas/torrentscripts/showfolders.list'
hist = getDownloadHistory(historyFile)
shows = getShowList(showfolderFile)
d = feedparser.parse("http://www.ezrss.it/feed/")
s = filter(lambda x: isShowSubscribed(x.title, shows), d.entries)
s = filter(lambda x: hist.count(x.link) == 0, s)
print 'Checking for new shows'
for show in s:
print '%s is new (%s)' % (show.title, show.link)
downloadFile(downloadTo, show.link)
markAsDownloaded(historyFile, show.link)
print 'Done'
About this script:
1) The showfolders.list file contains a list of where my TV Shows are stored. I've got two harddrives where I keep those:
/media/data1/TV Shows
/media/data2/TV Shows
Each of these folders contains folders with this typical pattern:
/ShowName/Season [n]
This script assumes you want to subscribe to anything you've got a show for.
If there is a /ShowName/keywords.list, the script will also include these keywords when searching in the RSS feed. I.e. you'd want to include a 720p line in keywords.list for shows you prefer in HD Quality.
Secondly, the script that sorts anything rtorrent completes:
Code:
import xmlrpclib, os, sys, re, shutil
def adoptionCandidates(basedir, file):
dirs = filter(lambda x : os.path.isdir(os.path.join(basedir, x)), os.listdir(basedir))
if os.path.isdir(file):
print '%s is a directory. Aborting' % file
return []
(filepath, filename) = os.path.split(file)
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
if filename.find(part) >= 0:
score = score + 1
if score == requiredScore:
candidates.append( (os.path.join(basedir, dir), score) )
#print '%s scored %i (req: %i)' % (dir, score, requiredScore)
#for (dir, score) in candidates:
# print '%s with score %i' % (dir, score)
return candidates
def getSeasonNumber(filename):
patterns = [
'.*S(\d+)E(\d+).*',
'.*(\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('started')
for dl in downloads:
rfile = rtorrent.d.get_base_filename(dl)
if rfile == filename:
return dl
def rtorrentNotifyMove(id, newBasePath):
rtorrent.d.set_directory(id, newBasePath)
rtorrent.d.resume(id)
print '--------------- BEGIN ---------------'
#basic input
orphanFile = sys.argv[1]
showLocations = ['/media/data2/TV Shows', '/media/data1/TV Shows']
allowedSourceLocation = '/home/jonas/torrents/completed'
#rtorrent xmlrpc
rtorrent = xmlrpclib.ServerProxy('http://localhost')
(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()
if os.path.isdir(orphanFile):
print 'STOP! Source is a directory and cannot be automaticly sorted!'
exit()
print 'Attempting to find a home for file %s' % orphanFile
for location in showLocations:
candidates.extend(adoptionCandidates(location, orphanFile))
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]
#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)
print 'Will move it to %s' % finaldir
#Check if season folder is present
if not os.path.isdir(finaldir):
print 'Season dir doesn\'t exsist. Creating now'
os.mkdir(finaldir)
rid = getRtorrentId(fname)
print '%s was resolved to rtorrent id: %s' % (fname, rid)
shutil.move(orphanFile, finaldir)
print 'Move successful. Notifying rtorrent about this'
print 'telling rtorrent to move %s to %s' % (rid, finaldir)
rtorrentNotifyMove(rid, finaldir)
print '----------------- done -----------------'
About this:
This is activated by rtorrent from .rtorrent.rc. These are the lines for it:
Code:
#Sort file
system.method.set_key = event.download.finished,move_complete,"d.set_directory=~/torrents/completed;execute=mv,-u,$d.get_base_path=,~/torrents/completed"
system.method.set_key = event.download.hash_done,sort_finished,"branch=$d.get_complete=,\"execute={~/torrentscripts/postProcessDownload.pl,$d.get_base_path=}\""
(post size limit hit)