Class: Ril::RilBot

Inherits:
Object
  • Object
show all
Defined in:
lib/ril.rb

Overview

The RilBot object creates a connection to an IRC server, and then sits in a processing loop, calling the appropriate functions.

The idea behind RilBot, is to create your own bot object that inherits RilBot, and then override the on_* methods, with your own.

Instance Method Summary collapse

Constructor Details

#initialize(server_args, &block) ⇒ RilBot

initializes an instance of RilBot.

* server_args is a hash variable containing appropriate settings.

  == IRC related settings ==
:hostname => server to connect to [required]
:port     => port number to connect to [defaults to 6667]
:nickname => nickname to use [required]
:username => username to use, [defaults to nickname if not set]
:realname => realname to use, [defaults to nickname if not set]
:password => PASS to send to server

  == RilBot related settings ==
:verbose  => true or false, if true prints the IRC messages out.
:throttle => throttle time for sending messages [defaults to 2 seconds.]
  • If a block is given it is executed when the IRC server sends either a

  • 422 (ERR_NOMOTD), or 376 (RPL_ENDOFMOTD). it will be called with one

  • parameter, which is just a reference to self.

Raises:

  • (ArgumentError)


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
# File 'lib/ril.rb', line 58

def initialize(server_args, &block)
  # verbose flag
  @verbose = server_args[:verbose]
  @verbose = false if @verbose.nil?

  # identified flag
  @identified = false

  # keep the run loop running
  @run_loop = true

  # output buffer
  @output_buffer = []

  # throttle time
  @throttle = server_args[:throttle]
  @throttle = 2 if @throttle.nil?

  # last time a message was sent
  @last_send = Time.now.to_i

  # server to connect to.
  @hostname = server_args[:hostname]
  raise ArgumentError, "No hostname defined." if @hostname.nil?

  # need a nickname to use
  @nickname = server_args[:nickname]
  raise ArgumentError, "No nickname defined." if @nickname.nil?

  # port, defaults to 6667 (obviously)
  @port = server_args[:port]
  @port = 6667 if @port.nil?

  # username
  @username = server_args[:username]
  @username = @nickname if @username.nil?

  # realname
  @realname = server_args[:realname]
  @realname = @nickname if @realname.nil?

  # IRC password
  @irc_password = server_args[:password]

  # initialize method keeper
  @method_keeper = Hash.new

  vputs "connecting to irc://#{@hostname}:#{@port}"

  # bind block
  if block_given?
    @method_keeper['first_run'] = block
  end

  # bind the default methods...
  bind_ping(method(:on_ping))
  bind_notice_auth(method(:on_notice_auth))

  begin
    # try to connect.
    @socket = TCPSocket.new(@hostname, @port)
    @socket_mutex = Mutex.new
  rescue
    vputs "Failed to connect to irc://#{@hostname}:#{@port}"
    raise
  end
end

Instance Method Details

#away(message = nil) ⇒ Object

set an away message to message

if message is nil, it will remove your away message.



275
276
277
278
# File 'lib/ril.rb', line 275

def away(message = nil)
  send_raw("AWAY :#{message}") unless message.nil?
  send_raw("AWAY") if message.nil?
end

#bind_notice_auth(callback_obj = nil, &block) ⇒ Object

binds to “NOTICE AUTH” Will either call the method pointed to by callback_obj, or execute the given block, this function should have one parameter, and it will contain the text given to you from the server. msg



130
131
132
133
134
135
136
137
138
# File 'lib/ril.rb', line 130

def bind_notice_auth(callback_obj = nil, &block)
  if block_given?
    @method_keeper['notice_auth'] = block
  elsif callback_obj.nil? == false
    @method_keeper['notice_auth'] = callback_obj
  else
    raise ArgumentError
  end
end

#bind_ping(callback_obj = nil, &block) ⇒ Object

binds to PING message will call the binded function with the servers hostname.



142
143
144
145
146
147
148
149
150
# File 'lib/ril.rb', line 142

def bind_ping(callback_obj = nil, &block)
  if block_given?
    @method_keeper['ping'] = block
  elsif callback_obj.nil? == false
    @method_keeper['ping'] = callback_obj
  else
    raise ArgumentError
  end
end

#identified?Boolean

returns whether or not you are identified to the server

Returns:

  • (Boolean)


183
184
185
# File 'lib/ril.rb', line 183

def identified?
  @identified
end

#invite(channel, nick) ⇒ Object

invite nick to channel



268
269
270
# File 'lib/ril.rb', line 268

def invite(channel, nick)
  send_raw("INVITE #{channel} #{nick}")
end

#join(channel, key = nil) ⇒ Object

joins channel with key

if channel is an array it will join each channel in that array. key can also be an array of keys.



235
236
237
238
239
240
241
# File 'lib/ril.rb', line 235

def join(channel, key = nil)
  channels = (channel.is_a? Array) ? channel.join(",") : channel
  keys = (key.is_a? Array) ? key.join(",") : key
  keys = "" if keys.nil?

  send_raw("JOIN #{channels} #{keys}")
end

#mode(target, mode, mode_opts = nil) ⇒ Object

adjusts mode to mode on target, with mode_opts

if mode_opts is an array it will be converted to a space delimited string.



251
252
253
254
255
256
# File 'lib/ril.rb', line 251

def mode(target, mode, mode_opts = nil)
  mode_opts = "" if mode_opts.nil?
  mode_opts = (mode_opts.is_a? Array) ? mode_opts.join(" ") : mode_opts

  send_raw("MODE #{target} #{mode} #{mode_opts}")
end

#my_nickObject

returns the nickname you are currently using.



188
189
190
# File 'lib/ril.rb', line 188

def my_nick
  @nickname
end

#notice(target, message, safety = true) ⇒ Object

sends message to target via notice, if safety is true check to see if target is my_nick, if so don’t send…



225
226
227
228
229
# File 'lib/ril.rb', line 225

def notice(target, message, safety = true)
  return if target == my_nick and safety == true

  send_raw("NOTICE #{target} :#{message}")
end

#on_notice_auth(msg) ⇒ Object

handles a NOTICE AUTH response, if you override this method be sure to send NICK, USER, PASS, and the .identified? method will become completely useless… msg is just what was sent as the message.



299
300
301
302
303
304
305
306
# File 'lib/ril.rb', line 299

def on_notice_auth(msg)
  unless @identified
    send_raw("NICK #{@nickname}\r\nUSER #{@username} 0 0 :#{@realname}")
    send_raw("PASS #{@irc_password}") if @irc_password.nil? == false

    @identified = true
  end
end

#on_ping(hostname) ⇒ Object

handles a PING response, if you override this function be sure to send a PONG back.



291
292
293
# File 'lib/ril.rb', line 291

def on_ping(hostname)
  send_raw("PONG :#{hostname}")
end

#part(channel, part_msg = nil) ⇒ Object

parts channel, leaving them with part_msg



244
245
246
# File 'lib/ril.rb', line 244

def part(channel, part_msg = nil)
  send_raw("PART #{channel} :#{part_msg}")
end

#privmsg(target, message, safety = true) ⇒ Object

send message to target, if safety is true check to see if target is my_nick, if so don’t send..



217
218
219
220
221
# File 'lib/ril.rb', line 217

def privmsg(target, message, safety = true)
  return if target == my_nick and safety == true

  send_raw("PRIVMSG #{target} :#{message}")
end

#quit(message = nil) ⇒ Object

quits the server with message

if message is nil, then it just quits reporting version info.



283
284
285
286
287
# File 'lib/ril.rb', line 283

def quit(message = nil)
  message = version if message.nil?

  send_raw("QUIT :#{message}")
end

#runObject

runs the bot in a main loop, sitting on the socket waiting for stuff to happen, then calling the appropriate bound function.



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/ril.rb', line 154

def run
  @output_thread = Thread.new { process_output_buffer }

  while @run_loop
    poll = select([@socket], nil, nil, 0)

    if poll
      irc_msg = ""

      @socket_mutex.synchronize do
        irc_msg = @socket.gets
      end

      if parse(irc_msg)
        @run_loop = false
      end
    end
  end

  @output_thread.terminate
  @socket.close
end

#send_raw(msg) ⇒ Object

sends msg as a raw IRC message, eg: PRIVMSG #ruby :hello



204
205
206
207
208
209
210
211
212
213
# File 'lib/ril.rb', line 204

def send_raw(msg)
  vputs ">>> #{msg}"

  if msg.length > 512
    vputs "*** WARNING: +msg+ is over 512 bytes cutting..."
    msg = msg[0..511]
  end

  @output_buffer << msg
end

#stopObject

call this when you want to kill the bot.



178
179
180
# File 'lib/ril.rb', line 178

def stop
  @run_loop = false
end

#topic(channel, new_topic = nil) ⇒ Object

changes topic on channel to new_topic

if new_topic is nil, it will unset the topic.



261
262
263
264
265
# File 'lib/ril.rb', line 261

def topic(channel, new_topic = nil)
  new_topic = "" if new_topic.nil?

  send_raw("TOPIC #{channel} :#{new_topic}")
end

#userinfo_to_a(userinfo) ⇒ Object

little utility function to convert a userinfo hash to an array useful so you can do:

nickname, username, hostname = userinfo_to_a(userinfo)


195
196
197
# File 'lib/ril.rb', line 195

def userinfo_to_a(userinfo)
  [ userinfo[:nickname], userinfo[:username], userinfo[:hostname] ]
end

#versionObject



308
309
310
# File 'lib/ril.rb', line 308

def version
  Ril::Ril_VERSION
end