net-irc 0.0.5 → 0.0.6
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/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
|
|