Blogging APIs

Author's note: It's officially the holiday season and I'm feeling lazy. So guess what - it's another episode of "From the Archives"! That's right, it's time for more of the series where I trot out something that's been sitting in my drafts folder for ten years because I can't muster the energy to write something new.

This article is from way back on March 18, 2007. It actually appears to be finished, so I'm not sure why I never published it. Perhaps I was filled with crippling self doubt that my analysis was actually stupid and people would make fun of me, so I never hit the publish button. That was actually a thing I did for many years. These days, I'm more casual about it. One of the benefits of getting older is that you're more experienced and able to have a more objective view of the quality of your work. Another is that you have a wider perspective on what really matters in life. Another way to put that is "you don't care as much what other people think."

Anyway, this article is about my attempts at implementing the various blogging APIs in LnBlog. This included the Blogger, MetaWeblog, and MoveableType APIs. I guess that seemed like a good idea at the time. In retrospect, it was a nice educational exercise, but not especially useful. I mean, the idea of a generic API that third-party clients can use to post to your blog is great. But in practice, it doesn't seem like that's a thing that many people actually need. I certainly never found a good use-case for it. Maybe that's why the APIs never really got fleshed out.

But that's enough out of present-day me. Let's hear from 2007 me. Enjoy!

Last month, I finally got around to doing some actual testing on the MetaWeblog and Blogger API implementations for LnBlog. By that, I mean that rather than testing it with my own code, I actually installed a few free blogging clients. I learned a few interesting lessons from this.

The Clients

I tested four blogging clients. The first is Deepest Sender 0.7.9, a Firefox extension that supports LiveJournal, Blogger, Wordpress, MSN Spaces, and generic MetaWeblog blogs. The second is KBlogger 0.6.2, a simple KDE panel applet that supports the MetaWeblog and Blogger APIs. Third is QTM 0.4.0, a C++/Qt4 application that support the Blogger, MetaWeblog, and MovableType APIs. Last is BloGTK 1.1, a Python/GTK+ application that also supports Blogger, MW, and MT.

My results were mixed. KBlogger worked basically as advertised. In fact, it's the only one of the clients that seemed to understand the APIs in the same way that I do. The only problem is that it's a bit short on features.

BloGTK seemed to work pretty well. However, it worked best when set to use the MoveableType API. When using the MetaWeblog API, I had problems editing posts. It also has a few weird little bugs, such as things getting messed up when switching accounts.

While it has a nice interface, QTM simply would not work with LnBlog. For the record, this is not my fault but rather due to the fact that this version of QTM did not correctly implement the APIs. When sending calls to the server, it sent blog IDs, post IDs, category IDs, etc. as integers, whereas the specification calls for them to be strings. While the difference may be academic for some servers, LnBlog really does use strings as IDs, so the requests raise errors in the XML-RPC library. (Note: this seems to have been corrected in CVS.)

And as for Deepest Sender, I just can't get it to work as advertised. I don't know why. It can post entries, but editing them results in a hung edit window, the "active blog" box is shrunk down to an unrecongizable control, and I have yet to even see a category selection box.

Server Problems

The first problem I encountered with LnBlog's implementation of the Blogger 1.0 and MetaWeblog APIs was my silly assumption that, just because they are two separate API specifications, I could implement them separately. And so, that's exactly what I did: I wrote one PHP script to implement the Blogger 1.0 API and a different one to implement the MetaWeblog API.

Oh, what a fool I was!

While that attitude made perfect sense when looking just at the specs, it just doesn't work that way in practice. Of the four clients I tested, KBlogger was the only one that worked when the MetaWeblog server didn't implement the Blogger 1.0 API at the same URI. The others all blithely assumed that the same URI would implement the Blogger, MetaWeblog, and MovableType APIs. I guess few people even stopped to consider that a server might have independent implementations of the different APIs. Or perhaps it's just that KBlogger is designed to support clients that only understand Blogger 1.0 while the others assume MetWeblog support. It's hard to tell.

Placing the blame

After going back to look at the specs, I believe much of the blame for this situation rests with the MetaWeblog API specification itself. The problem is that it's just a bad specification. In fact, it's really more a sketch of a specification than an actual spec. It's too vauge, too confusing, and leaves too much open to interpretation.

For instance, take the metaWeblog.getCategories method. According to the specification, this method returns a struct, with each member being a struct with the description, HTML URL, and RSS URL for each category.

For non-programmers, "struct" is short for "structure," and is simply set of key/value pairs. In this case, having member structs with keys for description and URLs makes perfect sense.

However, putting all of these in a struct doesn't make sense. The spec says that the category structs are to be returned in a struct, but says nothing about the key names of this container struct. But the entire point of having a struct is to associate key names with values. A struct with no particular key names is meaningless. It's like writing a book where the index lists words, but not page numbers - if you can't pick the word (key) you want and go straight to the corresponding page (value), then the entire exercise is pointless.

Another shortcoming of the API is that it does not clearly specify a way to identify blog posts. For example, the API includes the metaWeblog.editPost and metaWeblog.getPost methods, both of which take a post ID. It also includes a metaWeblog.getRecentPosts method to get an array of the most recent posts for a blog. You would think that you could call getRecentPosts, let the user pick a post, edit it, and then call editPost to commit the changes to the server. But you can't.

That's because the API does not specify how to get the post ID. The metaWeblog.getPost and metaWeblog.getRecentPosts methods return a struct and an array of structs respectively, and the spec states that the members of these post structs are the members of RSS items. But there is no mention of where the post ID comes in. RSS certainly has no concept of a post ID, so it's not clear which member should be used for that purpose. Presumably, this is why the MovableType extensions to MetaWeblog include a postId field in the post structs.

Of course, RSS does provide a GUID (Globally Uniquie Identifier) field, which seems a natural fit for the post ID. The problem is that the RSS spec does not require that this field be present. It could also be argued that the GUID has a meaning distinct from a blog post ID. But either way, if the MetaWeblog spec meant that the GUID should be the post ID, then it should have said so.

Judging from the MetaWeblog spec, the only place clients can count on getting a postID is from the return value of metaWeblog.newPost. That's fine if the client can assume it is making all posts to a blog, but it is insufficient if there is also, say, a web interface. If your blogging client can only edit posts it created, you've just cut its usefulness in half.

Missing Links

The MetaWeblog API depends heavily on the Blogger 1.0 API. By itself, it is missing too much to be truly useful for the development of rich blogging clients. If nothing else, this is clear from the absence of something resembling blogger.getUsersBlogs.

Actually, that's not entirely fair. There was an RFC to add the Blogger methods to MetaWeblog, so the spec has been amended to correct this shortcoming. Or has it? I actually only learned about this by reading the code for the WordPress MetaWeblog implementation. The "official" MetaWeblog spec doesn't actually mention this or contain a link to the new RFC. That seems rather odd considering that the spec does contain notes regarding other updates. So has the spec been ammended, superceded, or was this just a "Request For Comment" that was never actually adopted?

Bottom Line for Implementers

So what does all this mean for those enterprising individuals who want to try their hand at writing blogging software? It means you've got an up-hill battle.

Don't get me wrong - it's not that implementing the various specifications is difficult. The APIs are actually pretty simple. The problem is that you can't trust them.

For starters, if you want to write a server that is compatible with existing rich blogging clients, you will have to implement the Blogger 1.0, MetaWeblog, and MovableType APIs, and you will have to do it all at the same URI. This isn't really a problem, so much as an inconvenience, as you can't simply work from a single specification at a time, but have to jump back and forth between three of them just to get a workable MetaWeblog implementation.

If you're writing a client, things are just as annoying. As previously mentioned, there's the post ID problem to deal with. Handling that is not difficult, but you have to rely on the good will of the server to send you a sensible post struct, since it is not required to.

If you want to support MovableType, there's also their brain-damaged category handling to deal with. Rather than using MetaWeblog categories, MT has separate mt.getPostCategories and mt.setPostCategories methods, which deal with category IDs rather than textual categories. Again, this is not hard to deal with, but it means you have to implement category handling twice - once for MT, and once for servers that use MW categories. But on the up side, at least MT gives you an explicit postId field.

Conclusion

All in all, the old blogging APIs suck. They're imprecise, lacking in features, and tend not to be so platform-agnostic. I think they can be best described as "just barely adequate."

I have yet to look at the Atom API. I'm hoping it will turn out to be better, but I'm not going to hold out a lot of hope. At the very least, I suppose it can't be any worse than the old APIs.

Staying in shape in quarantine

A year ago, I did a post on getting in shape.  Well, a lot has happened since then.  For instance, there's been a global pandemic and people have been stuck in their houses for six months.  So I thought an update might be in order.

The food situation

In terms of general health, I've made it a point to maintain good habits.  I started working from home in March, but I've maintained the same schedule as when I was going into the office.  I still get up at 6:00 every morning to exercise - I just have a few more minutes to wake up before I start my workout.  And I still prepare all my lunches for the week every Sunday morning - my go-to lately is turkey burgers, roasted sweet potatoes or butternut squash, and sauteéd broccoli or brussels sprouts, along with half a bag of chopped salad.  I find that this is good for my mental health, in that it maintains a sense of normalcy and consistency, while keeping my on track in terms of physical health.

While my weight has been holding steady at around 165 pounds, I've noticed that I have been eating more.  This is probably to support the increased exercise and the extra muscle mass I've gained.  To deal with this, I've been making an effort to curb my sweet tooth and choose healthier foods when I'm hungry.  For snacks, I might have an apple, or a small handful of mixed nuts, or perhaps an RxBar.  (I wasn't a fan of RxBars the first time I tried one, but they've really grown on me.  The chocolate peanut butter is my favorite.)  They even have "mini" RxBars that are half the size if you just want something little.

I've also been eating a lot of PB2, which is powdered peanut butter.  I'm a big fan of peanut butter - I could easily stand there and just eat 1000 calories worth of it right out of the jar if I'm not careful.  PB2 isn't really the same as "real" peanut butter, but I think it's still pretty good and it's much safer as a diet-friendly food - a 2Tbsp serving of PB2 has 6g of protein and 60 calories, compared to 8g of protein and 190 calories for regular peanut butter.  So I get almost as much of the good stuff for a third of the calories, which means I don't have to be so concerned about over-eating.

PB2 has also become part of my typical evening dessert.  Sure, I still have "real" dessert if we have something special in the house, but when we don't, I've been having some Greek yogurt mixed with PB2, which makes a sort of "peanut butter pudding".  I throw in a little store-brand Fiber One cereal and some granola to add a little texture and it's actually a very nice before bed snack.

The training regimen

In terms of exercise, I've been making good progress.  I've been doing the Athlean-X programs for about a year and a half now.  For the first year, I did four rounds of AX-1, which I mentioned in a previous post.  After the first round, I standard integrating their TNT plugins, which each add an extra workout per week that targets a specific muscle group.  There are five of them and you can integrate up to two at a time, so I did one on my second round of AX-1 and two on my last two rounds.  I'll save the details for what the workouts were like for another post, but as you might guess from the fact that I did it four times, the "beginner-level bootcamp program" is actually fairly rigorous.

This summer I moved on to the next program - AX-2, or "Athlean Extreme" as they refer to it.  That's also a 12-week program like AX-1, but more difficult. It still focuses on general athleticism, but includes a bit more strength work.  After that, I did two rounds of Xero, which is their bodyweight-only program.  This has apparently gotten a lot more attention since the pandemic started.  Since people couldn't got to the gym, a home bodyweight program was just what a lot of people needed.

Before starting AX-1, I initially considered Xero, since at the time I didn't have any equipment.  Since it was listed as an "intermediate to advanced" program, I decided against it.  In retrospect, I'm glad I did, because it's actually quite challenging.  The strength training workouts are good, but some of the conditioning workouts are absolutely brutal.  Even after completing the first two programs, a few of them left me feeling like my heart was going to explode, which hadn't happened since my first time through AX-1.

In terms of training results, I think I'm doing pretty well.  My endurance has improved noticeably and I've actually started to develop visible muscles.  I'm stronger, my blood pressure is great, and those random aches and pains that I assumed were "just part of getting older" have gone away.  In a way, it's weird - between training daily and eating right, I feel physically good pretty much all the time.  I'm not used to that, but it's nice.  I highly recommend it.

Animaniacs is returning

A few weeks ago, I heard some very good news: Animaniacs is coming back!  I loved this show when it was on the air 20 years ago and in 2020, we really need something like this.  The new season is going to show on Hulu and is scheduled to start on November 20.  

Animaniacs logo with the Warners

If you've never seem Animaniacs, I recommend you check it out.  It only ran for a few seasons in the mid-90's, but even though some of the jokes are a little dated it's still funny.  It's technically a children's show, but it's produced by Steven Spielberg and is the type that has lots of jokes only the adults are going to get.  

As an added bonus, I can watch it as a family event!  When my wife told me about the new season, our son was curious about it.  So we showed him some of the original episodes and he loved it!  Now he wants to watch an episode or two every night.  It's a nice, light, family-friendly way to end the day.

Vim emulation in Komodo

Authors note: Here's yet another installment of "From the Archives".  Clearly I haven't really felt like coming up with new ideas lately.  I blame the pandemic.  Seriously - I'm not going to be back in the office until at least next summer.  Even though restrictions have eased (at least for the time being), lock-down fatigue has definitely long since set in.

At any rate, this is another one on using Komodo with Vim emulation.  This was written on April 16, 2014, just a few days after the last one on the same topic.  These days I'm using Vim all the time, so none of this is relevant to me anymore.  However, it is a nice example of how it's possible to extend a good IDE to customize your workflow.

In this case Komodo is (or was) customizable using JavaScript, which is nice - lots of people know JavaScript.  The down side is that, to do actually useful thing, you also it also used XUL and SciMoz, the Mozilla Scintilla binding.  These are less commonly known, to put it mildly.

To be fair, Vim isn't much better on this score.  While it supports multiple scripting languages, the primary one is, of course, VimScript, which is...not a great language.  However, it's also quite old, quite well documented, and there are lots of examples of how to use it.  The VimScript API is also pretty stable, as opposed to Komodo, which was in the process of moving away from the XUL-based stuff when I stopped using it.  And really, a little VimScript will actually take you farther than you think.

In any event, I guess the idea is that it's good to know how to customize your editor, at least a little.  You know, sharpening the saw, knowing your tools, and all that.  Good stuff.  Enjoy!


Since upgrading to Komodo IDE, I've been looking a little more at customizing my development environment.  This is actually made somewhat easier by Komodo's "sync" feature, which will synchronize things like color schemes, key bindings, etc. between IDE instances via ActiveState's cloud.

Anyway, as part of this I've also been looking more at the Vim keybindings.  I've been a casual Vim user for a very long time, but I was never hard-core enough to do things like stop using the arrow keys or give up using ctrl+C and ctrl+V for copy and paste.  So now I'm trying to do just that.

Of course, Komodo's VI emulation mode is a pale imitation of what's available in Vim.  However, even that pale imitation is actually pretty good.  In fact, its even better than Komodo's documentation would lead you to believe.  In addition to the basic modal editing stuff, Komodo supports a decent range of movement commands, variants of change and delete commands, etc.  Basically, it supports everything I already knew about plus a lot more.  So now I'm trying to get that extra stuff into my muscle memory.

In the course of looking at some Vim command guides, I naturally came across some handy looking commands that Komodo didn't support.  So I'm going to try to fix that.

The first one is the reg command.  Vim's registers were something I hadn't really worked with before, but it turns out that they're not only pretty cool, but that Komodo actually has some support for them.  I only know this because the documentation mentions the key binding for the "set register" command.  However, it doesn't implement the reg command, so you can't actually see what's in any of those registers.

So, long story short, I fixed that with a macro.  Just create a new macro named "reg" in your "Vi Commands" folder in your toolbox and add the following code (this requires another macro, executed at start-up, containing the "append_to_command_output_window" function lifted from here):

var viCommandDetails = Components.classes['@activestate.com/koViCommandDetail;1'].
                                getService(Components.interfaces.koIViCommandDetail);
var count = new Object();
var args = viCommandDetails.getArguments(count);

append_to_command_output_window('');
append_to_command_output_window("--- Registers ---");

for (item in gVimController._registers) {
    if (args.length > 0 && args.indexOf(item) < 0) {
        continue;
    }
    if (typeof gVimController._registers[item] !== 'undefined') {
        append_to_command_output_window('"' + item + '   ' + gVimController._registers[item].trimRight());
    }
}

This allows you to type ":reg" and get a list of the current registers in the "command output" window in the bottom pane.

Another good one:

var scimoz = ko.views.manager.currentView.scimoz;
if (scimoz.selText.length == 0) {
    ko.commands.doCommand('cmd_vim_cancel');
} else {
    ko.commands.doCommand('cmd_copy');
}

This can be bound to ctrl+C and allow you to keep the default "copy text" behavior when there is text selected, and still work for Vim's "back to normal mode" when nothing is selected.

Komodo and Vim

Author's Note: We're back with another installment of "From the Archives", the blog show where I declare writing bankruptcy and just post an old, half-finished article that's been sitting in my drafts for years.  This entry is from April 9, 2014.  This was in the midst of my long stint as a Komodo IDE user. 

One of my favorite things about Komodo was that it had pretty good Vim emulation.  I started using that because a few years before I'd spent a lot of time going back and forth between a Windows PC and a Macbook Pro.  The Macbook keyboard had that weird Apple layout going and it routinely messed with me, so I eventually gave up and decided to use Vim-mode because that's the same on both platforms.

Of course, things have changed since then.  I've become a full-time Vim user, and have all the fancy faux-IDE stuff set up.  I actually like it so much that I stopped using PHPStorm for work and switched to doing all my development in Vim.  So this post is no longer relevant to me, but it at least has a few handy links, so enjoy!


I've been a Vim user more or less since I started using Linux.  Mind you, I was never really a hard core Vim user.  I still use the arrow keys, for instance, and manage to get by on maybe a couple dozen keybindings and commands.  I have no clue how Vim's scripting or configuration systems work.  All I know about ctags is that they're a thing that exists.  So really, I'm more of a dabbler.

The other part of this is that I like at least a small amount of IDE in my normal working-day editor.  I kind of like having some sort of "project view" of my files, a code hierarchy viewer, some form of Intellisense, etc.  And while you can get most of the stuff I like in Vim, they're not there out of the box.  And even if you can get them, you can't count on having an obvious graphical way to manipulate them.  Typically, you just have to read the documentation to find out what the key bindings are to trigger everything.

So the upshot of this is that I use Komodo IDE with the Vi emulation setting.  This essentially turns on a Vim emulation mode that makes the editor modal and enables a lot of the standard Vim keybindings as well as a small subset of common commands.  So I get Vim goodness with all the convenience of a full IDE.  I had never really looked closely at just how much of Vim Komodo would emulate, though - I just knew it supported everything I commonly used.

Well, I had some extra time after finishing all my bug fixes the other day, and since really learning Vim has been on my list of things to do for, er, over 10 years, I decided to look up some Vim reference sheets and see how many of the commands and keybindings actually worked in Komodo.  Turns out it was a pretty decent amount.  (Note from the future: I didn't write down the details at the time and don't care enough to catalog now that I no longer use Komodo.  Suffice it do say that Komodo's Vi emulation was actually pretty good.  Maybe not as good as IdeaVim, but pretty good.)