Make Every Week: Texted Picture Catcher

“Let’s have people send pictures!”

This idea comes up a lot where I work. And we’ve done some great photo-crowdsourcing projects.

But how best to get pictures from an audience? Telling people tag us on Instagram, Twitter or Facebook can work, as in WNYC’s Bodega Cats project. But people have to be using those services.

Most folks can email a picture, especially when the email address is easy to remember. That’s what we did for WNYC’s Abandoned Bikes project.

What about texting pictures?

The phone/texting service I like to play with, Twilio, recently added MMS, or Multimedia Messaging Service. MMS is what you’re using when you text a picture or video.

So for this week’s #MakeEveryWeek, I wanted to figure out how to text a picture to my server, via Twilio, and then upload it to Flickr:

Phone -> Phone number -> Twilio -> My Server -> Flickr

Step 1: Setting up Twilio

First I need a number to text to. Twilio lets you buy a phone number for $1/month, and each text costs about a penny.

Once I got a number, I told Twilio to direct any incoming texts to http://myserver.com/texted-pictures and that it should send that data as a “POST” request. That’s basically submitting a web form with all of the text’s details inside — info about including any photos aboard.

Now I needed to set up something at http://myserver.com/texted-pictures to catch that data.

Step 2: Catching the Picture

I’ve set up “computer in the cloud” using Amazon’s EC2 service (here’s info on how you can set one up, too), and on that server I have a program running called “server.js.” That program deals with any web-based request that comes its way, including missives from Twilio.

Here’s the code I’m using for that program. I’ve added lots of comments to try to show what’s going on.

When Twilio gets a photo inside a text message, it kindly stores that image on its servers and gives it a super-long URL. So when a POST about that message hits my server from Twilio, that image URL is included in the data. The "server.js" code stores the URL as  req.body.MediaUrl0

Step 3: Saving the Picture

Now that I have the URL where Twilio is storing the picture, I want to use that to download the image to my own server.

In "server.js" I use some code to stream the data from the URL to a file called test.jpg. Streaming is handy because images can be big, so instead of holding the whole thing in memory, the image data flows right to the file.

Step 4: Uploading to Flickr

I like the idea of using Flickr as a destination. If you’re getting a bunch of pictures from lots of people, you can set them to be private at first (so you can make them public after viewing them), add tags, sort them, put them into galleries and so on. You don't have to write a photo-management system; Flickr can be your photo CMS.

Flickr also has a cool API, allowing computers to exchange images with Flickr deftly. But getting the API to work was trickier than I expected. I figured it out, but it took several steps.

The issue is that you need five secret values to make it go:

FLICKR_API_KEY
FLICKR_API_KEY_SECRET
FLICKR_USER_ID
FLICKR_ACCESS_TOKEN
FLICKR_ACCESS_TOKEN_SECRET

I got the first two FLICKR_API_KEY and FLICKR_API_KEY_SECRET by signing up for a Flickr API key here.

Then I put FLICKR_API_KEY and FLICKR_API_KEY_SECRET into the flickrOptions section of the code, leaving the other three out. Like this:

flickrOptions = {
  api_key: 'FLICKR_API_KEY_here',
  secret: 'FLICKR_API_KEY_SECRET_here',

  // console.logs the auth URL instead of opening a browser for it
  nobrowser: true,

  // suppress writing progress bars to stdout:
  progress: false,

  // give permissions to authenticate for writing
  permissions: "write"
};

Then, from the console I ran:

node server.js

… and tested the code by texting an image to my Twilio number. After the text went through, I got this message in the console:

please visit https://www.flickr.com/services/oauth/authorize?oauth_token=reallylongcodehere&perms=write
prompt: oauth_verifier:

I put the Flickr URL in a browser and clicked the authorize button.

Flickr then gave me a string of numbers, and I pasted those numbers in the console after oauth_verifier: and hit return. Finally I was given the values for the other secret fields: FLICKR_USER_ID, FLICKR_ACCESS_TOKEN and FLICKR_ACCESS_TOKEN_SECRET.

I put those into my code, like this:

flickrOptions = {
  api_key: "FLICKR_API_KEY_here",
  secret: "FLICKR_API_KEY_SECRET_here",
  user_id: "FLICKR_USER_ID_here",
  access_token: "FLICKR_ACCESS_TOKEN_here",
  access_token_secret: "FLICKR_ACCESS_TOKEN_SECRET_here",

  // console.logs the auth URL instead of opening a browser for it
  nobrowser: true,

  // suppress writing progress bars to stdout:
  progress: false,

  // give permissions to authenticate for writing
  permissions: "write"
};

Starting the server again with ...

node server.js

… and now it runs without interruption. If I want it to keep running while I’m away, I use the node forever module and type:

sudo forever start server.js

Step 5: Success!

It works! These texted images ...

... can be seen on Flickr here!

Improvements

I’m getting some warnings that the code I’m using to parse the text-message information from Twilio, called bodyParser, is depreciated. So I’ll have to figure that out.

Even tho everything is working, my Twilio logs say that it never heard back from my server, so it registers as an error. Gotta figure that out, too.