Thursday 15 March 2007

It's all about the del in del.icio.us

In my opinion what makes del.icio.us great is the ability to view or allow other people to view your bookmarks where ever you are. If you then put this into the blogging context then having the ability to show your bookmarks on your blog is an awesome way of publicising what you look at. Now if we take this a step further then having a daily update of links of articles, pages and tutorials that we found useful that day is mind bogglingly awesome.


Del.icio.us also thinks this is the way forward and offers (if a some what crude and unfriendly) interface for linking you del.icio.us links with your blog. However all is not strawberries and cream if you are a user of Blogger. The Blogger API doesn't seem to use the same XML-RPC interface. Meaning that del.icio.us won't talk to you blog and getting a daily blog of your links will be a pain.


I decided to come up with a way to overcome this. Bring in some PHP, Cron Job's and a hole lot of XML goodness, a touch of html email and just a hint of blogger configuration and you get the MJJames Del.icio.us blog poster :D


An Overview

Currently in alpha my PHP script takes a del.icio.us RSS feed, an email address and an optional range field and produces an email that gets sent to the specified email address.

As such it can be used for email daily, monthly or even yearly link lists to either a blog or to individuals or mailing lists.


The script works by taking the provided RSS feed and opening it as a PHP XML Source, the optional range field is then used to determine the date range of del.icio.us links to return. Currently the options are daily (default), month or year.


The date range returned is then used to loop through the del.icio.us RSS feed and pulls out any nodes that match the date criteria. These nodes are then used to generate the contents of the email. The beta version uses title, date, short description and link.


The entire email is then sent to the provided email address. Now the way this email appears on a blog is by letting your blog accept post's via email and setting up a unique email address for blog posts.


Of course with the script and blogger configured the next step is to schedule this script to run daily.


With most PHP installations running on UNIX the main way to schedule this script is to use Cron Jobs, this way we can specify to run this script daily, weekly, monthly or even yearly depending on your needs.


Now this is where I must say that I have ran into some problems. I got my Cron Job to execute my script by using /usr/bin/php -q /home/el/public_html/development/delicious/index.php


However, this doesn't allow me to specify any options for the script, so I have had to fall back to hard coded values for my feed and email. This is far from ideal and in effect renders alot of the script useless, now I was sure you could give Cron a URL with querystring parameters but it has alluded me thus far :(


Current Issues

  • The code used DOM and loops through the RSS feed using PHP to perform some logic checks, this is untidy and far from optimised code. My next version will use XPath to query the RSS feed and return the matching nodes which PHP can then render into an email
  • It doesn't do weeks. Currently you can schedule it to daily updates, monthly and yearly reminders / reading lists but there is no provision for weeks. This is mainly because at the time I couldn't be bothered to find the week's start and end date based on the day its ran. This is easily doable, I just need to get off of playing with .Net and back on to PHP for a night.
  • My issues with CRON and url's needs resolving so this script can be configured for multiple users
  • It assumes the url feed doesn't include http:// and adds this on, this should be looked for before adding
  • Currently it only handles del.icio.us feeds, the next step is to looking at how it would handle Google Bookmarks and making it work seamlessly with that.
  • It needs to be completely turned into object orientated PHP 5 code, not some functions and main code - Currently lazy code

Code

/* ====================================== MJJames - Blog Poster Alpha v 0.6 email: blogposter (at) michaeljames.me.uk ====================================== */ function loadXMLStream($input){ $xml = new DOMDocument; // We need to validate our document before refering to the id $xml->validateOnParse = true; $success = false; if ($xml->load($input)){ $success = true; } if ($success==true){ return $xml; } else{ echo "ERROR: Source Not Found"; //cronJob will email us any output - normally we don't want this but as the feed wasnt found we need an error message return "XML Source Not Found } } function makeDate($daterange){ switch (strtolower($daterange)){ //our date range field will stipulate if we return a day, week or month's worth of nodes case "day": $date = date("Y-m-d", time()); break; case "week": // needs to be added break; case "month": $date = date("Y-m", time()); break; case "year": $date = date("Y", time()); break; } return $date; } $url = "http://".$_GET["url"]; $xml = loadXMLStream($url); $range= strtolower($_GET["range"]); if ($range==""){ $range = "day"; } $date = makeDate($range); foreach ($xml->documentElement->childNodes as $links) { //if node is an element (nodeType == 1) and the name is "item" loop further if ($links->nodeType == 1 && $links->nodeName == "item") { foreach ($links->childNodes as $item) { //if node is an element and the name is "title" "link" or "description" then add to temp variables for the email if ($item->nodeName == "title" ) { $title = $item->nodeValue; } if ($item->nodeName =="link"){ $link = $item->nodeValue; } if ($item->nodeName == "description"){ $description = $item->nodeValue; } if ($item->nodeType == 1 && $item->nodeName == "dc:date" && stristr($item->nodeValue, $date)){ //if its a date node check to see if our date is in it $dates = $item->nodeValue; $output = true; //if we're here then its our date and we need to add it to our email } } } if ($output){ $email.= "

$title - ".date("j F, Y",strtotime($dates))."

$description

Link: $link

";
} $output = false; } $sendto = "".$_GET["email"]; if ($sendto == ""){ echo "email failed - no email address"; //cronJob will email us any output - normally we don't want this but as the email failed to send we should know this } else{ if ($email != ""){ //if we have content and an email address $email = "

Del.icio.us Links For ".date("d/m/Y", time())."

".$email;
$headers = 'From: blogposter@michaeljames.me.uk' . "\r\n" . 'Reply-To: blogposter@michaeljames.me.uk' . "\r\n" . 'X-Mailer: PHP/' . phpversion(). "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-type: text/html; charset=iso-8859-1' . "\r\n"; if (mail($sendto, "Del.icio.us Links For ".date("d/m/Y", time()), $email, $headers)){ } else{ echo "email failed"; //cronJob will email us any output - normally we don't want this but as the email failed to send we should know this } } } ?>