web/hosts/issues/detectors ciabot.py,NONE,1.1

Nathaniel Smith <[email protected]> Sun, 01 Jun 2003 20:21:07 -0500
Newsgroups gmane.comp.video.fresco.cvs
Message-ID <[email protected]>
Update of /cvs/fresco/web/hosts/issues/detectors
In directory purcel:/tmp/cvs-serv32265

Added Files:
	ciabot.py 
Log Message:
First try at channel notification for tracker changes.


--- NEW FILE: ciabot.py ---
from roundup import roundupdb, hyperdb

ADDRESSES = ["[email protected]"]
SUBJECT = "Announce Fresco"
BASEURL = "http://issues.fresco.org/"
# freenode can actually handle > 400, but we'll be conservative
MAXLINELENGTH = 300

def listminus(lst1, lst2):
    return [elt for elt in lst1 if elt not in lst2]

class Notifier:
    def __init__(self, event, cls):
        self.event = event
        self.cls = cls
    def __call__(self, db, cl, nodeid, oldvalues):
        def name(id):
            if id == -1: return "nobody"
            return db.user.get(id, "username")
        args = {}
        args["class"] = self.cls
        args["id"] = nodeid
        args["url"] = BASEURL + self.cls + nodeid
        args["title"] = cl.get(nodeid, "title")
        args["user"] = name(db.getuid())

        if self.event == "create":
            self.message("%(user)s created %(id)s: "
                         + "%(title)s  (see %(url)s )" % args)

        elif self.event == "retire":
            self.message("%(user)s retired %(id)s (%(title)s)" % args)

        else:  # self.event == "set"
            def modified(key):
                return oldvalues.has_key(key)
            mods = oldvalues.copy()
            def noted(key):
                del mods[key]

            interesting_fields = ("messages", "title", "files", "superseder",
                                  "assignedto", "topics", "status",
                                  "priority", "resolution", "dependson")
            msgstr = "%(user)s modified %(id)s"
            if modified("title"):
                noted("title")
                args["oldtitle"] = oldvalues["title"]
                msgstr += " (new title: %(title)s, was: %(oldtitle)s)"
            else:
                msgstr += " (%(title)s)"

            notes = []
            if modified("messages"):
                noted("messages")
                notes.append("added message")
            if modified("files"):
                noted("files")
                notes.append("added file")
            if modified("assignedto"):
                noted("assignedto")
                if self.event == "task":
                    addedids = listminus(cls.get(nodeid, "assignedto"),
                                         oldvalues["assignedto"])
                    added = map(name, addedids)
                    removedids = listminus(oldvalues["assignedto"],
                                           cls.get(nodeid, "assignedto"))
                    removed = map(name, removedids)
                    if added: notes.append("assigned to: " + ", ".join(added))
                    if removed: notes.append("unassigned from: "
                                             + ", ".join(removed))
                else:
                    notes.append("assigned to %s (was %s)"
                                 % (name(cls.get(nodeid, "assignedto")),
                                    name(oldvalues["assignedto"])))
            if modified("status"):
                noted("status")
                notes.append("Status: %s -> %s"
                             % (db.status.get(oldvalues["status"]),
                                db.status.get(cl.get(nodeid, "status"))))
            if modified("resolution"):
                noted("resolution")
                notes.append("Resolution: %s -> %s"
                             % (db.resolution.get(oldvalues["resolution"]),
                                db.resolution.get(cl.get(nodeid,
                                                         "resolution"))))
            if modified("priority"):
                noted("priority")
                notes.append("Priority: %s -> %s"
                             % (db.priority.get(oldvalues["priority"]),
                                db.priority.get(cl.get(nodeid, "priority"))))
            if modified("release_date"):
                noted("release_date")
                notes.append("Release date: %s -> %s"
                             % (oldvalues["release_date"],
                                cl.get(nodeid, "release_date")))
            if modified("bugs"):
                noted("bugs")
                addedbugs = listminus(cls.get(nodeid, "bugs"),
                                      oldvalues["bugs"])
                removedbugs = listminus(oldvalues["bugs"],
                                        cls.get(nodeid, "bugs"))
            if modified("tasks"):
                noted("tasks")
                addedtasks = listminus(cls.get(nodeid, "tasks"),
                                      oldvalues["tasks"])
                removedtasks = listminus(oldvalues["tasks"],
                                        cls.get(nodeid, "tasks"))
            # milestone specific attributes
            if addedtasks or addedbugs:
                tlist = [BASEURL + "task" + id for id in addedtasks]
                blist = [BASEURL + "bug" + id for id in addedbugs]
                notes.append("Added: " + ", ".join(blist + tlist))
            if removedtasks or removedbugs:
                tlist = [BASEURL + "task" + id for id in removedtasks]
                blist = [BASEURL + "bug" + id for id in removedbugs]
                notes.append("Removed: " + ", ".join(blist + tlist))

            noted("activity")
            notes.append("Also modified: " + ", ".join(mods.keys()))

            if notes:
                msgstr += ": " + ", ".join(notes)

            msgstr += 
            self.message(msgstr % args)
            
    def message(body):
        lines = []
        while len(body) > MAXLINELENGTH:
            i = MAXLINELENGTH
            while body[i] not in " \t\n":
                i -= 1
            lines.append(body[0:i])
            body = body[i+1:-1]
        lines.append(body)

        import cStringIO, MimeWriter
        message = cStringIO.StringIO()
        writer = MimeWriter.MimeWriter(message)
        writer.addheader("Subject", SUBJECT)
        writer.addheader("To", ", ".join(ADDRESSES))
        writer.addheader("From", db.config.ADMIN_EMAIL)

        body = writer.startbody("text/plain")
        for line in lines:
            body.write(line)
            body.write("\n")

        import smtplib
        smtp = smtplib.SMTP(db.config.MAILHOST)
        smtp.sendmail(db.config.ADMIN_EMAIL, ADDRESSES, message.getvalue())

def init(db):
    for event in ("create", "set", "retire"):
        for cls in ("bug", "task", "milestone"):
            db.getclass(cls).react(event, Notifier(event, cls))