Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Build Twitter Bot with Ruby
Truemark Technology profile imagePrabin Poudel
Prabin Poudel forTruemark Technology

Posted on • Originally published atprabinpoudel.com.np

     

Build Twitter Bot with Ruby

Today, we will be building a bot for Twitter that will retweet all hashtags related to #ruby or #rails. We can also configure it to retweet any hashtags so you can use this tutorial to create bot that can retweet whatever hashtag you want. Yes, and we will be building this Twitter bot with Ruby.

We will be usingTwitter gem (Github) to help us in getting up and running quickly with Twitter APIs.

Background

I am quite active in Twitter nowadays, and I have seen a lot of bots that retweet #100DaysOfCode. There were a lot of newbies trying out Javascript and getting help from the JS community. Dang, no one is using Ruby nowadays, I thought then. But it wasn't the case, yes less people are using it, but it's still popular. So I made plans to create a bot that will retweet all tweets with hashtag #ruby or #rails. The purpose of this bot is to bring Ruby and Rails community together, motivate newbies to use Ruby and for us to help each other.

Skills required to follow the tutorial

Intermediate:

  • Ruby
  • Deployment skills if you are trying to deploy the bot to remote server

You should have

  • Configured twitter app and have four keys and secrets from from Twitter. If you haven't done so, you can follow thistutorial to set it up and come back here after you have the keys and secret.

Steps

Step 1: Create a ruby file

Let's first create a ruby file with namere_tweet_service.rb where we will write code/script to instruct Twitter to retweet the hashtags we want.

# create a folder to save the bot service$ mkdir ruby-twitter-bot# create ruby file$ cd ruby-twitter-bot$ mkdir app/services/twitter$ cd app/services/twitter$ touch re_tweet_service.rb
Enter fullscreen modeExit fullscreen mode

What is happening?

  • We are following the folder structure of Rails framework and saving our service inside the folderapp/services/twitter
  • After that inside the twitter folder we created the filere_tweet_service.rb where we will be adding the code next.

Step 2: Require Twitter Gem in Ruby file

Inside there_tweet_service.rb, add the following code at the top:

require'rubygems'require'bundler/setup'require'twitter'
Enter fullscreen modeExit fullscreen mode

What is happening?

  • First two lines will let us use gem in our pure Ruby app, if you have used Rails before then it is automatically done by the framework and you may not have come across this.
  • Withrequire 'twitter', we are instructing our Ruby app to use twitter gem.

Step 3: Create application.yml to store twitter secrets and keys

Since secrets and keys should not be added to git repositories, let's create a folderconfig in the project root and addapplication.yml file to store secrets and keys which you get when configuring your twitter app.

# create config folder$ mkdir config# create application.yml$ cd config$ touch application.yml
Enter fullscreen modeExit fullscreen mode

Let's add the following to the file:

defaults:&defaultsCONSUMER_KEY:''# API KEYCONSUMER_SECRET:''# API KEY SECRETACCESS_TOKEN:''ACCESS_TOKEN_SECRET:''production:<<:*defaults
Enter fullscreen modeExit fullscreen mode

Add the keys and secret you get after configuring Twitter app in the file which currently has no values configured.

Step 4: Use figaro gem to load application.yml

If you have worked with Rails then you must be familiar with Figaro gem, if you haven't yet then here is what it does: it helps us in storing all our secret keys insideapplication.yml and lets us use these keys in our app accessible withENV

Let's add the following code to there_tweet_service.rb

require'figaro'Figaro.application=Figaro::Application.new(environment:'production',path:File.expand_path('config/application.yml'))Figaro.load
Enter fullscreen modeExit fullscreen mode

What is happening?

  • We are requiring the figaro gem so we can use it in our app
  • WithFigaro.application code, we are telling our app to load theapplication.yml located insideconfig folder so that we can use the keys we configured in previous step.

Step 5: Add twitter api configuration to the service

Add the following to there_tweet_service.rb

moduleTwitterclassReTweetServiceattr_reader:configdefinitialize@config=twitter_api_configenddefperformrest_client=configure_rest_clientstream_client=configure_stream_clientendprivatedeftwitter_api_config{consumer_key:ENV['CONSUMER_KEY'],consumer_secret:ENV['CONSUMER_SECRET'],access_token:ENV['ACCESS_TOKEN'],access_token_secret:ENV['ACCESS_TOKEN_SECRET']}enddefconfigure_rest_clientputs'Configuring Rest Client'Twitter::REST::Client.new(config)enddefconfigure_stream_clientputs'Configuring Stream Client'Twitter::Streaming::Client.new(config)endendend
Enter fullscreen modeExit fullscreen mode

You may be wondering what happened here all of a sudden. There are two ways to use Twitter API, first one is Rest Client, rest client provides endpoints to perform one time operations like tweet, retweet, like, etc. Second one is Stream Client, stream client streams all tweets in real time and watches the hashtags that we will configure later, i.e. stream client will give us the tweets with #ruby and #rails hashtags

What's happening in the code?

  • We are initializing our service and together with it initializing the api configuration required for twitter
  • perform is the only public method that we will expose in our service and make all other methods private
  • We then configured both rest and stream client which we will use in upcoming steps.

Step 6: Configure hashtags to watch

We will be watching out for three hashtags related to ruby and rails, let's add the following to service

privateHASHTAGS_TO_WATCH=%w[#rails #ruby #RubyOnRails]
Enter fullscreen modeExit fullscreen mode

We are using constant here since hashtags don't have to be changed once the bot starts retweeting.

Step 7: Retweet tweets with configured hashtags

Let's add the following code to the service, we will go through each block one by one to see what each code block is doing.

defperformrest_client=configure_rest_clientstream_client=configure_stream_clientwhiletrueputs'Starting to Retweet 3, 2, 1 ... NOW!'re_tweet(rest_client,stream_client)endendprivateMAXIMUM_HASHTAG_COUNT=10defhashtags(tweet)tweet_hash=tweet.to_hextended_tweet=tweet_hash[:extended_tweet](extended_tweet&&extended_tweet[:entities][:hashtags])||tweet_hash[:entities][:hashtags]enddeftweet?(tweet)tweet.is_a?(Twitter::Tweet)enddefretweet?(tweet)tweet.retweet?enddefallowed_hashtags?(tweet)includes_allowed_hashtags=falsehashtags(tweet).eachdo|hashtag|ifHASHTAGS_TO_WATCH.map(&:upcase).include?("##{hashtag[:text]&.upcase}")includes_allowed_hashtags=truebreakendendincludes_allowed_hashtagsenddefallowed_hashtag_count?(tweet)hashtags(tweet)&.count<=MAXIMUM_HASHTAG_COUNTenddefsensitive_tweet?(tweet)tweet.possibly_sensitive?enddefshould_re_tweet?(tweet)tweet?(tweet)&&!retweet?(tweet)&&allowed_hashtag_count?(tweet)&&!sensitive_tweet?(tweet)&&allowed_hashtags?(tweet)enddefre_tweet(rest_client,stream_client)stream_client.filter(:track=>HASHTAGS_TO_WATCH.join(','))do|tweet|puts"\nCaught the tweet ->#{tweet.text}"ifshould_re_tweet?(tweet)rest_client.retweettweetputs"[#{Time.now}] Retweeted successfully!\n"endendrescueStandardError=>eputs"=========Error========\n#{e.message}"puts"[#{Time.now}] Waiting for 60 seconds ....\n"sleep60end
Enter fullscreen modeExit fullscreen mode

What's happening?

defperformrest_client=configure_rest_clientstream_client=configure_stream_clientwhiletrueputs'Starting to Retweet 3, 2, 1 ... NOW!'re_tweet(rest_client,stream_client)endend
Enter fullscreen modeExit fullscreen mode
  • We are usingwhile true so that our service runs forever, once we start.
defshould_re_tweet?(tweet)tweet?(tweet)&&!retweet?(tweet)&&allowed_hashtag_count?(tweet)&&!sensitive_tweet?(tweet)&&allowed_hashtags?(tweet)enddefre_tweet(rest_client,stream_client)stream_client.filter(:track=>HASHTAGS_TO_WATCH.join(','))do|tweet|puts"\nCaught the tweet ->#{tweet.text}"ifshould_re_tweet?(tweet)rest_client.retweettweetputs"[#{Time.now}] Retweeted successfully!\n"endendrescueStandardError=>eputs"=========Error========\n#{e.message}"puts"[#{Time.now}] Waiting for 60 seconds ....\n"sleep60end
Enter fullscreen modeExit fullscreen mode
  • Stream client live streams the tweets that match configured hashtags, hence we are looping through each tweet withstream_client.filter(:track => HASHTAGS_TO_WATCH.join(','))
  • If there is any error, we are rescuing it so that Twitter Bot doesn't stop due to the error. We are then making the bot sleep for 60 seconds, it's just a cooldown period and you are right, it's absolutely not necessary and can remove it if you want.
  • should_re_tweet? method is calling bunch of other methods that is checking various conditions so that the bot knows if it should retweet the given tweet received from twitter stream client.
deftweet?(tweet)tweet.is_a?(Twitter::Tweet)end
Enter fullscreen modeExit fullscreen mode
  • Check if received tweet is an original tweet or retweeted one, if it was retweeted then this method returns false and bot doesn't retweet.
defretweet?(tweet)tweet.retweet?end
Enter fullscreen modeExit fullscreen mode
  • Check if received tweet is not original and just retweeted, bot will skip this tweet if this method return true
defsensitive_tweet?(tweet)tweet.possibly_sensitive?end
Enter fullscreen modeExit fullscreen mode
  • Check if tweet is sensitive and has content that is not suitable for the bot to retweet

Step 8: Execute 'perform' method to run the service

Let's add the following code at the absolute end of the service:

Twitter::ReTweetService.new.perform
Enter fullscreen modeExit fullscreen mode

Step 9: Run the bot

From the command line in project root, execute the ruby file and your bot should start retweeting:

$ ruby app/services/twitter/re_tweet_service.rb
Enter fullscreen modeExit fullscreen mode

Yayy! Now you can just sit back and watch you bot wreck havoc the twitter with retweets.

Final code

require'rubygems'require'bundler/setup'require'twitter'require'figaro'require'pry-byebug'Figaro.application=Figaro::Application.new(environment:'production',path:File.expand_path('config/application.yml'))Figaro.loadmoduleTwitterclassReTweetServiceattr_reader:configdefinitialize@config=twitter_api_configenddefperformrest_client=configure_rest_clientstream_client=configure_stream_clientwhiletrueputs'Starting to Retweet 3, 2, 1 ... NOW!'re_tweet(rest_client,stream_client)endendprivateMAXIMUM_HASHTAG_COUNT=10HASHTAGS_TO_WATCH=%w[#rails #ruby #RubyOnRails]deftwitter_api_config{consumer_key:ENV['CONSUMER_KEY'],consumer_secret:ENV['CONSUMER_SECRET'],access_token:ENV['ACCESS_TOKEN'],access_token_secret:ENV['ACCESS_TOKEN_SECRET']}enddefconfigure_rest_clientputs'Configuring Rest Client'Twitter::REST::Client.new(config)enddefconfigure_stream_clientputs'Configuring Stream Client'Twitter::Streaming::Client.new(config)enddefhashtags(tweet)tweet_hash=tweet.to_hextended_tweet=tweet_hash[:extended_tweet](extended_tweet&&extended_tweet[:entities][:hashtags])||tweet_hash[:entities][:hashtags]enddeftweet?(tweet)tweet.is_a?(Twitter::Tweet)enddefretweet?(tweet)tweet.retweet?enddefallowed_hashtags?(tweet)includes_allowed_hashtags=falsehashtags(tweet).eachdo|hashtag|ifHASHTAGS_TO_WATCH.map(&:upcase).include?("##{hashtag[:text]&.upcase}")includes_allowed_hashtags=truebreakendendincludes_allowed_hashtagsenddefallowed_hashtag_count?(tweet)hashtags(tweet)&.count<=MAXIMUM_HASHTAG_COUNTenddefsensitive_tweet?(tweet)tweet.possibly_sensitive?enddefshould_re_tweet?(tweet)tweet?(tweet)&&!retweet?(tweet)&&allowed_hashtag_count?(tweet)&&!sensitive_tweet?(tweet)&&allowed_hashtags?(tweet)enddefre_tweet(rest_client,stream_client)stream_client.filter(:track=>HASHTAGS_TO_WATCH.join(','))do|tweet|puts"\nCaught the tweet ->#{tweet.text}"ifshould_re_tweet?(tweet)rest_client.retweettweetputs"[#{Time.now}] Retweeted successfully!\n"endendrescueStandardError=>eputs"=========Error========\n#{e.message}"puts"[#{Time.now}] Waiting for 60 seconds ....\n"sleep60endendendTwitter::ReTweetService.new.perform
Enter fullscreen modeExit fullscreen mode

Bonus: Running the bot in remote server

With this, you should be able to run the bot in your local machine. If you want to keep it running even when your maching is powered off, then you will have to deploy the code to remote server.

I am assuming that you have a good knowledge of working with remote server and have already configured the server.

If you have already configured the server then you can run the bot in the server with following steps:

Step 1: Push code to git

Push the current folder to git repo so that we can download it to the server and use it to run the bot.

Step 2: Clone the project

Inside the server,git clone the project

Step 3: Move inside the project folder

$ cd ruby-twitter-bot # assuming your project is named ruby-twitter-bot
Enter fullscreen modeExit fullscreen mode

Step 4: Create a new shell

$ screen -S twitter-bot
Enter fullscreen modeExit fullscreen mode

Step 5: Run the ruby twitter bot

$ ruby app/services/twitter/re_tweet_service.rb
Enter fullscreen modeExit fullscreen mode

Step 6: Detach shell and move to original shell

$ CTRL + a + d
Enter fullscreen modeExit fullscreen mode

With that, you should now have a bot that will run forever unless your server is down or your twitter app has reached the tweet limit.

Conclusion

Now you have learned how to create Twitter bot with Ruby, go and show your power on Twitter. Hope you use the bot for the better of the community.

You can view the full code and folder structure atRuby Twitter Bot (Github)

Thanks for reading, see you in the next blog.

References:Run ruby script in the background (Stack Overflow)

Image Credits: Cover Image bySergei Tokmakov, Esq. onPixabay

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

More fromTruemark Technology

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp