#!/usr/bin/env python2.4
# -*-*- encoding:iso-8859-15 filetype:python expandtab:yes tabstop:4 shiftwidth:4 softtabstop:4
# autoindent:yes -*-*-
#
# havard@dahle.no GPL (C) 2005

__doc__ = "Usage: pipe email message to this script for automatic post on your blog"

BLURL = "http://www.orakel.ntnu.no/~havardda/blogg/xmlrpc.php" # blog xmlrpc url
BLOGG = "kibbitz"     # blog name
USRNM = "boink"       # your username
PSWRD = "babyJesus"   # your password
CTGRY = "10"          # default category
ENCOD = "iso-8859-15" # your blog's character encoding ('utf8' is Wordpress default)

DEBUG = 0

import sys

try:
    import xmlrpclib, time, email
    from email.Header import decode_header
    from email.Iterators import typed_subpart_iterator
    from email.Utils import parsedate
    from string import join
except ImportError:
    print  "Import Error"
    sys.exit(100)

def striptags(s):
    "Strip sgml/html tags"
    # stolen from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440481
    # this list is neccesarry because chk() would otherwise not know
    # that intag in stripTags() is ment, and not a new intag variable in chk().
    intag = [False]
    
    def chk(c):
            if intag[0]:
                    intag[0] = (c != '>')
                    return False
            elif c == '<':
                    intag[0] = True
                    return False
            return True
    
    return ''.join(c for c in s if chk(c))

def entitity(s):
    "Return string, substituting numerical entities for all non-ascii characters"
    ret = ""
    for char in s:
        if char == "<": ret += "&#60;"
        elif char == "&": ret += "&#38;"
        elif ord(char) < 160: ret += char
        else: ret += "&#%s;" % ord(char)
    return ret

def extract(msg):
    t = decode_header(msg.get("Subject"))
    title =  join([unicode(i[0], i[1]) for i in t])
    parts = typed_subpart_iterator(msg) # loops through "text/*" parts
    contents = None
    try:
        while not contents:
            p = parts.next()
            contents = unicode(p.get_payload(decode=1), p.get_content_charset())
            if p.get_content_subtype() == "html":
                #convert from html
                contents = striptags(contents)
            contents = contents.strip()
    except StopIteration:
        print "Crap! No text message part found"
        return 100

    try: isodate = time.strftime("%Y-%m-%dT%H:%M:%S", parsedate(msg['date']))
    except TypeError: isodate = None

    return title, contents, isodate

def post(title, text, isodate, categories = None):
    "Post to xmlrpc interface"

    if ENCOD.lower() != "utf8": 
        title, text = title.encode(ENCOD), text.encode(ENCOD)

    p = [ entitity(z) for z in (title, text) ]
    post = "<title>%s</title>%s" % (tuple(p))

    rpc = xmlrpclib.ServerProxy(BLURL, encoding=ENCOD, verbose=DEBUG)

    publish = xmlrpclib.Boolean(1)

    if not categories:
        cats = [{'categoryId': CTGRY},]
    else: 
        cats = []
        for c in rpc.metaWeblog.getCategories(BLOGG, USRNM, PSWRD):
            if categories.count(c["categoryName"]): 
                cats.append({'categoryId':c['categoryId']})
    try:
        id = rpc.blogger.newPost("",            # appkey
                    BLOGG,     # blogid
                    USRNM,   # username
                    PSWRD,   # password
                    post,    #content
                    publish     # publish?
                   )
        # set categories
        rpc.mt.setPostCategories(id, #postID
                                 USRNM, #username
                                 PSWRD, #password
                                 cats
                                )

        # set date
        if isodate:
            date = {'dateCreated':isodate,}
            metaWeblog.editPost(id, #postID
                                USRNM, #username
                                PSWRD, #password
                                date, 
                                publish
                            )
    except xmlrpclib.Fault, (msg):
        print msg
        return 100
    except:
        return 100

    return 0

if __name__ == "__main__":
    if sys.stdin.isatty():
        print __doc__
        sys.exit(100)

    if "-d" in sys.argv: DEBUG=1    
    try:
        msg = email.message_from_file(sys.stdin)
        cats = sys.argv[1:]
        title, text, date = extract(msg)
        if "-t" in sys.argv:
            print "[title]:", title
            print "[date]:", date
            print "[text]:", text
            sys.exit(100)
        sys.exit(post(title, text, date, cats))
    except:
        raise
        print "ouch! could not post email to blog"
        sys.exit(100)
    
    

