24 May 2004


The basic situation is this: you’re reading a news item in your feedreader, and you want to post it to your weblog via your favorite weblog editor application.

But how do you get the news item into your weblog editor? Copy-and-paste? Drag-and-drop?

The ideal thing would be a simple command in your feedreader—a Post to Weblog command—that takes the news item you’re reading and sends it to your weblog editor. Once it’s in your weblog editor, then you can edit it, choose which weblog to send it to, add commentary—all the things you would normally do.

But the trick is just getting it to the weblog editor in the first place. That’s where authors of feedreaders and weblog editors can work together to make it easy.

This page describes a simple Apple event interface that feedreaders can use to send news items to weblog editors that also support the interface.

Goals of the design

This interface was designed with a few things in mind:

1. It should be easy to implement in both feedreaders and weblog editors, which will promote broad adoption and not over-burden already-busy developers.

2. It should use a system of inter-application communication supported by Cocoa, Carbon, REALbasic, and various scripting languages. (That system turns out to be Apple events.)

3. It should not be tied to RSS or Atom or any other specific format.

4. It should bear in mind that you might want to send news items to applications other than weblog editors—outliners, databases, and so on might conceivably benefit from being able to receive news items.

5. It should have some room to grow for the future.

The Apple event

When the user chooses Post to Weblog (or equivalent), the sending application creates an Apple event and sends it to the weblog editor (or other) application.

The Apple event contains one parameter, the direct object parameter, which consists of an AERecord containing a variable number of items.

The Apple event class, Apple event ID, and keys for the AERecord are listed below:

const AEKeyword EditDataItemAppleEventClass = 'EBlg';
const AEKeyword EditDataItemAppleEventID = 'oitm';
const AEKeyword DataItemTitle = 'titl';
const AEKeyword DataItemDescription = 'desc';
const AEKeyword DataItemSummary = 'summ';
const AEKeyword DataItemLink = 'link';
const AEKeyword DataItemPermalink = 'plnk';
const AEKeyword DataItemSubject = 'subj';
const AEKeyword DataItemCreator = 'crtr';
const AEKeyword DataItemCommentsURL = 'curl';
const AEKeyword DataItemGUID = 'guid';
const AEKeyword DataItemSourceName = 'snam';
const AEKeyword DataItemSourceHomeURL = 'hurl';
const AEKeyword DataItemSourceFeedURL = 'furl';

The value associated with each of these keywords in the AERecord is a string.

The AERecord need not contain all of these items, since any individual news item may not have all these attributes. In practice, including at a minimum title, description, one of the link items, source name, and source home URL is recommended, though not required.

The information about the source is part of this interface so that weblog editors can create attribution strings, as in “Via XYZBlog,” when formatting a post for editing. It’s likely that other types of application will also have use for the source attributes.

It’s entirely possible that in the future additional optional items could be added, since the above list covers the basic attributes of a news item but does not cover every possible attribute of a news item.

Sample code for weblog editors

If you’re writing a weblog editor in Cocoa, the below code should help you get started. (If you’re writing a feedreader, or writing an editor but not in Cocoa, you should still should have enough information to be able to implement this interface.)

You need the keywords from above in your code.

Then, in awakeFromNib or similar appropriate place, you need to register to handle the Apple event, with something like this:

[[NSAppleEventManager sharedAppleEventManager]
    setEventHandler: self
    andSelector: @selector (editDataItem: withReplyEvent:)
    forEventClass: EditDataItemAppleEventClass
    andEventID: EditDataItemAppleEventID];

Then you need to write the Apple event handler which grabs the attributes from the Apple event and opens the post for editing. Something like this:

- (void) editDataItem: (NSAppleEventDescriptor *) event
    withReplyEvent: (NSAppleEventDescriptor *) reply {

    NSAppleEventDescriptor *recordDescriptor = [event descriptorForKeyword: keyDirectObject];
    NSString *title = [[recordDescriptor descriptorForKeyword: DataItemTitle] stringValue];
    NSString *body = [[recordDescriptor descriptorForKeyword: DataItemDescription] stringValue];
    NSString *summary = [[recordDescriptor descriptorForKeyword: DataItemSummary] stringValue];
    NSString *link = [[recordDescriptor descriptorForKeyword: DataItemLink] stringValue];
    NSString *permalink = [[recordDescriptor descriptorForKeyword: DataItemPermalink] stringValue];
    NSString *commentsURL = [[recordDescriptor descriptorForKeyword: DataItemCommentsURL] stringValue];
    NSString *sourceName = [[recordDescriptor descriptorForKeyword: DataItemSourceName] stringValue];
    NSString *sourceHomeURL = [[recordDescriptor descriptorForKeyword: DataItemSourceHomeURL] stringValue];
    NSString *sourceFeedURL = [[recordDescriptor descriptorForKeyword: DataItemSourceFeedURL] stringValue];
    ExternalPost *newPost = [[[ExternalPost alloc] init] autorelease];
    [newPost setTitle: title];
    if (body == nil)
        [newPost setBody: summary];
        [newPost setBody: body];
    if (permalink == nil) {
        if (commentsURL == nil)
            [newPost setLink: link];
            [newPost setLink: commentsURL];
        } /*if*/
        [newPost setLink: permalink];
    [newPost setSourceName: sourceName];
    [newPost setSourceHomeURLString: sourceHomeURL];
    [newPost setSourceFeedURLString: sourceFeedURL];
    [self editPost: newPost];
    } /*editDataItem: withReplyEvent:*/

What’s going on in the above is that first the various attributes are pulled from the Apple event record. Then an ExternalPost object is created, its attributes are set from the incoming data, then an editPost method is called. (The ExternalPost object and editPost method are hypothetical, for purposes of illustration. You’ll do what makes sense for your application.)

Note also that the code is aware that some items may not exist.