Class: Safubot::Twitter::Bot
- Inherits:
-
Object
- Object
- Safubot::Twitter::Bot
- Includes:
- Evented
- Defined in:
- lib/safubot/twitter.rb
Overview
A Twitter::Bot instance provides a Safubot::Bot with Twitter-specific processing.
Instance Attribute Summary collapse
-
#client ⇒ Object
readonly
Returns the value of attribute client.
-
#opts ⇒ Object
readonly
Returns the value of attribute opts.
-
#pid ⇒ Object
readonly
Returns the value of attribute pid.
-
#stream ⇒ Object
readonly
Returns the value of attribute stream.
-
#username ⇒ Object
readonly
Returns the value of attribute username.
Instance Method Summary collapse
-
#fork ⇒ Object
Starts our TweetStream client running in a new process.
-
#handle_message(message) ⇒ Object
Stores a DM and creates a matching Request as needed.
-
#handle_request(req) ⇒ Object
Emit a request event unless the request is already processed.
-
#handle_tweet(status) ⇒ Object
Stores a tweet.
-
#init_stream ⇒ Object
Initializes the TweetStream client.
-
#initialize(options = {}) ⇒ Bot
constructor
::Twitter, but the :username is ours and important.
-
#pull ⇒ Object
Pulls DMs and mentions using the AJAX API.
-
#reply(tweet, text) ⇒ Object
Replies to a tweet using the appropriate mentions.
-
#reply_header(tweet) ⇒ Object
Constructs the appropriate series of mentions for a reply to this tweet.
-
#run ⇒ Object
Starts our TweetStream client running.
-
#run_stream ⇒ Object
Runs the TweetStream client.
-
#send(resp) ⇒ Object
Sends a Twitter-sourced Response to the appropriate target.
-
#stop ⇒ Object
Shut down the TweetStream client.
Methods included from Evented
#bind, #emit, #on, #once, #unbind
Constructor Details
#initialize(options = {}) ⇒ Bot
::Twitter, but the :username is ours and important.
306 307 308 309 310 311 312 313 314 315 316 317 318 |
# File 'lib/safubot/twitter.rb', line 306 def initialize(={}) defaults = { :username => nil, :consumer_key => nil, :consumer_secret => nil, :oauth_token => nil, :oauth_token_secret => nil, :auth_method => :oauth } @opts = defaults.merge() DirectMessage.ensure_index('raw.id', :unique => true) Tweet.ensure_index('raw.id', :unique => true) @username = @opts[:username] @client = Object::Twitter::Client.new(@opts) end |
Instance Attribute Details
#client ⇒ Object (readonly)
Returns the value of attribute client.
164 165 166 |
# File 'lib/safubot/twitter.rb', line 164 def client @client end |
#opts ⇒ Object (readonly)
Returns the value of attribute opts.
164 165 166 |
# File 'lib/safubot/twitter.rb', line 164 def opts @opts end |
#pid ⇒ Object (readonly)
Returns the value of attribute pid.
164 165 166 |
# File 'lib/safubot/twitter.rb', line 164 def pid @pid end |
#stream ⇒ Object (readonly)
Returns the value of attribute stream.
164 165 166 |
# File 'lib/safubot/twitter.rb', line 164 def stream @stream end |
#username ⇒ Object (readonly)
Returns the value of attribute username.
164 165 166 |
# File 'lib/safubot/twitter.rb', line 164 def username @username end |
Instance Method Details
#fork ⇒ Object
Starts our TweetStream client running in a new process.
285 286 287 288 289 290 |
# File 'lib/safubot/twitter.rb', line 285 def fork @pid = Process.fork do Signal.trap("TERM") { stop } run end end |
#handle_message(message) ⇒ Object
Stores a DM and creates a matching Request as needed.
190 191 192 193 |
# File 'lib/safubot/twitter.rb', line 190 def () return if .sender.screen_name == @username handle_request(DirectMessage.from().make_request) end |
#handle_request(req) ⇒ Object
Emit a request event unless the request is already processed.
183 184 185 |
# File 'lib/safubot/twitter.rb', line 183 def handle_request(req) emit(:request, req) unless req.nil? || req.processed end |
#handle_tweet(status) ⇒ Object
Stores a tweet. If this tweet is directed at us, create a matching Request. Otherwise, emit a :timeline event.
199 200 201 202 203 204 205 206 207 |
# File 'lib/safubot/twitter.rb', line 199 def handle_tweet(status) return if status.user.screen_name == @username tweet = Tweet.from(status) if tweet.text.match(/@#{@username}/i) && !tweet.original_tweet handle_request(tweet.make_request) else emit(:timeline, tweet) end end |
#init_stream ⇒ Object
Initializes the TweetStream client.
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/safubot/twitter.rb', line 240 def init_stream @stream = TweetStream::Client.new(@opts) @stream. do || () end @stream.on_error do |err| if err.match(/invalid status code: 401/) Log.error "TweetStream authentication failure!" else Log.error "Unhandled TweetStream error: #{error_report($!)}" end end @stream.on_inited do Log.info("TweetStream client is online at @#{@username} :3") emit(:ready) end end |
#pull ⇒ Object
Pulls DMs and mentions using the AJAX API. Used in tandem with the streaming API to ensure we don’t miss too much while we’re offline.
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/safubot/twitter.rb', line 223 def pull begin @client..each do || () end @client.mentions.each do |mention| handle_tweet(mention) end rescue ::Twitter::Error::ServiceUnavailable Log.error "Twitter: Couldn't pull tweets due to temporary service unavailability." rescue Exception => e Log.error "Twitter: Unhandled error: #{error_report(e)}" end end |
#reply(tweet, text) ⇒ Object
Replies to a tweet using the appropriate mentions.
217 218 219 |
# File 'lib/safubot/twitter.rb', line 217 def reply(tweet, text) @client.update("#{reply_header(tweet)} #{text}", :in_reply_to_status_id => tweet.raw['id']) end |
#reply_header(tweet) ⇒ Object
Constructs the appropriate series of mentions for a reply to this tweet.
210 211 212 |
# File 'lib/safubot/twitter.rb', line 210 def reply_header(tweet) (["@#{tweet.username}"] + (tweet.header_mentions - ["@#{@username}"])).join(' ') end |
#run ⇒ Object
Starts our TweetStream client running.
279 280 281 282 |
# File 'lib/safubot/twitter.rb', line 279 def run init_stream run_stream end |
#run_stream ⇒ Object
Runs the TweetStream client.
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
# File 'lib/safubot/twitter.rb', line 262 def run_stream begin @stream.userstream do |status| handle_tweet(status) end rescue Exception => e if e.is_a?(Interrupt) || e.is_a?(SignalException) stop else Log.error "TweetStream client exited unexpectedly: #{error_report(e)}" Log.error "Restarting TweetStream client in 5 seconds." sleep 5; init_stream; run_stream end end end |
#send(resp) ⇒ Object
Sends a Twitter-sourced Response to the appropriate target.
169 170 171 172 173 174 175 176 177 178 |
# File 'lib/safubot/twitter.rb', line 169 def send(resp) source = resp.request.source if source.is_a?(DirectMessage) @client.(source.raw['sender']['screen_name'], resp.text) elsif source.is_a?(Tweet) reply source, resp.text else raise NotImplementedError, "Don't know how to send response to a #{req.source.class}!" end end |
#stop ⇒ Object
Shut down the TweetStream client.
293 294 295 296 297 298 299 300 301 |
# File 'lib/safubot/twitter.rb', line 293 def stop if @stream @stream.stop @stream = nil Log.info("TweetStream client shutdown complete.") else Process.kill("TERM", @pid) if @pid end end |