forked from mispy-archive/ebooks_example
-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathboodoo.rb
158 lines (139 loc) · 4.16 KB
/
boodoo.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
require 'twitter_ebooks'
include Ebooks
module Ebooks::Boodoo
# supports Ruby Range literal, Fixnum, or Float as string
def parse_num(value)
eval(value.to_s[/^\d+(?:\.{1,3})?\d*$/].to_s)
end
# Make expected/possible Range
def parse_range(value)
value = parse_num(value)
if value.nil?
value = nil
elsif !value.respond_to?(:to_a)
value = Range.new(value, value)
end
value
end
def obscure_curse(len)
s = []
c = ['!', '@', '$', '%', '^', '&', '*']
len.times do
s << c.sample
end
s.join('')
end
def obscure_curses(tweet)
# TODO: Ignore banned terms that are part of @-mentions
$banned_terms.each do |term|
re = Regexp.new("\\b#{term}\\b", "i")
tweet.gsub!(re, Ebooks::Boodoo.obscure_curse(term.size))
end
tweet
end
def parse_array(value, array_splitter=nil)
array_splitter ||= / *[,;]+ */
value.split(array_splitter).map(&:strip)
end
def make_client
Twitter::REST::Client.new do |config|
config.consumer_key = @consumer_key
config.consumer_secret = @consumer_secret
config.access_token = @access_token
config.access_token_secret = @access_token_secret
end
end
end
## Retweet check based on Really-Existing-RT practices
class Ebooks::TweetMeta
def is_retweet?
tweet.retweeted_status? || !!tweet.text[/[RM]T ?[@:]/i]
end
end
class Ebooks::Boodoo::BoodooBot < Ebooks::Bot
$required_fields = ['consumer_key', 'consumer_secret',
'access_token', 'access_token_secret',
'bot_name', 'original']
# Unfollow a user -- OVERRIDE TO FIX TYPO
# @param user [String] username or user id
def unfollow(user, *args)
log "Unfollowing #{user}"
twitter.unfollow(user, *args)
end
# A rough error-catch/retry for rate limit, dupe fave, server timeouts
def catch_twitter
begin
yield
rescue Twitter::Error => error
@retries += 1
raise if @retries > @max_error_retries
if error.class == Twitter::Error::TooManyRequests
reset_in = error.rate_limit.reset_in
log "RATE: Going to sleep for ~#{reset_in / 60} minutes..."
sleep reset_in
retry
elsif error.class == Twitter::Error::Forbidden
# don't count "Already faved/followed" message against attempts
@retries -= 1 if error.to_s.include?("already")
log "WARN: #{error.to_s}"
return true
elsif ["execution", "capacity"].any?(&error.to_s.method(:include?))
log "ERR: Timeout?\n\t#{error}\nSleeping for #{@timeout_sleep} seconds..."
sleep @timeout_sleep
retry
else
log "Unhandled exception from Twitter: #{error.to_s}"
raise
end
end
end
# Override Ebooks::Bot#blacklisted? to ensure lower<=>lower check
def blacklisted?(username)
if @blacklist.map(&:downcase).include?(username.downcase)
true
else
false
end
end
# Follow new followers, unfollow lost followers
def follow_parity
followers = catch_twitter { twitter.followers(:count=>200).map(&:screen_name) }
following = catch_twitter { twitter.following(:count=>200).map(&:screen_name) }
to_follow = followers - following
to_unfollow = following - followers
twitter.follow(to_follow) unless to_follow.empty?
twitter.unfollow(to_unfollow) unless to_unfollow.empty?
@followers = followers
@following = following - to_unfollow
if !(to_follow.empty? || to_unfollow.empty?)
log "Followed #{to_follow.size}; unfollowed #{to_unfollow.size}."
end
end
def has_model?
File.exists? @model_path
end
def has_archive?
File.exists? @archive_path
end
def get_archive!
@archive = Archive.new(@original, @archive_path, make_client).sync
end
def block(*args)
twitter.block(*args)
end
def make_model!
log "Updating model: #{@model_path}"
Ebooks::Model.consume(@archive_path).save(@model_path)
log "Loading model..."
@model = Ebooks::Model.load(@model_path)
end
def can_run?
missing_fields.empty?
end
def missing_fields
$required_fields.select { |field|
# p "#{field} = #{send(field)}"
send(field).nil? || send(field).empty?
}
end
end