Archive for June, 2009
A simple couchdb info widget for wordpress
I wrote a small wordpress widget to display some version details of the CouchDB server I'm running. Writing a wordpress widget wasn't to hard (I used this excellent tutorial to get started), parsing CouchDB JSON responses is even simpler.
The code for the widget (put it in 'wp-content/plugins' and enable the plugin afterwards) looks like this:
-
<?php
-
/*
-
Plugin Name: Couch-Info
-
Plugin URI: http://log4p.com
-
Description: Shows information of the configured couchdb server
-
Version: 0.1
-
Author: Peter Maas
-
Author URI: http://log4p.com
-
*/
-
-
class Couch_Info_Widget {
-
function control(){
-
$data = get_option('couchdb_info_widget');
-
?>
-
<p>Configure CouchDB location</p>
-
<p><label for="couchdb_info_widget_host">Host</label><input name="couchdb_info_widget_host" type="text" value="<?= $data['host'] ?>" /></p>
-
<p><label for="couchdb_info_widget_port">Port</label><input name="couchdb_info_widget_port" type="text" value="<?= $data['port'] ?>" /></p>
-
<?php
-
$data['host'] = attribute_escape($_POST['couchdb_info_widget_host']);
-
$data['port'] = attribute_escape($_POST['couchdb_info_widget_port']);
-
update_option('couchdb_info_widget', $data);
-
}
-
}
-
-
function widget($args){
-
$data = get_option('couchdb_info_widget');
-
-
$couchdb_version = json_decode(file_get_contents('http://'.$data['host'].':'.$data['port'].'/'))->version;
-
$num_articles = json_decode(file_get_contents('http://'.$data['host'].':'.$data['port'].'/articles/'))->doc_count;
-
-
?>
-
Parts of this blog are fed by <a href="http://couchdb.apache.org">CouchDB</a>
-
I'm running CouchDB of the <a href="http://svn.apache.org/repos/asf/couchdb/trunk/">current SVN trunk</a> and update once in a while. Current version: <strong><?= $couchdb_version ?></strong>
-
My CouchDB instance contains all <strong><?= $num_articles ?></strong> articles of this blog. All numbers in this widget are retrieved from CouchDB as well
-
<?php
-
echo $args['after_widget'];
-
}
-
function register(){
-
register_sidebar_widget('CouchDB Info', array('Couch_Info_Widget', 'widget'));
-
register_widget_control('CouchDB Info', array('Couch_Info_Widget', 'control'));
-
}
-
}
-
?>
As you can see it is one class which has two functions which are registered in wordpress. 'widget' retrieves the needed data and renders the actual widget. 'control' creates the control form to edit the widgets' settings. This is what the control form looks like in the admin interface:
The output of the 'widget' function should be visible in the bottem of the right sidebar.
2 comments3v12 api from Scala
I rewrote the code in my previous post in Scala, with a minor difference.. I'm not using an RSS api here.. Scala has native XML support... which makes writing basic RSS a breeze:
-
package v12_rss
-
-
import java.net.{URLConnection, URL}
-
import scala.xml._
-
-
// define some case classes as a simple model for the rss feed we're going to build
-
case class Channel(title:String, link:String, description:String, items:List[Item]) {
-
def toXML = <channel>
-
<title>{title}</title>
-
<link>{link}</link>
-
<description>{description}</description>
-
{items.map{_.toXML}}
-
</channel>
-
}
-
case class Item(title:String, link:String, description:String, enclosure:Enclosure) {
-
def toXML = <item>
-
<title>{title}</title>
-
<link>{link}</link>
-
<description>{}</description>
-
{enclosure.toXML}
-
</item>
-
}
-
case class Enclosure(url:String) {
-
def toXML = <enclosure url={url} type="image/jpeg"/>
-
}
-
-
// Helper for working with URN values from the API
-
case class Urn(urn:String) {
-
def comps = urn.split(":").slice(1, 4).toArray // remove the first value ('urn') not interesting
-
-
def src = comps.apply(0)
-
def mediaType = comps.apply(1)
-
def number = comps.apply(2)
-
}
-
-
object Main {
-
-
def main(args: Array[String]) = {
-
val groupElem = retrieveGroup(41129661)
-
println(<rss version="2.0">
-
{new Channel(title(groupElem), "http://3voor12.vpro.nl/tv/", shortTitle(groupElem), itemize(groupElem)).toXML}
-
</rss>)
-
}
-
-
def retrieveGroup(num:Int):Elem = {
-
XML.load("http://3voor12.vpro.nl/api/media/1/rest/group/"+ num + ".xml")
-
}
-
-
// short for getting an attribute as string
-
def attr(node:Node, name:String) = node.attribute(name).get.text
-
-
// retrieve the first title field from the given XML
-
def title(elem:Elem):String = (elem \\ "title").first.text
-
-
// retrieve the first shortTitle field from the given XML
-
def shortTitle(elem:Elem):String = (elem \\ "shortTitle").first.text
-
-
// determine the image url for the given media xml
-
def imageUrl(elem:Elem):String = "http://images.vpro.nl/images/" + new Urn(attr((elem \\ "image").first, "urn")).number
-
-
def itemize(group:Elem):List[Item] = {
-
val items = (group \\ "media") slice(0, 15) map{ m =>
-
val urn = new Urn(attr(m, "urn"))
-
println ("http://3voor12.vpro.nl/api/media/1/rest/"+ urn.mediaType +"/"+ urn.number + ".xml")
-
val media = XML.load("http://3voor12.vpro.nl/api/media/1/rest/"+ urn.mediaType +"/"+ urn.number + ".xml")
-
-
new Item(title(media), "http://3voor12.vpro.nl/tv/#/41129661/" + urn.number , shortTitle(media), new Enclosure(imageUrl(media)))
-
}
-
-
items.toList
-
}
-
}
Using the 3voor12 api to get an RSS feed of your favorite playlist
A couple of months ago we developed 3voor12TV. During festivals like Noorderslag, Pinkpop and (upcoming) Lowlands the 3voor12 crew tries to get as much high quality (h264) material online in the shortest time possible.
The application was developed in actionscript 3.0 on top of a public API. Well, it is public... but no public documentation yet. Sorry
The 3voor12 Pinkpop mashup was the first real utilization of the API.
Whilst waiting for the new video's I found myself refreshing the player over and over again; checking for new content.
I decided to automate this using the API. The Ruby script below uses the API to create a simple RSS feed with images and a direct link to each concert:
-
require 'rubygems'
-
require 'json'
-
require 'open-uri'
-
require 'rss'
-
-
API_URL_BASE = "http://3voor12.vpro.nl/api/media/1/rest/"
-
PLAYLIST_ID = "41129661"
-
-
# function to convert urn to urls
-
def urn_to_api_url(urn)
-
urn_parts = urn.split(":") # urn contains source, entity type and unique number
-
"#{API_URL_BASE}#{urn_parts[2]}/#{urn_parts[3]}.json" # bypass content negotiation, force json formatted responses
-
end
-
-
def urn_to_url(urn)
-
urn_parts = urn.split(":")
-
"http://3voor12.vpro.nl/tv/\#/#{PLAYLIST_ID}/#{urn_parts[3]}"
-
end
-
-
# retrieve and parse a playlist (group)
-
playlist = JSON.load(open("#{API_URL_BASE}group/#{PLAYLIST_ID}.json"))
-
# extract the playlist items
-
programUrns = playlist['group']['members']['member'].map{|m| m['media']['@urn']}
-
-
# create playlist
-
rss = RSS::Maker.make("2.0") do |maker|
-
maker.channel.title = "3voor12tv :: #{playlist['group']['title']}"
-
maker.channel.description = playlist['group']['shortTitle']
-
maker.channel.about = "http://3voor12.vpro.nl/tv/"
-
maker.channel.link = "http://3voor12.vpro.nl/tv/"
-
# retrieve the playlist items
-
programUrns[0..15].each do |urn|
-
maker.items.new_item do |item|
-
program = JSON.load(open(urn_to_api_url(urn)))['program']
-
img_url = "http://images.vpro.nl/images/#{program['relatedImages']['relatedImage']['image']['@id']}+s(320)"
-
-
item.title = program['title']
-
item.description = (program['synopsis'] || program['title']) + "<br/> <img src=\"#{img_url}\"/>"
-
item.link = urn_to_url(urn)
-
-
enclosure = maker.items.last.enclosure
-
enclosure.url = img_url
-
enclosure.length = -1
-
enclosure.type = "image/jpeg"
-
end
-
end
-
end
-
-
# write to disk
-
File.open("3v12feed.xml","w") do |f|
-
f.write(rss)
-
end
I have a cronjob executing the script once in a while:
http://feeds2.feedburner.com/3voor12tvPinkpop
3 comments
