Webhooks and Hookpress

05 Jan 2010

Webhooks: so simple you’ll think they’re stupid.
— Jeff Lindsay

A couple weeks ago we launched blog.spokt.com and we wanted to have links to recent blog posts in the footer at spokt.com (hosted on different servers):

recent blog posts listed in spokt.com footer

To accomplish this I created a url at spokt which when accessed would download the blog’s rss feed, parse it, and store it for later listing. I then used my nearly-zero wordpress & php experience to create plugin that just curl’d the url. Here’s the plugin code:

	<?php

	function notify_spokt() {
		$ch = curl_init('http://spokt.com/blog_update');
		curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
		curl_setopt( $ch, CURLOPT_HEADER, 0 );
		$page = curl_exec($ch);
		curl_close($ch);
	}

	add_filter('publish_post','notify_spokt');

	?>

I thought that this kind of functionality might be useful and considered investigating how to make the url configurable.

Yesterday I learned about webhooks and thought about how I might go about creating a wordpress plugin using the “hooks” already built in and exposing them as webhooks. I figured someone probably already had and sure enough: the hookpress plugin by Michael 芳貴 Erlewine

Once installed Click “Settings” in the wp admin then the “Webhooks” link. That will bring up an easy-to-use admin interface. Click “Add webhook” then choose your action, any fields you want to pass, and enter the url.

See Also: Useful hookpress screencast by Michael 芳貴 Erlewine

easy to use admin interface

On the rails server this class stores the information I need for my links in a background process. BlogPost is an ActiveRecord class:

require 'rss/2.0'
require 'open-uri'

class FeedReader
  attr_accessor :uri
  def initialize(feed_url)
    self.uri = feed_url
  end
  
  def process
    BlogPost.destroy_all
    feed_items.each do |item|
      BlogPost.create(:title=>item.title,:href=>item.link,:description=>item.description, :publish_date => item.pubDate.to_s)
    end  
  end

  def feed_items
    items = []
    open(self.uri) do |http|
      response = http.read
      result = RSS::Parser.parse(response, false)
      return result.items
    end
  end

end