-
Notifications
You must be signed in to change notification settings - Fork 7
/
auto_follow.rb
executable file
·126 lines (104 loc) · 3.14 KB
/
auto_follow.rb
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