#!/usr/bin/env python ## Copyright (C) 2007 Gary Benson ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. # Script to tag all but the first post in a thread so you can # filter pointless replies. # # I use it like this: # # :0 fw: $HOME/.superdeluxe.lock # * ^X-BeenThere: (announce|memo)-list@redhat.com # | $HOME/bin/superdeluxe # # :0 # * ^X-BeenThere: memo-list@redhat.com # * ^X-Super-Deluxe: seen # .churn.memo-list/ # 0.1 - initial revision # 0.2 - cope with Message-IDs with comments import cStringIO import os import re import rfc822 import time class IdStore: MAXAGE = 28 * 24 * 60 * 60 idre = re.compile("<([^>]+)>") def __init__(self): self.path = os.path.join(os.environ["HOME"], ".superdeluxe.store") self.load() def load(self): self.ids = {} if os.path.exists(self.path): cutoff = int(time.time()) - self.MAXAGE for line in open(self.path, "r").xreadlines(): date, id = line.rstrip().split() if date > cutoff: self.ids[id] = date def save(self): fp = open(self.path, "w") for id, date in self.ids.items(): print >>fp, date, id def add(self, id): self.ids[self.clean(id)] = int(time.time()) def has_key(self, id): return self.ids.has_key(self.clean(id)) def clean(self, id): match = self.idre.search(id) if match: id = "<%s>" % match.group(1) return "".join(id.split()) def tag(srcp, dstp): ids = IdStore() msg = rfc822.Message(srcp) dstp.write(msg.unixfrom) for header in msg.headers: dstp.write(header) if msg.has_key("In-Reply-To") and ids.has_key(msg["In-Reply-To"]): dstp.write("X-Super-Deluxe: seen\n") dstp.write("\n") while True: chunk = msg.fp.read(4096) if not chunk: break dstp.write(chunk) if msg.has_key("Message-ID"): ids.add(msg["Message-ID"]) ids.save() def safely(func, srcp, dstp): src = srcp.read() try: dst = cStringIO.StringIO() func(cStringIO.StringIO(src), dst) dst = dst.getvalue() except: dst = src dstp.write(dst) if __name__ == "__main__": import sys if len(sys.argv) == 1: safely(tag, sys.stdin, sys.stdout) else: import mailbox for path in sys.argv[1:]: mbox = mailbox.PortableUnixMailbox(open(path, "r"), lambda fp: fp) for fp in mbox: safely(tag, fp, sys.stdout)