Class: Twittbot::Bot
- Inherits:
-
Object
- Object
- Twittbot::Bot
- Includes:
- Thor::Shell
- Defined in:
- lib/twittbot/bot.rb
Overview
Class providing the streaming connections and callback logic for the bot.
Instance Method Summary collapse
-
#already_authed? ⇒ Boolean
Whether the bot is already authenticated or not.
-
#auth ⇒ Object
Authenticates an account with Twitter.
-
#check_config ⇒ Object
Checks some configuration values, e.g.
-
#do_callbacks(callback_type, object, options = {}) ⇒ Object
Runs callbacks.
-
#do_direct_message(dm, opts = {}) ⇒ Object
Processes a direct message.
- #do_periodic ⇒ Object
-
#handle_stream_object(object, type) ⇒ Object
Handles a object yielded from a Twitter::Streaming::Client.
-
#initialize(options = {}) ⇒ Bot
constructor
A new instance of Bot.
-
#load_bot_code ⇒ Object
Loads the bot’s actual code which is stored in the bot’s
libsubdirectory. - #modify_admin(screen_name, action = :add) ⇒ Object
-
#save_config ⇒ Object
Saves the bot’s config (i.e. not the botpart ones).
-
#start ⇒ Object
Starts the bot.
Constructor Details
#initialize(options = {}) ⇒ Bot
Returns a new instance of Bot.
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/twittbot/bot.rb', line 15 def initialize( = {}) = { current_dir: FileUtils.pwd } $bot = { botparts: [], callbacks: {}, commands: {}, config: Twittbot::DEFAULT_BOT_CONFIG.merge( YAML.load_file(File.("./#{Twittbot::CONFIG_FILE_NAME}", [:current_dir])) ), periodic: [] }.merge!() load_bot_code at_exit do save_config $bot[:botparts].each { |b| b.save_config } end end |
Instance Method Details
#already_authed? ⇒ Boolean
Returns whether the bot is already authenticated or not.
242 243 244 |
# File 'lib/twittbot/bot.rb', line 242 def already_authed? !($bot[:config][:access_token].empty? or $bot[:config][:access_token_secret].empty?) end |
#auth ⇒ Object
Authenticates an account with Twitter.
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 |
# File 'lib/twittbot/bot.rb', line 39 def auth require 'oauth' say "This will reset your current access tokens.", :red if already_authed? # get the request token URL callback = OAuth::OUT_OF_BAND consumer = OAuth::Consumer.new $bot[:config][:consumer_key], $bot[:config][:consumer_secret], site: Twitter::REST::Client::BASE_URL, scheme: :header request_token = consumer.get_request_token(oauth_callback: callback) url = request_token.(oauth_callback: callback) puts "Open this URL in a browser: #{url}" pin = '' until pin =~ /^\d+$/ print "Enter PIN =>" pin = $stdin.gets.strip end access_token = request_token.get_access_token(oauth_verifier: pin) $bot[:config][:access_token] = access_token.token $bot[:config][:access_token_secret] = access_token.secret # get the bot's user name (screen_name) and print it to the console $bot[:config][:screen_name] = get_screen_name access_token puts "Hello, #{$bot[:config][:screen_name]}!" end |
#check_config ⇒ Object
Checks some configuration values, e.g. if the bot is already authenticated with Twitter
154 155 156 157 158 159 |
# File 'lib/twittbot/bot.rb', line 154 def check_config unless already_authed? say "Please authenticate using `twittbot auth' first.", :red raise 'Not authenticated' end end |
#do_callbacks(callback_type, object, options = {}) ⇒ Object
Runs callbacks.
202 203 204 205 206 207 |
# File 'lib/twittbot/bot.rb', line 202 def do_callbacks(callback_type, object, = {}) return if $bot[:callbacks][callback_type].nil? $bot[:callbacks][callback_type].each do |c| c[:block].call object, end end |
#do_direct_message(dm, opts = {}) ⇒ Object
Processes a direct message.
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/twittbot/bot.rb', line 223 def (dm, opts = {}) return if dm.sender.screen_name == $bot[:config][:screen_name] return do_callbacks(:direct_message, dm, opts) unless dm.text.start_with? $bot[:config][:dm_command_prefix] dm_text = dm.text.sub($bot[:config][:dm_command_prefix], '').strip return if dm_text.empty? return unless /(?<command>[A-Za-z0-9]+)(?:\s*)(?<args>.*)/m =~ dm_text command = Regexp.last_match(:command).to_sym args = Regexp.last_match :args cmd = $bot[:commands][command] return say_status :dm, "#{dm.sender.screen_name} tried to issue non-existent command :#{command}, ignoring", :cyan if cmd.nil? return say_status :dm, "#{dm.sender.screen_name} tried to issue admin command :#{command}, ignoring", :cyan if cmd[:admin] and !dm.sender.admin? say_status :dm, "#{dm.sender.screen_name} issued command :#{command}", :cyan cmd[:block].call(args, dm.sender) end |
#do_periodic ⇒ Object
209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/twittbot/bot.rb', line 209 def do_periodic $bot[:periodic].each_with_index do |h, i| h[:remaining] = if h[:remaining] == 0 h[:block].call h[:interval] else h[:remaining] - 1 end $bot[:periodic][i] = h end end |
#handle_stream_object(object, type) ⇒ Object
Handles a object yielded from a Twitter::Streaming::Client.
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/twittbot/bot.rb', line 164 def handle_stream_object(object, type) opts = { stream_type: type } case object when Twitter::Streaming::FriendList # object: Array with IDs do_callbacks :friend_list, object when Twitter::Tweet # object: Twitter::Tweet is_mention = (object.user.screen_name != $bot[:config][:screen_name] and object.text.include?("@" + $bot[:config][:screen_name]) and not object.retweet?) do_callbacks :retweet, object, opts if object.retweet? and object.retweeted_tweet.user.screen_name == $bot[:config][:screen_name] do_callbacks :mention, object, opts if is_mention do_callbacks :tweet, object, opts.merge({ mention: is_mention, retweet: object.retweet? }) when Twitter::Streaming::Event case object.name when :follow, :favorite # :follow -- object: Twitter::Streaming::Event(name: :follow, source: Twitter::User, target: Twitter::User) # :favorite -- object: Twitter::Streaming::Event(name: :favorite, source: Twitter::User, target: Twitter::User, target_object: Twitter::Tweet) do_callbacks object.name, object, opts else puts "no handler for #{object.class.to_s}/#{object.name}\n -- object data:" require 'pp' pp object do_callbacks object.name, object, opts end when Twitter::DirectMessage object, opts else puts "no handler for #{object.class.to_s}\n -- object data:" require 'pp' pp object end end |
#load_bot_code ⇒ Object
Loads the bot’s actual code which is stored in the bot’s lib subdirectory.
137 138 139 140 141 142 |
# File 'lib/twittbot/bot.rb', line 137 def load_bot_code files = Dir["#{File.expand_path('./lib', @options[:current_dir])}/**/*"] files.each do |file| require_relative file.sub(/\.rb$/, '') if file.end_with? '.rb' end end |
#modify_admin(screen_name, action = :add) ⇒ Object
120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/twittbot/bot.rb', line 120 def modify_admin(screen_name, action = :add) init_clients user = $bot[:client].user screen_name case action when :add $bot[:config][:admins] << user.id unless $bot[:config][:admins].include? user.id when :del, :delete $bot[:config][:admins].delete user.id if $bot[:config][:admins].include? user.id else say "Unknown action " + action.to_s, :red end rescue Twitter::Error::NotFound say "User not found.", :red end |
#save_config ⇒ Object
Saves the bot’s config (i.e. not the botpart ones).
145 146 147 148 149 150 151 |
# File 'lib/twittbot/bot.rb', line 145 def save_config config = $bot[:config].clone config.delete :client File.open "./#{Twittbot::CONFIG_FILE_NAME}", 'w' do |f| f.write config.to_yaml end end |
#start ⇒ Object
Starts the bot.
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 |
# File 'lib/twittbot/bot.rb', line 69 def start check_config init_clients @userstream_thread ||= Thread.new do loop do begin puts "connected to user stream" @streamer.user do |obj| handle_stream_object obj, :user end rescue => e puts "lost user stream connection: " + e. end puts "reconnecting in #{Twittbot::RECONNECT_WAIT_TIME} seconds..." sleep Twittbot::RECONNECT_WAIT_TIME end end @tweetstream_thread ||= Thread.new do loop do begin puts "connected to tweet stream" @streamer.filter track: $bot[:config][:track].join(",") do |obj| handle_stream_object obj, :filter end rescue puts "lost tweet stream connection: " + e. end puts "reconnecting in #{Twittbot::RECONNECT_WAIT_TIME} seconds..." sleep Twittbot::RECONNECT_WAIT_TIME end end @periodic_thread ||= Thread.new do loop do begin do_periodic rescue => _ end sleep 60 end end @userstream_thread.join @tweetstream_thread.join @periodic_thread.join end |