Archive for December, 2007

Moab

Tuesday, December 18th, 2007

The posting binge continues. Lots of people search me for “moab“, so I thought I’d meet my readers expectations and write a Moab post, complete with link to a flickr set.

Of course, when speaking of MTB or Moab (or crafting a post for search results), I also need to be sure to link to my buddy Brian’s site SingleTrackRides.

SAC alert “application”

Tuesday, December 18th, 2007

During the recovery from my previously mentioned osteotomy, I’ve been spending lots of time chatting with my physical therapist Larry Meyer. He’s an interesting and personable guy (and is really handling my PT well). In my dozens of appointments, we’ve talked about lots of stuff, including Lijit, Christmas presents, and something near and very dear to me, bargain hunting.

Along the way, I mentioned Steep & Cheap, which is basically like the woot of outdoor gear. They have single deal after single deal, about every 20 minutes or so, all day long. It’s fine for me because I work at a computer all day long and can see each deal as soon as it is posted. But Larry is not at a computer, though he does have access to one.

What Larry does have, though, is a pager with an email address. It got me to thinking, so I hacked together a little PHP code, mixed it gently with cygwin cron, to poll the SAC deal feed. If the deal changes, the application will send him a page.

So far, he’s not tired of the constant buzzing on his hip.

Here it is. Standard disclaimer applies: this is quick n’ dirty(tm):

<?
// Requires PEAR::Mail
require_once( 'Mail.php' );

$sac_rss = "http://www.steepandcheap.com/steepcheap/rss.xml";
$item_element = "ITEM";
$have_item = FALSE;
$in_item = FALSE;
$current_element = "";
$message = "";
$statusFile = "sacdeal.txt";

$to_list = array( "pager_email_address" );

$from = 'SAC Alert <sacalert@my.hosting.company>';
$subject = 'SAC deal alert';

$host = 'smtp.server.name';
$username = 'smtp.userid';
$password = 'smtp.password';

$to = "";
foreach( $to_list as $emailaddy )
{
  $to .= "$emailaddy, ";
}
echo "$to\\n";

function startElement( $parser, $name, $attrs )
{
  global $current_element, $have_item, $in_item, $item_element;
  $current_element = $name;
  if ( $name == $item_element )
    $in_item = TRUE;
}

function endElement( $parser, $name )
{
  global $current_element, $have_item, $in_item, $item_element;
  $current_element = "";
  if ( $name == $item_element )
  {
    $in_item = FALSE;
    $have_item = TRUE;
  }
}

function elementData( $parser, $text )
{
  global $current_element, $have_item, $in_item, $message;
  if ( $in_item && !$have_item )
  {
    // the message content is only the title or the price
    if ( $current_element == "TITLE" || $current_element == "SAC:PRICE" )
      $message .= "$text\\n";
  }
}

$xml_parser = xml_parser_create();
xml_set_element_handler( $xml_parser, "startElement", "endElement" );
xml_set_character_data_handler( $xml_parser, "elementData" );

// fetch the feed content and parse it
$xml = file_get_contents( $sac_rss );
xml_parse( $xml_parser, $xml );
xml_parser_free($xml_parser);

// compare the current item in the feed to the last one we sent email about
$oldcontents = file_get_contents( $statusFile );
if ( $oldcontents != $message )
{
  $headers = array( 'From' => $from,
                    'To' => $to,
                    'Subject' => $subject );

  $smtpParams = array( 'host' => $host,
                       'auth' => true,
                       'username' => $username,
                       'password' => $password );

  $smtp = Mail::factory( 'smtp', $smtpParams );

  $mail = $smtp->send( $to, $headers, $message );

  echo $message;
  if (PEAR::isError($mail))
  {
    echo( $mail->getMessage() . "\\n" );
  }
  else
  {
    echo( "Message successfully sent!\\n" );
    file_put_contents( $statusFile, $message );
  }
}
else
{
  echo "same deal as last time\\n";
}
?>

W countdown

Monday, December 17th, 2007

A milestone. We’re now within 400 days of the end of the worst… president… ever…

399 days

Unfortunately we’ll be cleaning up for years. (Perhaps his replacement won’t any good either, but doubt he/she could be worse.)

You mean somebody might actually read this?

Monday, December 17th, 2007

I noticed today that Todd has added me to his blogroll. And somebody’s been searching me on physical therapy. That must be my physical therapist Larry Meyer up at BCSM. (I’m recovering from a double-osteotomy to correct a valgus malalignment. I have way better pictures than that Wikipedia article.)

So my reaction? Uh oh; I guess I’d better do something more here than just post ridiculous YouTube videos and random text.

Blinklist -> del.icio.us

Friday, December 7th, 2007

Long ago I migrated from del.icio.us to Blinklist. Why? Blinklist would let me combine tags when trying to find a link, and del.icio.us wouldn’t. For example, with Blinklist I could find a link tagged with both “reference” AND “css”. On del.icio.us, only “reference” OR “css”.

Unfortunately, Blinklist dropped that feature a while back. I just noticed del.icio.us added it, and I’m tired of waiting for Blinklist to add it back in.

But I faced the problem of getting all my bookmarks from Blinklist back to del.icio.us. Probably such a tool exists already, but it was pretty easy to hack together in PHP.

Download your Blinklist bookmarks in XML from http://www.blinklist.com/?Action=User/Export/export.php and save them in blinklist.xml.

Blinklist allowed spaces in tags, del.icio.us does not. The code converts spaces in the tags to hyphens. PEAR HTTP_Request and openssl is required in your PHP install.

Run it from the command line: php blinklist-to-delicious.php blinklist.xml

Here’s the code. Standard disclaimer applies: this is quick n’ dirty(tm):

<?php
/* Take blinklist bookmarks xml
             and add them to del.icio.us via the API.

---------------------------------------------------
del.icio.us API:

https://api.del.icio.us/v1/posts/add?

&url (required) - the url of the item.
&description (required) - the description of the item.
&extended (optional) - notes for the item.
&tags (optional) - tags for the item (space delimited).
&dt (optional) - datestamp (format "CCYY-MM-DDThh:mm:ssZ").
&replace=no (optional) - don't replace bookmark if already posted.
&shared=no (optional) - make the item private

---------------------------------------------
Blinklist entry XML:
  <item>
   <title>MrBalky Heavy Industries</title>
   <description></description>
   <link>http://www.mrbalky.com</link>
   <guid></guid>
   <pubDate>1197042355</pubDate>
   <private></private>
   <favourite></favourite>
   <vote>0</vote>
   <category>awesome,cool,stupid</category>
  </item>
*/
require_once "HTTP/Request.php";

$delicious_id = 'mydeliciousid';
$delicious_pass = 'mypassword';

define( "ITEM", "ITEM" );
define( "TITLE", "TITLE" );
define( "LINK", "LINK" );
define( "PUBDATE", "PUBDATE" );
define( "CATEGORY", "CATEGORY" );

$item = array();
$have_item = FALSE;
$in_item = FALSE;

function startElement( $parser, $name, $attrs )
{
  global $current_element, $in_item, $item;

  $current_element = $name;
  if ( $name == ITEM )
  {
    $item = array();
    $in_item = TRUE;
  }
}

function endElement( $parser, $name )
{
  global $current_element, $in_item, $item;

  $current_element = "";
  if ( $name == ITEM )
  {
    $in_item = FALSE;
    addToDelIcioUs();
  }
}

function elementData( $parser, $text )
{
  global $current_element, $in_item, $item;

  if ( $in_item )
  {
    $item[ $current_element ] .= $text;
  }
}

function addToDelIcioUs()
{
  global $item, $delicious_id, $delicious_pass;

  $itemURL = urlencode( $item[LINK] );
  $itemTitle = urlencode( $item[TITLE] );
  $itemDate = strftime( '%Y-%m-%dT%H:%M:%SZ', $item[ PUBDATE ] ); 

  $apiURL = "https://api.del.icio.us/v1/posts/add?url=$itemURL";
  $apiURL .= "&description=$itemTitle";
  $apiURL .= "&dt=$itemDate";
  $apiURL .= '&tags=';
  $sep = "";

  $itemTags = split( ',', $item[ CATEGORY ] );
  foreach( $itemTags as $tag )
  {
    $tag = str_replace( ' ', '-', $tag );
    $apiURL .= "$sep$tag";
    $sep = '+';
  }
  echo "$apiURL\\n";

  $req =& new HTTP_Request( $apiURL );
  $req->setBasicAuth( $delicious_id, $delicious_pass );

  $response = $req->sendRequest();

  if ( PEAR::isError($response) )
  {
    echo 'Error: '.$response->getMessage()."\\n";
  }
  else
  {
    echo 'Response: '.$req->getResponseBody()."\\n";
  }

  echo "\\n";

  sleep( 5 );  // be polite to del.icio.us
}

$inputFile = $argv[1];
echo "input: $inputFile\\n";
$xml = file_get_contents( $inputFile );
$xml_parser = xml_parser_create();
xml_set_element_handler( $xml_parser, "startElement", "endElement" );
xml_set_character_data_handler( $xml_parser, "elementData" );
xml_parse( $xml_parser, $xml );
xml_parser_free($xml_parser);
?>

4x madness - the bike wins!

Wednesday, December 5th, 2007


http://view.break.com/411656 - Watch more free videos