TiVoTweet

Ok, I'm not entirely sure how I found myself doing this but I somehow found the TweeVo website talking about sending TiVo recording info out to twitter. Since I'm not much of a windows person, I thought maybe I can get one of my linux boxes to do the same thing. Yes, probably won't have a nifty interface and yes is not out finding my tivos automatically but it would tweet.

So, I started my web search and initially came up with this forum discussing this very thing on the tivocommunity. Ok, it looks like this code was in PHP which is not a difficult language to figure out so I began putting it all together.

I liked the output of TweeVo so I had to add some additional functionality to the original script tweetTivo.php from the MrBalky Heavy Industries site. Once I figured out how to get curl to post to twitter everything was working fine that is, until, Twitter changed to the OAuth method of authentication. Luckily, I found Jaisen Mathai's web site regarding PHP OAuth for twitter. Using the examples provided I was able to get OAuth working as shown in the script and below.

#!/usr/bin/php
//$Id: tivotweet.php,v 1.8 2010/03/13 03:29:16 root Exp root $
//$Source: /usr/local/kelnet-tivo-dev/RCS/tivotweet.php,v $
<?
//error_reporting(E_ALL);
error_reporting(0);

require "/usr/local/oauth-php/lib/EpiCurl.php";
require "/usr/local/oauth-php/lib/EpiOAuth.php";
require "/usr/local/oauth-php/lib/EpiTwitter.php";


require_once( 'parse_tivo_xml.php' );

//if ( $argc < 3 )
//{
//  echo 'USAGE: '.$argv[0].": <twitter user> <twitter pwd> [<master's name> [<input file> [<old data file> [<no tweet>]]]]\n";
//  exit( 1 );
//}

$mastersName = '';
$nowPlayingFile = dirname($_SERVER['PHP_SELF']).'/tivo_nowplaying.xml';
$suggestionsFile = dirname($_SERVER['PHP_SELF']).'/tivo_suggestions.xml';
$oldDataFile = dirname($_SERVER['PHP_SELF']).'/oldTiVoData.php';
$oldSuggestionsFile = dirname($_SERVER['PHP_SELF']).'/oldSuggestions.php';
$tivo1 = 'https://';
$tivo2 = 'https://';
//$tivoNowplaying='TiVoConnect?Command=QueryContainer&Container=/NowPlaying&Recurse=Yes&ItemCount=20';
//$tivoSuggestions='TiVoConnect?Command=QueryContainer&Container=/NowPlaying/0&Recurse=Yes&ItemCount=20';

$tivoNowplaying='TiVoConnect?Command=QueryContainer&Container=/NowPlaying&Recurse=Yes&ItemCount=20';
$tivoSuggestions='TiVoConnect?Command=QueryContainer&Container=/NowPlaying/0&ItemCount=20';

//$twitterUser=$argv[1];
//$twitterPW=$argv[2];
$twitterUser='';
$twitterPW='';

//if ( $argc > 3 )
//  $mastersName = $argv[3];
//if ( $argc > 4 )
//  $inputFile = $argv[4];
//if ( $argc > 5 )
//  $oldDataFile = $argv[5];
//if ( $argc > 6 )
//  $noTweet = $argv[6];

//Get nowplaying xml from the tivo
$xml_data = get_tivo_xml($tivo1."/".$tivoNowplaying);

//Save the nowplaying xml to a file
save_xml($nowPlayingFile,$xml_data);

//Get suggestions xml from the tivo
$xml_data = get_tivo_xml($tivo1."/".$tivoSuggestions);

//Save the suggestions xml to a file
save_xml($suggestionsFile,$xml_data);

// Parse the nowplaying XML returned by the tivo
$programs = parseTiVoXML( $nowPlayingFile );
$nowPlaying = $programs['programs'];

// Parse the suggestions XML returned by the tivo
$programs = parseTiVoXML( $suggestionsFile );
$suggestions = $programs['programs'];


function cleanTitle( $title )
{
// clean up the title
$title = str_replace( "amp;", "&", $title );
$title = str_replace( "\"", "", $title );
//return( urlencode($title) );
return( $title );
}

// As it says tweetit
function tweetIt( $tweetTxt )
{
global $twitterUser;
global $twitterPW;
global $noTweet;

echo "$tweetTxt\n";
$curlCmd = "curl -u $twitterUser:$twitterPW -d status=\"$tweetTxt\" http://twitter.com/statuses/update.json";
echo "$curlCmd\n";
if ( !$noTweet )
exec( $curlCmd );
}

function oauth_tweetIt( $tweetTxt )
{
define(CONSUMER_KEY,"");
define(CONSUMER_SECRET,"");
define(USER_TOKEN,"");
define(USER_SECRET,"");
// Format text as utf8 and chomp at 140 chars
//$text = utf8_encode(substr($_SERVER["argv"][1],0,140));
$text = utf8_encode(substr($tweetTxt,0,140));

$twitterObj = new EpiTwitter(CONSUMER_KEY,CONSUMER_SECRET,USER_TOKEN,USER_SECRET);
$x = $twitterObj->post_statusesUpdate(array('status' => $text));
if ($x->id) {
echo "Tweet Posted: ".$x->id."\n";
} else {
echo "Error Posting Tweet\n";
}
}


// used to acquire a tiny url from a given url
function get_tiny_url($url)  
{  
$ch = curl_init();  
$timeout = 5;  
curl_setopt($ch,CURLOPT_URL,'http://tinyurl.com/api-create.php?url='.$url);  
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);  
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);  
$data = curl_exec($ch);  
curl_close($ch);  
return $data;  
}

//pad numbers to the appropriate size
//0 => 0000
//1 => 0001
//20 => 0020
//432 => 0432
function number_pad($number,$n) {
return str_pad($number,$n,"0",STR_PAD_LEFT);
}

//format programid to work with 14 character string
//EP6871430062 = EP006871430062
function format_programid($pid)
{
$firstchars = substr($pid,0,2);
$number = substr($pid,2,strlen($pid));
$newid = $firstchars.number_pad($number,12);
return $newid;
}

//Download the tivo xml data
function get_tivo_xml($tivo_url)
{
## HTTPS url that you are targeting.
$url = $tivo_url;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
// Set your login and password for authentication
curl_setopt($ch, CURLOPT_USERPWD, 'tivo:');
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
//  curl_setopt($ch, CURLOPT_USERAGENT, 'Opera/9.23 (Windows NT 5.1; U; en)');
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT,5);

## Below two option will enable the HTTPS option.
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,  2);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}

//wsave the tivo xml data to a file
function save_xml($file,$data)
{
$fh = fopen( $file, 'w' ) or die("can't open $file");
fwrite( $fh, $data );
fclose($fh);
}

function getNewRecording($data,$file)
{  
//tvlisting URL 
$tv_listings = 'http://tvlistings.zap2it.com/tv/x';

// load up the old recording, offset and watching data.  this file
// contains the $recordingInfo, $oldOffset and $watchingState variables.
include( $file );

// now look through the new now playing data and see if it's recording anything new
$i = 0;
foreach ( $data as $programInfo )
{
$title = cleanTitle( $programInfo['title'] );
if ( $title != '' )
{
//building array of titles with byteoffsets
$newOffsets[$title] = $programInfo['byteoffset'];
//must be for the top 2 programs in the list 0 and 1
if ( $i < 2 )
{
//checks programInfo to see if something is recording
if ( $programInfo['customicon'] == "urn:tivo:image:in-progress-recording" )
{
//if the recordingInfo[0 or 1]->title from the oldData is not equal to the current title
// then we must have a new recording 
if ( $recordingInfo[$i] != $title )
{
// If this is the first recording, shift the old recording down one so that
// this reflects the old recording
if ( $i == 0 )
$recordingInfo[1] = $recordingInfo[0];

// assign the new title which will get recorded in the oldTivoData file
$recordingInfo[$i] = $title;

//Now get the details from the currently recording program
$readable_date=date("@ g:i a", $programInfo['capturedate']);
$episode_title = $programInfo['episodetitle'] ;
$source_channel = $programInfo['sourcechannel'] ;
$source_station = $programInfo['sourcestation'] ;
$programid = $programInfo['programid'] ;

//create url for tv listings to send to tinyurl
$newtv_listings = $tv_listings."/".format_programid($programid);

//Get the tiny url from the string created above
$tinyurl = get_tiny_url($newtv_listings);

//tweetit("kelnet-tivo1> $title: '$episode_title' $readable_date on $source_channel $source_station $tinyurl\n");
oauth_tweetIt("kelnet-tivo1> $title: '$episode_title' $readable_date on $source_channel $source_station $tinyurl\n");
//   echo "kelnet-tivo> $title: '$episode_title' $readable_date on $source_channel $source_station $tinyurl\n";
}
else
echo "already were recording: $title\n";
$i++;
}
}
}
}

echo "$i recordings in progress\n";
$fh = fopen( $file, 'w' ) or die("can't open old data file $file");
fwrite( $fh, "<?\n" );
fwrite( $fh, '$recordingInfo = '.var_export( $recordingInfo, TRUE ).";\n" );
fwrite( $fh, '$oldOffsets = '.var_export( $newOffsets, TRUE ).";\n" );
fwrite( $fh, '$watchingState = '.var_export( $watchingState, TRUE ).";\n" );
fwrite( $fh, "?>\n" );
fclose($fh);
} 

getNewRecording($nowPlaying,$oldDataFile);
getNewRecording($suggestions,$oldSuggestionsFile);
?>