emacs-blogger /

Python library but maybe it overcomes the BloggerClient API
from gdata import service
import gdata
import atom
from collections import namedtuple
from dateutil.parser import parse

Entry = namedtuple("Entry", "title content id published updated category feed")

class Blog(object):
    Encapsulate a Blog object, this istance should no be istantiated,
    but obtained from the Blogger object with Blogger.get_blogs
    def __init__(self, name, id_, service): = name = id_
        self.service = service

    def update_post(self, post_id, title=None, content=None):
        Update the post identified by post_id
        entry = self.get_entry(post_id)
        if title!=None:
            entry.feed.title = atom.Title('xhtml',title)
        if content!=None:
            entry.feed.content = atom.Content(content_type='html',text=content)
        self.service.Put(entry.feed, entry.feed.GetEditLink().href)
    def add_tags(self, post_id, tags, replace=False):
        """Add or remove labels on a post.
        if replace is True, remove all old tags.
        scheme = ''
        post = self.get_entry(post_id).feed

        if replace:
            # Remove categories that match the scheme we are updating.
            post.category = [c for c in post.category if c.scheme != scheme]
        new_tags = [atom.Category(term=tag, scheme=scheme) for tag in tags]

        self.service.Put(post, post.GetEditLink().href)

    def remove_tags(self, post_id, tags):
        Remove tags from a post
        scheme = ''
        post = self.get_entry(post_id).feed
        post.category = [c for c in post.category \
                             if c.scheme != scheme or \
                             (c.scheme == scheme and c.term not in tags)]
        self.service.Put(post, post.GetEditLink().href)
    def get_entries(self):
        '''Generate Entry objects for the blog 
        feed = self.service.GetFeed('/feeds/' + + '/posts/default')
        for entry in feed.entry:
            yield self._convert_entry_feed(entry)

    def get_entry(self, post_id):
        return next(entry for entry in self.get_entries() if == post_id)

    def publish_post(self, title, content, tags=None, draft=False):
        publish post with the given entries, return the post itself
        entry = gdata.GDataEntry()
        entry.title = atom.Title('xhtml', title)
        entry.content = atom.Content(content_type='html', text=content)
        if draft:
              control = atom.Control()
              control.draft = atom.Draft(text='yes')
              entry.control = control
        post = self._convert_entry_feed(self.service.Post(entry, '/feeds/%s/posts/default' %
        if tags:
            self.add_tags(, tags)
        return post

    def delete_post(self, post_id):
        Delete post identified by post_id
        entry = self.get_entry(post_id)

    def _convert_entry_feed(self, entry):
        '''Convert the entry feed returned by the method of the
        service in an Entry Object (a namedtuple, actually)
        title = entry.title.text
        content = entry.content.text
        post_id = entry.GetSelfLink().href.split('/')[-1]
        published = parse(entry.published.text)
        updated = parse(entry.updated.text)
        tags = [tag.term for tag in entry.category]

        return Entry(title, content, post_id, published, updated, tags, entry)        

class Blogger(object):
    Blogger client that returns python objects (usually tuples and
    namedtuples) instead of xml entries
    def __init__(self, username, password):
        s = service.GDataService(username, password)
        s.source = "gl-emacsblogging-0.1"
        s.service = "blogger"
        s.account_type = "GOOGLE"
        s.server = ""
        self.service = s

    def get_blogs(self):
        '''Return a list of blogs for the current user
        query = service.Query()
        query.feed = "/feeds/default/blogs"
        feed = self.service.Get(query.ToUri())
        for entry in feed.entry:
            name = entry.title.text
            blog_id = entry.GetSelfLink().href.split("/")[-1]
            yield Blog(name, blog_id, self.service)

def test_getting():
    blogger = Blogger(username, password)
    blog = next(i for i in blogger.get_blogs())
    entries = blog.get_entries()
    for entry in entries:
        print "Entry", entry.title,"Published", entry.published.strftime("%d/%m/%Y"), "Id",

def test_updating():
    blogger = Blogger(username, password)
    blog = next(i for i in blogger.get_blogs())
    blog.update_post('6296823132147746563', title="Ok", content="Fubbo")
    blog.add_tags('6296823132147746563',["hello", "world"])