#!/usr/bin/env python import feedparser import re import time import subprocess import urllib2 import tempfile import shelve import ConfigParser class App(object): def __init__(self): self.seen = [] self.downloaded = [] self.feeds = [] def load_config(self): config = ConfigParser.RawConfigParser({}) config.readfp(file('.feed-transmission.ini')) feed_names = config.get("config", "feeds") feed_names = feed_names.split(",") for i in feed_names: i = i.strip() f = {} url = config.get(i, "url") poll_delay = config.getint(i, "poll_delay") match = [] for m in config.items(i): if not m[0].startswith("match"): continue try: re.compile(m[1]) except re.error: print "Invalid regular expression at %s, %s: %s" % (i, m[0], m[1]) match.append(m[1]) match = "|".join(match) match = re.compile(match) self.add_feed(Feed(url, poll_delay, match)) def load_stor(self): self.stor = shelve.open(".feed-transmission.data") if not "downloaded" in self.stor: self.stor["downloaded"] = [] if not "seen" in self.stor: self.stor["seen"] = [] self.downloaded = self.stor["downloaded"] self.seen = self.stor["seen"] def setup_env(self): opener = urllib2.build_opener(urllib2.HTTPCookieProcessor()) urllib2.install_opener(opener) def add_feed(self, feed): self.feeds.append(feed) def get_next_feed(self): """Returns a (delay, feed) tuple of time to delay before next feed, and next feed to run """ # TODO return (self.feeds[0].poll_delay, self.feeds[0]) def run_relavent(self, feed): found = feed.find_relavant(self.seen) self.seen = self.seen[-500:] self.stor["seen"] = self.seen for i in found: if i in self.downloaded: continue self.downloaded.append(i) f = urllib2.urlopen(i) temp = tempfile.NamedTemporaryFile() temp.write(f.read()) f.close() temp.flush() ret = subprocess.call(["transmission-remote", "localhost", "-a", temp.name]) temp.close() if ret: print "Error adding torrent" self.downloaded = self.downloaded[-500:] self.stor["downloaded"] = self.downloaded self.stor.sync() def main(self): try: for feed in self.feeds: self.run_relavent(feed) while True: (delay, feed) = self.get_next_feed() time.sleep(delay) try: self.run_relavent(feed) except urllib2.URLError, e: print e except KeyboardInterrupt: pass class Feed(object): def __init__(self, url, poll_delay, match): self.url = url self.poll_delay = poll_delay self.match = match def load_feed(self): f = urllib2.urlopen(self.url) d = feedparser.parse(f.read()) f.close() return d def find_relavant(self, seen): d = self.load_feed() found = [] print "New RSS Items:" for i in d['items']: if i.title in seen: continue seen.append(i.title) print " ", i.title if not self.match.match(i.title): continue print " Matched" found.append(i.link) return found if __name__ == "__main__": app = App() app.load_config() app.load_stor() app.setup_env() app.main()