#!/usr/local/bin/python -u

import cgi
import cgitb
import os
import string
import sys
import time
import urllib
import xml.dom.minidom

cgitb.enable()

pageheader = '''\
Content-type: text/html

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <title>livejournal foaf to opml</title>
  <link rev="made" href="mailto:fn@hungry.com" />
  <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=iso-8859-1" />
  <meta name="Keywords" content="foaf, livejournal" />
  <meta name="Author" content="Faried Nawaz" />
  <meta name="ContactEmail" content="fn@hungry.com" />
  <meta name="Description" content="LiveJournal FOAF to OPML" />
  <meta name="Generator" content="XEmacs" />
  <meta name="copyright" content="Copyright (C) 2005, 2008, 2009 Faried Nawaz" />
  <style type="text/css">
    .center { text-align: center; }
    .right { text-align: right; margin-right: 1%; }
    .red { background-color: white; color: red; }
    .block { 
      font-family: verdana, arial, sans-serif;
      margin-left: 15%;
      width: 65%;
      color: black;
      font-size: small;
      font-weight: normal;
      background: white;
      line-height: 120%;
      border-left: 1px dotted #666666;
      border-top: 1px dotted #666666;
      border-right: 1px dotted #666666;
      border-bottom: 1px dotted #666666;
      padding: 5px;
    }
  </style>
  <script type="text/javascript">
  <!--
  function formFocus() { document.f.lj.focus(); }
  google_ad_client = "pub-5678250147441885";
  google_alternate_ad_url = "http://www.hungry.com/~fn/ad.cgi";
  google_ad_width = 728;
  google_ad_height = 90;
  google_ad_format = "728x90_as";
  google_ad_type = "text_image";
  google_ad_channel ="";
  google_color_border = "B0E0E6";
  google_color_bg = "FFFFFF";
  google_color_link = "000000";
  google_color_url = "336699";
  google_color_text = "333333";
  // -->
  </script>
</head>

<body onload="javascript:formFocus();">
'''

footer = '''\
<p class="right"> &mdash; <a href="http://www.hungry.com/~fn/" title="web page">Faried Nawaz</a> (<a href="mailto:fn@hungry.com"><em>fn@hungry.com</em></a>)<br />
(garbage collection for the masses!)</p>

<div class="center">
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
</div>
</body>
</html>
'''


class MyUrlOpener(urllib.FancyURLopener):
    """Subclassed FancyURLopener to generate a version string."""
    
    def __init__(self, *args):
        self.version = 'http://www.hungry.com/~fn/; fn@hungry.org'
        urllib.FancyURLopener.__init__(self, *args)



def toOPML(items, lj, auth):
    """Take parsed XML FOAF entries and display an OPML file."""

    if auth:
        appendToUrl = 'data/atom?auth=digest'
    else:
        appendToUrl = 'data/atom'

    # items[0] is us.  skip it.
    items = items[1:]

    opml = ['''\
<?xml version="1.0" encoding="utf-8"?>
<opml version="1.1">
<head>
<title>%s\'s friends on livejournal</title>
<dateCreated>%s</dateCreated>
</head>
<body>
''' % (lj, time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime()))]
    
    opml.append('<outline text="from livejournal">')

    for item in items:
        text = item.getElementsByTagName('foaf:nick')[0].childNodes[0].data
        url = item.getElementsByTagName('foaf:weblog')[0].getAttribute('rdf:resource')
        feed = url + appendToUrl
        descr = '%s\'s feed' % (text)
        opml.append('''\
<outline title="%s" htmlUrl="%s" language="en" text="%s" xmlUrl="%s" />
''' % (descr, url, text, feed))

    opml.append('</outline></body></opml>')

    print 'Content-type: application/x.opml+xml'
    print 'Content-Disposition: attachment; filename=lj-%s.opml' % (lj)
    print ''
    print string.join(opml, '')

    
def getFoafData(form):
    """Grab FOAF data from LiveJournal's site."""
    
    if not form.has_key('lj'):
        return showMainPage(form, err='Missing username.')

    lj = form['lj'].value
    if form.has_key('auth'):
        auth = 1
    else:
        auth = None
        
    urllib._urlopener = MyUrlOpener()
    try:
        data = urllib.urlopen('http://www.livejournal.com/users/%s/data/foaf' % (lj))
    except:
        return showMainPage(form, err='An error occurred while trying to retrieve %s.' % (url))

    try:
        parser = xml.dom.minidom.parse(data)
    except:
        return showMainPage(form, err='I couldn\'t parse the FOAF for %s.' % (lj))

    people = parser.getElementsByTagName('foaf:Person')
    toOPML(people, lj, auth)


def showSource():
    """Display the source code for this app."""
    
    print 'Content-type: text/plain'
    print ''

    f = file('foaf.cgi', 'r')
    for line in f.readlines():
        sys.stdout.write(line)
    f.close()


def showForm(form):
    """Display the entry form."""
    
    me = os.environ.get('SCRIPT_URL', '')

    if form.has_key('lj'):
        lj = form['lj'].value
    else:
        lj = ''
    if form.has_key('auth'):
        checked = 'checked="checked"'
    else:
        checked = ''

    print '''\
<form method="get" action="foaf.cgi" name="f">
<div class="center">
<p>livejournal username: <input type="text" size="16" name="lj" value="%s" />
   generate with auth links <input type="checkbox" name="auth" %s />
   <input type="submit" value="get it" name="foaf" /> or show me the <a href="%s?source=source" title="source code">source</a>.</p>
</div>
</form>
''' % (lj, checked, me)


def showMainPage(form, err=None):
    """The site page."""
    
    print pageheader
    print '<div class="center"><h3>LiveJournal FOAF to OPML</h3></div>'
    if err:
        print '<div class="center"><h4 class="red">%s</h4></div>' % (err)
    showForm(form)
    print '''
<div class="block">
<p>This app reads your <a href="http://www.foaf-project.org/" title="friend of a friend">foaf</a> data from <a href="http://www.livejournal.com/" title="LiveJournal">LiveJournal</a> and converts it into an <a href="http://www.opml.org/" title="outline processor markup language">OPML</a> file suitable for use with a <a href="http://en.wikipedia.org/wiki/News_aggregator" title="news aggregator, or feed aggregator">feed aggregator</a>.  The <em>foaf</em> data contains a list of all your LiveJournal friends.</p>
<p>If you check the <em>auth</em> checkbox, the OPML file will contain links that will let you read private (<em>friends only</em>) messages.  Not all feed aggregators support this feature &mdash; check with your product documentation.</p>
</div>
'''
    print footer



def main():
    """Main branching logic."""
    
    form = cgi.FieldStorage()
    if form.has_key('foaf'):
        getFoafData(form)
    elif form.has_key('source'):
        showSource()
    else:
        showMainPage(form)
    sys.exit(0)



if __name__ == '__main__': main()
