#!/usr/local/bin/python import sys, os, string, time, socket import nntplib, rfc822 NNTPSERVER = "ca.news.verio.net" PATH = os.path.expanduser("~/News/") def exceptionString(): import StringIO, traceback ## get the traceback message sfp = StringIO.StringIO() traceback.print_exc(file=sfp) exception = sfp.getvalue() sfp.close() return exception class FetchNews: def __init__ (self, server, path): self._server = server self._rc = os.path.expanduser("~/.fetchnews-%s" % server) self._read = {} self._path = path self._cur_filename = None self._cur_fp = None def lock (self): lock_file = "%s.lock" % self._rc if os.path.exists(lock_file): raise Locked, "Lock Exists" pid = os.getpid() fp = open(lock_file, 'w') fp.write("%s" % pid) fp.close() def unlock (self): lock_file = "%s.lock" % self._rc try: os.unlink(lock_file) except: pass def load_rc (self): fp = open (self._rc) while 1: line = fp.readline() if not line: break line = string.strip(line) if line[0] == '#': continue (group, last) = string.split (line, ':', 1) self._read[group] = int(last) def save_rc (self): fp = open (self._rc, 'w') for (group, last) in self._read.items(): fp.write("%s: %s\n" % (group, last)) fp.close() def output_file (self, group, date): date_str = time.strftime("%Y-%m", date) new_filename = os.path.join (self._path, "%s.%s" % (group, date_str)) if new_filename != self._cur_filename: self._cur_filename = new_filename self._cur_fp = open(self._cur_filename, 'a') latest_date_str = time.strftime("%Y-%m", time.localtime(time.time())) if latest_date_str == date_str: latest_fn = os.path.join (self._path, "%s.latest" % (group)) try: os.unlink (latest_fn) except os.error: pass os.symlink (new_filename, latest_fn) return self._cur_fp def update_group (self, group, lastread): lastread = int(lastread) s = nntplib.NNTP(self._server) (resp, count, first, last, name) = s.group(group) first = int(first) last = int(last) if first > lastread: lastread = first if lastread >= last: return sys.stdout.write("XOVER %s %d-%d\n" % (group, lastread, last)) (resp, arts) = s.xover(str(lastread+1), str(last)) host = socket.gethostname() for (num, subj, poster, date, id, ref, size, lines) in arts: if lines and int(lines) < 100: continue if string.find(subj, ".jpg") != -1: continue if string.find(subj, ".gif") != -1: continue try: post = s.article(num) tdate = rfc822.parsedate(date) author = rfc822.parseaddr(poster) fp = self.output_file(group, tdate) fp.write("From %s %s\n" % (author[1], time.asctime(tdate))) time_str = time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.localtime(time.time())) fp.write("Received: from %s by %s with NNTP; %s\n" % (self._server, host, time_str)) fp.write(string.join(post[3], '\n')) fp.write("\n\n") sys.stdout.write("%s\r" % num) except: sys.stderr.write("%s\n" % exceptionString()) sys.stderr.write("Unable to handle post %s, skipping...\n" % num) self._read[group] = last def update (self): self.lock() self.load_rc() for (group, last) in self._read.items(): self.update_group (group, last) self.save_rc() self.unlock() def main(argv): fn = FetchNews(NNTPSERVER, PATH) fn.update() if __name__ == "__main__": main (sys.argv)