cinch 0.3.5 → 1.0.0
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.
- data/LICENSE +20 -0
- data/README.md +192 -0
- data/Rakefile +53 -43
- data/examples/basic/autovoice.rb +32 -0
- data/examples/basic/google.rb +35 -0
- data/examples/basic/hello.rb +15 -0
- data/examples/basic/join_part.rb +38 -0
- data/examples/basic/memo.rb +39 -0
- data/examples/basic/msg.rb +16 -0
- data/examples/basic/seen.rb +36 -0
- data/examples/basic/urban_dict.rb +35 -0
- data/examples/basic/url_shorten.rb +35 -0
- data/examples/plugins/autovoice.rb +40 -0
- data/examples/plugins/custom_prefix.rb +23 -0
- data/examples/plugins/google.rb +37 -0
- data/examples/plugins/hello.rb +22 -0
- data/examples/plugins/join_part.rb +42 -0
- data/examples/plugins/memo.rb +50 -0
- data/examples/plugins/msg.rb +22 -0
- data/examples/plugins/multiple_matches.rb +41 -0
- data/examples/plugins/seen.rb +45 -0
- data/examples/plugins/urban_dict.rb +30 -0
- data/examples/plugins/url_shorten.rb +32 -0
- data/lib/cinch.rb +7 -20
- data/lib/cinch/ban.rb +41 -0
- data/lib/cinch/bot.rb +479 -0
- data/lib/cinch/callback.rb +11 -0
- data/lib/cinch/channel.rb +419 -0
- data/lib/cinch/constants.rb +369 -0
- data/lib/cinch/exceptions.rb +25 -0
- data/lib/cinch/helpers.rb +21 -0
- data/lib/cinch/irc.rb +344 -38
- data/lib/cinch/isupport.rb +96 -0
- data/lib/cinch/logger/formatted_logger.rb +80 -0
- data/lib/cinch/logger/logger.rb +44 -0
- data/lib/cinch/logger/null_logger.rb +18 -0
- data/lib/cinch/mask.rb +46 -0
- data/lib/cinch/message.rb +183 -0
- data/lib/cinch/message_queue.rb +62 -0
- data/lib/cinch/plugin.rb +205 -0
- data/lib/cinch/rubyext/infinity.rb +1 -0
- data/lib/cinch/rubyext/module.rb +18 -0
- data/lib/cinch/rubyext/queue.rb +19 -0
- data/lib/cinch/rubyext/string.rb +24 -0
- data/lib/cinch/syncable.rb +55 -0
- data/lib/cinch/user.rb +325 -0
- data/spec/bot_spec.rb +5 -0
- data/spec/channel_spec.rb +5 -0
- data/spec/cinch_spec.rb +5 -0
- data/spec/irc_spec.rb +5 -0
- data/spec/message_spec.rb +5 -0
- data/spec/plugin_spec.rb +5 -0
- data/spec/{helper.rb → spec_helper.rb} +0 -0
- data/spec/user_spec.rb +5 -0
- metadata +69 -51
- data/README.rdoc +0 -195
- data/examples/autovoice.rb +0 -32
- data/examples/custom_patterns.rb +0 -19
- data/examples/custom_prefix.rb +0 -25
- data/examples/google.rb +0 -31
- data/examples/hello.rb +0 -13
- data/examples/join_part.rb +0 -26
- data/examples/memo.rb +0 -40
- data/examples/msg.rb +0 -14
- data/examples/named-param-types.rb +0 -19
- data/examples/seen.rb +0 -41
- data/examples/urban_dict.rb +0 -31
- data/examples/url_shorten.rb +0 -34
- data/lib/cinch/base.rb +0 -368
- data/lib/cinch/irc/message.rb +0 -135
- data/lib/cinch/irc/parser.rb +0 -141
- data/lib/cinch/irc/socket.rb +0 -329
- data/lib/cinch/names.rb +0 -54
- data/lib/cinch/rules.rb +0 -171
- data/spec/base_spec.rb +0 -94
- data/spec/irc/helper.rb +0 -8
- data/spec/irc/message_spec.rb +0 -61
- data/spec/irc/parser_spec.rb +0 -103
- data/spec/irc/socket_spec.rb +0 -90
- data/spec/names_spec.rb +0 -393
- data/spec/options_spec.rb +0 -45
- data/spec/rules_spec.rb +0 -109
@@ -0,0 +1,25 @@
|
|
1
|
+
module Cinch
|
2
|
+
module Exceptions
|
3
|
+
# Generic error. Superclass for all Cinch-specific errors.
|
4
|
+
class Generic < ::StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
class ArgumentTooLong < Generic
|
8
|
+
end
|
9
|
+
|
10
|
+
# Error that is raised when a topic is too long to be set.
|
11
|
+
class TopicTooLong < ArgumentTooLong
|
12
|
+
end
|
13
|
+
|
14
|
+
# Error that is raised when a nick is too long to be used.
|
15
|
+
class NickTooLong < ArgumentTooLong
|
16
|
+
end
|
17
|
+
|
18
|
+
# Error that is raised when a kick reason is too long.
|
19
|
+
class KickReasonTooLong < ArgumentTooLong
|
20
|
+
end
|
21
|
+
|
22
|
+
class UnsupportedFeature < Generic
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Cinch
|
2
|
+
module Helpers
|
3
|
+
# Helper method for turning a String into a {Channel} object.
|
4
|
+
#
|
5
|
+
# @param (see Bot#Channel)
|
6
|
+
# @return (see Bot#Channel)
|
7
|
+
# @example (see Bot#Channel)
|
8
|
+
def Channel(*args)
|
9
|
+
@bot.Channel(*args)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Helper method for turning a String into an {User} object.
|
13
|
+
#
|
14
|
+
# @param (see Bot#User)
|
15
|
+
# @return (see Bot#User)
|
16
|
+
# @example (see Bot#User)
|
17
|
+
def User(*args)
|
18
|
+
@bot.User(*args)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/cinch/irc.rb
CHANGED
@@ -1,45 +1,351 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Cinch
|
2
|
+
class IRC
|
3
|
+
# @return [ISupport]
|
4
|
+
attr_reader :isupport
|
5
|
+
def initialize(bot, config)
|
6
|
+
@bot, @config = bot, config
|
7
|
+
@isupport = ISupport.new
|
8
|
+
end
|
3
9
|
|
4
|
-
|
5
|
-
|
10
|
+
# Establish a connection.
|
11
|
+
#
|
12
|
+
# @return [void]
|
13
|
+
def connect
|
14
|
+
@registration = []
|
6
15
|
|
7
|
-
|
8
|
-
|
9
|
-
require 'irc/socket'
|
16
|
+
@whois_updates = Hash.new {|h, k| h[k] = {}}
|
17
|
+
@in_lists = Set.new
|
10
18
|
|
11
|
-
|
19
|
+
tcp_socket = TCPSocket.open(@config.server, @config.port)
|
20
|
+
|
21
|
+
if @config.ssl
|
22
|
+
require 'openssl'
|
23
|
+
|
24
|
+
ssl_context = OpenSSL::SSL::SSLContext.new
|
25
|
+
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
26
|
+
|
27
|
+
@bot.logger.debug "Using SSL with #{@config.server}:#{@config.port}"
|
28
|
+
|
29
|
+
@socket = OpenSSL::SSL::SSLSocket.new(tcp_socket, ssl_context)
|
30
|
+
@socket.sync = true
|
31
|
+
@socket.connect
|
32
|
+
else
|
33
|
+
@socket = tcp_socket
|
34
|
+
end
|
35
|
+
@socket.set_encoding(@bot.config.encoding || Encoding.default_external,
|
36
|
+
Encoding.default_internal,
|
37
|
+
{:invalid => :replace, :undef => :replace})
|
38
|
+
|
39
|
+
@queue = MessageQueue.new(@socket, @bot)
|
40
|
+
message "PASS #{@config.password}" if @config.password
|
41
|
+
message "NICK #{@config.nick}"
|
42
|
+
message "USER #{@config.nick} 0 * :#{@config.realname}"
|
43
|
+
|
44
|
+
Thread.new do
|
45
|
+
begin
|
46
|
+
while line = @socket.gets
|
47
|
+
begin
|
48
|
+
parse line
|
49
|
+
rescue => e
|
50
|
+
@bot.logger.log_exception(e)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
rescue => e
|
54
|
+
@bot.logger.log_exception(e)
|
55
|
+
end
|
56
|
+
|
57
|
+
@bot.dispatch(:disconnect)
|
58
|
+
end
|
59
|
+
begin
|
60
|
+
@queue.process!
|
61
|
+
rescue => e
|
62
|
+
@bot.logger.log_exception(e)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# @api private
|
67
|
+
# @return [void]
|
68
|
+
def parse(input)
|
69
|
+
@bot.logger.log(input, :incoming) if @bot.config.verbose
|
70
|
+
msg = Message.new(input, @bot)
|
71
|
+
events = []
|
72
|
+
|
73
|
+
if ("001".."004").include? msg.command
|
74
|
+
@registration << msg.command
|
75
|
+
if registered?
|
76
|
+
events << :connect
|
77
|
+
end
|
78
|
+
elsif ["PRIVMSG", "NOTICE"].include?(msg.command)
|
79
|
+
events << :ctcp if msg.ctcp?
|
80
|
+
if msg.channel?
|
81
|
+
events << :channel
|
82
|
+
else
|
83
|
+
events << :private
|
84
|
+
end
|
85
|
+
|
86
|
+
if msg.command == "PRIVMSG"
|
87
|
+
events << :message
|
88
|
+
else
|
89
|
+
events << :notice
|
90
|
+
end
|
91
|
+
else
|
92
|
+
meth = "on_#{msg.command.downcase}"
|
93
|
+
__send__(meth, msg) if respond_to?(meth, true)
|
94
|
+
|
95
|
+
if msg.error?
|
96
|
+
events << :error
|
97
|
+
else
|
98
|
+
events << msg.command.downcase.to_sym
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
msg.instance_variable_set(:@events, events)
|
103
|
+
events.each do |event|
|
104
|
+
@bot.dispatch(event, msg)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# @return [Boolean] true if we successfully registered yet
|
109
|
+
def registered?
|
110
|
+
(("001".."004").to_a - @registration).empty?
|
111
|
+
end
|
112
|
+
|
113
|
+
# Send a message.
|
114
|
+
# @return [void]
|
115
|
+
def message(msg)
|
116
|
+
@queue.queue(msg)
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
def on_join(msg)
|
121
|
+
if msg.user == @bot
|
122
|
+
@bot.channels << msg.channel
|
123
|
+
msg.channel.sync_modes
|
124
|
+
end
|
125
|
+
msg.channel.add_user(msg.user)
|
126
|
+
end
|
127
|
+
|
128
|
+
def on_kick(msg)
|
129
|
+
target = User.find_ensured(msg.params[1], @bot)
|
130
|
+
if target == @bot
|
131
|
+
@bot.channels.delete(msg.channel)
|
132
|
+
end
|
133
|
+
msg.channel.remove_user(target)
|
134
|
+
end
|
135
|
+
|
136
|
+
def on_kill(msg)
|
137
|
+
user = User.find_ensured(msg.params[1], @bot)
|
138
|
+
Channel.all.each do |channel|
|
139
|
+
channel.remove_user(user)
|
140
|
+
end
|
141
|
+
user.synced = false
|
142
|
+
end
|
143
|
+
|
144
|
+
def on_mode(msg)
|
145
|
+
msg.channel.sync_modes if msg.channel?
|
146
|
+
end
|
147
|
+
|
148
|
+
def on_nick(msg)
|
149
|
+
if msg.user == @bot
|
150
|
+
@bot.config.nick = msg.params.last
|
151
|
+
end
|
152
|
+
|
153
|
+
msg.user.instance_variable_set(:@nick, msg.params.last)
|
154
|
+
end
|
155
|
+
|
156
|
+
def on_part(msg)
|
157
|
+
msg.channel.remove_user(msg.user)
|
158
|
+
if msg.user == @bot
|
159
|
+
@bot.channels.delete(msg.channel)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def on_ping(msg)
|
164
|
+
message "PONG :#{msg.params.first}"
|
165
|
+
end
|
166
|
+
|
167
|
+
def on_topic(msg)
|
168
|
+
msg.channel.sync(:topic, msg.params[1])
|
169
|
+
end
|
170
|
+
|
171
|
+
def on_quit(msg)
|
172
|
+
Channel.all.each do |channel|
|
173
|
+
channel.remove_user(msg.user)
|
174
|
+
end
|
175
|
+
msg.user.synced = false
|
176
|
+
end
|
177
|
+
|
178
|
+
def on_005(msg)
|
179
|
+
# ISUPPORT
|
180
|
+
@isupport.parse(*msg.params[1..-2].map {|v| v.split(" ")}.flatten)
|
181
|
+
end
|
182
|
+
|
183
|
+
def on_311(msg)
|
184
|
+
# RPL_WHOISUSER
|
185
|
+
user = User.find_ensured(msg.params[1], @bot)
|
186
|
+
@whois_updates[user].merge!({
|
187
|
+
:user => msg.params[2],
|
188
|
+
:host => msg.params[3],
|
189
|
+
:realname => msg.params[5],
|
190
|
+
})
|
191
|
+
end
|
192
|
+
|
193
|
+
def on_317(msg)
|
194
|
+
# RPL_WHOISIDLE
|
195
|
+
user = User.find_ensured(msg.params[1], @bot)
|
196
|
+
@whois_updates[user].merge!({
|
197
|
+
:idle => msg.params[2].to_i,
|
198
|
+
:signed_on_at => Time.at(msg.params[3].to_i),
|
199
|
+
})
|
200
|
+
end
|
201
|
+
|
202
|
+
def on_318(msg)
|
203
|
+
# RPL_ENDOFWHOIS
|
204
|
+
user = User.find_ensured(msg.params[1], @bot)
|
205
|
+
user.instance_variable_set(:@in_whois, false)
|
206
|
+
if @whois_updates[user].empty? && !user.attr(:unknown?, true, true)
|
207
|
+
# for some reason, we did not receive user information. one
|
208
|
+
# reason is freenode throttling WHOIS
|
209
|
+
Thread.new do
|
210
|
+
sleep 2
|
211
|
+
user.whois
|
212
|
+
end
|
213
|
+
else
|
214
|
+
{
|
215
|
+
:authname => nil,
|
216
|
+
:idle => 0,
|
217
|
+
:secure? => false,
|
218
|
+
}.merge(@whois_updates[user]).each do |attr, value|
|
219
|
+
user.sync(attr, value, true)
|
220
|
+
end
|
221
|
+
|
222
|
+
user.sync(:unknown?, false, true)
|
223
|
+
user.instance_variable_set(:@synced, true)
|
224
|
+
@whois_updates.delete user
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def on_319(msg)
|
229
|
+
# RPL_WHOISCHANNELS
|
230
|
+
user = User.find_ensured(msg.params[1], @bot)
|
231
|
+
channels = msg.params[2].scan(/#{@isupport["CHANTYPES"].join}[^ ]+/o).map {|c| Channel.find_ensured(c, @bot) }
|
232
|
+
user.sync(:channels, channels, true)
|
233
|
+
end
|
234
|
+
|
235
|
+
def on_324(msg)
|
236
|
+
# RPL_CHANNELMODEIS
|
237
|
+
|
238
|
+
modes = {}
|
239
|
+
arguments = msg.params[3..-1]
|
240
|
+
msg.params[2][1..-1].split("").each do |mode|
|
241
|
+
if (@isupport["CHANMODES"]["B"] + @isupport["CHANMODES"]["C"]).include?(mode)
|
242
|
+
modes[mode] = arguments.shift
|
243
|
+
else
|
244
|
+
modes[mode] = true
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
msg.channel.sync(:modes, modes, false)
|
249
|
+
end
|
250
|
+
|
251
|
+
def on_330(msg)
|
252
|
+
# RPL_WHOISACCOUNT
|
253
|
+
user = User.find_ensured(msg.params[1], @bot)
|
254
|
+
authname = msg.params[2]
|
255
|
+
@whois_updates[user].merge!({:authname => authname})
|
256
|
+
end
|
257
|
+
|
258
|
+
def on_331(msg)
|
259
|
+
# RPL_NOTOPIC
|
260
|
+
msg.channel.sync(:topic, "")
|
261
|
+
end
|
262
|
+
|
263
|
+
def on_332(msg)
|
264
|
+
# RPL_TOPIC
|
265
|
+
msg.channel.sync(:topic, msg.params[2])
|
266
|
+
end
|
267
|
+
|
268
|
+
def on_353(msg)
|
269
|
+
# RPL_NAMEREPLY
|
270
|
+
unless @in_lists.include?(:names)
|
271
|
+
msg.channel.clear_users
|
272
|
+
end
|
273
|
+
@in_lists << :names
|
274
|
+
|
275
|
+
msg.params[3].split(" ").each do |user|
|
276
|
+
if @isupport["PREFIX"].values.include?(user[0..0])
|
277
|
+
prefix = user[0..0]
|
278
|
+
nick = user[1..-1]
|
279
|
+
else
|
280
|
+
nick = user
|
281
|
+
prefix = nil
|
282
|
+
end
|
283
|
+
user = User.find_ensured(nick, @bot)
|
284
|
+
msg.channel.add_user(user, prefix)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def on_366(msg)
|
289
|
+
# RPL_ENDOFNAMES
|
290
|
+
@in_lists.delete :names
|
291
|
+
msg.channel.mark_as_synced(:users)
|
292
|
+
end
|
293
|
+
|
294
|
+
def on_367(msg)
|
295
|
+
# RPL_BANLIST
|
296
|
+
unless @in_lists.include?(:bans)
|
297
|
+
msg.channel.bans_unsynced.clear
|
298
|
+
end
|
299
|
+
@in_lists << :bans
|
300
|
+
|
301
|
+
mask = msg.params[2]
|
302
|
+
by = User.find_ensured(msg.params[3].split("!").first, @bot)
|
303
|
+
at = Time.at(msg.params[4].to_i)
|
304
|
+
|
305
|
+
ban = Ban.new(mask, by, at)
|
306
|
+
msg.channel.bans_unsynced << ban
|
307
|
+
end
|
308
|
+
|
309
|
+
def on_368(msg)
|
310
|
+
# RPL_ENDOFBANLIST
|
311
|
+
if @in_lists.include?(:bans)
|
312
|
+
@in_lists.delete :bans
|
313
|
+
else
|
314
|
+
# we never received a ban, yet an end of list => no bans
|
315
|
+
msg.channel.bans_unsynced.clear
|
316
|
+
end
|
317
|
+
|
318
|
+
msg.channel.mark_as_synced(:bans)
|
319
|
+
end
|
320
|
+
|
321
|
+
def on_396(msg)
|
322
|
+
# note: designed for freenode
|
323
|
+
User.find_ensured(msg.params[0], @bot).sync(:host, msg.params[1], true)
|
324
|
+
end
|
325
|
+
|
326
|
+
def on_401(msg)
|
327
|
+
# ERR_NOSUCHNICK
|
328
|
+
user = User.find_ensured(msg.params[1], @bot)
|
329
|
+
user.sync(:unknown?, true, true)
|
330
|
+
end
|
331
|
+
|
332
|
+
def on_402(msg)
|
333
|
+
# ERR_NOSUCHSERVER
|
334
|
+
if user = User.find(msg.params[1]) # not _ensured, we only want a user that already exists
|
335
|
+
user.sync(:unknown?, true, true)
|
336
|
+
@whois_updates.delete user
|
337
|
+
# TODO freenode specific, test on other IRCd
|
338
|
+
end
|
339
|
+
end
|
12
340
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
# You can use these tools through Cinch or include them directly and use
|
18
|
-
# them on their own.
|
19
|
-
#
|
20
|
-
# Each class inside of this module can be used direcly as they contain
|
21
|
-
# no references to higher level classes inside Cinch
|
22
|
-
#
|
23
|
-
# == Example
|
24
|
-
# require 'cinch/irc'
|
25
|
-
# require 'pp'
|
26
|
-
#
|
27
|
-
# parser = Cinch::IRC::Parser.new
|
28
|
-
#
|
29
|
-
# Cinch::IRC::Socket.new('irc.2600.net') do |irc|
|
30
|
-
# irc.nick "Cinch"
|
31
|
-
# irc.user "Cinch", 0, '*', "Cinch IRC bot"
|
32
|
-
#
|
33
|
-
# while line = irc.read
|
34
|
-
# message = parser.parse(line)
|
35
|
-
#
|
36
|
-
# pp message
|
37
|
-
# end
|
38
|
-
# end
|
39
|
-
#
|
40
|
-
# == Author
|
41
|
-
# * Lee Jarvis - ljjarvis@gmail.com
|
42
|
-
module IRC
|
341
|
+
def on_433(msg)
|
342
|
+
# ERR_NICKNAMEINUSE
|
343
|
+
@bot.nick = msg.params[1] + "_"
|
344
|
+
end
|
43
345
|
|
346
|
+
def on_671(msg)
|
347
|
+
user = User.find_ensured(msg.params[1], @bot)
|
348
|
+
@whois_updates[user].merge!({:secure? => true})
|
349
|
+
end
|
44
350
|
end
|
45
351
|
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Cinch
|
2
|
+
class ISupport < Hash
|
3
|
+
@@mappings = {
|
4
|
+
%w[PREFIX] => lambda {|v|
|
5
|
+
modes, prefixes = v.match(/^\((.+)\)(.+)$/)[1..2]
|
6
|
+
h = {}
|
7
|
+
modes.split("").each_with_index do |c, i|
|
8
|
+
h[c] = prefixes[i]
|
9
|
+
end
|
10
|
+
h
|
11
|
+
},
|
12
|
+
|
13
|
+
%w[CHANTYPES] => lambda {|v| v.split("")},
|
14
|
+
%w[CHANMODES] => lambda {|v|
|
15
|
+
h = {}
|
16
|
+
h["A"], h["B"], h["C"], h["D"] = v.split(",").map {|l| l.split("")}
|
17
|
+
h
|
18
|
+
},
|
19
|
+
|
20
|
+
%w[MODES MAXCHANNELS NICKLEN MAXBANS TOPICLEN
|
21
|
+
KICKLEN CHANNELLEN CHIDLEN SILENCE AWAYLEN
|
22
|
+
MAXTARGETS WATCH] => lambda {|v| v.to_i},
|
23
|
+
|
24
|
+
%w[CHANLIMIT MAXLIST IDCHAN] => lambda {|v|
|
25
|
+
h = {}
|
26
|
+
v.split(",").each do |pair|
|
27
|
+
args, num = pair.split(":")
|
28
|
+
args.split("").each do |arg|
|
29
|
+
h[arg] = num.to_i
|
30
|
+
end
|
31
|
+
end
|
32
|
+
h
|
33
|
+
},
|
34
|
+
|
35
|
+
%w[TARGMAX] => lambda {|v|
|
36
|
+
h = {}
|
37
|
+
v.split(",").each do |pair|
|
38
|
+
name, value = pair.split(":")
|
39
|
+
h[name] = value.to_i
|
40
|
+
end
|
41
|
+
h
|
42
|
+
},
|
43
|
+
|
44
|
+
%w[NETWORK] => lambda {|v| v},
|
45
|
+
%w[STATUSMSG] => lambda {|v| v.split("")},
|
46
|
+
%w[CASEMAPPING] => lambda {|v| v.to_sym},
|
47
|
+
%w[ELIST] => lambda {|v| v.split("")},
|
48
|
+
# TODO STD
|
49
|
+
}
|
50
|
+
|
51
|
+
def initialize(*args)
|
52
|
+
super
|
53
|
+
# by setting most numeric values to "Infinity", we let the
|
54
|
+
# server truncate messages and lists while at the same time
|
55
|
+
# allowing the use of strictness=:strict for servers that don't
|
56
|
+
# support ISUPPORT (hopefully none, anyway)
|
57
|
+
|
58
|
+
self["PREFIX"] = {"o" => "@", "v" => "+"}
|
59
|
+
self["CHANTYPES"] = ["#"]
|
60
|
+
self["CHANMODES"] = {
|
61
|
+
"A" => ["b"],
|
62
|
+
"B" => ["k"],
|
63
|
+
"C" => ["l"],
|
64
|
+
"D" => %w[i m n p s t r]
|
65
|
+
}
|
66
|
+
self["MODES"] = 1
|
67
|
+
self["NICKLEN"] = Infinity
|
68
|
+
self["MAXBANS"] = Infinity
|
69
|
+
self["TOPICLEN"] = Infinity
|
70
|
+
self["KICKLEN"] = Infinity
|
71
|
+
self["CHANNELLEN"] = Infinity
|
72
|
+
self["CHIDLEN"] = 5
|
73
|
+
self["AWAYLEN"] = Infinity
|
74
|
+
self["MAXTARGETS"] = 1
|
75
|
+
self["MAXCHANNELS"] = Infinity # deprecated
|
76
|
+
self["CHANLIMIT"] = {"#" => Infinity}
|
77
|
+
self["STATUSMSG"] = ["@", "+"]
|
78
|
+
self["CASEMAPPING"] = :rfc1459
|
79
|
+
self["ELIST"] = []
|
80
|
+
end
|
81
|
+
|
82
|
+
# @api private
|
83
|
+
# @return [void]
|
84
|
+
def parse(*options)
|
85
|
+
options.each do |option|
|
86
|
+
name, value = option.split("=")
|
87
|
+
if value
|
88
|
+
proc = @@mappings.find {|key, value| key.include?(name)}
|
89
|
+
self[name] = (proc && proc[1].call(value)) || value
|
90
|
+
else
|
91
|
+
self[name] = true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|