ril 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. data/examples/opbot.rb +186 -0
  2. data/lib/ril.rb +67 -17
  3. metadata +2 -2
  4. data/examples/vbot.rb +0 -43
@@ -0,0 +1,186 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ # opbot.rb - simple operator bot!
4
+ # simple bot that connects to <server> with <nick>, joins <channel>, and
5
+ # handles the one command !version
6
+
7
+ require 'ril'
8
+ include Ril
9
+
10
+ # c:VersionBot
11
+ class VersionBot < RilBot
12
+ # override the initialize function.. not really.. just want to pre-define
13
+ # a few of our own variables...
14
+ def initialize(server_args, &block)
15
+ super(server_args, &block)
16
+
17
+ @banning_user = nil
18
+ @unbanning_user = nil
19
+ @motd = ""
20
+ end # initialize
21
+
22
+ # handle a PRIVMSG message.
23
+ def on_privmsg(userinfo, target, message)
24
+ msg = message.split(' ')
25
+ command = msg.shift
26
+
27
+ data = msg.join(' ')
28
+
29
+ case command
30
+ when '!version'
31
+ privmsg(target, version)
32
+ when '!say'
33
+ privmsg(target, data)
34
+ when '!action'
35
+ data = "\001ACTION #{data}\001"
36
+ privmsg(target, data)
37
+ else
38
+ if $privy.index(userinfo[:nickname]) != nil
39
+ return privy_command(userinfo, target, command, data)
40
+ end
41
+ end
42
+
43
+ false
44
+ end # on_privmsg
45
+
46
+ # handle the invite command
47
+ def on_invite(userinfo, target, message)
48
+ if $privy.index(userinfo[:nickname]) != nil
49
+ join(message)
50
+ end
51
+
52
+ false
53
+ end # on_invite
54
+
55
+ # handles a privileged users command
56
+ def privy_command(userinfo, target, command, data)
57
+ if target[0..0] != '#'
58
+ return false
59
+ end
60
+
61
+ if data.length == 0
62
+ nickname = userinfo[:nickname]
63
+ else
64
+ nickname = data
65
+ end
66
+
67
+ case command
68
+ when '!quit'
69
+ quit(data)
70
+ return true # kill the bot processor
71
+ when '!op'
72
+ mode(target, '+ooo', nickname)
73
+ when '!deop'
74
+ mode(target, '-ooo', nickname)
75
+ when '!voice'
76
+ mode(target, '+vvv', nickname)
77
+ when '!devoice'
78
+ mode(target, '-vvv', nickname)
79
+ when '!topic'
80
+ topic(target, data)
81
+ when '!join'
82
+ join(data)
83
+ when '!part'
84
+ if data.length == 0
85
+ data = target
86
+ end
87
+
88
+ part(data)
89
+ when '!cycle'
90
+ if data.length == 0
91
+ data = target
92
+ end
93
+
94
+ part(data)
95
+ sleep 0.2
96
+ join(data)
97
+ when '!invite'
98
+ invite(target, data)
99
+ when '!print_motd'
100
+ puts @motd
101
+ when '!ban'
102
+ if data != userinfo[:nickname]
103
+ @banning_user = target
104
+ whois(data)
105
+ end
106
+ when '!unban'
107
+ if data != userinfo[:nickname]
108
+ @unbanning_user = target
109
+ whois(data)
110
+ end
111
+ end
112
+
113
+ false
114
+ end # privy_command
115
+
116
+ # whois ?
117
+ def whois(nick)
118
+ send_raw("WHOIS #{nick}")
119
+
120
+ false
121
+ end # whois
122
+
123
+ # RPL_MOTDSTART
124
+ def on_375(userinfo, target, message)
125
+ @motd = ""
126
+
127
+ false
128
+ end # on_375
129
+
130
+ # RPL_MOTD
131
+ def on_372(userinfo, target, message)
132
+ @motd += "#{message}\n"
133
+
134
+ false
135
+ end # on_372
136
+
137
+ # ERR_NOMOTD
138
+ def on_422(userinfo, target, message)
139
+ on_376(userinfo, target, message)
140
+
141
+ false
142
+ end # on_422
143
+
144
+ # RPL_WHOISUSER
145
+ def on_311(userinfo, target, message)
146
+ # target contains something like:
147
+ # <<my nick>> <<their nick>> <<their user>> <<their host>> *
148
+ ####
149
+ me, nick, user, host, ast = target.split(' ')
150
+
151
+ unless @banning_user.nil?
152
+ mode(@banning_user, "+b", "#{nick}!#{user}@#{host}")
153
+ @banning_user = nil
154
+ end
155
+
156
+ unless @unbanning_user.nil?
157
+ mode(@unbanning_user, "-b", "#{nick}!#{user}@#{host}")
158
+ end
159
+
160
+ false
161
+ end # on_311
162
+
163
+ # RPL_ENDOFMOTD
164
+ def on_376(userinfo, target, message)
165
+ join($channel)
166
+
167
+ false
168
+ end # on_376
169
+ end # /c:VersionBot
170
+
171
+ if __FILE__ == $0
172
+ if ARGV.length < 3
173
+ puts "Usage: #{$0} <irc server> <nickname> <channel> [privileged,users]"
174
+ exit 1
175
+ end
176
+
177
+ $channel = ARGV[2]
178
+
179
+ if ARGV[3] != nil
180
+ $privy = ARGV[3].split(',')
181
+ end
182
+
183
+ vbot = VersionBot.new(:hostname => ARGV[0],
184
+ :nickname => ARGV[1], :verbose => true)
185
+ vbot.run
186
+ end
data/lib/ril.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  ###
2
2
  # ril.rb - ruby irc library
3
- # $Release Version: 0.1.1 $
4
- # $Revision: 4 $
3
+ # $Release Version: 0.1.2 $
4
+ # $Revision: 9 $
5
5
  # by Joey Kinsella <jkinsella(at)rubyforge(dot)org>
6
6
  #
7
7
  # This program is free software; you can redistribute it and/or modify
@@ -22,7 +22,7 @@
22
22
  require 'socket'
23
23
 
24
24
  module Ril
25
- Ril_VERSION = "Ril - Ruby IRC Library v0.1.1 by Joey Kinsella"
25
+ Ril_VERSION = "Ril - Ruby IRC Library v0.1.2 by Joey Kinsella"
26
26
 
27
27
  ####
28
28
  # c:RilBot
@@ -49,6 +49,7 @@ class RilBot
49
49
  #
50
50
  # == RilBot related settings ==
51
51
  # :verbose => true or false, if true prints the IRC messages out.
52
+ # :throttle => throttle time for sending messages [defaults to 2 seconds.]
52
53
  #
53
54
  # * If a block is given it is executed when the IRC server sends either a
54
55
  # * 422 (ERR_NOMOTD), or 376 (RPL_ENDOFMOTD). it will be called with one
@@ -65,6 +66,16 @@ class RilBot
65
66
  # keep the run loop running
66
67
  @run_loop = true
67
68
 
69
+ # output buffer
70
+ @output_buffer = []
71
+
72
+ # throttle time
73
+ @throttle = server_args[:throttle]
74
+ @throttle = 2 if @throttle.nil?
75
+
76
+ # last time a message was sent
77
+ @last_send = Time.now.to_i
78
+
68
79
  # server to connect to.
69
80
  @hostname = server_args[:hostname]
70
81
  raise ArgumentError, "No hostname defined." if @hostname.nil?
@@ -105,6 +116,7 @@ class RilBot
105
116
  begin
106
117
  # try to connect.
107
118
  @socket = TCPSocket.new(@hostname, @port)
119
+ @socket_mutex = Mutex.new
108
120
  rescue
109
121
  vputs "Failed to connect to irc://#{@hostname}:#{@port}"
110
122
  raise
@@ -140,19 +152,31 @@ class RilBot
140
152
  # runs the bot in a main loop, sitting on the socket waiting for stuff
141
153
  # to happen, then calling the appropriate bound function.
142
154
  def run
143
- # the irc standard denotes that no message is over 512, but I'll
144
- # double that here, if for some reason you use this library on a
145
- # non RFC compliant server.
146
- while @run_loop and (irc_msg = @socket.recv(1024)) != ""
147
- parse(irc_msg)
155
+ @output_thread = Thread.new { process_output_buffer }
156
+
157
+ while @run_loop
158
+ poll = select([@socket], nil, nil, 0)
159
+
160
+ if poll
161
+ irc_msg = ""
162
+
163
+ @socket_mutex.synchronize do
164
+ irc_msg = @socket.gets
165
+ end
166
+
167
+ if parse(irc_msg)
168
+ @run_loop = false
169
+ end
170
+ end
148
171
  end
172
+
173
+ @output_thread.terminate
174
+ @socket.close
149
175
  end # run
150
176
 
151
177
  # call this when you want to kill the bot.
152
178
  def stop
153
179
  @run_loop = false
154
-
155
- @socket.close
156
180
  end
157
181
 
158
182
  # returns whether or not you are identified to the server
@@ -185,7 +209,7 @@ class RilBot
185
209
  msg = msg[0..511]
186
210
  end
187
211
 
188
- @socket.puts msg
212
+ @output_buffer << msg
189
213
  end
190
214
 
191
215
  # send +message+ to +target+, if +safety+ is true check to see if
@@ -218,7 +242,7 @@ class RilBot
218
242
 
219
243
  # parts +channel+, leaving them with +part_msg+
220
244
  def part(channel, part_msg = nil)
221
- send_raw("PART #{channel} :#{msg}")
245
+ send_raw("PART #{channel} :#{part_msg}")
222
246
  end # part
223
247
 
224
248
  # adjusts mode to +mode+ on +target+, with +mode_opts+
@@ -257,9 +281,8 @@ class RilBot
257
281
  #
258
282
  # if +message+ is nil, then it just quits reporting version info.
259
283
  def quit(message = nil)
260
- message = version() if quit.nil?
284
+ message = version if message.nil?
261
285
 
262
- stop
263
286
  send_raw("QUIT :#{message}")
264
287
  end # quit
265
288
 
@@ -282,7 +305,6 @@ class RilBot
282
305
  end
283
306
  end
284
307
 
285
- protected
286
308
  def version
287
309
  Ril::Ril_VERSION
288
310
  end
@@ -293,9 +315,32 @@ private
293
315
  puts str if @verbose
294
316
  end
295
317
 
318
+ # just checks the output buffer, if there is data, send it when you
319
+ # it is safe to do so.
320
+ def process_output_buffer
321
+ while true
322
+ if not @output_buffer.empty?
323
+ @socket_mutex.synchronize do
324
+ while @output_buffer.empty? == false
325
+ if Time.now.to_i > (@last_send + @throttle)
326
+ data = @output_buffer.pop
327
+
328
+ @socket.puts data
329
+ @last_send = Time.now.to_i
330
+ end
331
+ sleep 0.2
332
+ end
333
+ end
334
+ end
335
+
336
+ sleep 0.5 # don't chew the processor...
337
+ end
338
+ end # process_output_buffer
339
+
296
340
  # parses the irc +msg+
297
341
  def parse(msg)
298
342
  vputs "<<< #{msg}"
343
+ result = false
299
344
 
300
345
  msg.each_line do |m|
301
346
  prefix, data = m.split(' :')
@@ -322,15 +367,18 @@ private
322
367
  end
323
368
 
324
369
  # run the appropriate method...
325
- lookup_method(irc_message, prefix, data)
370
+ result = lookup_method(irc_message, prefix, data)
326
371
  end # prefix == ???
327
372
  end # msg.each
373
+
374
+ result
328
375
  end # parse
329
376
 
330
377
  # this does the actual parsing, and running of methods...
331
378
  def lookup_method(message, prefix, data)
332
379
  # prefix chunked out by a space...
333
380
  prefix_a = prefix.split(' ')
381
+ result = false
334
382
 
335
383
  if prefix_a.nil? and $DEBUG
336
384
  vputs ">>>DEBUGGING<<<"
@@ -357,8 +405,10 @@ private
357
405
 
358
406
  callback = "on_#{message}".downcase.to_sym
359
407
  if self.respond_to?(callback)
360
- method(callback).call(userinfo, target, data)
408
+ result = method(callback).call(userinfo, target, data)
361
409
  end
410
+
411
+ result
362
412
  end # lookup_method
363
413
  end # /c:RilBot
364
414
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ril
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joey Kinsella
@@ -23,7 +23,7 @@ extra_rdoc_files: []
23
23
 
24
24
  files:
25
25
  - lib/ril.rb
26
- - examples/vbot.rb
26
+ - examples/opbot.rb
27
27
  - README
28
28
  - COPYING
29
29
  has_rdoc: true
@@ -1,43 +0,0 @@
1
- #! /usr/bin/env ruby
2
- #
3
- # vbot.rb - just prints the version!
4
- # simple bot that connects to <server> with <nick>, joins <channel>, and
5
- # handles the one command !version
6
-
7
- require 'ril'
8
- include Ril
9
-
10
- # c:VersionBot
11
- class VersionBot < RilBot
12
- # hanle a PRIVMSG message.
13
- def on_privmsg(userinfo, target, message)
14
- command = message.split(' ').first
15
-
16
- if command == '!version'
17
- privmsg(target, version)
18
- end
19
- end # on_privmsg
20
-
21
- # ERR_NOMOTD
22
- def on_422(userinfo, target, message)
23
- on_376(userinfo, target, message)
24
- end # on_422
25
-
26
- # RPL_ENDOFMOTD
27
- def on_376(userinfo, target, message)
28
- join($channel)
29
- end # on_376
30
- end # /c:VersionBot
31
-
32
- if __FILE__ == $0
33
- if ARGV.length != 3
34
- puts "Usage: #{$0} <irc server> <nickname> <channel>"
35
- exit 1
36
- end
37
-
38
- $channel = ARGV[2]
39
-
40
- vbot = VersionBot.new(:hostname => ARGV[0],
41
- :nickname => ARGV[1], :verbose => true)
42
- vbot.run
43
- end