#!/usr/local/bin/python # -*- coding: UTF-8 -*- __author__ = "neuschnee" __version__ = "$Revision: 0.2 $" __copyright__ = "2006 blah blah" """ Synclosure automatically downloads files found in RSS enclosures. """ import feedparser, sys, os, urllib, ConfigParser, os, re #customized user agent, python docs to urllib class AppURLopener(urllib.FancyURLopener): def __init__(self, *args): self.version = "Synclosure 0.2" urllib.FancyURLopener.__init__(self, *args) urllib._urlopener = AppURLopener() feedlist, enclosures, oldenclosures, nl = [], [], [], '\n' basedir = '/home/nhewitt/.syn/exigo/' dldir = '/home/nhewitt/t' #OptParse is a pain, so as of now i'm sticking to that custom format configfile, cache, matchinfile, matchexfile = basedir+'sources.ini', basedir+'cache.ini', basedir+'match_include.ini', basedir+'match_exclude.ini' def WriteFile(filename, msg): if os.access(filename, os.W_OK) and os.path.isfile(filename): f = open(filename, 'a') f.write(msg) f.close() else: try: f = open(filename,'w') f.write(msg) f.close() except: print nl+'[error] couldnt create/access/read file (' + filename + '), ' \ 'check permissions.'+nl return False #load a file into a list, ignore lines beginning with a '#' def ParseFile(filename): result = [] if os.access(filename, os.W_OK) and os.path.isfile(filename): f = open(filename) for line in f.xreadlines(): if line[0] == '#': continue result.append(line[:-1]) f.close() else: return False return result #parse command line arguments, 'sys.argv' from optparse import * optParser = OptionParser() optParser.add_option( "-a", "--action", action="append", dest="action_list", nargs=2, help="File matching keyword (string 1) gets executed as param of program (string 2)") optParser.add_option( "-d", "--destination", action="store", dest="destination", help="Destination folder for downloaded files") (options, remainingArgs) = optParser.parse_args() action_list, destination = options.action_list, options.destination #define download folter, etc if destination and os.path.isdir(destination) and not os.path.isfile(destination): downloadfolder = destination else: downloadfolder = dldir if not os.path.isdir(downloadfolder): try: os.mkdir(downloadfolder) except: sys.exit(nl+'[error] cannot create download folder (' + downloadfolder + ') ' \ 'check permissions') # pickle this or something. ugly. defaultfeedlist = '# Default list of xml feeds with enclosures\n# this is a comment\n' \ 'http://fsa.com\n' \ 'http://asf.com\n' feedlist = ParseFile(configfile) #load rss list oldenclosures = ParseFile(cache) #load downloaded files list includes = ParseFile(matchinfile) #load regex include list excludes = ParseFile(matchexfile) #load regex exclude list if not feedlist: #feedlist empty, create default WriteFile(configfile, defaultfeedlist) feedlist = ParseFile(configfile) if not oldenclosures: #cache empty, create new file WriteFile(cache, '') oldenclosures = ParseFile(cache) for feed in feedlist: try: parsed = feedparser.parse(feed, agent="Synclosure 0.1") except KeyboardInterrupt: sys.exit(nl+'[error] parsing interrupted') except bozo_exception: #ignoring the feedparser 'parsing illformed xml' exception continue for entry in parsed['entries']: if entry.has_key('enclosures'): for _enclosure in entry['enclosures']: title = entry['title'] enclosure = _enclosure['url'] if enclosure not in oldenclosures: if includes: if not [True for include in includes if re.search(include,title,re.I)]: continue if excludes: if [True for exclude in excludes if re.search(exclude,title,re.I)]: continue try: print ' * ' + title enclosurefilename = os.path.join(downloadfolder, urllib.quote(title+".torrent","")) urllib.urlretrieve(enclosure, enclosurefilename.replace('%20', ' ')) WriteFile(cache, enclosure+'\n') if action_list: for action in action_list: keyword, program = action if keyword in enclosure: tempname = 'actionstart.bat' WriteFile(tempname, '@start "'+program+'" "'+os.path.abspath(enclosurefilename.replace('%20', ' '))+'"') os.system(tempname) os.remove(tempname) except IOError: print nl+'[error] url broken/no more disk space (..'\ +enclosure[-60:]+')'+nl except KeyboardInterrupt: sys.exit(nl+'[error] interrupted. file ('\ +os.path.basename(enclosure)+') unfinished')