ircsupport 0.1.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.
@@ -0,0 +1,33 @@
1
+ module IRCSupport
2
+ module Validations
3
+ # @private
4
+ @@nickname = /
5
+ \A
6
+ [A-Za-z_`\-^\|\\\{}\[\]]
7
+ [A-Za-z_0-9`\-^\|\\\{}\[\]]*
8
+ \z
9
+ /x
10
+ # @private
11
+ @@channel = /[^\x00\x07\x0a\x0d :,]+/
12
+
13
+ # @param [String] nickname A nickname to validate.
14
+ # @return [Boolean] Will be true if the nickname is valid.
15
+ def valid_nickname?(nickname)
16
+ return true if nickname =~ @@nickname
17
+ return false
18
+ end
19
+
20
+ # @param [String] channel A channel name to validate.
21
+ # @param [Array] chantypes The channel types which are allowed. This is
22
+ # the same as the "CHANTYPES" isupport option.
23
+ # @return [Boolean] Will be true if the channel name is valid.
24
+ def valid_channel_name?(channel, chantypes = ['#', '&'])
25
+ prefix = Regexp.quote(chantypes.join)
26
+ return false if channel.bytesize > 200
27
+ return true if channel =~ /\A[#{prefix}]#@@channel\z/
28
+ return false
29
+ end
30
+
31
+ module_function :valid_nickname?, :valid_channel_name?
32
+ end
33
+ end
@@ -0,0 +1,4 @@
1
+ module IRCSupport
2
+ # @private
3
+ VERSION = '0.1.0'
4
+ end
data/test/case_test.rb ADDED
@@ -0,0 +1,41 @@
1
+ # coding: utf-8
2
+
3
+ require 'test_helper'
4
+
5
+ include IRCSupport::Case
6
+
7
+ describe "IRCUpcase" do
8
+ it "should put string into IRC uppercase" do
9
+ irc_upcase("simple").must_equal "SIMPLE"
10
+ irc_upcase("c0mpl^{x}").must_equal "C0MPL~[X]"
11
+ irc_upcase("c0mpl~[x]").must_equal "C0MPL~[X]"
12
+ irc_upcase("c0mpl~{x}").must_equal "C0MPL~[X]"
13
+ irc_upcase("c0mpl|{x}").must_equal "C0MPL\\[X]"
14
+ irc_upcase("c0mpl^{x}", :'strict-rfc1459').must_equal "C0MPL^[X]"
15
+ irc_upcase("c0mpl^{x}", :ascii).must_equal "C0MPL^{X}"
16
+ proc { irc_upcase("c0mpl^{x}", :foobar) }.must_raise ArgumentError
17
+ end
18
+ end
19
+
20
+ describe "IRCDowncase" do
21
+ it "should put string into IRC lowercase" do
22
+ irc_downcase("SIMPLE").must_equal "simple"
23
+ irc_downcase("C0MPL~[X]").must_equal "c0mpl^{x}"
24
+ irc_downcase("C0MPL^{X}").must_equal "c0mpl^{x}"
25
+ irc_downcase("C0MPL^[X]").must_equal "c0mpl^{x}"
26
+ irc_downcase("C0MPL\\[X]").must_equal "c0mpl|{x}"
27
+ irc_downcase("C0MPL~[x]", :'strict-rfc1459').must_equal "c0mpl~{x}"
28
+ irc_downcase("c0mpl^{x}", :ascii).must_equal "c0mpl^{x}"
29
+ proc { irc_downcase("c0mpl^{x}", :foobar) }.must_raise ArgumentError
30
+ end
31
+ end
32
+
33
+ describe "IRCEql" do
34
+ it "should say they are equal in IRC-case" do
35
+ irc_eql?('C0MPL~[X]', 'c0mpl^{x}').must_equal true
36
+ end
37
+ it "should say they are unequal in IRC-case" do
38
+ irc_eql?('C0MPL~[X]', 'c0mpl^{x}', :'strict-rfc1459').must_equal false
39
+ irc_eql?('C0MPL|[X]', 'c0mpl~{x}').must_equal false
40
+ end
41
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+
3
+ require 'test_helper'
4
+
5
+ include IRCSupport::Encoding
6
+
7
+ describe "Encoding" do
8
+ utf8 = "lúði"
9
+ cp1252 = "l\xFA\xF0i"
10
+
11
+ it "should decode correctly" do
12
+ if %w{jruby rbx}.include?(RUBY_ENGINE)
13
+ skip("Encoding support is incomplete on rbx and jruby")
14
+ end
15
+ decode_irc(utf8).must_equal utf8
16
+ decode_irc(utf8, 'UTF-8').must_equal utf8
17
+ decode_irc(cp1252).must_equal utf8
18
+ end
19
+
20
+ it "should encode correctly" do
21
+ if %w{jruby rbx}.include?(RUBY_ENGINE)
22
+ skip("Encoding support is incomplete on rbx and jruby")
23
+ end
24
+ encode_irc(utf8).bytes.to_a.must_equal cp1252.bytes.to_a
25
+ encode_irc(utf8, 'UTF-8').bytes.to_a.must_equal utf8.bytes.to_a
26
+ end
27
+ end
@@ -0,0 +1,65 @@
1
+ # coding: utf-8
2
+
3
+ require 'test_helper'
4
+
5
+ include IRCSupport::Formatting
6
+
7
+ describe "HasColor" do
8
+ it "should detect color codes" do
9
+ has_color?("mIRC color \x0303green and\x0f normal").must_equal true
10
+ has_color?("\x1b\x00\x40ecma color").must_equal true
11
+ has_color?("\x04eeff00rgb color").must_equal true
12
+ end
13
+ it "should not detect any color codes" do
14
+ has_color?("normal text").must_equal false
15
+ has_color?("mIRC \x02bold and\x16 reverse").must_equal false
16
+ end
17
+ end
18
+
19
+ describe "HasFormatting" do
20
+ it "should detect formatting codes" do
21
+ has_formatting?("mIRC \x02bold and\x16 reverse").must_equal true
22
+ end
23
+ it "should not detect any formatting codes" do
24
+ has_formatting?("normal text").must_equal false
25
+ has_formatting?("mIRC color \x0303green and\x0f normal").must_equal false
26
+ end
27
+ end
28
+
29
+ describe "Strip" do
30
+ it "should strip color coldes" do
31
+ colored = "\x0304,05Hi, I am\x03 a \x03,05color\x03 \x0305junkie\x03"
32
+ has_color?(colored).must_equal true
33
+ stripped = strip_color(colored)
34
+ has_color?(stripped).must_equal false
35
+ end
36
+
37
+ it "should strip formatting codes" do
38
+ formatted = "This is \x02bold\x0f and this is \x1funderlined\x0f"
39
+ has_formatting?(formatted).must_equal true
40
+ stripped = strip_formatting(formatted)
41
+ has_formatting?(stripped).must_equal false
42
+ end
43
+
44
+ it "should strip color and formatting codes" do
45
+ form_color = "Foo \x0305\x02bar\x0f baz"
46
+ has_color?(form_color).must_equal true
47
+ has_formatting?(form_color).must_equal true
48
+ stripped = strip_color(form_color)
49
+ stripped = strip_formatting(stripped)
50
+ has_color?(stripped).must_equal false
51
+ has_formatting?(stripped).must_equal false
52
+ end
53
+ end
54
+
55
+ describe "IRCFormat" do
56
+ it "should format the string" do
57
+ formatted = irc_format(:underline, "Hello %s!" % irc_format(:bold, "you"))
58
+ has_color?(formatted).must_equal false
59
+ has_formatting?(formatted).must_equal true
60
+ colored = irc_format(:yellow, "Hello %s!" % irc_format(:blue, "you"))
61
+ has_color?(colored).must_equal true
62
+ has_formatting?(colored).must_equal false
63
+ proc { irc_format(:blue, :yellow, :orange, "Foo") }.must_raise ArgumentError
64
+ end
65
+ end
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+
3
+ require 'test_helper'
4
+
5
+ include IRCSupport::Masks
6
+
7
+ describe "Masks" do
8
+ it "should normalize the mask" do
9
+ normalize_mask('*@*').must_equal '*!*@*'
10
+ normalize_mask('foo*').must_equal 'foo*!*@*'
11
+ end
12
+
13
+ banmask = 'stalin*!*@*'
14
+
15
+ it "should match the mask" do
16
+ match = 'stalin!joe@kremlin.ru'
17
+ matches_mask(banmask, match).must_equal true
18
+ result = matches_mask_array([banmask], [match])
19
+ result.must_be_kind_of Hash
20
+ result.must_include 'stalin*!*@*'
21
+ result['stalin*!*@*'].must_be_kind_of Array
22
+ result['stalin*!*@*'].must_include "stalin!joe@kremlin.ru"
23
+ end
24
+
25
+ it "should not match the mask" do
26
+ no_match = 'BinGOs!foo@blah.com'
27
+ matches_mask(banmask, no_match).must_equal false
28
+ no_result = matches_mask_array([banmask], [no_match])
29
+ no_result.must_be_kind_of Hash
30
+ no_result.must_be_empty
31
+ end
32
+
33
+ it "should fail miserably" do
34
+ proc { matches_mask('$r:Lee*', 'foo') }.must_raise ArgumentError
35
+ end
36
+ end
@@ -0,0 +1,416 @@
1
+ # coding: utf-8
2
+
3
+ require 'test_helper'
4
+ require 'ipaddr'
5
+
6
+ traffic = [
7
+ [
8
+ 'CAP ACK :identify-msg',
9
+ ->(msg) {
10
+ msg.capabilities.must_equal({
11
+ "identify-msg" => [:enable]
12
+ })
13
+ }
14
+ ],
15
+ [
16
+ ':adams.freenode.net 001 dsfdsfdsf :Welcome to the freenode Internet Relay Chat Network dsfdsfdsf',
17
+ ->(msg) {
18
+ msg.prefix.must_equal 'adams.freenode.net'
19
+ msg.command.must_equal '001'
20
+ msg.args[0].must_equal 'dsfdsfdsf'
21
+ msg.args[1].must_equal 'Welcome to the freenode Internet Relay Chat Network dsfdsfdsf'
22
+ msg.type.must_equal '001'
23
+ msg.numeric_name.must_equal 'RPL_WELCOME'
24
+ msg.is_error?.must_equal false
25
+ },
26
+ ],
27
+
28
+ [
29
+ ':adams.freenode.net 005 dsfdsfdsf CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQcgimnprstz CHANLIMIT=#:120 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=freenode KNOCK STATUSMSG=@+ CALLERID=g :are supported by this server',
30
+ ->(msg) {
31
+ msg.args[1].must_equal 'CHANTYPES=#'
32
+ msg.args[13].must_equal 'are supported by this server'
33
+ msg.isupport["MODES"].must_equal 4
34
+ msg.isupport["STATUSMSG"].must_equal %w{@ +}
35
+ msg.isupport["CHANTYPES"].must_equal ['#']
36
+ msg.isupport["CHANMODES"].must_equal({
37
+ 'A' => %w{e I b q},
38
+ 'B' => ['k'],
39
+ 'C' => %w{f l j},
40
+ 'D' => %w{C F L M P Q c g i m n p r s t z},
41
+ })
42
+ msg.isupport["CHANLIMIT"].must_equal({ '#' => 120 })
43
+ msg.isupport["PREFIX"].must_equal({ 'o' => '@', 'v' => '+' })
44
+ msg.isupport["NETWORK"].must_equal 'freenode'
45
+ },
46
+ ],
47
+ [
48
+ ':adams.freenode.net 005 dsfdsfdsf CASEMAPPING=rfc1459 CHARSET=ascii NICKLEN=16 CHANNELLEN=50 TOPICLEN=390 ETRACE CPRIVMSG CNOTICE DEAF=D MONITOR=100 FNC TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: :are supported by this server',
49
+ ->(msg) {
50
+ msg.isupport["CASEMAPPING"].must_equal :rfc1459
51
+ msg.isupport["TARGMAX"].must_equal({
52
+ 'NAMES' => 1,
53
+ 'LIST' => 1,
54
+ 'KICK' => 1,
55
+ 'WHOIS' => 1,
56
+ 'PRIVMSG' => 4,
57
+ 'NOTICE' => 4,
58
+ 'ACCEPT' => 0,
59
+ 'MONITOR' => 0,
60
+ })
61
+ },
62
+ ],
63
+ [
64
+ ':adams.freenode.net 353 dsfdsfdsf @ #foo4321 :dsfdsfdsf @literal',
65
+ ->(msg) {
66
+ msg.channel.must_equal '#foo4321'
67
+ msg.channel_type.must_equal '@'
68
+ msg.users.must_equal [[nil, 'dsfdsfdsf'], %w{@ literal}]
69
+ },
70
+ ],
71
+ [
72
+ ':adams.freenode.net 352 dsfdsfdsf #foo4321 ~hinrik 191-108-22-46.fiber.hringdu.is adams.freenode.net dsfdsfdsf H :0 Hinrik Örn Sigurðsson',
73
+ ->(msg) {
74
+ msg.target.must_equal '#foo4321'
75
+ msg.username.must_equal '~hinrik'
76
+ msg.hostname.must_equal '191-108-22-46.fiber.hringdu.is'
77
+ msg.server.must_equal 'adams.freenode.net'
78
+ msg.nickname.must_equal 'dsfdsfdsf'
79
+ msg.away.must_equal false
80
+ msg.hops.must_equal 0
81
+ msg.realname.must_equal 'Hinrik Örn Sigurðsson'
82
+ }
83
+ ],
84
+ [
85
+ ':NickServ!NickServ@services. NOTICE dsfdsfdsf :+This nickname is registered. Please choose a different nickname, or identify via /msg NickServ identify <password>.',
86
+ ->(msg) {
87
+ msg.type.must_equal 'message'
88
+ msg.is_notice?.must_equal true
89
+ msg.sender.must_equal 'NickServ!NickServ@services.'
90
+ msg.identified?.must_equal true
91
+ msg.message.must_equal 'This nickname is registered. Please choose a different nickname, or identify via /msg NickServ identify <password>.'
92
+ }
93
+ ],
94
+ [
95
+ ':literal!hinrik@w.nix.is INVITE dsfdsfdsf :#foo4321',
96
+ ->(msg) {
97
+ msg.inviter.must_equal 'literal!hinrik@w.nix.is'
98
+ msg.channel.must_equal '#foo4321'
99
+ },
100
+ ],
101
+ [
102
+ ':literal!hinrik@w.nix.is PRIVMSG #foo4321 :-dsfdsfsdfds',
103
+ ->(msg) {
104
+ msg.channel.must_equal '#foo4321'
105
+ msg.identified?.must_equal false
106
+ },
107
+ ],
108
+ [
109
+ ':literal!hinrik@w.nix.is PRIVMSG #foo4321 :+dsfdsfsdfds',
110
+ ->(msg) {
111
+ msg.identified?.must_equal true
112
+ },
113
+ ],
114
+ [
115
+ ":literal!hinrik@w.nix.is PRIVMSG #foo4321 :\x01-ACTION dsfdsfsdfds\x01",
116
+ ->(msg) {
117
+ msg.identified?.must_equal false
118
+ msg.is_action?.must_equal true
119
+ },
120
+ ],
121
+ [
122
+ ":literal!hinrik@w.nix.is PRIVMSG #foo4321 :\x01+ACTION dsfdsfsdfds\x01",
123
+ ->(msg) {
124
+ msg.identified?.must_equal true
125
+ msg.is_action?.must_equal true
126
+ },
127
+ ],
128
+ [
129
+ ":literal!hinrik@w.nix.is PRIVMSG #foo4321 :\x01FOOBAR dsfdsfsdfds\x01",
130
+ ->(msg) {
131
+ msg.type.must_equal 'ctcp_foobar'
132
+ msg.ctcp_args.must_equal 'dsfdsfsdfds'
133
+ },
134
+ ],
135
+ [
136
+ ":literal!hinrik@w.nix.is NOTICE #foo4321 :\x01FOOBAR dsfdsfsdfds\x01",
137
+ ->(msg) {
138
+ msg.type.must_equal 'ctcpreply_foobar'
139
+ msg.ctcp_args.must_equal 'dsfdsfsdfds'
140
+ },
141
+ ],
142
+ [
143
+ ":literal!hinrik@w.nix.is PRIVMSG #foo4321 :\x01DCC FOO dsfdsfsdfds\x01",
144
+ ->(msg) {
145
+ msg.type.must_equal 'dcc_foo'
146
+ msg.sender.must_equal 'literal!hinrik@w.nix.is'
147
+ msg.dcc_args.must_equal 'dsfdsfsdfds'
148
+ },
149
+ ],
150
+ [
151
+ ":literal!hinrik@w.nix.is PRIVMSG #foo4321 :\x01DCC CHAT dummy 3232246293 12345\x01",
152
+ ->(msg) {
153
+ msg.address.must_equal IPAddr.new(3232246293, Socket::AF_INET)
154
+ msg.port.must_equal 12345
155
+ },
156
+ ],
157
+ [
158
+ ":literal!hinrik@w.nix.is PRIVMSG #foo4321 :\x01DCC SEND foobar.txt 3232246293 12345 5000\x01",
159
+ ->(msg) {
160
+ msg.filename.must_equal Pathname.new('foobar.txt')
161
+ msg.address.must_equal IPAddr.new(3232246293, Socket::AF_INET)
162
+ msg.port.must_equal 12345
163
+ msg.size.must_equal 5000
164
+ },
165
+ ],
166
+ [
167
+ %Q{:literal!hinrik@w.nix.is PRIVMSG #foo4321 :\x01DCC SEND "foo and bar.txt" 3232246293 12345 5000\x01},
168
+ ->(msg) {
169
+ msg.filename.must_equal Pathname.new('foo and bar.txt')
170
+ msg.address.must_equal IPAddr.new(3232246293, Socket::AF_INET)
171
+ msg.port.must_equal 12345
172
+ msg.size.must_equal 5000
173
+ },
174
+ ],
175
+ [
176
+ %Q{:literal!hinrik@w.nix.is PRIVMSG #foo4321 :\x01DCC ACCEPT "foo and bar.txt" 12345 1000\x01},
177
+ ->(msg) {
178
+ msg.filename.must_equal Pathname.new('foo and bar.txt')
179
+ msg.port.must_equal 12345
180
+ msg.position.must_equal 1000
181
+ },
182
+ ],
183
+ [
184
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is JOIN #foo4321',
185
+ ->(msg) {
186
+ msg.joiner.must_equal 'dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is'
187
+ msg.channel.must_equal '#foo4321'
188
+ },
189
+ ],
190
+ [
191
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is PART #foo4321',
192
+ ->(msg) {
193
+ msg.parter.must_equal 'dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is'
194
+ msg.channel.must_equal '#foo4321'
195
+ msg.message.must_equal nil
196
+ },
197
+ ],
198
+ [
199
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is PART #foo4321 :',
200
+ ->(msg) {
201
+ msg.message.must_equal nil
202
+ },
203
+ ],
204
+ [
205
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is PART #foo4321 :bye!',
206
+ ->(msg) {
207
+ msg.message.must_equal 'bye!'
208
+ },
209
+ ],
210
+ [
211
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is KICK #foo4321 boring_person :bye!',
212
+ ->(msg) {
213
+ msg.kicker.must_equal 'dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is'
214
+ msg.kickee.must_equal 'boring_person'
215
+ msg.message.must_equal 'bye!'
216
+ },
217
+ ],
218
+ [
219
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is KICK #foo4321 boring_person :',
220
+ ->(msg) {
221
+ msg.message.must_equal nil
222
+ },
223
+ ],
224
+ [
225
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is KICK #foo4321 boring_person',
226
+ ->(msg) {
227
+ msg.message.must_equal nil
228
+ },
229
+ ],
230
+ [
231
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is NICK new_name',
232
+ ->(msg) {
233
+ msg.changer.must_equal 'dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is'
234
+ msg.nickname.must_equal 'new_name'
235
+ },
236
+ ],
237
+ [
238
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is TOPIC #foo4321 :fooo',
239
+ ->(msg) {
240
+ msg.changer.must_equal 'dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is'
241
+ msg.channel.must_equal '#foo4321'
242
+ msg.topic.must_equal 'fooo'
243
+ },
244
+ ],
245
+ [
246
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is TOPIC #foo4321 :',
247
+ ->(msg) {
248
+ msg.topic.must_equal nil
249
+ },
250
+ ],
251
+ [
252
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is TOPIC #foo4321',
253
+ ->(msg) {
254
+ msg.topic.must_equal nil
255
+ },
256
+ ],
257
+ [
258
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is QUIT :gone',
259
+ ->(msg) {
260
+ msg.quitter.must_equal 'dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is'
261
+ msg.message.must_equal 'gone'
262
+ },
263
+ ],
264
+ [
265
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is QUIT :',
266
+ ->(msg) {
267
+ msg.message.must_equal nil
268
+ },
269
+ ],
270
+ [
271
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is QUIT',
272
+ ->(msg) {
273
+ msg.message.must_equal nil
274
+ },
275
+ ],
276
+ [
277
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is PING',
278
+ ->(msg) {
279
+ msg.message.must_equal nil
280
+ },
281
+ ],
282
+ [
283
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is PING :',
284
+ ->(msg) {
285
+ msg.message.must_equal nil
286
+ },
287
+ ],
288
+ [
289
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is PING :123',
290
+ ->(msg) {
291
+ msg.message.must_equal '123'
292
+ },
293
+ ],
294
+ [
295
+ 'NOTICE :foo bar',
296
+ ->(msg) {
297
+ msg.type.must_equal 'server_notice'
298
+ msg.sender.must_equal nil
299
+ msg.target.must_equal nil
300
+ msg.message.must_equal 'foo bar'
301
+ },
302
+ ],
303
+ [
304
+ ':fooserver NOTICE AUTH :foo bar',
305
+ ->(msg) {
306
+ msg.type.must_equal 'server_notice'
307
+ msg.sender.must_equal 'fooserver'
308
+ msg.target.must_equal 'AUTH'
309
+ msg.message.must_equal 'foo bar'
310
+ },
311
+ ],
312
+ [
313
+ ':foo-service NOTICE :foo bar',
314
+ ->(msg) {
315
+ msg.type.must_equal 'server_notice'
316
+ msg.sender.must_equal 'foo-service'
317
+ msg.message.must_equal 'foo bar'
318
+ },
319
+ ],
320
+ [
321
+ 'CAP LS :foo -bar ~baz ~=quux',
322
+ ->(msg) {
323
+ msg.multipart.must_equal false
324
+ msg.type.must_equal 'cap_ls'
325
+ msg.subcommand.must_equal 'LS'
326
+ msg.reply.must_equal 'foo -bar ~baz ~=quux'
327
+ msg.capabilities.must_equal({
328
+ 'foo' => [:enable],
329
+ 'bar' => [:disable],
330
+ 'baz' => [:enable],
331
+ 'quux' => [:enable, :sticky],
332
+ })
333
+ }
334
+ ],
335
+ [
336
+ 'CAP LS * :foo -bar ~baz ~=quux',
337
+ ->(msg) {
338
+ msg.multipart.must_equal true
339
+ }
340
+ ],
341
+ [
342
+ 'ERROR :Closing Link: 191-108-22-46.fiber.hringdu.is (Client Quit)',
343
+ ->(msg) {
344
+ msg.error.must_equal 'Closing Link: 191-108-22-46.fiber.hringdu.is (Client Quit)'
345
+ }
346
+ ],
347
+ [
348
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is MODE +i',
349
+ ->(msg) {
350
+ msg.type.must_equal 'user_mode_change'
351
+ msg.mode_changes.must_equal [
352
+ {
353
+ mode: 'i',
354
+ set: true,
355
+ },
356
+ ]
357
+ },
358
+ ],
359
+ [
360
+ ':dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is MODE #foo4321 +tlk 300 foo',
361
+ ->(msg) {
362
+ msg.type.must_equal 'channel_mode_change'
363
+ msg.changer.must_equal 'dsfdsfdsf!~hinrik@191-108-22-46.fiber.hringdu.is'
364
+ msg.channel.must_equal '#foo4321'
365
+ msg.mode_changes.must_equal [
366
+ {
367
+ mode: 't',
368
+ set: true,
369
+ },
370
+ {
371
+ mode: 'l',
372
+ set: true,
373
+ argument: 300,
374
+ },
375
+ {
376
+ mode: 'k',
377
+ set: true,
378
+ argument: 'foo',
379
+ },
380
+ ]
381
+ },
382
+ ],
383
+ [
384
+ 'FOO BAR :baz',
385
+ ->(msg) {
386
+ msg.type.must_equal 'foo'
387
+ msg.prefix.must_equal nil
388
+ msg.args.must_equal ['BAR', 'baz']
389
+ }
390
+ ],
391
+ [
392
+ 'CAP ACK :-identify-msg',
393
+ ->(msg) {
394
+ msg.capabilities.must_equal({
395
+ "identify-msg" => [:disable]
396
+ })
397
+ }
398
+ ],
399
+ [
400
+ ':literal!hinrik@w.nix.is PRIVMSG #foo4321 :dsfdsfsdfds',
401
+ ->(msg) {
402
+ msg.respond_to?(:identified?).must_equal false
403
+ },
404
+ ],
405
+ ]
406
+
407
+ describe "IRCTraffic" do
408
+ parser = IRCSupport::Parser.new
409
+ it "should return correct messages for the IRC traffic" do
410
+ traffic.each_with_index do |line_info, index|
411
+ line, handler = *line_info
412
+ parsed = parser.parse(line)
413
+ handler.call(parsed)
414
+ end
415
+ end
416
+ end