net-irc 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +7 -0
- data/Rakefile +1 -1
- data/examples/echo_bot.rb +31 -0
- data/examples/gmail.rb +201 -0
- data/examples/hatena-star-stream.rb +1 -1
- data/examples/hig.rb +733 -0
- data/examples/iig.rb +842 -0
- data/examples/lig.rb +2 -2
- data/examples/lingr.rb +1 -0
- data/examples/mixi.rb +23 -8
- data/examples/nig.rb +1 -1
- data/examples/sig.rb +5 -4
- data/examples/tig.rb +324 -124
- data/examples/wig.rb +107 -50
- data/lib/net/irc.rb +1 -1
- data/lib/net/irc/constants.rb +1 -1
- data/lib/net/irc/message.rb +1 -1
- data/lib/net/irc/pattern.rb +2 -2
- data/spec/channel_manager_spec.rb +5 -0
- data/spec/net-irc_spec.rb +15 -29
- metadata +6 -2
data/examples/wig.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: UTF-8 -*-
|
2
3
|
=begin
|
3
4
|
|
4
5
|
# wig.rb
|
@@ -21,7 +22,7 @@ Configuration example for Tiarra ( http://coderepos.org/share/wiki/Tiarra ).
|
|
21
22
|
|
22
23
|
wassr {
|
23
24
|
host: localhost
|
24
|
-
port:
|
25
|
+
port: 16670
|
25
26
|
name: username@example.com athack jabber=username@example.com:jabberpasswd tid=10 ratio=10:3:5
|
26
27
|
password: password on Wassr
|
27
28
|
in-encoding: utf8
|
@@ -181,8 +182,8 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
181
182
|
log "Client Options: #{@opts.inspect}"
|
182
183
|
@log.info "Client Options: #{@opts.inspect}"
|
183
184
|
|
184
|
-
|
185
|
-
footing =
|
185
|
+
@ratio = Struct.new(:timeline, :friends, :channel).new(*(@opts["ratio"] || "10:3:5").split(":").map {|ratio| ratio.to_f })
|
186
|
+
@footing = @ratio.inject {|r,i| r + i }
|
186
187
|
|
187
188
|
@timeline = []
|
188
189
|
@check_friends_thread = Thread.start do
|
@@ -197,7 +198,7 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
197
198
|
@log.error "\t#{l}"
|
198
199
|
end
|
199
200
|
end
|
200
|
-
sleep freq(
|
201
|
+
sleep freq(@ratio[:friends] / @footing)
|
201
202
|
end
|
202
203
|
end
|
203
204
|
|
@@ -217,7 +218,7 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
217
218
|
@log.error "\t#{l}"
|
218
219
|
end
|
219
220
|
end
|
220
|
-
sleep freq(
|
221
|
+
sleep freq(@ratio[:timeline] / @footing)
|
221
222
|
end
|
222
223
|
end
|
223
224
|
|
@@ -236,7 +237,7 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
236
237
|
@log.error "\t#{l}"
|
237
238
|
end
|
238
239
|
end
|
239
|
-
sleep freq(
|
240
|
+
sleep freq(@ratio[:channel] / @footing)
|
240
241
|
end
|
241
242
|
end
|
242
243
|
end
|
@@ -257,23 +258,26 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
257
258
|
begin
|
258
259
|
if target =~ /^#(.+)/
|
259
260
|
channel = Regexp.last_match[1]
|
260
|
-
|
261
|
+
reply = message[/\s+>(.+)$/, 1]
|
262
|
+
message = Iconv.iconv("UTF-7", "UTF-8", message).join if @utf7
|
263
|
+
if !reply && @opts.key?("alwaysim") && @im && @im.connected? # in jabber mode, using jabber post
|
261
264
|
message = "##{channel} #{message}" unless "##{channel}" == main_channel
|
262
265
|
ret = @im.deliver(jabber_bot_id, message)
|
263
266
|
post "#{nick}!#{nick}@#{api_base.host}", TOPIC, channel, untinyurl(message)
|
264
267
|
else
|
265
268
|
if "##{channel}" == main_channel
|
266
|
-
|
269
|
+
rid = rid_for(reply) if reply
|
270
|
+
ret = api("statuses/update", {"status" => message, "reply_status_rid" => rid})
|
267
271
|
else
|
268
272
|
ret = api("channel_message/update", {"name_en" => channel, "body" => message})
|
269
273
|
end
|
274
|
+
log "Status Updated via API"
|
270
275
|
end
|
271
276
|
else
|
272
277
|
# direct message
|
273
278
|
ret = api("direct_messages/new", {"user" => target, "text" => message})
|
274
279
|
end
|
275
280
|
raise ApiFailed, "API failed" unless ret
|
276
|
-
log "Status Updated" unless @im && @im.connected?
|
277
281
|
rescue => e
|
278
282
|
@log.error [retry_count, e.inspect].inspect
|
279
283
|
if retry_count > 0
|
@@ -289,6 +293,14 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
289
293
|
def on_ctcp(target, message)
|
290
294
|
_, command, *args = message.split(/\s+/)
|
291
295
|
case command
|
296
|
+
when "utf7"
|
297
|
+
begin
|
298
|
+
require "iconv"
|
299
|
+
@utf7 = !@utf7
|
300
|
+
log "utf7 mode: #{@utf7 ? 'on' : 'off'}"
|
301
|
+
rescue LoadError => e
|
302
|
+
log "Can't load iconv."
|
303
|
+
end
|
292
304
|
when "list"
|
293
305
|
nick = args[0]
|
294
306
|
@log.debug([ nick, message ])
|
@@ -298,41 +310,49 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
298
310
|
end
|
299
311
|
|
300
312
|
unless res
|
301
|
-
post
|
313
|
+
post server_name, ERR_NOSUCHNICK, nick, "No such nick/channel"
|
302
314
|
end
|
303
315
|
when "fav"
|
304
|
-
|
305
|
-
st = @tmap[
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
316
|
+
target = args[0]
|
317
|
+
st = @tmap[target]
|
318
|
+
id = rid_for(target)
|
319
|
+
if st || id
|
320
|
+
unless id
|
321
|
+
if @im && @im.connected?
|
322
|
+
# IM のときはいろいろめんどうなことする
|
323
|
+
nick, count = *st
|
324
|
+
pos = @counters[nick] - count
|
325
|
+
@log.debug "%p %s %d/%d => %d" % [
|
326
|
+
st,
|
327
|
+
nick,
|
328
|
+
count,
|
329
|
+
@counters[nick],
|
330
|
+
pos
|
331
|
+
]
|
332
|
+
res = api("statuses/user_timeline", { "id" => nick })
|
333
|
+
raise ApiFailed, "#{nick} may be private mode" if res.empty?
|
334
|
+
if res[pos]
|
335
|
+
id = res[pos]["rid"]
|
336
|
+
else
|
337
|
+
raise ApiFailed, "#{pos} of #{nick} is not found."
|
338
|
+
end
|
339
|
+
else
|
340
|
+
id = st["id"] || st["rid"]
|
341
|
+
end
|
322
342
|
end
|
323
343
|
res = api("favorites/create/#{id}", {})
|
324
|
-
post
|
344
|
+
post server_name, NOTICE, main_channel, "Fav: #{res["screen_name"]}: #{res["text"]}"
|
325
345
|
else
|
326
|
-
post
|
346
|
+
post server_name, NOTICE, main_channel, "No such id or status #{target}"
|
327
347
|
end
|
328
348
|
when "link"
|
329
349
|
tid = args[0]
|
330
350
|
st = @tmap[tid]
|
331
351
|
if st
|
332
352
|
st["link"] = (api_base + "/#{st["user"]["screen_name"]}/statuses/#{st["id"]}").to_s unless st["link"]
|
333
|
-
post
|
353
|
+
post server_name, NOTICE, main_channel, st["link"]
|
334
354
|
else
|
335
|
-
post
|
355
|
+
post server_name, NOTICE, main_channel, "No such id #{tid}"
|
336
356
|
end
|
337
357
|
end
|
338
358
|
rescue ApiFailed => e
|
@@ -343,12 +363,12 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
343
363
|
nick = m.params[0]
|
344
364
|
f = (@friends || []).find {|i| i["screen_name"] == nick }
|
345
365
|
if f
|
346
|
-
post
|
347
|
-
post
|
348
|
-
post
|
349
|
-
post
|
366
|
+
post server_name, RPL_WHOISUSER, @nick, nick, nick, api_base.host, "*", "#{f["name"]} / #{f["description"]}"
|
367
|
+
post server_name, RPL_WHOISSERVER, @nick, nick, api_base.host, api_base.to_s
|
368
|
+
post server_name, RPL_WHOISIDLE, @nick, nick, "0", "seconds idle"
|
369
|
+
post server_name, RPL_ENDOFWHOIS, @nick, nick, "End of WHOIS list"
|
350
370
|
else
|
351
|
-
post
|
371
|
+
post server_name, ERR_NOSUCHNICK, nick, "No such nick/channel"
|
352
372
|
end
|
353
373
|
end
|
354
374
|
|
@@ -356,10 +376,15 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
356
376
|
channels = m.params[0].split(/\s*,\s*/)
|
357
377
|
channels.each do |channel|
|
358
378
|
next if channel == main_channel
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
379
|
+
res = api("channel/exists", { "name_en" => channel.sub(/^#/, "") })
|
380
|
+
if res["exists"]
|
381
|
+
@channels[channel] = {
|
382
|
+
:read => []
|
383
|
+
}
|
384
|
+
post "#{@nick}!#{@nick}@#{api_base.host}", JOIN, channel
|
385
|
+
else
|
386
|
+
post server_name, ERR_NOSUCHNICK, channel, "No such nick/channel"
|
387
|
+
end
|
363
388
|
end
|
364
389
|
end
|
365
390
|
|
@@ -381,20 +406,20 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
381
406
|
user = nick = f["screen_name"]
|
382
407
|
host = serv = api_base.host
|
383
408
|
real = f["name"]
|
384
|
-
post
|
409
|
+
post server_name, RPL_WHOREPLY, @nick, channel, user, host, serv, nick, "H*@", "0 #{real}"
|
385
410
|
end
|
386
|
-
post
|
411
|
+
post server_name, RPL_ENDOFWHO, @nick, channel
|
387
412
|
when @groups.key?(channel)
|
388
413
|
@groups[channel].each do |name|
|
389
414
|
f = @friends.find {|i| i["screen_name"] == name }
|
390
415
|
user = nick = f["screen_name"]
|
391
416
|
host = serv = api_base.host
|
392
417
|
real = f["name"]
|
393
|
-
post
|
418
|
+
post server_name, RPL_WHOREPLY, @nick, channel, user, host, serv, nick, "H*@", "0 #{real}"
|
394
419
|
end
|
395
|
-
post
|
420
|
+
post server_name, RPL_ENDOFWHO, @nick, channel
|
396
421
|
else
|
397
|
-
post
|
422
|
+
post server_name, ERR_NOSUCHNICK, @nick, nick, "No such nick/channel"
|
398
423
|
end
|
399
424
|
end
|
400
425
|
|
@@ -455,6 +480,14 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
455
480
|
mesg = s["text"]
|
456
481
|
@log.debug(mesg)
|
457
482
|
|
483
|
+
begin
|
484
|
+
require 'iconv'
|
485
|
+
mesg = mesg.sub(/^.+ > |^.+/) {|str| Iconv.iconv("UTF-8", "UTF-7", str).join }
|
486
|
+
mesg = "[utf7]: #{mesg}" if body =~ /[^a-z0-9\s]/i
|
487
|
+
rescue LoadError
|
488
|
+
rescue Iconv::IllegalSequence
|
489
|
+
end
|
490
|
+
|
458
491
|
# added @user in no use @user reply message (Wassr only)
|
459
492
|
if s.has_key?("reply_status_url") and s["reply_status_url"] and s["text"] !~ /^@.*/ and %r{([^/]+)/statuses/[^/]+}.match(s["reply_status_url"])
|
460
493
|
reply_user_id = $1
|
@@ -490,11 +523,16 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
490
523
|
def check_friends
|
491
524
|
first = true unless @friends
|
492
525
|
@friends ||= []
|
493
|
-
friends =
|
526
|
+
friends = []
|
527
|
+
1.upto(5) do |i|
|
528
|
+
f = api("statuses/friends", {"page" => i.to_s})
|
529
|
+
friends += f
|
530
|
+
break if f.length < 100
|
531
|
+
end
|
494
532
|
if first && !@opts.key?("athack")
|
495
533
|
@friends = friends
|
496
|
-
post
|
497
|
-
post
|
534
|
+
post server_name, RPL_NAMREPLY, @nick, "=", main_channel, @friends.map{|i| "@#{i["screen_name"]}" }.join(" ")
|
535
|
+
post server_name, RPL_ENDOFNAMES, @nick, main_channel, "End of NAMES list"
|
498
536
|
else
|
499
537
|
prv_friends = @friends.map {|i| i["screen_name"] }
|
500
538
|
now_friends = friends.map {|i| i["screen_name"] }
|
@@ -535,6 +573,13 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
535
573
|
if Regexp.last_match
|
536
574
|
nick, id = Regexp.last_match.captures
|
537
575
|
body = CGI.unescapeHTML(body)
|
576
|
+
begin
|
577
|
+
require 'iconv'
|
578
|
+
body = body.sub(/^.+ > |^.+/) {|str| Iconv.iconv("UTF-8", "UTF-7", str).join }
|
579
|
+
body = "[utf7]: #{body}" if body =~ /[^a-z0-9\s]/i
|
580
|
+
rescue LoadError
|
581
|
+
rescue Iconv::IllegalSequence
|
582
|
+
end
|
538
583
|
|
539
584
|
case
|
540
585
|
when nick == "投稿完了"
|
@@ -582,7 +627,7 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
582
627
|
|
583
628
|
uri = api_base.dup
|
584
629
|
uri.path = "/#{path}.json"
|
585
|
-
uri.query = q.inject([]) {|r,(k,v)| v
|
630
|
+
uri.query = q.inject([]) {|r,(k,v)| v ? r << "#{k}=#{URI.escape(v, /[^-.!~*'()\w]/n)}" : r }.join("&")
|
586
631
|
|
587
632
|
|
588
633
|
req = nil
|
@@ -642,6 +687,18 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
642
687
|
}
|
643
688
|
end
|
644
689
|
|
690
|
+
# return rid of most recent matched status with text
|
691
|
+
def rid_for(text)
|
692
|
+
target = Regexp.new(Regexp.quote(text.strip), "i")
|
693
|
+
status = api("statuses/friends_timeline").find {|i|
|
694
|
+
next false if i["user_login_id"] == @nick # 自分は除外
|
695
|
+
i["text"] =~ target
|
696
|
+
}
|
697
|
+
|
698
|
+
@log.debug "Looking up status contains #{text.inspect} -> #{status.inspect}"
|
699
|
+
status ? status["rid"] : nil
|
700
|
+
end
|
701
|
+
|
645
702
|
class TypableMap < Hash
|
646
703
|
Roma = %w|k g ky gy s z sh j t d ch n ny h b p hy by py m my y r ry w v q|.unshift("").map {|consonant|
|
647
704
|
case
|
data/lib/net/irc.rb
CHANGED
data/lib/net/irc/constants.rb
CHANGED
data/lib/net/irc/message.rb
CHANGED
data/lib/net/irc/pattern.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# coding: ASCII-8BIT
|
2
2
|
module Net::IRC::PATTERN # :nodoc:
|
3
3
|
# letter = %x41-5A / %x61-7A ; A-Z / a-z
|
4
4
|
# digit = %x30-39 ; 0-9
|
@@ -56,7 +56,7 @@ module Net::IRC::PATTERN # :nodoc:
|
|
56
56
|
# =/ 14( SPACE middle ) [ SPACE [ ":" ] trailing ]
|
57
57
|
MIDDLE = "[#{NOSPCRLFCL}][:#{NOSPCRLFCL}]*"
|
58
58
|
TRAILING = "[: #{NOSPCRLFCL}]*"
|
59
|
-
PARAMS = "(?:((?: #{MIDDLE}){0,14})(?: :(#{TRAILING}))?|((?: #{MIDDLE}){14})(
|
59
|
+
PARAMS = "(?:((?: #{MIDDLE}){0,14})(?: :(#{TRAILING}))?|((?: #{MIDDLE}){14}):?(#{TRAILING}))"
|
60
60
|
|
61
61
|
# crlf = %x0D %x0A ; "carriage return" "linefeed"
|
62
62
|
# message = [ ":" prefix SPACE ] command [ params ] crlf
|
@@ -56,6 +56,7 @@ describe Net::IRC, "server and client" do
|
|
56
56
|
@server.start
|
57
57
|
end
|
58
58
|
|
59
|
+
Thread.pass
|
59
60
|
true until @server.instance_variable_get(:@serv)
|
60
61
|
|
61
62
|
@port = @server.instance_variable_get(:@serv).addr[1]
|
@@ -70,6 +71,9 @@ describe Net::IRC, "server and client" do
|
|
70
71
|
})
|
71
72
|
@client.start
|
72
73
|
end
|
74
|
+
|
75
|
+
Thread.pass
|
76
|
+
true until @client
|
73
77
|
end
|
74
78
|
|
75
79
|
server_q = ChannelManagerTestServerSession.testq
|
@@ -79,6 +83,7 @@ describe Net::IRC, "server and client" do
|
|
79
83
|
client = @client
|
80
84
|
client.instance_variable_set(:@prefix, Prefix.new("foonick!foouser@localhost"))
|
81
85
|
|
86
|
+
true until ChannelManagerTestServerSession.instance
|
82
87
|
ChannelManagerTestServerSession.instance.instance_eval do
|
83
88
|
Thread.exclusive do
|
84
89
|
post client.prefix, JOIN, "#test"
|
data/spec/net-irc_spec.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# ENCODING=ASCII-8BIT
|
3
|
+
# :vim:encoding=utf-8:
|
4
|
+
# ↑ どうするのが正解?
|
2
5
|
|
3
6
|
$LOAD_PATH << "lib"
|
4
7
|
$LOAD_PATH << "../lib"
|
@@ -229,18 +232,19 @@ describe Net::IRC, "server and client" do
|
|
229
232
|
@server, @client = nil, nil
|
230
233
|
|
231
234
|
Thread.abort_on_exception = true
|
232
|
-
Thread.start do
|
235
|
+
@tserver = Thread.start do
|
233
236
|
@server = Net::IRC::Server.new("localhost", @port, TestServerSession, {
|
234
237
|
:logger => Logger.new(nil),
|
235
238
|
})
|
236
239
|
@server.start
|
237
240
|
end
|
238
241
|
|
242
|
+
Thread.pass
|
239
243
|
true until @server.instance_variable_get(:@serv)
|
240
244
|
|
241
245
|
@port = @server.instance_variable_get(:@serv).addr[1]
|
242
246
|
|
243
|
-
Thread.start do
|
247
|
+
@tclient = Thread.start do
|
244
248
|
@client = TestClient.new("localhost", @port, {
|
245
249
|
:nick => "foonick",
|
246
250
|
:user => "foouser",
|
@@ -250,6 +254,9 @@ describe Net::IRC, "server and client" do
|
|
250
254
|
})
|
251
255
|
@client.start
|
252
256
|
end
|
257
|
+
|
258
|
+
Thread.pass
|
259
|
+
true until @client
|
253
260
|
end
|
254
261
|
|
255
262
|
server_q = TestServerSession.testq
|
@@ -285,41 +292,20 @@ describe Net::IRC, "server and client" do
|
|
285
292
|
post nil, NOTICE, "#test", "sep1"
|
286
293
|
end
|
287
294
|
end
|
295
|
+
Thread.pass
|
288
296
|
true until client_q.pop.to_s == "NOTICE #test sep1\r\n"
|
289
297
|
client.prefix.should == "foonick"
|
290
298
|
end
|
291
299
|
|
292
|
-
it "should destroy closed session" do
|
293
|
-
|
294
|
-
@client.finish
|
295
|
-
|
296
|
-
Thread.start do
|
297
|
-
@client = TestClient.new("localhost", @port, {
|
298
|
-
:nick => "foonick",
|
299
|
-
:user => "foouser",
|
300
|
-
:real => "foo real name",
|
301
|
-
:pass => "foopass",
|
302
|
-
:logger => Logger.new(nil),
|
303
|
-
})
|
304
|
-
@client.start
|
305
|
-
end
|
306
|
-
|
307
|
-
Thread.pass
|
308
|
-
true while @client == oldclient
|
309
|
-
|
310
|
-
c = @client.instance_variable_get(:@channels)
|
311
|
-
TestServerSession.instance.instance_eval do
|
312
|
-
Thread.exclusive do
|
313
|
-
post nil, NOTICE, "#test", "sep1"
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
true until client_q.pop.to_s == "NOTICE #test sep1\r\n"
|
318
|
-
end
|
300
|
+
# it "should destroy closed session" do
|
301
|
+
# end
|
319
302
|
|
320
303
|
after :all do
|
321
304
|
@server.finish
|
322
305
|
@client.finish
|
306
|
+
@tserver.kill
|
307
|
+
@tclient.kill
|
308
|
+
@server = @client = @tserver = @tclient = nil
|
323
309
|
end
|
324
310
|
end
|
325
311
|
|