Implementing Twitter Bot using Ruby

When I was 15 years old, I dreamed of being able to develop bots. The story behind was terribly simple, – back then it was way too popular among us (the little nerds) to manage own IRC bots which could do some fancy things like log the discussion or just stay online for a long time. We thought it was kind of outstanding, and it reveals the level of our knowledge.

That’s why this time, living with this unbodied belief at the very heart, – I want us to create a Twitter bot. Moreover, I want him to compliment us because being a good person is also essential, right? In fact today we make the world a better place not only because our program will compliment a stranger, but because the person has to ask him nicely including a “please” keyword. Just like our parents have taught us.

Thus I have googled a little bit and found a gem named “twitter” written by Eric Michaels-Ober or sferik if you will. In simple words, this library will help us to achieve our goal. By using Twitter API – we will be able to post a status. And with the support of Streaming API, we will try to catch the particular keywords of the Tweet in real time, and hopefully, if it matches our expectation we get a respond back.

Firstly let’s begin with a simple class called “Complimentator”… just like the “Terminator” 😁. We create an instance of Twitter::REST::Client in #initialize method and by the examples from here, we see that we can update the status using #update method. Besides we can define in_reply_to_status_id attribute, meaning we can point to concrete tweet. In other words – reply to it, which is exactly what we are looking for.

If you will try to include and execute the following example above – providing your keys, of course, you can see, that indeed we nail this task with a “Hello World” message on our Twitter account. Congratulations, a first part of the mission is complete.

We are happy and stuff, but – let us think. What else is left? Well, at the beginning I was saying we want to catch the message. For this purpose presumably, would be a good idea to use Twitter::Streaming::Client because we want to receive a message and respond immediately without any pauses listening for new arrivals.

Important: You have limits for both REST and Streaming API, you can find more information here.

By calling #user here, we are going to stream the feed of our account. If you try to write a status mentioning @mysuperbot with any text, it will respond to you with “Hello World!” which is astonishing, eh?

But not really, our plan is to recognize whether this status addressed to us includes the given keyword. Let’s say, – the compliment. We expect to receive a message “Tell me a compliment, please” and therefore reply to it with a random expression defined in our data set.

You can make it differently, although I decided to go here by defining a module inside of my class, just to keep it simple… I have created Command module with methods I want to represent my keywords, – such as “compliment”, and then I included this module inside of my main “Complimentator” class to make them available to call.

UPDATE: I have moved compliments to instance variable which is defined in initialize method. It’s obviously a better place since you define your list only once. See the final script on Gist.

Here I go with only 5 compliments in Array, – you can extend the list of course, but don’t forget to keep the phrases short. Then with #sample method, I randomly choose one of them. Hereafter using Rest client #update method I post a status, providing a tweet id I am replying to. And voila, most of our program is finished. But wait, let’s take a look at what have happened to our cycle.

So what we have done over here. First of all, inside this loop where we follow our home feed, we check whether the object is a Twitter::Tweet or not. Then, with #instance_methods we get the list of all our instance methods defined in the Command module and by iterating over it; We question if the given text (which by the way is downcased) includes the keyword which is a method of our module. Don’t forget that we want the person who asks for a compliment to ask it politely. So we require him to include “please” keyword as well.

This is the end result. I would love to hear all the suggestions whether would it be a different kind of logic, some witty phrase or anything else.

Thanks for reading. I hope you enjoyed it. If you have found this article helpful – I would appreciate if you support my motivation and share it along with your friends.

P.S. You always can catch up with me on Twitter, mentioning me as @rrubyist