Writing & deploying a super simple Twitterbot

Introduction

After tiring myself out emailing my ISP over and over for a refund, I decided to write a super simple twitterbot reminding @RCommCare at 8 a.m. everyday about the number of days it has been since they have not sent me my refund. A fun little hour-long project, if you will.

This is the guide I wish I had when setting up my project, including both the program and how to deploy it on the server. It may or may not suit your use case. Keep in mind this is an extremely simple bot.

Overview

  • Folder structure
  • Set up our Ruby work environment
  • Get our Twitter API codes
  • Write our application
  • Deploy

Folder structure

Let’s go over our folder structure:

- twitterbot          // Root folder
  - config            // Configuration folder
    - client.rb       // API keys
    - schedule.rb     // Schedule using 'whenever' gem
  - .ruby-version     // Ruby version for collaboration if required
  - app.rb            // Consumption of Twitter API
  - Gemfile           // Gems used
  - Gemfile.lock      // Lock file generated by Bundler
  - README.md         // Optional readme file

Set up our Ruby work environment

I am using rbenv for managing ruby versions and will use Ruby 2.3.0 for the project. I have specified my ruby version in a .ruby-version file as follows. If you use a version control system such as Git, you’d want to committ this file.

1
2.3.0

Next, we need one of the Twitter API libraries. Since we’re using Ruby and are not concerned with the Streaming API, we can install twitter by @sferik by specifying it in our Gemfile:

1
2
source "https://rubygems.org"
gem "twitter"

Run bundle to install the gem and its dependencies.

Note that the twitter gem does not support Ruby 2.4.

Get our Twitter API codes

Head over to Create Application page on Twitter (you must be logged in) and fill in the details as required on the form:

Create New Application page

Once you’ve created an app, head over to the ‘Keys and Access Tokens’ tab and copy your Consumer keys.

Keys and Access Tokens tab - Consumer keys

Next, generate an access token from the same page and copy the two keys as well.

Keys and Access Tokens tab - Access Token keys

Write our application

We’re going to store our secret API keys in environment variables as opposed to the config/client.rb file for security reasons. Twitter recommends against storing the secret keys in human-readable form. Presuming you have shell access on the deployment server, add the following to the /etc/environment file for permanently setting up the environment variables.

1
2
TWITTERBOT_CONSUMER_SECRET="YOUR_CONSUMER_SECRET"
TWITTERBOT_ACCESS_TOKEN_SECRET="YOUR_ACCESS_TOKEN_SECRET"

The configuration, then, will lie in config/client.rb as follows:

1
2
3
4
5
6
7
8
require 'twitter'

CLIENT = Twitter::REST::Client.new do |config|
  config.consumer_key        = "YOUR_CONSUMER_KEY"
  config.consumer_secret     = TWITTERBOT_CONSUMER_SECRET
  config.access_token        = "YOUR_ACCESS_TOKEN"
  config.access_token_secret = TWITTERBOT_ACCESS_TOKEN_SECRET
end

Next, we’ll schedule a cronjob using the whenever gem. You can avoid using a gem and simply add a cronjob using crontab utility using your server’s shell, but for human readability and having the entire code at one place, I have chosen to use the aforementioned gem.

We’re going to include it in our Gemfile and then bundle it:

1
2
3
source "https://rubygems.org"
gem "twitter"
gem "whenever", :require => false

Edit the config/schedule.rb file:

1
2
3
4
5
6
7
8
9
10
11
12
# Use this file to easily define all of your cron jobs.
# It's helpful, but not entirely necessary to understand cron before proceeding.
# http://en.wikipedia.org/wiki/Cron
# Learn more: http://github.com/javan/whenever

# Location for log file in case of errors
set :output, "~/.logs/cron_twitterbot.log"

# Deployed to MSK timezone
every 1.day, :at => '5:30 am' do
  command 'username ruby ~/apps/twitterbot/app.rb'
end

Of course, replace the username on line 11 with a user on your server who has ruby installed. If you’re not concerned with version management on the server, you can skip installing rbenv or rvm and install Ruby from your distribution’s repositories:

1
sudo apt install ruby --yes

My application is pretty simple. Here’s the app.rb file.

1
2
3
4
5
6
7
8
9
10
require_relative 'config/client'
require 'date'

def days_since_cancellation
  start_date = Date.new(2017,02,06)
  current_date = Date.today
  return (current_date-start_date).to_i
end

CLIENT.update("Broadband cancelled on 02/06/17. Waiting for ₹302.41 refund since #{days_since_cancellation} days. Company policy 45-60 days. @RCommCare #CustomerService #Pathetic")

Deploy

Upload your twitterbot folder to your server via sftp or rsync. More on using those two here.

On your server shell, cd to your twitterbot folder, pass the schedule file to whenever, and let it update your user’s crontab:

1
2
whenever --load-file config/schedule.rb
whenever --update-crontab

You can check the crontab equivalent of your schedule by running before committing it to the crontab file.

1
whenever --crontab-command

Key to note is that the user who is going to run the program must have access to Ruby binaries (via a ruby version manager or without) and the same user must be logged in when running whenever commands.