//
archives

Twitterbots

This category contains 2 posts

How to build your Twitterbot part 2

So after building a very annoying bot in part 1 we will try to make it a bit smarter so it can do actually something useful.

Today we will give the bot the methods: get_friends, get_followers, to find out more about himself.

In order to perform some actions we will write the methods: follow_user,  retweet_somebody and favorite_some_tweet.

Follow user will follow a person from our list of persons, retweet_somebody will simply retweet somebody, and favorite_some_tweet will favorite a random tweet.So in a way the robot will mimic a typical user behavior on twitter.

def get_friends(username)
  begin
    result = Twitter.friend_ids(username)
    friends_ids = result.ids
    old_cursor = 0
    next_cursor = result.next_cursor
    while old_cursor != next_cursor and next_cursor != 0
      old_cursor = next_cursor
        result = Twitter.friend_ids username, :cursor => next_cursor
      friends_ids += result.ids
        next_cursor = result.next_cursor
    end
    return friends_ids
  rescue
    @log.error "Couldn't get friends"
  end
 end

 def get_followers(username)
  begin
    result = Twitter.follower_ids username
    followers_ids = result.ids
    old_cursor = 0
    next_cursor = result.next_cursor
    while old_cursor != next_cursor and next_cursor != 0
      old_cursor = next_cursor
      result = Twitter.follower_ids username, :cursor => next_cursor
        followers_ids += result.ids
      next_cursor = result.next_cursor
    end
    return followers_ids
  rescue
    @log.error "Could'nt get followers"
  end
 end

Those two methods are almost similar,  where for a given name we can get the follower resp. friends ids.So having those methods in the Twitterbot class we will use them in the initialization to have a bot that knows something about himself.

def initialize(config_file)
  [...]
  # Adding those lines to our initial init method
  #New find out what my friends are
  @friends_ids = self.get_friends(Twitter.user.screen_name)
  #Find out what my followers are
  @followers_ids = self.get_followers(Twitter.user.screen_name)
end

def retweet_somebody
         begin
            all_retweets = Twitter.retweeted_to_me(:count => 100)
            retweets = []
            #Strategy 1: Only keep english AND keyword AND more then 1 retweet
            all_retweets.each{|e| retweets << e if e.retweeted_status.user.lang == "en" && e.retweeted_status.text.include?(@twitter_config["keyword"]) && e.retweet_count > 1}
                        #Strategy 2: Just retweet the most retweeted retweet.
            #best_retweet = retweets.sort{|a,b| a.retweet_count.to_i  b.retweet_count.to_i} # retweet highly retweeted ones
            if retweets.length > 0
                best_retweet = retweets[rand(retweets.length)]
                Twitter.retweet(best_retweet.id)
                @log.info "Retweeted: #{best_retweet.retweeted_status.text} with RT:#{best_retweet.retweet_count}"
                return best_retweet
            else
                @log.info "Wanted to retweet but found not material matching #{@twitter_config["keyword"]}"
                return []
            end
        rescue
            @log.error "Failed to retweet #{best_retweet.retweeted_status.text}"
        end
 end

The favorite some tweet method works similiar like the retweet method, where we first get a bunch of tweets from our timeline and then consider tweets as favoritable candidates if those tweets have been retweeted by somebody before and if the tweet has been written by some of my followers. We could have come up with a different heuristic but this one works just fine.

def follow_user(user)
  begin
        Twitter.follow(user.screen_name)
        @log.info "Followed person #{user.screen_name}"
        rescue
         cleanup(user,@log)
            @log.error "Could not follow person #{user.sceen_name}"
        end
 end

The follow method simply makes the bot follow a given user. For it to work we will need to add the following lines to the init function in order to have a list of persons that we would like to follow:

#Read in People to Follow
  @persons_to_follow_ids = CSV.read(@twitter_config["followers_file"]).flatten.collect{|f| f.to_i}

  #Find out whom of the persons that i should follow i am already following
  @persons_to_follow_ids = @persons_to_follow_ids - @friends_ids

Having written all of those extra functions for the bot we can make our bot logic a bit more intelligent. We will simply roll a dice and depending on the outcome the bot will either follow a person, retweet a person, or facorite a tweet or at_message a person:

#Follow procedure only follow people on a chance 1/3
dice = rand(3)

if dice == 1

 #Chose up to 4 persons
 t.persons_to_follow_ids[0..rand(4)].each do |person_to_follow|

  #Get a User
  user = t.get_user(person_to_follow)

  #Follow
  if t.twitter_config["follow_people"] == true
   t.follow_user(user)
  end

  #At Message
  if t.twitter_config["message_people"] == true
   t.at_message(user)
  end
 end

elsif dice == 2

 #Retweet some of my friends
 if t.twitter_config["retweet_people"] == true
  t.retweet_somebody
 end

elsif dice == 3

 #Favorite some Tweet
 if t.twitter_config["favorite_tweets"] == true
  t.favorite_some_tweet
 end

else
 t.log.info "Skipped run this time"
end

We will call the bot periodically to perform one of the actions and see how he is perceived by persons. Please consider that all of the above is rather an experimental toy example of  a bot and shouldnt be used to build spam bots on Twitter.

How to build your Twitter bot Part 1

In case you want to build a Twitter bot, it is quite easy with ruby and a few gems. We will write a small bot that will know a list of target persons and try to follow them and chat them up with some pickup lines.

Well I know this is kind of close to spam, so please use caution, but in part 2 I will try to teach the bot to write something more sophisticated in order to be useful. Plus it might definitely make much more sense to have some state machine mechanism in the background to control the robot. But we will start with something easy now.

To get started all you will need in ruby are those libraries twitter, csv, logger, yaml. The twitter gem is great to handle everything that has to do with Twitter. The logger gem is great if you want to maintain a log file of all the things that are going on.The remaining csv and yaml gems are practical to write down some human readable config files. So that is the code we have so far.


require 'rubygems'
require 'twitter'
require 'csv'
require 'logger'
require 'yaml'

class Twitterbot
    attr_accessor :persons_to_text_ids, :twitter_config, :log

    def initialize(config_file)
        @twitter_config = YAML.load_file(config_file)
        @log = Logger.new(@twitter_config["log_file"])

        #Read in Pickup Lines
        @pickup_lines = CSV.read(@twitter_config["pickup_file"])

        #Read in People to Follow
        @persons_to_follow_ids = CSV.read(@twitter_config["persons_file"]).flatten.collect{|f| f.to_i}

    end
end

Obviously we need some config file and a follower file. The config file will contain everything config parameter for a given account and the follower file will contain the followers per account that the account should follow.

#Config Twitterbot
consumer_key: "your consumer key"
consumer_secret: "your consumer secret"
access_token: "your access token"
access_token_secret: "your access token secret"

#Configure Behavior
persons_file: "your persons file.csv"
log_file: "your log file.log"
pickup_file: "your file with pickup lines.csv"
message_people: true

Ok lets have a look on the persons file. This is a simple .csv file where we will put a twitter id in each line:

9951012
9934442
9924592
9853212
9836732
9833962
9819862
9733542
97096813
...

And lets have a look at the pickup lines file. It should contain some “pickup lines” that the bot writes towards this person.

I've seen you are enthousiastic about xyz. Want to chat about it?
Have you heard about our xyz. I am quite interested in xyz. Do you want to be friends?
...

Well now we have everything that bot needs in order to get started. It only needs a method where he addresses the persons.

def at_message(user)
        begin
            pickup_line = "@#{user.screen_name} #{@pickup_lines[rand(@pickup_lines.length)]}"
            Twitter.update(pickup_line)
            @log.info "At Messaged: #{pickup_line}"
        rescue
            @log.error "Failed to adress member #{user.screen_name}"
        end
end

So you see we are using the log to note down whatever the bot did. Well now its time for a test run. So fire up your ruby console (irb) and load yourself a bot and have a look if it addresses our first person in the list.

require 'init'
t = Twitterbot.new("your config file")
user = t.persons_to_text_ids[0]
t.at_message(user)

I hope that works for you. If it does you can create a small robot.rb file that you going to call by a cronjob.

require 'init'

#Config Robot Client
if ARGV[0] == nil
    puts "You have to provide a config file e.g. ruby robot.rb twitter.yml"
    exit
else
    t = Twitterbot.new(ARGV[0])
end

if t.twitter_config["message_people"] == true
   t.at_message(t.persons_to_text_ids[t.persons_to_text_ids.length])
end

Finally the last thing left is to call the robot periodically using a cronjob. (Use: crontab -e) Lets suppose you want to call it every hour:

*/60 * * * * cd /home/plotti/twitterbot/;  ruby robot.rb your_config_file.yml

Tadaaa, you are done. Now you have  a bot that wakes up every hour and texts one of the people in the list.

As already mentioned, its not very useful and even quite spam like behavior, but I promise we will make the bot a bit smarter in the next episode in order to be useful.

Cheers Thomas