Class: Jabbot::Bot

Inherits:
Object
  • Object
show all
Includes:
Handlers
Defined in:
lib/jabbot/bot.rb

Overview

The main Bot class.

It handles the connection as well as the method dispatching.

Defined Under Namespace

Classes: Message

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Handlers

#add_handler, #dispatch, #handlers, #handlers=

Constructor Details

#initialize(options = nil) ⇒ Bot

Public: Initialize a Bot instance.

options - A Jabbot::Config options instance (default: nil).



36
37
38
39
40
41
42
43
44
45
# File 'lib/jabbot/bot.rb', line 36

def initialize(options=nil)
  @conf = nil
  @config = options || Jabbot::Config.default << Jabbot::FileConfig.new
  @log = nil
  @abort = false
  @users = []

rescue Exception => krash
  raise SystemExit.new(krash.message)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object

Internal: Maps configuration settings to real methods.

Returns the value of the configuration setting

or nil if none is found.


276
277
278
279
280
281
# File 'lib/jabbot/bot.rb', line 276

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

#clientObject (readonly)

Returns the value of attribute client.



13
14
15
# File 'lib/jabbot/bot.rb', line 13

def client
  @client
end

#usersObject (readonly)

Returns the value of attribute users.



14
15
16
# File 'lib/jabbot/bot.rb', line 14

def users
  @users
end

Instance Method Details

#closeObject Also known as: quit

Public: Close the server connection.

Returns nothing.



150
151
152
153
154
155
# File 'lib/jabbot/bot.rb', line 150

def close
  if connected?
    @connected = false
    client.close
  end
end

#configObject

Public: Get the current configuration settings.

Returns the configuration Hash.



286
287
288
289
# File 'lib/jabbot/bot.rb', line 286

def config
  return @conf if @conf
  @conf = @config.to_hash
end

#configure {|@config| ... } ⇒ Object

Public: Set configure options for the bot.

Returns the configure Hash.

Yields:



267
268
269
270
# File 'lib/jabbot/bot.rb', line 267

def configure
  yield @config
  @conf = @config.to_hash
end

#connectObject

Internal: Connect to Jabber and join channel.

It will exit the process and log any exception on ‘$stderr` on failure.

Returns nothing.



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
# File 'lib/jabbot/bot.rb', line 66

def connect
  @jid = Jabber::JID.new()
  @mucjid = Jabber::JID.new("#{channel}@#{server}")

  if @jid.node.nil?
    raise "Your Jabber ID must contain a user name and therefore contain one @ character."
  elsif @jid.resource
    raise "If you intend to set a custom resource, put that in the right text field. Remove the slash!"
  elsif @mucjid.node.nil?
    raise "Please set a room name, e.g. [email protected]"
  elsif @mucjid.resource
    raise "The MUC room must not contain a resource. Remove the slash!"
  else
    @jid.resource = config[:resource] || "jabbot"
    @mucjid.resource = config[:nick] || "jabbot"
    @users << config[:nick]
  end

  @client = Jabber::Client.new(@jid)
  @client.on_exception do |*args|
    $stderr.puts "got an intern EXCEPTION, args where:"
    $stderr.puts args.inspect
    $stderr.puts "exiting..."

    EventMachine.stop_event_loop
    exit
  end
  begin
    @client.connect
    @client.auth(password)
    @muc = Jabber::MUC::SimpleMUCClient.new(@client)
    muc_handlers.call(@muc)
    @muc.join(@mucjid)
    @connected = true
  rescue => errmsg
    @connected = false
    $stderr.write "#{errmsg.class}\n#{errmsg}, #{errmsg.backtrace.join("\n")}"
    exit 1
  end
end

#connected?Boolean

Internal: Get information if the bot is still connected.

Returns the connection state as a Boolean.

Returns:

  • (Boolean)


143
144
145
# File 'lib/jabbot/bot.rb', line 143

def connected?
  @connected
end

#debug!Object

Internal: Enable debugging mode.

All xmpp4r-internal calls to Jabber::Debuglog are printed to $stderr by default. You may change the logger by using

Jabber::Logger = Logger.new()

Returns nothing.



56
57
58
# File 'lib/jabbot/bot.rb', line 56

def debug!
  Jabber::debug = true
end

#dispatch_messages(type, messages) ⇒ Object

Dispatch a collection of messages.

type - The Symbol type to be processed. messages - An Array of String messages to be dispatched.

Returns the Integer count of messages dispatched.



248
249
250
251
# File 'lib/jabbot/bot.rb', line 248

def dispatch_messages(type, messages)
  messages.each { |message| dispatch(type, message) }
  messages.length
end

#logObject

Internal: Instanciates a logger.

Returns logger instance.



256
257
258
259
260
261
262
# File 'lib/jabbot/bot.rb', line 256

def log
  return @log if @log
  os = config[:log_file] ? File.open(config[:log_file], "a") : $stdout
  @log = Logger.new(os)
  @log.level = Logger.const_get(config[:log_level] ? config[:log_level].upcase : "INFO")
  @log
end

#muc_handlersObject

Internal: Assigns handlers for different xmpp messages.

The handled messages are:

* public messages
* private messages
* joins
* leaves
* subject changes

Returs nothing.



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# File 'lib/jabbot/bot.rb', line 179

def muc_handlers
  Proc.new do |muc|
    muc.on_message do |time, nick, text|
      if time.nil?
        begin
          dispatch_messages(:message, [Message.new(nick, text, Time.now, :public)]) unless nick == config[:nick]
        rescue Exception => boom
          log.fatal boom.inspect
          log.fatal boom.backtrace[0..5].join("\n")
        end
      end
    end

    muc.on_private_message do |time, nick, text|
      if time.nil?
        begin
          dispatch_messages(:private, [Message.new(nick, text, Time.now, :query)]) unless nick == config[:nick]
        rescue Exception => boom
          log.fatal boom.inspect
          log.fatal boom.backtrace[0..5].join("\n")
        end
      end
    end

    muc.on_join do |time, nick|
      unless @users.include? nick
        @users << nick
      end
      if time.nil?
        begin
          dispatch_messages(:join, [Message.new(nick, "join", Time.now, :join)]) unless nick == config[:nick]
        rescue Exception => boom
          log.fatal boom.inspect
          log.fatal boom.backtrace[0..5].join("\n")
        end
      end
    end

    muc.on_leave do |time, nick|
      @users.delete(nick)
      if time.nil?
        begin
          dispatch_messages(:leave, [Message.new(nick, "leave", Time.now, :leave)])
        rescue Exception => boom
          log.fatal boom.inspect
          log.fatal boom.backtrace[0..5].join("\n")
        end
      end
    end

    muc.on_subject do |time, nick, subject|
      if time.nil?
        begin
          dispatch_messages(:subject, [Message.new(nick, subject, Time.now, :subject)])
        rescue Exception => boom
          log.fatal boom.inspect
          log.fatal boom.backtrace[0..5].join("\n")
        end
      end
    end
  end
end

#run!Object

Public: Starts the jabber bot.

Internally it starts the jabber connection inside of ‘EventMachine.run`, so you are free to use all EventMachine tasks out there for asynchronously working on input data.

Returns nothing.



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
# File 'lib/jabbot/bot.rb', line 114

def run!
  puts "Jabbot #{Jabbot::VERSION} imposing as #{} on #{channel}@#{server}"

  onclose_block = proc {
    close
    puts "\nAnd it's a wrap. See ya soon!"
    exit
  }

  Kernel.trap(:INT, onclose_block)
  Kernel.trap(:QUIT, onclose_block)

  debug! if config[:debug]

  # connect the bot and keep it running
  EventMachine.run do
    connect

    stop_timer = EventMachine.add_periodic_timer(1) do
      if !connected?
        EventMachine.stop_event_loop
      end
    end
  end
end

#send_message(msg, to = nil) ⇒ Object

Public: Send a message to a given user or publicly.

msg - A String message. to - A String username to send to (default: nil).

Returns nothing.



164
165
166
# File 'lib/jabbot/bot.rb', line 164

def send_message(msg, to=nil)
  @muc.say(msg.to_s, to) if connected?
end