Roger Stringer Shows You How To Live Blog With Twilio SMS And Simperium

January 23, 2014
Written by

Twilio Bug Logo

RogerStringer
When you’re at a conference it’s easy to get inspired but hard to find the time to share your thoughts then and there. Going from talk, to demo, to meetup, carving out time to blog and share your thoughts might not be an option.

Roger Stringer (pictured right), independent developer, Twilio DOer, and author of the Twilio Cookbook built a hack that lets you post photo and text updates to your blog via Twilio SMS.

Read the full post originally published on his blog here, and check out his tutorial below.

Live Blogging with Twilio and Simperium

Live blogging is pretty handy, when attending events, it never hurts to be able live blog about the latest new gadgets.

We’re going to build a simple live blogging app using PHP, Simperium and Twilio.

This particular live blog solution is set up for one event, this means all posts to the phone number we specify will show up.

You could build on this to allow for multiple events, but that’s a little more than we want to dive into today.

And yes, we could also use Pusher for this, but I like Simperium as it serves as both a datastore and a real-time push service, so that way we can store our posts on Simperium, and viewers are updated instantly.

Since these posts are just a line or two or text and a picture.. We don’t need anything too advanced for our data storage…

Since it’s the framework I use for a lot of projects, I once again, built this using the Jolt Micro Framework, which works well for building apps rapidly.

You’ll need a few things things to set this up:

  1. A Twilio account
  2. A Simperium.com account
  3. The Twilio PHP library
  4. The Simperium PHP library
  5. Download the Jolt PHP Framework
  6. Unzip it, open up config.ini, and add the following settings:

 

; site info
site.name = My Live Blog
site.url = http://mysiteurl/

; rendering vars
views.root = views
views.layout = layout

; session vars
cookies.secret = IeNj0yt0sQu33zeflUFfym0nk1e
cookies.flash = _F

; twilio vars
twilio.accountsid = MY TWILIO ACCOUNT SID
twilio.authtoken = MY TWILIO AUTH TOKEN
twilio.fromNumber = MY TWILIO FROM NUMBER

; simperium stuff
simperium.appname = MY SIMPERIUM APP NAME
simperium.apikey = MY SIMPERIUM API KEY
simperium.token = MY SIMPERIUM TOKEN
simperium.bucket = twilio-liveblog

 

  1. Create a folder called Services/
  2. Download the Twilio PHP library and save it to the Services/ folder.
  3. Download the Simperium PHP library and save it to the Services/ folder.
  4. Open index.php and copy the following code:

 

<!--?php include("jolt.php"); require 'Services/simperium.php'; require 'Services/Twilio.php'; require 'functions.php'; $app = new Jolt(); $app--->option('source', 'config.ini');

$client = new Services_Twilio($app->option('twilio.accountsid'), $app->option('twilio.authtoken') );
$fromNumber = $app->option('twilio.from');

$app->store('client',$client);

$simperium = new Simperium($app->option('simperium.appname'), $app->option('simperium.apikey') );
$simperium->set_token( $app->option('simperium.token') );

$app->store('simperium',$simperium);

$app->post('/listener', function(){
	$app = Jolt::getInstance();

	$bucket = (String)$app->option('simperium.bucket');

	if ( isset($_POST['NumMedia']) && $_POST['NumMedia'] > 0 ){
		for ($i = 0; $i < $_POST['NumMedia']; $i++){
			if (strripos($_POST['MediaContentType'.$i], 'image') === False){
				continue;
			}

//			generate a unique UUID to use as the post id:
			$sms_id = $app->store('simperium')->generate_uuid();

			$file = sha1($_POST['MediaUrl'.$i]).'.jpg';
			file_put_contents( 'images/original/'.$file, file_get_contents($_POST['MediaUrl'.$i]) );
			chmod ('images/original/'.$file, 01777);

			// Edit image
			$in = 'images/original/'.$file;
			$out = 'images/processed/'.$file;
			cropResize($in,$out,250);
			chmod ('images/processed/'.$file, 01777);

			// Remove Original Image
			unlink('images/original/'.$file);

			$app->store('simperium')->$bucket->post( $sms_id,array(
				'text'=>'<img src="'.$app->option('site.url').'/images/processed/'.$file.'" /><br />'.$_POST['Body'],
				'from'=>$_POST['From'],
				'image'=>$file,
				'timeStamp' => time(),
			) );

		}
		$message = $app->store('client')->account->messages->sendMessage(
			$app->option('twilio.from'), // From a valid Twilio number
			$_POST['From'], // Text this number
			"Posted!"
		);
		return true;
	}else{
//		generate a unique UUID to use as the post id:
		$sms_id = $app->store('simperium')->generate_uuid();

		//	no image... text post
		$app->store('simperium')->$bucket->post( $sms_id,array(
			'text'=>$_POST['Body'],
			'from'=>$_POST['From'],
			'timeStamp' => time(),
		) );
		$message = $app->store('client')->account->messages->sendMessage(
			$app->option('twilio.from'), // From a valid Twilio number
			$_POST['From'], // Text this number
			"Posted!"
		);
		return true;
	}
});

$app->get('/', function(){
	$app = Jolt::getInstance();

	$app->render( 'home',array(
		'appname'=>$app->option('simperium.appname'), 
		'apikey'=>$app->option('simperium.apikey'),
		'token'=>$app->option('simperium.token'),
		'bucket'=>$app->option('simperium.bucket'),
	));
	exit;
});

$app->listen();

Our main focus is the /listener section of the code, which is what talks to Twilio.

When we receive a new message, we check to see if the message had any images or not, and if it did, then we cycle through each image. We then save the image locally, resize it, and post it to Simperium using the Simperium PHP library. If no image was passed, then we just save the message as it was sent to the system.

The other part of this is how we get a unique id for each post, which is using the generate_uuid() to create a unique UUID compatible string.

7. Create a file called functions.php, and copy the following code:

<!--?php
	function slugify( $string ){
		$string = strtolower( trim($string) );
		$slug=preg_replace('/[^A-Za-z0-9-]+/', '-', $string);
		return $slug;
	}

	function cropResize($img,$out='',$dSize=170){
		$x = @getimagesize($img);
		$sw = $x[0];
		$sh = $x[1];
		$yOff = 0;
		$xOff = 0;
		if($sw < $sh) {
			$scale = $dSize / $sw;
			$yOff = $sh/2 - $dSize/$scale/2; 
		} else {
			$scale = $dSize / $sh;
			$xOff = $sw/2 - $dSize/$scale/2; 
		}

		$im = @ImageCreateFromJPEG ($img) or // Read JPEG Image
		$im = @ImageCreateFromPNG ($img) or // or PNG Image
		$im = @ImageCreateFromGIF ($img) or // or GIF Image
		$im = false; // If image is not JPEG, PNG, or GIF

		if (!$im) {
			readfile ($img);
		} else {
			$thumb = @ImageCreateTrueColor ($dSize,$dSize);
			imagecopyresampled($thumb, $im, 
			0, 0, 
			$xOff,$yOff,
			$dSize, $dSize, 
			$dSize / $scale ,$dSize / $scale);
		}
		if( $out == '' ){
			header('content-type:image/jpeg');
			imagejpeg($thumb);
		}else{
			imagejpeg($thumb, $out);
		}
	}
</pre-->

The main part of this file is the cropResize function which will take any given image and crop and resize it to fit the dimensions we give it. This is handy when dealing with larger sized images.
8. Open views/home.php and copy the following code:

<div class="jumbotron">
  <h1>Live Blog</h1>
</div>
<br />
<section id="talkwrap" style="overflow: auto;margin-bottom: 10px;">
  <div id="talk"></div>
</section>
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
  <script type="text/javascript" src="https://js.simperium.com/v0.1/"></script>
  <script>
    function formatDate(date, fmt) {
        function pad(value) {
            return (value.toString().length < 2) ? '0' + value : value;
        }
        return fmt.replace(/%([a-zA-Z])/g, function (_, fmtCode) {
            switch (fmtCode) {
            case 'Y':
                return date.getUTCFullYear();
            case 'M':
                return pad(date.getUTCMonth() + 1);
            case 'd':
                return pad(date.getUTCDate());
            case 'H':
                return pad(date.getUTCHours());
            case 'm':
                return pad(date.getUTCMinutes());
            case 's':
                return pad(date.getUTCSeconds());
            default:
                throw new Error('Unsupported format code: ' + fmtCode);
            }
        });
    }
    var simperium = new Simperium('<?=$appname?>', { token : '<?=$token?>'});
    var bucket = simperium.bucket('<?=$bucket?>');
    bucket.on('notify', function(id, data) {
      var date = formatDate(new Date(data.timeStamp*1000), '%d/%M/%Y @ %H:%m:%s');
      $("#talk").append("<div class='well'><strong>"+date+':</strong><br />'+data.text+'</div>');
      $('#talkwrap').scrollTop($('#talkwrap')[0].scrollHeight);
    });
    bucket.on('local', function(id) {
        console.log("request for local state for object "+id+" received");
        return {"some": "json"};
    });
    bucket.start();
  </script>

 

  1. This is the brains of our real-time notifications, as we send posts and images to our live blogging app, this is where it will get displayed as soon as the posts are processed.
  2. Upload the files to your web server.
  3. Create a folder called images/ and make it writable, inside this folder, create a folder called original/ and a folder called procesed/, make sure these are writable as well.
  4. Log into your twilio account, and point a phone number to http://MYSITEURL/listener for SMS messages
  5. Open up your web site: http://MYSITEURL/
  6. Send some text or a picture to the phone number and watch it appear on the web site.

We’ve now built a basic live blogging tool, nothing too fancy, but you can take it from here and build on it to make something more fancy.

I’ve also uploaded the demo app to Github, so you can view it in its entirety here