Advertisement

Check Reddit from OS X Terminal

by
Student iconAre you a student? Get a yearly Tuts+ subscription for $45 →

Screencast

Reddit is a social network that, in recent years, has exploded in popularity. It's user-driven content model makes is a great place to find news, humor, things you never knew you wanted to know, and some things you can never un-see. It's great!

Much of Reddit's popularity comes from its notion of sub-reddits. These are nothing more than posts lumped together by a common person, place, item, or ideal. As an example, one of the most popular sub-reddits to date is r/aww. A sub-reddit filled with nothing but pictures of adorable animals.

If only there was a way to surf Reddit at work without drawing too much attention to yourself (or the screen).

In this tutorial, I’ll show you how to surf Reddit from Terminal. You will learn:

  • Basic Ruby code syntax
  • Reddit's JSON feed and how it will help the script run
  • How to parse the JSON feed and display it
  • How to alias the script to a simple command

Ruby Basics

The first thing you need to know is how to output messages to the terminal and how to get user input in from the terminal. These methods are gets and puts, respectively. 

Anytime you want to output anything to the screen, use the puts method and wrap the text in quotation marks. Anytime you need to get information from the user, use the gets method. 

You now need a way to store anything the user enters. To do this, you will use variables. To declare a variable, give it a name, then initiate it by following it with an = and finally add a value to store in it.

So the first lines of the program should read like this:

puts "What subreddit? Example: /r/aww put aww"
sub = gets.chomp!.downcase
puts "Getting you the top posts for /r/#{sub}."

In the first line, you are greeting the user and asking them to choose a sub-reddit. In the second line you are creating the variable sub and giving it the value of whatever the user types in. 

The chomp! and downcase methods just remove trailing whitespace and make all of the input lowercase, which adds a bit of consistency. You may now include that variable anywhere in the output by wrapping it in #{}. This is called string interpolation.

Reddit's JSON Feed

JSON stands for Javascript Object Notation. In simple terms, it is just a great way to grab all of the data from a particular website (that has a JSON API in place) without all of the extra markup or style. 

In the terminal, you don't want any style or markup; just the data. So JSON fits in well here.

Reddit's JSON API is dead simple to use. Append a .json to any Reddit URL you would normally input into the web browser. As an example: to get the /r/aww JSON feed, you would go to http://www.reddit.com/r/aww.json.

The Reddit JSON feed of raww
The Reddit JSON feed of /r/aww

That is a lot of data. Fortunately, Ruby already has a simple way to parse JSON and get you only the information you need.

Parsing the JSON Feed

To get the feed and parse it, you will need to install some existing Ruby libraries. In the terminal run the following commands:

gem install faraday
gem install json

Then add the following lines to the very top of the file:

require 'faraday'
require 'json'

Faraday will allow you to use Ruby to make calls to URLs on the internet and JSON will help you parse the information you get back. Once you have these new libraries available you can use the following code to:

  1. Grab the user input
  2. Generate a URL
  3. Call the URL and get the JSON feed back
#Bring in additional libs
require 'faraday'
require 'json'

#Greet the user
puts "What subreddit?  Example:  For r/aww, type aww"
sub = gets.chomp!.to_s.downcase

#Output response
puts "Getting you the top posts for /r/#{sub}."

#Get JSON feed of selected Reddit
response = Faraday.get "http://www.reddit.com/r/#{sub}.json"
json_response = JSON.parse response.body
posts = json_response['data']['children']

To iterate (or loop) over each of the posts you get back and display each one in a readable format. Do this by using a for-loop. Here is the code that accomplishes that task:

i = 1
posts.take(10).each do |p|
  post = p['data']
  puts "#{i}. " + post['title']
  puts "Ups: #{post['ups']} | Downs: #{post['downs']} | Score: #{post['score']}"
  puts ''
  i += 1
end

If you would like to give yourself the option to open one of the posts in the Mac's default browser run gem install launchy

Then add it to the list of other libraries you are including by adding require 'launchy' to the top of the file. 

Finally add this piece of code below the for-loop:

#Present option to launch any post in default browser
puts "Would you like to open any of these?  Choose the number to open, or reply 'No'"
open_url = gets.chomp!.to_s
if open_url.downcase == "no" || open_url.to_i > 10
  puts "ok"
else
  Launchy.open posts[open_url.to_i - 1]['data']['url']
end

The complete script should look like this:

#Bring in additional libs
require 'faraday'
require 'json'
require 'launchy'

#Greet the user
puts "Hi! What subreddit?  Example: For r/aww, simply type aww"
sub = gets.chomp!.to_s.downcase

#Output response
puts "Getting you the top posts for /r/#{sub}."

#Get JSON feed of selected Reddit
response = Faraday.get "http://www.reddit.com/r/#{sub}.json"
json_response = JSON.parse response.body
posts = json_response['data']['children']

#Iterate over the feed and outputting the posts
i = 1
posts.take(10).each do |p|
  post = p['data']
  puts "#{i}. " + post['title']
  puts "Ups: #{post['ups']} | Downs: #{post['downs']} | Score: #{post['score']}"
  puts ''
  i += 1
end

#Present option to launch any post in default browser
puts "Would you like to open any of these?  Choose the number to open, or reply 'No'"
open_url = gets.chomp!.to_s
if open_url.downcase == "no" || open_url.to_i > 10
  puts "ok"
else
  Launchy.open posts[open_url.to_i - 1]['data']['url']
end

Save the file as check_reddit.rb in the Documents folder. To run the script, open Terminal and run ruby ~/Documents/check_reddit.rb.

Creating an Alias to the Script

Being able to run ruby ~/Documents/check_reddit.rb is all well and good, but it would be better if you could type check-reddit in the terminal and have the script magically run.

To accomplish this, you can alias the word check-reddit to the command ruby ~/Documents/check_reddit.rb. In terminal run nano ~/.bash_profile . This will load the bash_profile file in a text editor. 

Arrow down to move the cursor below any existing text and add alias check-reddit='ruby ~/Documents/check_reddit.rb' to a new line. 

To exit and save the file press Control-X. You’ll be prompted to save the changes. Press the Y key then Return to confirm. Run a source ~/.bash_profile to reload the bash_profile into Terminal.

Conclusion

From now on you’ll be able to run check-reddit in the terminal to surf in style.

The ability to see the top 10 posts in any sub Reddit via the terminal is awesome. It allows you to quickly surf Reddit, without drawing any attention to yourself and even makes it look like you are hard at work. 

Along the way you picked up some basic Ruby and JSON skills as well. Great job!

Advertisement