#!/usr/bin/python import cgi, sys, os, glob, xml.dom.minidom, re, time import cgitb; cgitb.enable() import feedwriter xml_dir = "/hosts/log.us-lot.org/pages" script_location = "http://log.us-lot.org" log_title = "Us-Lot Log" log_byline = "Stuff we've discussed on IRC." def get_text(node): return "".join([n.toxml().replace(" />", ">") for n in node.childNodes]) def maybe_get_text(nodes): if nodes == []: return None else: return get_text(nodes[0]) def get_val(node, name): return node.getElementsByTagName(name)[0].getAttribute("value") def make_link(path_info): return script_location + "/" + path_info def nick_class(nick): return re.sub('[^0-9a-z]+', '', nick.lower()) def format_date(t): return time.strftime("%Y-%m-%d %H:%M", time.gmtime(t)) class Link: def __init__(self, dom, seq): self.seq = seq self.time = float(get_val(dom, "time")) self.title = maybe_get_text(dom.getElementsByTagName("title")) self.url = maybe_get_text(dom.getElementsByTagName("url")) self.nick = maybe_get_text(dom.getElementsByTagName("nick")) self.comments = [] for comment in dom.getElementsByTagName("comment"): nick = comment.getAttribute("nick") text = get_text(comment) self.comments.append((nick, text)) def title_html(self): if self.title is not None: return self.title elif self.url is not None: return self.url else: return "Erm." def title_link(self): title = self.title_html() if self.url is not None: return '' + title + '' else: return title def article_link(self, date): return make_link(date + "#link" + date + "n" + str(self.seq)) def comments_html(self): bits = [] current_nick = None for (nick, text) in self.comments: if nick != current_nick: if current_nick is not None: bits.append("

\n") bits.append('

' + cgi.escape(nick) + ':\n') current_nick = nick else: bits.append("
") bits.append(text + "\n") if current_nick is not None: bits.append("

\n") return "".join(bits) class Churn: def __init__(self, fn): dom = xml.dom.minidom.parse(fn) self.last_updated = float(get_val(dom, "last-updated")) self.links = [] links = dom.getElementsByTagName("link") # We have to number the links backwards because the order is # reversed in the XML file. i = len(links) - 1 for link in links: self.links.append(Link(link, i)) i -= 1 def main(): dates = [] xml_fns = {} date_pos = {} n = 0 fns = glob.glob(xml_dir + "/20??/??/??/????-??-??.xml") fns.sort() for fn in fns: date = fn[-14:-4] dates.append(date) xml_fns[date] = fn date_pos[date] = n n += 1 mode = "page" path_info = os.getenv("PATH_INFO") show_dates = dates[-7:] if path_info is not None and path_info != "": path_info = path_info[1:] if path_info == "index": mode = "index" show_dates = dates elif path_info == "feed": mode = "feed" elif xml_fns.has_key(path_info): show_dates = [path_info] def write(s): sys.stdout.write(s.encode("UTF-8")) e = cgi.escape if mode == "page" or mode == "index": title = log_title if len(show_dates) == 1: title += ": " + show_dates[0] write("Content-type: text/html; charset=UTF-8\n\n") write(''' ''' + e(title) + '''

''' + e(title) + '''

''' + log_byline + '''

''') write('\n') show_dates.reverse() for date in show_dates: churn = Churn(xml_fns[date]) write('
\n') write('

' + date + '

\n') write('\n') write('
\n') write(""" """) elif mode == "feed": write("Content-type: application/rss+xml; charset=UTF-8\n\n") show_dates.reverse() c = feedwriter.Channel(title = log_title, link = make_link(""), description = log_byline) for date in show_dates: churn = Churn(xml_fns[date]) for link in churn.links: c.add_item(title = link.title_html().replace(""", '"'), link = link.article_link(date), description = link.comments_html(), pubDate = link.time) sys.stdout.write(c.rss2()) if __name__ == "__main__": main()