Class: Twibot::Bot
Overview
Main bot “controller” class
Instance Attribute Summary collapse
-
#prompt ⇒ Object
writeonly
Sets the attribute prompt.
-
#twitter ⇒ Object
readonly
Returns the value of attribute twitter.
Instance Method Summary collapse
- #add_follower!(user_or_id) ⇒ Object
- #add_friend!(user_or_id, only_local = false) ⇒ Object
-
#add_hook(event, &blk) ⇒ Object
registers a block to be called at the given
event
. -
#configure {|@config| ... } ⇒ Object
Configure bot.
-
#dispatch_messages(type, messages, labels) ⇒ Object
Dispatch a collection of messages.
- #follower_ids ⇒ Object
- #friend_ids ⇒ Object
-
#hooks ⇒ Object
returns a Hash of all registered hooks.
- #id_for_user_or_id(user_or_id) ⇒ Object
-
#initialize(options = nil, prompt = false) ⇒ Bot
constructor
A new instance of Bot.
- #is_follower?(user_or_id) ⇒ Boolean
- #is_friend?(user_or_id) ⇒ Boolean
-
#load_followers ⇒ Object
retrieve a list of friend ids and store it as a Hash.
-
#load_friends ⇒ Object
retrieve a list of friend ids and store it as a Hash.
-
#log ⇒ Object
Return logger instance.
-
#poll ⇒ Object
Poll Twitter API in a loop and pass on messages and tweets when they appear.
- #processed ⇒ Object
- #prompt? ⇒ Boolean
-
#receive_followers ⇒ Object
Receive any new followers.
-
#receive_messages ⇒ Object
Receive direct messages.
-
#receive_replies ⇒ Object
Receive tweets that start with @<login>.
-
#receive_searches ⇒ Object
Receive tweets that match the query parameters.
-
#receive_tweets ⇒ Object
Receive tweets.
- #remove_follower!(user_or_id) ⇒ Object
- #remove_friend!(user_or_id, only_local = false) ⇒ Object
-
#run! ⇒ Object
Run application.
-
#run_hook(event, *args) ⇒ Object
calls the hook method for the
event
if one has been defined. -
#with_hooks(type, &blk) ⇒ Object
invokes the given block, running the before and after hooks for the given type.
Methods included from Handlers
#add_handler, #dispatch, #handlers, #handlers=, #handlers_for_type
Constructor Details
#initialize(options = nil, prompt = false) ⇒ Bot
Returns a new instance of Bot.
14 15 16 17 18 19 20 21 22 |
# File 'lib/twibot/bot.rb', line 14 def initialize( = nil, prompt = false) @prompt = prompt @conf = nil @config = || Twibot::Config.default << Twibot::FileConfig.new << Twibot::CliConfig.new @log = nil @abort = false rescue Exception => krash raise SystemExit.new(krash.) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, &block) ⇒ Object (private)
Map configuration settings
337 338 339 340 341 342 |
# File 'lib/twibot/bot.rb', line 337 def method_missing(name, *args, &block) return super unless config.key?(name) self.class.send(:define_method, name) { config[name] } config[name] end |
Instance Attribute Details
#prompt=(value) ⇒ Object (writeonly)
Sets the attribute prompt
12 13 14 |
# File 'lib/twibot/bot.rb', line 12 def prompt=(value) @prompt = value end |
#twitter ⇒ Object (readonly)
Returns the value of attribute twitter.
11 12 13 |
# File 'lib/twibot/bot.rb', line 11 def twitter @twitter end |
Instance Method Details
#add_follower!(user_or_id) ⇒ Object
147 148 149 |
# File 'lib/twibot/bot.rb', line 147 def add_follower!(user_or_id) follower_ids[id_for_user_or_id(user_or_id)] = true end |
#add_friend!(user_or_id, only_local = false) ⇒ Object
127 128 129 130 131 |
# File 'lib/twibot/bot.rb', line 127 def add_friend!(user_or_id, only_local=false) id = id_for_user_or_id(user_or_id) sandbox(0) { twitter.friend(:add, id) } unless only_local friend_ids[id] = true end |
#add_hook(event, &blk) ⇒ Object
registers a block to be called at the given event
193 194 195 |
# File 'lib/twibot/bot.rb', line 193 def add_hook(event, &blk) hooks[event.to_sym] = blk end |
#configure {|@config| ... } ⇒ Object
Configure bot
327 328 329 330 331 |
# File 'lib/twibot/bot.rb', line 327 def configure yield @config @conf = nil @twitter = nil end |
#dispatch_messages(type, messages, labels) ⇒ Object
Dispatch a collection of messages
286 287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'lib/twibot/bot.rb', line 286 def (type, , labels) .each {|| with_hooks(type) { dispatch(type, ) } } # Avoid picking up messages over again if type.is_a? Array # [TODO] (mikedemers) this is an ugly hack processed[type.first][type.last] = .first.id if .length > 0 else processed[type] = .first.id if .length > 0 end num = .length log.info "#{config[:host]}: Received #{num} #{num == 1 ? labels[0] : labels[1]}" num end |
#follower_ids ⇒ Object
143 144 145 |
# File 'lib/twibot/bot.rb', line 143 def follower_ids @follower_ids ||= {} end |
#friend_ids ⇒ Object
123 124 125 |
# File 'lib/twibot/bot.rb', line 123 def friend_ids @friend_ids ||= {} end |
#hooks ⇒ Object
returns a Hash of all registered hooks
186 187 188 |
# File 'lib/twibot/bot.rb', line 186 def hooks @hooks ||= {} end |
#id_for_user_or_id(user_or_id) ⇒ Object
159 160 161 |
# File 'lib/twibot/bot.rb', line 159 def id_for_user_or_id(user_or_id) (user_or_id.respond_to?(:screen_name) ? user_or_id.id : user_or_id).to_i end |
#is_follower?(user_or_id) ⇒ Boolean
155 156 157 |
# File 'lib/twibot/bot.rb', line 155 def is_follower?(user_or_id) !!follower_ids[id_for_user_or_id(user_or_id)] end |
#is_friend?(user_or_id) ⇒ Boolean
139 140 141 |
# File 'lib/twibot/bot.rb', line 139 def is_friend?(user_or_id) !!friend_ids[id_for_user_or_id(user_or_id)] end |
#load_followers ⇒ Object
retrieve a list of friend ids and store it as a Hash
176 177 178 179 180 |
# File 'lib/twibot/bot.rb', line 176 def load_followers sandbox(0) do twitter.graph(:followers, config[:login]).each {|id| add_follower!(id) } end end |
#load_friends ⇒ Object
retrieve a list of friend ids and store it as a Hash
167 168 169 170 171 |
# File 'lib/twibot/bot.rb', line 167 def load_friends sandbox(0) do twitter.graph(:friends, config[:login]).each {|id| add_friend!(id, true) } end end |
#log ⇒ Object
Return logger instance
315 316 317 318 319 320 321 322 |
# File 'lib/twibot/bot.rb', line 315 def log return @log if @log os = config[:log_file] ? File.open(config[:log_file], "a") : $stdout os.sync = !!config[:log_flush] @log = Logger.new(os) @log.level = Logger.const_get(config[:log_level] ? config[:log_level].upcase : "INFO") @log end |
#poll ⇒ Object
Poll Twitter API in a loop and pass on messages and tweets when they appear
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/twibot/bot.rb', line 98 def poll max = max_interval step = interval_step interval = min_interval while !@abort do run_hook :before_all = 0 += || 0 += receive_replies || 0 += receive_tweets || 0 += receive_searches || 0 receive_followers run_hook :after_all, interval = > 0 ? min_interval : [interval + step, max].min log.debug "#{config[:host]} sleeping for #{interval}s" sleep interval end end |
#processed ⇒ Object
28 29 30 31 32 33 34 35 |
# File 'lib/twibot/bot.rb', line 28 def processed @processed ||= { :message => nil, :reply => nil, :tweet => nil, :search => {} } end |
#prompt? ⇒ Boolean
24 25 26 |
# File 'lib/twibot/bot.rb', line 24 def prompt? @prompt end |
#receive_followers ⇒ Object
Receive any new followers
271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/twibot/bot.rb', line 271 def receive_followers newbies = [] sandbox(0) do twitter.graph(:followers, config[:login]).each {|id| newbies << id unless is_friend?(id) or is_follower?(id) } newbies.each do |id| add_follower!(id) with_hooks(:follower) { handlers_for_type(:follower).each {|h| h.handle(id, {}) } } end end log.info "#{config[:host]}: Received #{newbies.size} new #{newbies.size == 1 ? 'follower' : 'followers'}" end |
#receive_messages ⇒ Object
Receive direct messages
208 209 210 211 212 213 214 215 216 217 |
# File 'lib/twibot/bot.rb', line 208 def type = :message return false unless handlers_for_type(type).length > 0 = {} [:since_id] = processed[type] if processed[type] sandbox(0) do (type, twitter.(:received, ), %w{message messages}) end end |
#receive_replies ⇒ Object
Receive tweets that start with @<login>
236 237 238 239 240 241 242 243 244 245 |
# File 'lib/twibot/bot.rb', line 236 def receive_replies type = :reply return false unless handlers_for_type(type).length > 0 = {} [:since_id] = processed[type] if processed[type] sandbox(0) do (type, twitter.status(:replies, ), %w{reply replies}) end end |
#receive_searches ⇒ Object
Receive tweets that match the query parameters
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/twibot/bot.rb', line 250 def receive_searches result_count = 0 handlers_for_type(:search).each_pair do |query, search_handlers| = { :q => query, :rpp => 100 } [:lang, :geocode].each do |param| [param] = search_handlers.first.[param] if search_handlers.first.[param] end [:since_id] = processed[:search][query] if processed[:search][query] result_count += sandbox(0) do ([:search, query], twitter.search(.merge()), %w{tweet tweets}.map {|l| "#{l} for \"#{query}\""}) end end result_count end |
#receive_tweets ⇒ Object
Receive tweets
222 223 224 225 226 227 228 229 230 231 |
# File 'lib/twibot/bot.rb', line 222 def receive_tweets type = :tweet return false unless handlers_for_type(type).length > 0 = {} [:since_id] = processed[type] if processed[type] sandbox(0) do (type, twitter.timeline_for(config.to_hash[:timeline_for] || :public, ), %w{tweet tweets}) end end |
#remove_follower!(user_or_id) ⇒ Object
151 152 153 |
# File 'lib/twibot/bot.rb', line 151 def remove_follower!(user_or_id) follower_ids[id_for_user_or_id(user_or_id)] = false end |
#remove_friend!(user_or_id, only_local = false) ⇒ Object
133 134 135 136 137 |
# File 'lib/twibot/bot.rb', line 133 def remove_friend!(user_or_id, only_local=false) id = id_for_user_or_id(user_or_id) sandbox(0) { twitter.friend(:remove, id) } unless only_local friend_ids[id] = false end |
#run! ⇒ Object
Run application
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 |
# File 'lib/twibot/bot.rb', line 46 def run! puts "Twibot #{Twibot::VERSION} imposing as @#{login} on #{config[:host]}" trap(:INT) do puts "\nAnd it's a wrap. See ya soon!" exit end case config[:process] when :all, nil # do nothing so it will fetch ALL when :new # Make sure we don't process messages and tweets received prior to bot launch = twitter.(:received, { :count => 1 }) processed[:message] = .first.id if .length > 0 handle_tweets = !handlers.nil? && handlers_for_type(:tweet).length + handlers_for_type(:reply).length + handlers_for_type(:search).keys.length > 0 # handle_tweets ||= handlers_for_type(:search).keys.length > 0 tweets = [] sandbox do tweets = handle_tweets ? twitter.timeline_for(config[:timeline_for], { :count => 1 }) : [] end processed[:tweet] = tweets.first.id if tweets.length > 0 processed[:reply] = tweets.first.id if tweets.length > 0 # for searches, use latest tweet on public timeline # if handle_tweets && config[:timeline_for].to_s != "public" sandbox { tweets = twitter.timeline_for(:public, { :count => 1 }) } end if tweets.length > 0 handlers_for_type(:search).each_key {|q| processed[:search][q] = tweets.first.id } end load_followers when Numeric, /\d+/ # a tweet ID to start from processed[:tweet] = processed[:reply] = processed[:message] = config[:process] handlers[:search].each_key {|q| processed[:search][q] = config[:process] } else abort "Unknown process option #{config[:process]}, aborting..." end load_friends unless handlers_for_type(:follower).empty? poll end |
#run_hook(event, *args) ⇒ Object
calls the hook method for the event
if one has been defined
201 202 203 |
# File 'lib/twibot/bot.rb', line 201 def run_hook(event, *args) hooks[event.to_sym].call(*args) if hooks[event.to_sym].respond_to? :call end |
#with_hooks(type, &blk) ⇒ Object
invokes the given block, running the before and after hooks for the given type
304 305 306 307 308 309 310 |
# File 'lib/twibot/bot.rb', line 304 def with_hooks(type, &blk) event = type.is_a?(Array) ? type.first : type run_hook :"before_#{event}" value = yield run_hook :"after_#{event}" value end |