How to call the reddit REST API using Node.js – Part III

In Part I and Part II, I called the reddit REST API using the curl command line tool.

Now, I’m going to create a Node.js script that does this. Why create a script, when I can already do what I want with curl?

(1) I can more easily reuse the code that I’ve written. In Part II, I mentioned performing a search for the word “Starbucks” at reddit. If I wanted to do a different type of search, I could alter my script to search for something else instead.

(2) I can more easily execute the code that I’ve written. For example, I could run the script on a daily or hourly basis using a cron job, without having to do anything manually. “Set it and forget it” is awesome!

(3) I can more easily use the code that I’ve written. For example, I can bring in Node.js libraries to process the output of my script, and easily get from it what interests me.

So, now I’m going to move from curl to Node.js to do what I want, repeatedly, in an automated way.

Recall that I am pretending to be in charge of reputation management for Starbucks. I want to get recent comments that come up on reddit that mention Starbucks so I can quickly look for problems (or, hopefully, compliments!), and respond.

Below, I’ve shown just the Node.js code which can be used to retrieve my access token. Notice how much more complicated this is than the single curl command that I used previously! By the way, there are definitely simpler ways to do this using Node.js. I’m writing this example using just the built-in libraries that come with Node.js, which makes things a bit more complicated than they have to be.

const https = require('https');

let postData = "grant_type=password&username=my_user_name&password=MyExcellentPassword";
let username = "my_reddit_id";
let password = "my_reddit_secret";

/**
 * A method to get an access token to call reddit Search API
 */
const getAccessToken = function () {
	const options = {
		hostname: "www.reddit.com",
		port: 443,
		path: '/api/v1/access_token',
		method: 'POST',
		headers: {
			"Content-Type": "application/x-www-form-urlencoded",
			"Content-Length": postData.length,
			"Authorization": "Basic " + new Buffer(username + ":" + password).toString("base64"),
			"User-Agent": "my test bot 1.0"
		}
	}

	const req = https.request(options, (res) => {
		if (res.statusCode === 200) {
			let chunks = [];
			res.on('data', (d) => {
				/*
				* the output data has the format
				* {"access_token": "271295382352-tV_vIeKVRgq7Juh3iYHmW4oyT64",
				* "token_type": "bearer", "expires_in": 3600, "scope": "*"}
				* But d is a Buffer object, and has to be translated into an
			    * object at the end.
				*/
				chunks.push(d);
			}).on('end', () => {
				let result = Buffer.concat(chunks);
				let tmpResult = result.toString();
				try {
					let parsedObj = JSON.parse(tmpResult); // TODO do something with this Object, which contains my access token

				} catch (err) {
					process.stderr.write(err);
				}
			});
		} else {
			console.log("Received a statusCode " + res.statusCode);
		}
	});

	req.on('error', (error) => {
		process.stderr.write(error);
	})

	req.write(postData);
	req.end();
};

getAccessToken();

You don’t have to understand all this code in detail. If you skim it, you should get an idea what it’s doing. You are making an https request to reddit’s API. When a web browser makes an https request, there’s a lot of “stuff” going on under the hood. We have to code up some of that stuff here; that’s what the options object is for. Once the request is made to reddit, the information is returned in “chunks” of binary data over the network. Node.js waits for all of that data to get to us. When it’s finished, we use the built-in Buffer.concat method to concatenate all the binary data into one Buffer object, turn it into a JSON string, and parse that into an Object. The Object contains our access_token property. In my next post, we’ll use that to access the reddit API to search for recent posts about “Starbucks”.

If you found this interesting, click the subscribe button below! I write a new post about once a week.

Leave a Reply

Your email address will not be published. Required fields are marked *