public
Description: Twitter auto follow script
Homepage:
Clone URL: git://github.com/shenie/auto_follow.git
auto_follow / auto_follow.rb
100755 126 lines (104 sloc) 3.213 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/usr/bin/env ruby
 
require 'rubygems'
require "logger"
require "yaml"
gem "twitter", '>=0.6.6'
require 'twitter'
require 'hpricot'
require 'yaml'
require 'open-uri'
 
#
# Usage:
# follower = AutoFollower.new('admin@example.com', 'password')
# follower.start
# follower.stalk('cincinnati')
#
# Another option if you only want to follow your followers is
# running it off command line like auto_follow.rb admin@example.com password
#
class AutoFollower
  
  FOLLOW_INTERVAL = 5
  TWITTER_PAGE_SIZE = 100
  BLACK_LIST = "#{File.dirname(__FILE__)}/black_list.yml"
  
  attr_accessor :black_list
  
  def initialize(username, password, output = STDOUT, level = Logger::INFO)
    httpauth = Twitter::HTTPAuth.new(username, password)
    @twitter = Twitter::Base.new(httpauth)
    
    output = eval(output) if output.is_a?(String)
    level = eval(level) if level.is_a?(String)
    
    @log = Logger.new(output)
    @log.sev_threshold = level
    @log.formatter = Logger::Formatter.new
    
    @black_list = File.exist?(BLACK_LIST) ? YAML.load_file(BLACK_LIST) : []
  end
  
  def start
    peeps = (followers - friends).find_all { |n| !black_listed?(n) }
    
    @log.info "Need to follow #{peeps.size} people"
    execute { peeps.each { |name| follow(name) } }
  end
  
  def stalk(query, page = 1)
    execute do
      names = search(query, page)
 
      while !names.empty?
        @log.debug("Stalking page: #{page}")
        (names - friends).find_all { |n| !black_listed?(n) }.each { |name| follow(name) }
        page = page + 1
        names = search(query, page)
      end
    end
  end
  
  def search(query, page)
    doc = Hpricot(open("http://twitter.com/search/users?q=#{query}&page=#{page}"))
    names = doc.search(".screen_name span").collect { |d| d.innerHTML }
  end
  
  def followers
    @followers ||= find_followers
  end
  
  def friends
    @friends ||= find_friends
  end
 
  private
  
    def execute(&block)
      begin
        block.call
      ensure
        File.open(BLACK_LIST, 'w') {|f| f.write(black_list.to_yaml) }
      end
    end
  
    def black_listed?(name)
      black_list.include?(name)
    end
  
    def follow(name, delay = FOLLOW_INTERVAL)
      begin
        @twitter.friendship_create(name)
        @log.info "Following: #{name}"
      rescue => e
        if e.message.include? "403"
          black_list << name
          @log.warn "Black listed: #{name}"
        elsif e.message.include? "400"
          raise "APILimitHit"
        else
          @log.error "Failed to follow #{name}"
          @log.error e
        end
      ensure
        sleep delay
      end
    end
    
    def find_followers(page = 1)
      @log.debug "followers page: #{page}"
      f = @twitter.followers(:lite => true, :page => page).collect { |f| f.screen_name }
      return f if f.empty? || f.size < TWITTER_PAGE_SIZE
      f + find_followers(page + 1)
    end
    
    def find_friends(page = 1)
      @log.debug "friends page: #{page}"
      f = @twitter.friends(:lite => true, :page => page).collect { |f| f.screen_name }
      return f if f.empty? || f.size < TWITTER_PAGE_SIZE
      f + find_friends(page + 1)
    end
end
 
if $0 == __FILE__
  AutoFollower.new(*ARGV).start
end