#!/usr/bin/env python

"""Generate a RSS feed for The Null Device"""

import sys
sys.path.append('/home/acb/null_include')

from nullcgi import *
from nullconfig import *

from xmlentity import vetEntities

MAXBLOGDAYS=7
MAXBLOGITEMS=18

blogstore = BlogStore(BLOGDIR)

print """Content-Type: text/xml
"""

print """<?xml version="1.0" encoding="utf-8"?>

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns="http://purl.org/rss/1.0/">
<channel rdf:about="http://dev.null.org/">
<title>The Null Device</title>
<link>http://dev.null.org/</link>"""
print "<description>%s</description>"%''  # FIXME
print "<language>en-au</language>"
print "<webMaster></webMaster>"
# print "<lastBuildDate>%s</lastBuildDate>"
# print "<pubDate>%s</pubDate>"%


# iterate over items 

def itemiterator(store, item, user):
  """make a XML item for a blog item.  user is the actual function which
does the formatting, accepting (itemid,title,archiveurl,dcdate) and returning a 
string"""

  try:
    text,attr = store.getByID(item)
  except TypeError:
    return None
  if attr.has_key('title'):
    title = vetEntities(attr['title'])
  else:
    title = vetEntities(item)
  
  (y,m,d) = store.idToDate(item)
  archiveurl = "http://dev.null.org/blog/archive.cgi/%04d/%02d/%02d#%s"%(y,m,d,item[8:])
  dc_date = "%04d-%02d-%02dT%s:%s:00+10:00"%(y,m,d,item[8:10],item[10:12])
  return user(item, title, archiveurl, dc_date, text)

def truncate_text(text):
  "given an item's body text, truncate it to a suitable point."
  ntext = string.join(string.split(text)[:20])
  # cut off any HTML tags chopped in half
  if string.rfind(ntext,'<') > string.rfind(ntext,'>'):
    ntext = ntext[:string.rfind(ntext,'<')]
  if len(ntext)<len(text):  
    ntext = ntext + "..."
  # close any HTML tags which are open
  re_opentag = re.compile('<(/?)([A-Za-z0-9_]+)[^>]*>')
  to_search = ntext
  close_stack = []
  match = re_opentag.search(to_search)
  while match:
    if match.group(1)=='/':
      try:
        close_stack.remove(match.group(2).lower())
      except ValueError:
#        sys.stderr.write('</%s> found but no opening tag\n'%match.group(2).lower())
        pass
    else:  close_stack.insert(0,match.group(2).lower())
    to_search = to_search[match.end():]
    match = re_opentag.search(to_search)
  return ntext + ''.join(map(lambda s:"</%s>"%s, close_stack))

def body_fmtfunc(item,title,archiveurl,dc_date,text):
  #text = truncate_text(text)
  text = text.replace('&', '&amp;') 
  text = text.replace('<', '&lt;') 
  text = text.replace('>', '&gt;') 
  return """<item rdf:about="%s">
<title>%s</title>
<link>%s</link>
<dc:date>%s</dc:date>
<description>%s</description>
</item>"""%(archiveurl,title,archiveurl,dc_date,text)

def toc_fmtfunc(item,title,archiveurl,dc_date,text):
  return '<rdf:li rdf:resource="%s" />'%archiveurl

print "<items>\n<rdf:Seq>"

for i in mapItems(blogstore,MAXBLOGDAYS,MAXBLOGITEMS,itemiterator,toc_fmtfunc):
  print i

print "</rdf:Seq></items>"
  
print "</channel>"

for i in mapItems(blogstore,MAXBLOGDAYS,MAXBLOGITEMS,itemiterator,body_fmtfunc):
  print i

print "</rdf:RDF>"
