I'm basically done.

OK, that's a total lie—there's plenty more to do. But I am to the point where I feel like (except for one bug I'll mention later) doing an actual release—say a 0.90 release—would make sense.

Today, we'll implement org-blog-save, which is all about getting what you wrote onto the server, and the server's output integrated back into your post. It starts out with a couple of boilerplate XML-RPC wrappers:

(defun org-blog-wp-post-retrieve (xmlrpc blog-id username password post-id &optional fields)
  "Fetches a single post from the weblog system."
  (let ((params (list xmlrpc
                      'wp.getPost
                      blog-id
                      username
                      password
                      post-id)))
    (when fields
      (append params (list fields) nil))
    (apply 'xml-rpc-method-call params)))

(defun org-blog-wp-post-update (xmlrpc blog-id username password post-id post)
  "Edit an existing post on the blog."
  (xml-rpc-method-call xmlrpc
                       'wp.editPost
                       blog-id
                       username
                       password
                       post-id
                       (org-blog-post-to-wp post))
  post-id)

Simple, straightforward, still a little boilerplate-y, but I'll address that down the road.

Then there's org-blog-save which, I'm happy to say, is also pretty simple and straightforward. That such an important chunk of code is this easy to understand makes me feel that I've probably got the design mostly right:

(defun org-blog-save ()
  "Publish an article to a server and save locally.

By default org-blog will try and save the article in a hierarchy
that mirrors the permalink structure for the blog in question."
  (interactive)
  (condition-case failure
      (let* ((post (org-blog-buffer-extract-post))
             (blog (org-blog-post-to-blog post))
             (post-id (if (cdr (assq :id post))
                          (org-blog-call blog "post-update" (cdr (assq :id post)) post)
                        (org-blog-call blog "post-create" post)))
             (post (org-blog-call blog "post-retrieve" post-id)))
        (org-blog-buffer-merge-post (org-blog-wp-to-post post)))
    (error (apply 'message (cdr failure)))))

It uses condition-case to make sure that it catches any exceptions that bubble up, and then goes about its business fairly straightforwardly:

  • Get a post structure from the buffer
  • Get a blog structure from the post
  • Look to see if the post already has a post-id

    • If it does, update the post
    • If it doesn't, create a new post
  • Either way, return the post-id
  • Retrieve the post using the post-id
  • Merge the post into the buffer

What could be easier? In fact, this is the code I've been using (with some small improvements) to write this series of posts so it works.

Oh, except for the bug I mentioned earlier. Timestamp handling is a little wonky—WordPress has a tendency to not add TZ information to their timestamps, or XML-RPC doesn't actually pay attention to them, so the structure I get back from the server has a time stamp that is off by (in my case) four hours. I've tried to use the GMT versions of timestamp fields, but I fear I haven't gotten it quite right.

The test I have for org-blog-save is still a little crude. It's on github, and I intend to tweak it as well—that will probably be a necessary part of fixing the timestamp issue.

So, this weekend will probably be dedicated to cleanup and documentation, and then a release early next week. Whew.