rbot 0.9.9 → 0.9.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/AUTHORS +8 -0
  2. data/ChangeLog +51 -0
  3. data/INSTALL +4 -0
  4. data/README +1 -0
  5. data/REQUIREMENTS +11 -0
  6. data/TODO +2 -0
  7. data/bin/rbot +21 -2
  8. data/data/rbot/languages/german.lang +4 -1
  9. data/data/rbot/languages/russian.lang +75 -0
  10. data/data/rbot/plugins/autoop.rb +42 -51
  11. data/data/rbot/plugins/bans.rb +205 -0
  12. data/data/rbot/plugins/bash.rb +56 -0
  13. data/data/rbot/plugins/chucknorris.rb +74 -0
  14. data/data/rbot/plugins/chucknorris.yml.gz +0 -0
  15. data/data/rbot/plugins/deepthoughts.rb +95 -0
  16. data/data/rbot/plugins/demauro.rb +95 -0
  17. data/data/rbot/plugins/digg.rb +51 -0
  18. data/data/rbot/plugins/figlet.rb +24 -0
  19. data/data/rbot/plugins/forecast.rb +133 -0
  20. data/data/rbot/plugins/freshmeat.rb +13 -7
  21. data/data/rbot/plugins/google.rb +2 -0
  22. data/data/rbot/plugins/grouphug.rb +36 -0
  23. data/data/rbot/plugins/imdb.rb +92 -0
  24. data/data/rbot/plugins/insult.rb +8 -1
  25. data/data/rbot/plugins/iplookup.rb +227 -0
  26. data/data/rbot/plugins/karma.rb +2 -2
  27. data/data/rbot/plugins/keywords.rb +470 -0
  28. data/data/rbot/plugins/lart.rb +132 -146
  29. data/data/rbot/plugins/lastfm.rb +25 -0
  30. data/data/rbot/plugins/markov.rb +204 -0
  31. data/data/rbot/plugins/math.rb +5 -1
  32. data/data/rbot/plugins/nickserv.rb +71 -11
  33. data/data/rbot/plugins/opme.rb +19 -19
  34. data/data/rbot/plugins/quakeauth.rb +2 -2
  35. data/data/rbot/plugins/quotes.rb +40 -25
  36. data/data/rbot/plugins/remind.rb +1 -1
  37. data/data/rbot/plugins/rot13.rb +2 -2
  38. data/data/rbot/plugins/roulette.rb +49 -15
  39. data/data/rbot/plugins/rss.rb +585 -0
  40. data/data/rbot/plugins/rubyurl.rb +39 -0
  41. data/data/rbot/plugins/seen.rb +2 -1
  42. data/data/rbot/plugins/slashdot.rb +5 -5
  43. data/data/rbot/plugins/spell.rb +5 -0
  44. data/data/rbot/plugins/theyfightcrime.rb +121 -0
  45. data/data/rbot/plugins/threat.rb +55 -0
  46. data/data/rbot/plugins/tinyurl.rb +39 -0
  47. data/data/rbot/plugins/topic.rb +204 -0
  48. data/data/rbot/plugins/urban.rb +71 -0
  49. data/data/rbot/plugins/url.rb +399 -4
  50. data/data/rbot/plugins/wow.rb +123 -0
  51. data/data/rbot/plugins/wserver.rb +1 -1
  52. data/data/rbot/templates/levels.rbot +2 -0
  53. data/lib/rbot/auth.rb +207 -96
  54. data/lib/rbot/channel.rb +5 -5
  55. data/lib/rbot/config.rb +125 -24
  56. data/lib/rbot/dbhash.rb +87 -21
  57. data/lib/rbot/httputil.rb +181 -13
  58. data/lib/rbot/ircbot.rb +525 -179
  59. data/lib/rbot/ircsocket.rb +330 -54
  60. data/lib/rbot/message.rb +66 -23
  61. data/lib/rbot/messagemapper.rb +25 -17
  62. data/lib/rbot/plugins.rb +244 -115
  63. data/lib/rbot/post-clean.rb +1 -0
  64. data/lib/rbot/{post-install.rb → post-config.rb} +1 -1
  65. data/lib/rbot/rbotconfig.rb +29 -14
  66. data/lib/rbot/registry.rb +111 -72
  67. data/lib/rbot/rfc2812.rb +208 -197
  68. data/lib/rbot/timer.rb +4 -0
  69. data/lib/rbot/utils.rb +2 -2
  70. metadata +127 -104
  71. data/data/rbot/plugins/rss.rb.disabled +0 -414
  72. data/lib/rbot/keywords.rb +0 -433
@@ -0,0 +1 @@
1
+ File.unlink("pkgconfig.rb") if FileTest.exist?("pkgconfig.rb")
@@ -1,5 +1,5 @@
1
1
  # write out our datadir so we can reference it at runtime
2
- File.open("#{config('rbdir')}/rbot/pkgconfig.rb", "w") {|f|
2
+ File.open("pkgconfig.rb", "w") {|f|
3
3
  f.puts "module Irc"
4
4
  f.puts " module PKGConfig"
5
5
  f.puts " DATADIR = '#{config('datadir')}/rbot'"
@@ -1,22 +1,37 @@
1
1
  module Irc
2
2
  module Config
3
3
  @@datadir = nil
4
+
5
+ # first try for the default path to the data dir
6
+ defaultdir = File.expand_path(File.dirname($0) + '/../data')
7
+
8
+ if File.directory? "#{defaultdir}/rbot"
9
+ @@datadir = "#{defaultdir}/rbot"
10
+ end
11
+
4
12
  # setup pkg-based configuration - i.e. where were we installed to, where
5
13
  # are our data files, etc.
6
- begin
7
- debug "trying to load rubygems"
8
- require 'rubygems'
9
- debug "loaded rubygems, looking for rbot-#$version"
10
- gemname, gem = Gem.source_index.find{|name, spec| spec.name == 'rbot' && spec.version.version == $version}
11
- debug "got gem #{gem}"
12
- if gem && path = gem.full_gem_path
13
- debug "installed via rubygems to #{path}"
14
- @@datadir = "#{path}/data/rbot"
15
- else
16
- debug "not installed via rubygems"
14
+ if @@datadir.nil?
15
+ begin
16
+ debug "trying to load rubygems"
17
+ require 'rubygems'
18
+ debug "loaded rubygems, looking for rbot-#$version"
19
+ if $version =~ /(.*)-svn\Z/
20
+ version = $1
21
+ else
22
+ version = $version
23
+ end
24
+ gemname, gem = Gem.source_index.find{|name, spec| spec.name == 'rbot' && spec.version.version == version}
25
+ debug "got gem #{gem}"
26
+ if gem && path = gem.full_gem_path
27
+ debug "installed via rubygems to #{path}"
28
+ @@datadir = "#{path}/data/rbot"
29
+ else
30
+ debug "not installed via rubygems"
31
+ end
32
+ rescue LoadError,NameError,NoMethodError
33
+ debug "no rubygems installed"
17
34
  end
18
- rescue LoadError
19
- debug "no rubygems installed"
20
35
  end
21
36
 
22
37
  if @@datadir.nil?
@@ -24,7 +39,7 @@ module Irc
24
39
  require 'rbot/pkgconfig'
25
40
  @@datadir = PKGConfig::DATADIR
26
41
  rescue LoadError
27
- puts "fatal - no way to determine data dir"
42
+ error "fatal - no way to determine data dir"
28
43
  exit 2
29
44
  end
30
45
  end
data/lib/rbot/registry.rb CHANGED
@@ -2,19 +2,13 @@ require 'rbot/dbhash'
2
2
 
3
3
  module Irc
4
4
 
5
- # this is the backend of the RegistryAccessor class, which ties it to a
6
- # DBHash object called plugin_registry(.db). All methods are delegated to
7
- # the DBHash.
5
+ # this class is now used purely for upgrading from prior versions of rbot
6
+ # the new registry is split into multiple DBHash objects, one per plugin
8
7
  class BotRegistry
9
8
  def initialize(bot)
10
9
  @bot = bot
11
10
  upgrade_data
12
- @db = DBTree.new @bot, "plugin_registry"
13
- end
14
-
15
- # delegation hack
16
- def method_missing(method, *args, &block)
17
- @db.send(method, *args, &block)
11
+ upgrade_data2
18
12
  end
19
13
 
20
14
  # check for older versions of rbot with data formats that require updating
@@ -22,24 +16,64 @@ module Irc
22
16
  # work with is @bot.botclass.
23
17
  def upgrade_data
24
18
  if File.exist?("#{@bot.botclass}/registry.db")
25
- puts "upgrading old-style (rbot 0.9.5 or earlier) plugin registry to new format"
26
- old = BDB::Hash.open "#{@bot.botclass}/registry.db", nil,
27
- "r+", 0600, "set_pagesize" => 1024,
28
- "set_cachesize" => [0, 32 * 1024, 0]
29
- new = BDB::CIBtree.open "#{@bot.botclass}/plugin_registry.db", nil,
30
- BDB::CREATE | BDB::EXCL | BDB::TRUNCATE,
31
- 0600, "set_pagesize" => 1024,
32
- "set_cachesize" => [0, 32 * 1024, 0]
19
+ log "upgrading old-style (rbot 0.9.5 or earlier) plugin registry to new format"
20
+ old = BDB::Hash.open("#{@bot.botclass}/registry.db", nil,
21
+ "r+", 0600)
22
+ new = BDB::CIBtree.open("#{@bot.botclass}/plugin_registry.db", nil,
23
+ BDB::CREATE | BDB::EXCL,
24
+ 0600)
33
25
  old.each {|k,v|
34
26
  new[k] = v
35
27
  }
36
28
  old.close
37
29
  new.close
38
- File.delete("#{@bot.botclass}/registry.db")
30
+ File.rename("#{@bot.botclass}/registry.db", "#{@bot.botclass}/registry.db.old")
31
+ end
32
+ end
33
+
34
+ def upgrade_data2
35
+ if File.exist?("#{@bot.botclass}/plugin_registry.db")
36
+ Dir.mkdir("#{@bot.botclass}/registry") unless File.exist?("#{@bot.botclass}/registry")
37
+ env = BDB::Env.open("#{@bot.botclass}", BDB::INIT_TRANSACTION | BDB::CREATE | BDB::RECOVER )
38
+ dbs = Hash.new
39
+ log "upgrading previous (rbot 0.9.9 or earlier) plugin registry to new split format"
40
+ old = BDB::CIBtree.open("#{@bot.botclass}/plugin_registry.db", nil,
41
+ "r+", 0600, "env" => env)
42
+ old.each {|k,v|
43
+ prefix,key = k.split("/", 2)
44
+ prefix.downcase!
45
+ # subregistries were split with a +, now they are in separate folders
46
+ if prefix.gsub!(/\+/, "/")
47
+ # Ok, this code needs to be put in the db opening routines
48
+ dirs = File.dirname("#{@bot.botclass}/registry/#{prefix}.db").split("/")
49
+ dirs.length.times { |i|
50
+ dir = dirs[0,i+1].join("/")+"/"
51
+ unless File.exist?(dir)
52
+ log "creating subregistry directory #{dir}"
53
+ Dir.mkdir(dir)
54
+ end
55
+ }
56
+ end
57
+ unless dbs.has_key?(prefix)
58
+ log "creating db #{@bot.botclass}/registry/#{prefix}.db"
59
+ dbs[prefix] = BDB::CIBtree.open("#{@bot.botclass}/registry/#{prefix}.db",
60
+ nil, BDB::CREATE | BDB::EXCL,
61
+ 0600, "env" => env)
62
+ end
63
+ dbs[prefix][key] = v
64
+ }
65
+ old.close
66
+ File.rename("#{@bot.botclass}/plugin_registry.db", "#{@bot.botclass}/plugin_registry.db.old")
67
+ dbs.each {|k,v|
68
+ log "closing db #{k}"
69
+ v.close
70
+ }
71
+ env.close
39
72
  end
40
73
  end
41
74
  end
42
75
 
76
+
43
77
  # This class provides persistent storage for plugins via a hash interface.
44
78
  # The default mode is an object store, so you can store ruby objects and
45
79
  # reference them with hash keys. This is because the default store/restore
@@ -54,7 +88,7 @@ module Irc
54
88
  # blah = @registry[:blah]
55
89
  # The registry can of course be used to store simple strings, fixnums, etc as
56
90
  # well, and should be useful to store or cache plugin data or dynamic plugin
57
- # configuration.
91
+ # configuration.
58
92
  #
59
93
  # WARNING:
60
94
  # in object store mode, don't make the mistake of treating it like a live
@@ -86,19 +120,29 @@ module Irc
86
120
  class BotRegistryAccessor
87
121
  # plugins don't call this - a BotRegistryAccessor is created for them and
88
122
  # is accessible via @registry.
89
- def initialize(bot, prefix)
123
+ def initialize(bot, name)
90
124
  @bot = bot
91
- @registry = @bot.registry
92
- @orig_prefix = prefix
93
- @prefix = prefix + "/"
125
+ @name = name.downcase
126
+ dirs = File.dirname("#{@bot.botclass}/registry/#{@name}").split("/")
127
+ dirs.length.times { |i|
128
+ dir = dirs[0,i+1].join("/")+"/"
129
+ unless File.exist?(dir)
130
+ debug "creating subregistry directory #{dir}"
131
+ Dir.mkdir(dir)
132
+ end
133
+ }
134
+ @registry = DBTree.new bot, "registry/#{@name}"
94
135
  @default = nil
95
- # debug "initializing registry accessor with prefix #{@prefix}"
136
+ # debug "initializing registry accessor with name #{@name}"
96
137
  end
97
138
 
98
- # use this to chop up your namespace into bits, so you can keep and
99
- # reference separate object stores under the same registry
100
- def sub_registry(prefix)
101
- return BotRegistryAccessor.new(@bot, @orig_prefix + "+" + prefix)
139
+ def flush
140
+ @registry.flush
141
+ @registry.sync
142
+ end
143
+
144
+ def close
145
+ @registry.close
102
146
  end
103
147
 
104
148
  # convert value to string form for storing in the registry
@@ -120,13 +164,28 @@ module Irc
120
164
  # val
121
165
  # end
122
166
  def restore(val)
123
- Marshal.restore(val)
167
+ begin
168
+ Marshal.restore(val)
169
+ rescue Exception => e
170
+ warning "failed to restore marshal data for #{val.inspect}, falling back to default"
171
+ debug e.inspect
172
+ debug e.backtrace.join("\n")
173
+ if @default != nil
174
+ begin
175
+ return Marshal.restore(@default)
176
+ rescue
177
+ return nil
178
+ end
179
+ else
180
+ return nil
181
+ end
182
+ end
124
183
  end
125
184
 
126
185
  # lookup a key in the registry
127
186
  def [](key)
128
- if @registry.has_key?(@prefix + key)
129
- return restore(@registry[@prefix + key])
187
+ if @registry.has_key?(key)
188
+ return restore(@registry[key])
130
189
  elsif @default != nil
131
190
  return restore(@default)
132
191
  else
@@ -136,7 +195,7 @@ module Irc
136
195
 
137
196
  # set a key in the registry
138
197
  def []=(key,value)
139
- @registry[@prefix + key] = store(value)
198
+ @registry[key] = store(value)
140
199
  end
141
200
 
142
201
  # set the default value for registry lookups, if the key sought is not
@@ -148,42 +207,36 @@ module Irc
148
207
  # just like Hash#each
149
208
  def each(&block)
150
209
  @registry.each {|key,value|
151
- if key.gsub!(/^#{Regexp.escape(@prefix)}/, "")
152
- block.call(key, restore(value))
153
- end
210
+ block.call(key, restore(value))
154
211
  }
155
212
  end
156
-
213
+
157
214
  # just like Hash#each_key
158
215
  def each_key(&block)
159
216
  @registry.each {|key, value|
160
- if key.gsub!(/^#{Regexp.escape(@prefix)}/, "")
161
- block.call(key)
162
- end
217
+ block.call(key)
163
218
  }
164
219
  end
165
-
220
+
166
221
  # just like Hash#each_value
167
222
  def each_value(&block)
168
223
  @registry.each {|key, value|
169
- if key =~ /^#{Regexp.escape(@prefix)}/
170
- block.call(restore(value))
171
- end
224
+ block.call(restore(value))
172
225
  }
173
226
  end
174
227
 
175
228
  # just like Hash#has_key?
176
229
  def has_key?(key)
177
- return @registry.has_key?(@prefix + key)
230
+ return @registry.has_key?(key)
178
231
  end
179
232
  alias include? has_key?
180
233
  alias member? has_key?
181
234
 
182
235
  # just like Hash#has_both?
183
236
  def has_both?(key, value)
184
- return @registry.has_both?(@prefix + key, store(value))
237
+ return @registry.has_both?(key, store(value))
185
238
  end
186
-
239
+
187
240
  # just like Hash#has_value?
188
241
  def has_value?(value)
189
242
  return @registry.has_value?(store(value))
@@ -192,58 +245,44 @@ module Irc
192
245
  # just like Hash#index?
193
246
  def index(value)
194
247
  ind = @registry.index(store(value))
195
- if ind && ind.gsub!(/^#{Regexp.escape(@prefix)}/, "")
248
+ if ind
196
249
  return ind
197
250
  else
198
251
  return nil
199
252
  end
200
253
  end
201
-
254
+
202
255
  # delete a key from the registry
203
256
  def delete(key)
204
- return @registry.delete(@prefix + key)
257
+ return @registry.delete(key)
205
258
  end
206
259
 
207
260
  # returns a list of your keys
208
261
  def keys
209
- return @registry.keys.collect {|key|
210
- if key.gsub!(/^#{Regexp.escape(@prefix)}/, "")
211
- key
212
- else
213
- nil
214
- end
215
- }.compact
262
+ return @registry.keys
216
263
  end
217
264
 
218
265
  # Return an array of all associations [key, value] in your namespace
219
266
  def to_a
220
267
  ret = Array.new
221
268
  @registry.each {|key, value|
222
- if key.gsub!(/^#{Regexp.escape(@prefix)}/, "")
223
- ret << [key, restore(value)]
224
- end
269
+ ret << [key, restore(value)]
225
270
  }
226
271
  return ret
227
272
  end
228
-
273
+
229
274
  # Return an hash of all associations {key => value} in your namespace
230
275
  def to_hash
231
276
  ret = Hash.new
232
277
  @registry.each {|key, value|
233
- if key.gsub!(/^#{Regexp.escape(@prefix)}/, "")
234
- ret[key] = restore(value)
235
- end
278
+ ret[key] = restore(value)
236
279
  }
237
280
  return ret
238
281
  end
239
282
 
240
283
  # empties the registry (restricted to your namespace)
241
284
  def clear
242
- @registry.each_key {|key|
243
- if key =~ /^#{Regexp.escape(@prefix)}/
244
- @registry.delete(key)
245
- end
246
- }
285
+ @registry.clear
247
286
  end
248
287
  alias truncate clear
249
288
 
@@ -256,16 +295,16 @@ module Irc
256
295
  return ret
257
296
  end
258
297
 
298
+ def sub_registry(prefix)
299
+ return BotRegistryAccessor.new(@bot, @name + "/" + prefix)
300
+ end
301
+
259
302
  # returns the number of keys in your registry namespace
260
303
  def length
261
304
  self.keys.length
262
305
  end
263
306
  alias size length
264
307
 
265
- def flush
266
- @registry.flush
267
- end
268
-
269
308
  end
270
309
 
271
310
  end
data/lib/rbot/rfc2812.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Irc
2
2
  # RFC 2812 Internet Relay Chat: Client Protocol
3
- #
3
+ #
4
4
  RPL_WELCOME=001
5
5
  # "Welcome to the Internet Relay Network
6
6
  # <nick>!<user>@<host>"
@@ -11,53 +11,53 @@ module Irc
11
11
  RPL_MYINFO=004
12
12
  # "<servername> <version> <available user modes>
13
13
  # <available channel modes>"
14
- #
14
+ #
15
15
  # - The server sends Replies 001 to 004 to a user upon
16
16
  # successful registration.
17
- #
17
+ #
18
18
  # RPL_BOUNCE=005
19
19
  # # "Try server <server name>, port <port number>"
20
20
  RPL_ISUPPORT=005
21
21
  # "005 nick PREFIX=(ov)@+ CHANTYPES=#& :are supported by this server"
22
- #
22
+ #
23
23
  # - Sent by the server to a user to suggest an alternative
24
24
  # server. This is often used when the connection is
25
25
  # refused because the server is already full.
26
- #
26
+ #
27
27
  RPL_USERHOST=302
28
28
  # ":*1<reply> *( " " <reply> )"
29
- #
29
+ #
30
30
  # - Reply format used by USERHOST to list replies to
31
31
  # the query list. The reply string is composed as
32
32
  # follows:
33
- #
33
+ #
34
34
  # reply = nickname [ "*" ] "=" ( "+" / "-" ) hostname
35
- #
35
+ #
36
36
  # The '*' indicates whether the client has registered
37
37
  # as an Operator. The '-' or '+' characters represent
38
38
  # whether the client has set an AWAY message or not
39
39
  # respectively.
40
- #
40
+ #
41
41
  RPL_ISON=303
42
42
  # ":*1<nick> *( " " <nick> )"
43
- #
43
+ #
44
44
  # - Reply format used by ISON to list replies to the
45
45
  # query list.
46
- #
46
+ #
47
47
  RPL_AWAY=301
48
48
  # "<nick> :<away message>"
49
49
  RPL_UNAWAY=305
50
50
  # ":You are no longer marked as being away"
51
51
  RPL_NOWAWAY=306
52
52
  # ":You have been marked as being away"
53
- #
53
+ #
54
54
  # - These replies are used with the AWAY command (if
55
55
  # allowed). RPL_AWAY is sent to any client sending a
56
56
  # PRIVMSG to a client which is away. RPL_AWAY is only
57
57
  # sent by the server to which the client is connected.
58
58
  # Replies RPL_UNAWAY and RPL_NOWAWAY are sent when the
59
59
  # client removes and sets an AWAY message.
60
- #
60
+ #
61
61
  RPL_WHOISUSER=311
62
62
  # "<nick> <user> <host> * :<real name>"
63
63
  RPL_WHOISSERVER=312
@@ -70,7 +70,7 @@ module Irc
70
70
  # "<nick> :End of WHOIS list"
71
71
  RPL_WHOISCHANNELS=319
72
72
  # "<nick> :*( ( "@" / "+" ) <channel> " " )"
73
- #
73
+ #
74
74
  # - Replies 311 - 313, 317 - 319 are all replies
75
75
  # generated in response to a WHOIS message. Given that
76
76
  # there are enough parameters present, the answering
@@ -85,107 +85,107 @@ module Irc
85
85
  # has been granted permission to speak on a moderated
86
86
  # channel. The RPL_ENDOFWHOIS reply is used to mark
87
87
  # the end of processing a WHOIS message.
88
- #
88
+ #
89
89
  RPL_WHOWASUSER=314
90
90
  # "<nick> <user> <host> * :<real name>"
91
91
  RPL_ENDOFWHOWAS=369
92
92
  # "<nick> :End of WHOWAS"
93
- #
93
+ #
94
94
  # - When replying to a WHOWAS message, a server MUST use
95
95
  # the replies RPL_WHOWASUSER, RPL_WHOISSERVER or
96
96
  # ERR_WASNOSUCHNICK for each nickname in the presented
97
97
  # list. At the end of all reply batches, there MUST
98
98
  # be RPL_ENDOFWHOWAS (even if there was only one reply
99
99
  # and it was an error).
100
- #
100
+ #
101
101
  RPL_LISTSTART=321
102
102
  # Obsolete. Not used.
103
- #
103
+ #
104
104
  RPL_LIST=322
105
105
  # "<channel> <# visible> :<topic>"
106
106
  RPL_LISTEND=323
107
107
  # ":End of LIST"
108
- #
108
+ #
109
109
  # - Replies RPL_LIST, RPL_LISTEND mark the actual replies
110
110
  # with data and end of the server's response to a LIST
111
111
  # command. If there are no channels available to return,
112
112
  # only the end reply MUST be sent.
113
- #
113
+ #
114
114
  RPL_UNIQOPIS=325
115
115
  # "<channel> <nickname>"
116
- #
116
+ #
117
117
  RPL_CHANNELMODEIS=324
118
118
  # "<channel> <mode> <mode params>"
119
- #
119
+ #
120
120
  RPL_NOTOPIC=331
121
121
  # "<channel> :No topic is set"
122
122
  RPL_TOPIC=332
123
123
  # "<channel> :<topic>"
124
- #
124
+ #
125
125
  # - When sending a TOPIC message to determine the
126
126
  # channel topic, one of two replies is sent. If
127
127
  # the topic is set, RPL_TOPIC is sent back else
128
128
  # RPL_NOTOPIC.
129
- #
129
+ #
130
130
  RPL_TOPIC_INFO=333
131
131
  # <channel> <set by> <unixtime>
132
132
  RPL_INVITING=341
133
133
  # "<channel> <nick>"
134
- #
134
+ #
135
135
  # - Returned by the server to indicate that the
136
136
  # attempted INVITE message was successful and is
137
137
  # being passed onto the end client.
138
- #
138
+ #
139
139
  RPL_SUMMONING=342
140
140
  # "<user> :Summoning user to IRC"
141
- #
141
+ #
142
142
  # - Returned by a server answering a SUMMON message to
143
143
  # indicate that it is summoning that user.
144
- #
144
+ #
145
145
  RPL_INVITELIST=346
146
146
  # "<channel> <invitemask>"
147
147
  RPL_ENDOFINVITELIST=347
148
148
  # "<channel> :End of channel invite list"
149
- #
149
+ #
150
150
  # - When listing the 'invitations masks' for a given channel,
151
151
  # a server is required to send the list back using the
152
152
  # RPL_INVITELIST and RPL_ENDOFINVITELIST messages. A
153
153
  # separate RPL_INVITELIST is sent for each active mask.
154
154
  # After the masks have been listed (or if none present) a
155
155
  # RPL_ENDOFINVITELIST MUST be sent.
156
- #
156
+ #
157
157
  RPL_EXCEPTLIST=348
158
158
  # "<channel> <exceptionmask>"
159
159
  RPL_ENDOFEXCEPTLIST=349
160
160
  # "<channel> :End of channel exception list"
161
- #
161
+ #
162
162
  # - When listing the 'exception masks' for a given channel,
163
163
  # a server is required to send the list back using the
164
164
  # RPL_EXCEPTLIST and RPL_ENDOFEXCEPTLIST messages. A
165
165
  # separate RPL_EXCEPTLIST is sent for each active mask.
166
166
  # After the masks have been listed (or if none present)
167
167
  # a RPL_ENDOFEXCEPTLIST MUST be sent.
168
- #
168
+ #
169
169
  RPL_VERSION=351
170
170
  # "<version>.<debuglevel> <server> :<comments>"
171
- #
171
+ #
172
172
  # - Reply by the server showing its version details.
173
173
  # The <version> is the version of the software being
174
174
  # used (including any patchlevel revisions) and the
175
175
  # <debuglevel> is used to indicate if the server is
176
176
  # running in "debug mode".
177
- #
177
+ #
178
178
  # The "comments" field may contain any comments about
179
179
  # the version or further version details.
180
- #
180
+ #
181
181
  RPL_WHOREPLY=352
182
182
  # "<channel> <user> <host> <server> <nick>
183
183
  # ( "H" / "G" > ["*"] [ ( "@" / "+" ) ]
184
184
  # :<hopcount> <real name>"
185
- #
185
+ #
186
186
  RPL_ENDOFWHO=315
187
187
  # "<name> :End of WHO list"
188
- #
188
+ #
189
189
  # - The RPL_WHOREPLY and RPL_ENDOFWHO pair are used
190
190
  # to answer a WHO message. The RPL_WHOREPLY is only
191
191
  # sent if there is an appropriate match to the WHO
@@ -193,16 +193,16 @@ module Irc
193
193
  # with a WHO message, a RPL_ENDOFWHO MUST be sent
194
194
  # after processing each list item with <name> being
195
195
  # the item.
196
- #
196
+ #
197
197
  RPL_NAMREPLY=353
198
198
  # "( "=" / "*" / "@" ) <channel>
199
199
  # :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )
200
200
  # - "@" is used for secret channels, "*" for private
201
201
  # channels, and "=" for others (public channels).
202
- #
202
+ #
203
203
  RPL_ENDOFNAMES=366
204
204
  # "<channel> :End of NAMES list"
205
- #
205
+ #
206
206
  # - To reply to a NAMES message, a reply pair consisting
207
207
  # of RPL_NAMREPLY and RPL_ENDOFNAMES is sent by the
208
208
  # server back to the client. If there is no channel
@@ -212,81 +212,81 @@ module Irc
212
212
  # channels and contents are sent back in a series of
213
213
  # RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark
214
214
  # the end.
215
- #
215
+ #
216
216
  RPL_LINKS=364
217
217
  # "<mask> <server> :<hopcount> <server info>"
218
218
  RPL_ENDOFLINKS=365
219
219
  # "<mask> :End of LINKS list"
220
- #
220
+ #
221
221
  # - In replying to the LINKS message, a server MUST send
222
222
  # replies back using the RPL_LINKS numeric and mark the
223
223
  # end of the list using an RPL_ENDOFLINKS reply.
224
- #
224
+ #
225
225
  RPL_BANLIST=367
226
226
  # "<channel> <banmask>"
227
227
  RPL_ENDOFBANLIST=368
228
228
  # "<channel> :End of channel ban list"
229
- #
229
+ #
230
230
  # - When listing the active 'bans' for a given channel,
231
231
  # a server is required to send the list back using the
232
232
  # RPL_BANLIST and RPL_ENDOFBANLIST messages. A separate
233
233
  # RPL_BANLIST is sent for each active banmask. After the
234
234
  # banmasks have been listed (or if none present) a
235
235
  # RPL_ENDOFBANLIST MUST be sent.
236
- #
236
+ #
237
237
  RPL_INFO=371
238
238
  # ":<string>"
239
239
  RPL_ENDOFINFO=374
240
240
  # ":End of INFO list"
241
- #
241
+ #
242
242
  # - A server responding to an INFO message is required to
243
243
  # send all its 'info' in a series of RPL_INFO messages
244
244
  # with a RPL_ENDOFINFO reply to indicate the end of the
245
245
  # replies.
246
- #
246
+ #
247
247
  RPL_MOTDSTART=375
248
248
  # ":- <server> Message of the day - "
249
249
  RPL_MOTD=372
250
250
  # ":- <text>"
251
251
  RPL_ENDOFMOTD=376
252
252
  # ":End of MOTD command"
253
- #
253
+ #
254
254
  # - When responding to the MOTD message and the MOTD file
255
255
  # is found, the file is displayed line by line, with
256
256
  # each line no longer than 80 characters, using
257
257
  # RPL_MOTD format replies. These MUST be surrounded
258
258
  # by a RPL_MOTDSTART (before the RPL_MOTDs) and an
259
259
  # RPL_ENDOFMOTD (after).
260
- #
260
+ #
261
261
  RPL_YOUREOPER=381
262
262
  # ":You are now an IRC operator"
263
- #
263
+ #
264
264
  # - RPL_YOUREOPER is sent back to a client which has
265
265
  # just successfully issued an OPER message and gained
266
266
  # operator status.
267
- #
267
+ #
268
268
  RPL_REHASHING=382
269
269
  # "<config file> :Rehashing"
270
- #
270
+ #
271
271
  # - If the REHASH option is used and an operator sends
272
272
  # a REHASH message, an RPL_REHASHING is sent back to
273
273
  # the operator.
274
- #
274
+ #
275
275
  RPL_YOURESERVICE=383
276
276
  # "You are service <servicename>"
277
- #
277
+ #
278
278
  # - Sent by the server to a service upon successful
279
279
  # registration.
280
- #
280
+ #
281
281
  RPL_TIME=391
282
282
  # "<server> :<string showing server's local time>"
283
- #
283
+ #
284
284
  # - When replying to the TIME message, a server MUST send
285
285
  # the reply using the RPL_TIME format above. The string
286
286
  # showing the time need only contain the correct day and
287
287
  # time there. There is no further requirement for the
288
288
  # time string.
289
- #
289
+ #
290
290
  RPL_USERSSTART=392
291
291
  # ":UserID Terminal Host"
292
292
  RPL_USERS=393
@@ -295,14 +295,14 @@ module Irc
295
295
  # ":End of users"
296
296
  RPL_NOUSERS=395
297
297
  # ":Nobody logged in"
298
- #
298
+ #
299
299
  # - If the USERS message is handled by a server, the
300
300
  # replies RPL_USERSTART, RPL_USERS, RPL_ENDOFUSERS and
301
301
  # RPL_NOUSERS are used. RPL_USERSSTART MUST be sent
302
302
  # first, following by either a sequence of RPL_USERS
303
303
  # or a single RPL_NOUSER. Following this is
304
304
  # RPL_ENDOFUSERS.
305
- #
305
+ #
306
306
  RPL_TRACELINK=200
307
307
  # "Link <version & debug level> <destination>
308
308
  # <next server> V<protocol version>
@@ -333,7 +333,7 @@ module Irc
333
333
  # "File <logfile> <debug level>"
334
334
  RPL_TRACEEND=262
335
335
  # "<server name> <version & debug level> :End of TRACE"
336
- #
336
+ #
337
337
  # - The RPL_TRACE* are all returned by the server in
338
338
  # response to the TRACE message. How many are
339
339
  # returned is dependent on the TRACE message and
@@ -350,12 +350,12 @@ module Irc
350
350
  # response to a TRACE command traversing the IRC
351
351
  # network should reflect the actual connectivity of
352
352
  # the servers themselves along that path.
353
- #
353
+ #
354
354
  # RPL_TRACENEWTYPE is to be used for any connection
355
355
  # which does not fit in the other categories but is
356
356
  # being displayed anyway.
357
357
  # RPL_TRACEEND is sent to indicate the end of the list.
358
- #
358
+ #
359
359
  RPL_LOCALUSERS=265
360
360
  # ":Current local users: 3 Max: 4"
361
361
  RPL_GLOBALUSERS=266
@@ -367,7 +367,7 @@ module Irc
367
367
  # "<linkname> <sendq> <sent messages>
368
368
  # <sent Kbytes> <received messages>
369
369
  # <received Kbytes> <time open>"
370
- #
370
+ #
371
371
  # - reports statistics on a connection. <linkname>
372
372
  # identifies the particular connection, <sendq> is
373
373
  # the amount of data that is queued and waiting to be
@@ -378,45 +378,45 @@ module Irc
378
378
  # Kbytes> for received data, respectively. <time
379
379
  # open> indicates how long ago the connection was
380
380
  # opened, in seconds.
381
- #
381
+ #
382
382
  RPL_STATSCOMMANDS=212
383
383
  # "<command> <count> <byte count> <remote count>"
384
- #
384
+ #
385
385
  # - reports statistics on commands usage.
386
- #
386
+ #
387
387
  RPL_ENDOFSTATS=219
388
388
  # "<stats letter> :End of STATS report"
389
- #
389
+ #
390
390
  RPL_STATSUPTIME=242
391
391
  # ":Server Up %d days %d:%02d:%02d"
392
- #
392
+ #
393
393
  # - reports the server uptime.
394
- #
394
+ #
395
395
  RPL_STATSOLINE=243
396
396
  # "O <hostmask> * <name>"
397
- #
397
+ #
398
398
  # - reports the allowed hosts from where user may become IRC
399
399
  # operators.
400
- #
400
+ #
401
401
  RPL_UMODEIS=221
402
402
  # "<user mode string>"
403
- #
403
+ #
404
404
  # - To answer a query about a client's own mode,
405
405
  # RPL_UMODEIS is sent back.
406
- #
406
+ #
407
407
  RPL_SERVLIST=234
408
408
  # "<name> <server> <mask> <type> <hopcount> <info>"
409
- #
409
+ #
410
410
  RPL_SERVLISTEND=235
411
411
  # "<mask> <type> :End of service listing"
412
- #
412
+ #
413
413
  # - When listing services in reply to a SERVLIST message,
414
414
  # a server is required to send the list back using the
415
415
  # RPL_SERVLIST and RPL_SERVLISTEND messages. A separate
416
416
  # RPL_SERVLIST is sent for each service. After the
417
417
  # services have been listed (or if none present) a
418
418
  # RPL_SERVLISTEND MUST be sent.
419
- #
419
+ #
420
420
  RPL_LUSERCLIENT=251
421
421
  # ":There are <integer> users and <integer>
422
422
  # services on <integer> servers"
@@ -429,7 +429,7 @@ module Irc
429
429
  RPL_LUSERME=255
430
430
  # ":I have <integer> clients and <integer>
431
431
  # servers"
432
- #
432
+ #
433
433
  # - In processing an LUSERS message, the server
434
434
  # sends a set of replies from RPL_LUSERCLIENT,
435
435
  # RPL_LUSEROP, RPL_USERUNKNOWN,
@@ -438,7 +438,7 @@ module Irc
438
438
  # RPL_LUSERCLIENT and RPL_LUSERME. The other
439
439
  # replies are only sent back if a non-zero count
440
440
  # is found for them.
441
- #
441
+ #
442
442
  RPL_ADMINME=256
443
443
  # "<server> :Administrative info"
444
444
  RPL_ADMINLOC1=257
@@ -447,7 +447,7 @@ module Irc
447
447
  # ":<admin info>"
448
448
  RPL_ADMINEMAIL=259
449
449
  # ":<admin info>"
450
- #
450
+ #
451
451
  # - When replying to an ADMIN message, a server
452
452
  # is expected to use replies RPL_ADMINME
453
453
  # through to RPL_ADMINEMAIL and provide a text
@@ -458,82 +458,82 @@ module Irc
458
458
  # and finally the administrative contact for the
459
459
  # server (an email address here is REQUIRED)
460
460
  # in RPL_ADMINEMAIL.
461
- #
461
+ #
462
462
  RPL_TRYAGAIN=263
463
463
  # "<command> :Please wait a while and try again."
464
- #
464
+ #
465
465
  # - When a server drops a command without processing it,
466
466
  # it MUST use the reply RPL_TRYAGAIN to inform the
467
467
  # originating client.
468
- #
468
+ #
469
469
  # 5.2 Error Replies
470
- #
470
+ #
471
471
  # Error replies are found in the range from 400 to 599.
472
- #
472
+ #
473
473
  ERR_NOSUCHNICK=401
474
474
  # "<nickname> :No such nick/channel"
475
- #
475
+ #
476
476
  # - Used to indicate the nickname parameter supplied to a
477
477
  # command is currently unused.
478
- #
478
+ #
479
479
  ERR_NOSUCHSERVER=402
480
480
  # "<server name> :No such server"
481
- #
481
+ #
482
482
  # - Used to indicate the server name given currently
483
483
  # does not exist.
484
- #
484
+ #
485
485
  ERR_NOSUCHCHANNEL=403
486
486
  # "<channel name> :No such channel"
487
- #
487
+ #
488
488
  # - Used to indicate the given channel name is invalid.
489
- #
489
+ #
490
490
  ERR_CANNOTSENDTOCHAN=404
491
491
  # "<channel name> :Cannot send to channel"
492
- #
492
+ #
493
493
  # - Sent to a user who is either (a) not on a channel
494
494
  # which is mode +n or (b) not a chanop (or mode +v) on
495
495
  # a channel which has mode +m set or where the user is
496
496
  # banned and is trying to send a PRIVMSG message to
497
497
  # that channel.
498
- #
498
+ #
499
499
  ERR_TOOMANYCHANNELS=405
500
500
  # "<channel name> :You have joined too many channels"
501
- #
501
+ #
502
502
  # - Sent to a user when they have joined the maximum
503
503
  # number of allowed channels and they try to join
504
504
  # another channel.
505
- #
505
+ #
506
506
  ERR_WASNOSUCHNICK=406
507
507
  # "<nickname> :There was no such nickname"
508
- #
508
+ #
509
509
  # - Returned by WHOWAS to indicate there is no history
510
510
  # information for that nickname.
511
- #
511
+ #
512
512
  ERR_TOOMANYTARGETS=407
513
513
  # "<target> :<error code> recipients. <abort message>"
514
- #
514
+ #
515
515
  # - Returned to a client which is attempting to send a
516
516
  # PRIVMSG/NOTICE using the user@host destination format
517
517
  # and for a user@host which has several occurrences.
518
- #
518
+ #
519
519
  # - Returned to a client which trying to send a
520
520
  # PRIVMSG/NOTICE to too many recipients.
521
- #
521
+ #
522
522
  # - Returned to a client which is attempting to JOIN a safe
523
523
  # channel using the shortname when there are more than one
524
524
  # such channel.
525
- #
525
+ #
526
526
  ERR_NOSUCHSERVICE=408
527
527
  # "<service name> :No such service"
528
- #
528
+ #
529
529
  # - Returned to a client which is attempting to send a SQUERY
530
530
  # to a service which does not exist.
531
- #
531
+ #
532
532
  ERR_NOORIGIN=409
533
533
  # ":No origin specified"
534
- #
534
+ #
535
535
  # - PING or PONG message missing the originator parameter.
536
- #
536
+ #
537
537
  ERR_NORECIPIENT=411
538
538
  # ":No recipient given (<command>)"
539
539
  ERR_NOTEXTTOSEND=412
@@ -544,161 +544,161 @@ module Irc
544
544
  # "<mask> :Wildcard in toplevel domain"
545
545
  ERR_BADMASK=415
546
546
  # "<mask> :Bad Server/host mask"
547
- #
547
+ #
548
548
  # - 412 - 415 are returned by PRIVMSG to indicate that
549
549
  # the message wasn't delivered for some reason.
550
550
  # ERR_NOTOPLEVEL and ERR_WILDTOPLEVEL are errors that
551
551
  # are returned when an invalid use of
552
552
  # "PRIVMSG $<server>" or "PRIVMSG #<host>" is attempted.
553
- #
553
+ #
554
554
  ERR_UNKNOWNCOMMAND=421
555
555
  # "<command> :Unknown command"
556
- #
556
+ #
557
557
  # - Returned to a registered client to indicate that the
558
558
  # command sent is unknown by the server.
559
- #
559
+ #
560
560
  ERR_NOMOTD=422
561
561
  # ":MOTD File is missing"
562
- #
562
+ #
563
563
  # - Server's MOTD file could not be opened by the server.
564
- #
564
+ #
565
565
  ERR_NOADMININFO=423
566
566
  # "<server> :No administrative info available"
567
- #
567
+ #
568
568
  # - Returned by a server in response to an ADMIN message
569
569
  # when there is an error in finding the appropriate
570
570
  # information.
571
- #
571
+ #
572
572
  ERR_FILEERROR=424
573
573
  # ":File error doing <file op> on <file>"
574
- #
574
+ #
575
575
  # - Generic error message used to report a failed file
576
576
  # operation during the processing of a message.
577
- #
577
+ #
578
578
  ERR_NONICKNAMEGIVEN=431
579
579
  # ":No nickname given"
580
- #
580
+ #
581
581
  # - Returned when a nickname parameter expected for a
582
582
  # command and isn't found.
583
- #
583
+ #
584
584
  ERR_ERRONEUSNICKNAME=432
585
585
  # "<nick> :Erroneous nickname"
586
- #
586
+ #
587
587
  # - Returned after receiving a NICK message which contains
588
588
  # characters which do not fall in the defined set. See
589
589
  # section 2.3.1 for details on valid nicknames.
590
- #
590
+ #
591
591
  ERR_NICKNAMEINUSE=433
592
592
  # "<nick> :Nickname is already in use"
593
- #
593
+ #
594
594
  # - Returned when a NICK message is processed that results
595
595
  # in an attempt to change to a currently existing
596
596
  # nickname.
597
- #
597
+ #
598
598
  ERR_NICKCOLLISION=436
599
599
  # "<nick> :Nickname collision KILL from <user>@<host>"
600
- #
600
+ #
601
601
  # - Returned by a server to a client when it detects a
602
602
  # nickname collision (registered of a NICK that
603
603
  # already exists by another server).
604
- #
604
+ #
605
605
  ERR_UNAVAILRESOURCE=437
606
606
  # "<nick/channel> :Nick/channel is temporarily unavailable"
607
- #
607
+ #
608
608
  # - Returned by a server to a user trying to join a channel
609
609
  # currently blocked by the channel delay mechanism.
610
- #
610
+ #
611
611
  # - Returned by a server to a user trying to change nickname
612
612
  # when the desired nickname is blocked by the nick delay
613
613
  # mechanism.
614
- #
614
+ #
615
615
  ERR_USERNOTINCHANNEL=441
616
616
  # "<nick> <channel> :They aren't on that channel"
617
- #
617
+ #
618
618
  # - Returned by the server to indicate that the target
619
619
  # user of the command is not on the given channel.
620
- #
620
+ #
621
621
  ERR_NOTONCHANNEL=442
622
622
  # "<channel> :You're not on that channel"
623
- #
623
+ #
624
624
  # - Returned by the server whenever a client tries to
625
625
  # perform a channel affecting command for which the
626
626
  # client isn't a member.
627
- #
627
+ #
628
628
  ERR_USERONCHANNEL=443
629
629
  # "<user> <channel> :is already on channel"
630
- #
630
+ #
631
631
  # - Returned when a client tries to invite a user to a
632
632
  # channel they are already on.
633
- #
633
+ #
634
634
  ERR_NOLOGIN=444
635
635
  # "<user> :User not logged in"
636
- #
636
+ #
637
637
  # - Returned by the summon after a SUMMON command for a
638
638
  # user was unable to be performed since they were not
639
639
  # logged in.
640
- #
641
- #
640
+ #
641
+ #
642
642
  ERR_SUMMONDISABLED=445
643
643
  # ":SUMMON has been disabled"
644
- #
644
+ #
645
645
  # - Returned as a response to the SUMMON command. MUST be
646
646
  # returned by any server which doesn't implement it.
647
- #
647
+ #
648
648
  ERR_USERSDISABLED=446
649
649
  # ":USERS has been disabled"
650
- #
650
+ #
651
651
  # - Returned as a response to the USERS command. MUST be
652
652
  # returned by any server which does not implement it.
653
- #
653
+ #
654
654
  ERR_NOTREGISTERED=451
655
655
  # ":You have not registered"
656
- #
656
+ #
657
657
  # - Returned by the server to indicate that the client
658
658
  # MUST be registered before the server will allow it
659
659
  # to be parsed in detail.
660
- #
660
+ #
661
661
  ERR_NEEDMOREPARAMS=461
662
662
  # "<command> :Not enough parameters"
663
- #
663
+ #
664
664
  # - Returned by the server by numerous commands to
665
665
  # indicate to the client that it didn't supply enough
666
666
  # parameters.
667
- #
667
+ #
668
668
  ERR_ALREADYREGISTRED=462
669
669
  # ":Unauthorized command (already registered)"
670
- #
670
+ #
671
671
  # - Returned by the server to any link which tries to
672
672
  # change part of the registered details (such as
673
673
  # password or user details from second USER message).
674
- #
674
+ #
675
675
  ERR_NOPERMFORHOST=463
676
676
  # ":Your host isn't among the privileged"
677
- #
677
+ #
678
678
  # - Returned to a client which attempts to register with
679
679
  # a server which does not been setup to allow
680
680
  # connections from the host the attempted connection
681
681
  # is tried.
682
- #
682
+ #
683
683
  ERR_PASSWDMISMATCH=464
684
684
  # ":Password incorrect"
685
- #
685
+ #
686
686
  # - Returned to indicate a failed attempt at registering
687
687
  # a connection for which a password was required and
688
688
  # was either not given or incorrect.
689
- #
689
+ #
690
690
  ERR_YOUREBANNEDCREEP=465
691
691
  # ":You are banned from this server"
692
- #
692
+ #
693
693
  # - Returned after an attempt to connect and register
694
694
  # yourself with a server which has been setup to
695
695
  # explicitly deny connections to you.
696
- #
696
+ #
697
697
  ERR_YOUWILLBEBANNED=466
698
- #
698
+ #
699
699
  # - Sent by a server to a user to inform that access to the
700
700
  # server will soon be denied.
701
- #
701
+ #
702
702
  ERR_KEYSET=467
703
703
  # "<channel> :Channel key already set"
704
704
  ERR_CHANNELISFULL=471
@@ -717,99 +717,100 @@ module Irc
717
717
  # "<channel> :Channel doesn't support modes"
718
718
  ERR_BANLISTFULL=478
719
719
  # "<channel> <char> :Channel list is full"
720
- #
720
+ #
721
721
  ERR_NOPRIVILEGES=481
722
722
  # ":Permission Denied- You're not an IRC operator"
723
- #
723
+ #
724
724
  # - Any command requiring operator privileges to operate
725
725
  # MUST return this error to indicate the attempt was
726
726
  # unsuccessful.
727
- #
727
+ #
728
728
  ERR_CHANOPRIVSNEEDED=482
729
729
  # "<channel> :You're not channel operator"
730
- #
730
+ #
731
731
  # - Any command requiring 'chanop' privileges (such as
732
732
  # MODE messages) MUST return this error if the client
733
733
  # making the attempt is not a chanop on the specified
734
734
  # channel.
735
- #
736
- #
735
+ #
736
+ #
737
737
  ERR_CANTKILLSERVER=483
738
738
  # ":You can't kill a server!"
739
- #
739
+ #
740
740
  # - Any attempts to use the KILL command on a server
741
741
  # are to be refused and this error returned directly
742
742
  # to the client.
743
- #
743
+ #
744
744
  ERR_RESTRICTED=484
745
745
  # ":Your connection is restricted!"
746
- #
746
+ #
747
747
  # - Sent by the server to a user upon connection to indicate
748
748
  # the restricted nature of the connection (user mode "+r").
749
- #
749
+ #
750
750
  ERR_UNIQOPPRIVSNEEDED=485
751
751
  # ":You're not the original channel operator"
752
- #
752
+ #
753
753
  # - Any MODE requiring "channel creator" privileges MUST
754
754
  # return this error if the client making the attempt is not
755
755
  # a chanop on the specified channel.
756
- #
756
+ #
757
757
  ERR_NOOPERHOST=491
758
758
  # ":No O-lines for your host"
759
- #
759
+ #
760
760
  # - If a client sends an OPER message and the server has
761
761
  # not been configured to allow connections from the
762
762
  # client's host as an operator, this error MUST be
763
763
  # returned.
764
- #
764
+ #
765
765
  ERR_UMODEUNKNOWNFLAG=501
766
766
  # ":Unknown MODE flag"
767
- #
767
+ #
768
768
  # - Returned by the server to indicate that a MODE
769
769
  # message was sent with a nickname parameter and that
770
770
  # the a mode flag sent was not recognized.
771
- #
771
+ #
772
772
  ERR_USERSDONTMATCH=502
773
773
  # ":Cannot change mode for other users"
774
- #
774
+ #
775
775
  # - Error sent to any user trying to view or change the
776
776
  # user mode for a user other than themselves.
777
- #
777
+ #
778
778
  # 5.3 Reserved numerics
779
- #
779
+ #
780
780
  # These numerics are not described above since they fall into one of
781
781
  # the following categories:
782
- #
782
+ #
783
783
  # 1. no longer in use;
784
- #
784
+ #
785
785
  # 2. reserved for future planned use;
786
- #
786
+ #
787
787
  # 3. in current use but are part of a non-generic 'feature' of
788
788
  # the current IRC server.
789
- RPL_SERVICEINFO=231
789
+ RPL_SERVICEINFO=231
790
790
  RPL_ENDOFSERVICES=232
791
791
  RPL_SERVICE=233
792
- RPL_NONE=300
792
+ RPL_NONE=300
793
793
  RPL_WHOISCHANOP=316
794
- RPL_KILLDONE=361
794
+ RPL_KILLDONE=361
795
795
  RPL_CLOSING=362
796
- RPL_CLOSEEND=363
796
+ RPL_CLOSEEND=363
797
797
  RPL_INFOSTART=373
798
798
  RPL_MYPORTIS=384
799
- RPL_STATSCLINE=213
799
+ RPL_STATSCLINE=213
800
800
  RPL_STATSNLINE=214
801
- RPL_STATSILINE=215
801
+ RPL_STATSILINE=215
802
802
  RPL_STATSKLINE=216
803
803
  RPL_STATSQLINE=217
804
804
  RPL_STATSYLINE=218
805
- RPL_STATSVLINE=240
805
+ RPL_STATSVLINE=240
806
806
  RPL_STATSLLINE=241
807
- RPL_STATSHLINE=244
807
+ RPL_STATSHLINE=244
808
808
  RPL_STATSSLINE=244
809
- RPL_STATSPING=246
809
+ RPL_STATSPING=246
810
810
  RPL_STATSBLINE=247
811
811
  ERR_NOSERVICEHOST=492
812
-
812
+ RPL_DATASTR=290
813
+
813
814
  # implements RFC 2812 and prior IRC RFCs.
814
815
  # clients register handler proc{}s for different server events and IrcClient
815
816
  # handles dispatch
@@ -819,7 +820,7 @@ module Irc
819
820
  @handlers = Hash.new
820
821
  @users = Array.new
821
822
  end
822
-
823
+
823
824
  # key:: server event to handle
824
825
  # value:: proc object called when event occurs
825
826
  # set a handler for a server event
@@ -854,26 +855,26 @@ module Irc
854
855
  def []=(key, value)
855
856
  @handlers[key] = value
856
857
  end
857
-
858
+
858
859
  # key:: event name
859
860
  # remove a handler for a server event
860
861
  def deletehandler(key)
861
862
  @handlers.delete(key)
862
863
  end
863
-
864
+
864
865
  # takes a server string, checks for PING, PRIVMSG, NOTIFY, etc, and parses
865
866
  # numeric server replies, calling the appropriate handler for each, and
866
867
  # sending it a hash containing the data from the server
867
868
  def process(serverstring)
868
869
  data = Hash.new
869
870
  data[:serverstring] = serverstring
870
-
871
+
871
872
  unless serverstring =~ /^(:(\S+)\s)?(\S+)(\s(.*))?/
872
- raise "Unparseable Server Message!!!: #{serverstring}"
873
+ raise "Unparseable Server Message!!!: #{serverstring}"
873
874
  end
874
-
875
+
875
876
  prefix, command, params = $2, $3, $5
876
-
877
+
877
878
  if prefix != nil
878
879
  data[:source] = prefix
879
880
  if prefix =~ /^(\S+)!(\S+)$/
@@ -885,11 +886,14 @@ module Irc
885
886
  # split parameters in an array
886
887
  argv = []
887
888
  params.scan(/(?!:)(\S+)|:(.*)/) { argv << ($1 || $2) } if params
888
-
889
+
889
890
  case command
890
891
  when 'PING'
891
892
  data[:pingid] = argv[0]
892
893
  handle(:ping, data)
894
+ when 'PONG'
895
+ data[:pingid] = argv[0]
896
+ handle(:pong, data)
893
897
  when /^(\d+)$/ # numeric server message
894
898
  num=command.to_i
895
899
  case num
@@ -952,10 +956,14 @@ module Irc
952
956
  # TOPICLEN=450 KICKLEN=450 CHANNELLEN=30 KEYLEN=23 CHANTYPES=#
953
957
  # PREFIX=(ov)@+ CASEMAPPING=ascii CAPAB IRCD=dancer :are available
954
958
  # on this server"
955
- #
956
- argv.each {|a|
959
+ #
960
+ argv[0,argv.length-1].each {|a|
957
961
  if a =~ /^(.*)=(.*)$/
958
962
  data[$1.downcase.to_sym] = $2
963
+ debug "server's #{$1.downcase.to_sym} is #{$2}"
964
+ else
965
+ data[a.downcase.to_sym] = true
966
+ debug "server supports #{a.downcase.to_sym}"
959
967
  end
960
968
  }
961
969
  handle(:isupport, data)
@@ -1027,6 +1035,9 @@ module Irc
1027
1035
  when RPL_ENDOFMOTD
1028
1036
  data[:motd] = @motd
1029
1037
  handle(:motd, data)
1038
+ when RPL_DATASTR
1039
+ data[:text] = argv[1]
1040
+ handle(:datastr, data)
1030
1041
  else
1031
1042
  handle(:unknown, data)
1032
1043
  end
@@ -1038,9 +1049,9 @@ module Irc
1038
1049
  data[:target] = argv[0]
1039
1050
  data[:message] = argv[1]
1040
1051
  handle(:privmsg, data)
1041
-
1052
+
1042
1053
  # Now we split it
1043
- if(data[:target] =~ /^(#|&).*/)
1054
+ if(data[:target] =~ /^[#&!+].*/)
1044
1055
  handle(:public, data)
1045
1056
  else
1046
1057
  handle(:msg, data)
@@ -1091,7 +1102,7 @@ module Irc
1091
1102
  end
1092
1103
 
1093
1104
  private
1094
-
1105
+
1095
1106
  # key:: server event name
1096
1107
  # data:: hash containing data about the event, passed to the proc
1097
1108
  # call client's proc for an event, if they set one as a handler