Get Notified When Someone Posts An Article From Your Domain on Hacker News Using Node.js, Firebase and Twilio

April 16, 2015
Written by

Mobile phone text message or e-mail

Last October Hacker News launched their official API and I’ve been trying to find an excuse to play with it ever since. The idea finally hit me last week: what if I built an application that notified me via SMS whenever someone posted a link to my domain on Hacker News? Hacker News is known to drive a ton of traffic and I probably want to be ready to spin up some extra servers if I end up making it on the front page. If you’ve also been waiting for an excuse to play with the Hacker News API you’re in luck because today I’m going to show you how to build this application using Node.js, Firebase and Twilio SMS.

Our Tools

Sit by the Fire(base)

It’s time to get our project started. First we will create a new directory called ‘hn-sms-notifier’:

mkdir hn-sms-notifier
cd hn-sms-notifier

Now let’s initialize our project:

npm init

One last thing before we start writing code, we need to install the Firebase node module:

npm install firebase --save

Now that we have our foundation in place let’s create a new file called index.js and start writing our code:

var Firebase = require("firebase");
var newStoriesRef = new Firebase("https://hacker-news.firebaseio.com/v0/newstories/0");

newStoriesRef.on("value", function(snapshot) {
  console.log(snapshot.val());
});

We’ve only written five lines of code but let’s take a second to unpack what’s going on so far. First, we import the firebase library so that we can interact with the Hacker News API. On the next line, we’re getting a Firebase reference for the first element in new stories. Let me walk through why. We can view an array of all the new stories on Hacker News on Firebase at this url:

https://hacker-news.firebaseio.com/v0/newstories/

For our scenario we only care about when a new story is added into the first position. Which is the value here:

https://hacker-news.firebaseio.com/v0/newstories/0

On the third line, we’re listening for whenever the value changes on this reference. Confused? It’s ok, this threw me off at first too! I thought I would be listening for when a child is added but this data is structured as an array with five hundred elements. When a new story is added to Hacker News the value in each element is updated with a new key. By listening for changes in the first element we’ll always receive a notification when a new story is added.

With that out of the way, it’s time to run our code:

node index.js

If you watch, you’ll see that every time a new story is added we log the ID of that story. At first you’ll only see one ID output at first but just give it time. Depending on the time of day it can take a few minutes for a new story to be added.

Story Time

You’ve probably realized that we need more than just the ID of the story. With the Hacker News API each story is an item and we can access information about that item from a URL structured like this: https://hacker-news.firebaseio.com/v0/item/%storyID%

Let’s add the code within our newStories value callback that gets information about our specific story:

newStoriesRef.on("value", function(snapshot) {
  var storyRef = new Firebase("https://hacker-news.firebaseio.com/v0/item/"+snapshot.val());

  storyRef.on('value', function(storySnapshot) {
    console.log(storySnapshot.val());
  });
});

Run your app again and you’ll see that we’re now logging information about each new story that gets added:

hn

But the wise among you may notice we’re getting notifications each time the data in a story changes. That’s because we’ve subscribed to updates for that item in perpetuity. Set that issue asIDe, we’ll be fixing it a bit later on in the code.

You’ll see we have data like the title of the story, who posted the story and url. If we wanted to know whenever the user named sama posted a story, we could look at the by field or if we wanted to get notified whenever someone posts a story at WebRTC we could search in the title. But for our app, we’re going to use the url value so we can see if the story came from our domain.

Since we’re working with URLs let’s use node’s URL parser to make things a bit easier. We can start by requiring it at the top of our index.js file:

var Firebase = require("firebase");
var url = require("url");

var newStoriesRef = new Firebase("https://hacker-news.firebaseio.com/v0/newstories/0");

Now within the callback for our storyRef we can use url.parse() to get the host domain of each story:

storyRef.on('value', function(storySnapshot) {
  var story = storySnapshot.val();
  var host = url.parse(story.url).host;

  console.log(story.url);
  console.log(host);
});

Let’s run our app again and see it in action:

hn-2

Ok, if you let the app run for more than a couple minutes it probably crashed. Don’t worry, we can fix this. What’s happening is sometimes Firebase fires the callback indicating a new story has been added before the story data is actually available. There are lots of ways we could fix this today we’re going to make sure our snapshot.val() isn’t null. If we don’t, we’ll just return. The great thing about firebase is since we’re subscribed to updates for this item the callback will get triggered again with the story data is added:

if(storySnapshot.val() === null) {
  return
}

var story = storySnapshot.val();
var host = url.parse(story.url).host;

Remember that issue we had with getting multiple updates for the same story? We can fix that now too. Let’s unsubscribe from updates about our story once we know that we’ve retrieved the data about that specific item:

var story = storySnapshot.val();
var host = url.parse(story.url).host;
storyRef.off();

Run your app again and you’ll see we fixed both of our bugs. Isn’t fixing bugs fun!?!

Alert! Alert! Alert!

Our app is pulling new stories from Hacker New and getting the host that the story links to.  The last thing we need to do is check to see if it links to our host and notifies us via SMS if it is. For sake of being able to quickly test our app let’s check for a domain that we know gets frequently posted to Hacker News: “github.com”:

console.log(story.url);
console.log(host);

if(host === "github.com") {
}

Before we can send our text message we need to install the Twilio node library:

npm install twilio --save

We need to require our Twilio library at the top of our file:

var Firebase = require("firebase");
var client = require('twilio')('ACCOUNT_SID', 'AUTH_TOKEN');
var url = require("url");

Make sure to replace the ACCOUNT_SID and AUTH_TOKEN with your own Twilio credentials. You can find these in your account dashboard.

Within our conditional that checks for our host let’s add the code to send our SMS message. Replace the to and from phone numbers with your phone number and twilio number:

if(host === "github.com") {
  client.messages.create({
    body: story.by + " just posted " + story.title + "on HN!",
    to: "+15555555555", // your cell number
    from: "+15555551234" // your twilio number
  }, function(err, message) {
    console.log(message);
  });
}

It’s the moment of truth – start up your app up again and wait… you’ll get an SMS message when someone posts a story linking to ‘github.com’ on Hacker News. Once you know it works replace github.com with your own domain, fire up the app and wait for it to work it’s magic.

I’m Not Just Reading Hacker News, I’m Working!

We can now get SMS notifications when someone posts a story to our domain on Hacker News. But most importantly, we’ve learned how to work with the Hacker News API and can safely tell our bosses that we spent all afternoon looking at Hacker News for work. Have questions or want to share what you’re going to build with the Hacker News API? Holler at me on twitter (@rickyrobinett) or e-mail (ricky@twilio.com)