ril 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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