net-irc 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +17 -6
- data/Rakefile +0 -5
- data/examples/client.rb +0 -0
- data/examples/lig.rb +102 -28
- data/examples/lingr.rb +29 -36
- data/examples/nig.rb +13 -7
- data/examples/sig.rb +186 -0
- data/examples/tig.rb +210 -76
- data/examples/wig.rb +18 -8
- data/lib/net/irc.rb +23 -21
- data/spec/net-irc_spec.rb +0 -0
- metadata +7 -6
data/ChangeLog
CHANGED
@@ -1,18 +1,29 @@
|
|
1
|
-
|
1
|
+
2008-06-14 cho45
|
2
|
+
|
3
|
+
* [bug]:
|
4
|
+
Fixed examples. (twitter, wassr, lingr gateways)
|
5
|
+
* [release]:
|
6
|
+
Released 0.0.3
|
7
|
+
|
8
|
+
2008-02-06 cho45
|
9
|
+
|
10
|
+
* [release] @5832:
|
11
|
+
Released 0.0.2
|
12
|
+
|
2
13
|
|
3
14
|
2008-02-01 cho45
|
4
15
|
|
5
16
|
* [bug] @5986:
|
6
|
-
|
17
|
+
Fixed to destroy closed stream.
|
7
18
|
|
8
19
|
2008-01-31 cho45
|
9
20
|
|
10
21
|
* [new] @5939:
|
11
|
-
|
22
|
+
Added client example.
|
12
23
|
|
13
24
|
* [new] @5929:
|
14
|
-
|
15
|
-
|
25
|
+
Updated tests.
|
26
|
+
Made allow lame prefix in RPL_WELCOME (like freenode)
|
16
27
|
|
17
28
|
2008-01-29 cho45
|
18
29
|
|
@@ -23,5 +34,5 @@ ChangeLog of http://svn.coderepos.org/share/lang/ruby/net-irc/trunk
|
|
23
34
|
Net::IRC::Server の修正に追従できていなかった
|
24
35
|
|
25
36
|
* [release] @5832:
|
26
|
-
|
37
|
+
Released 0.0.1
|
27
38
|
|
data/Rakefile
CHANGED
@@ -117,11 +117,6 @@ Rake::ShipitTask.new do |s|
|
|
117
117
|
s.Step.new {
|
118
118
|
system("svn", "up")
|
119
119
|
}.and {}
|
120
|
-
s.Step.new {
|
121
|
-
raise "changelog-with-hatenastar.rb is not found" unless system("which", "changelog-with-hatenastar.rb")
|
122
|
-
}.and {
|
123
|
-
system("changelog-with-hatenastar.rb > ChangeLog")
|
124
|
-
}
|
125
120
|
s.ChangeVersion "lib/net/irc.rb", "VERSION"
|
126
121
|
s.Commit
|
127
122
|
s.Task :clean, :package
|
data/examples/client.rb
CHANGED
File without changes
|
data/examples/lig.rb
CHANGED
@@ -69,6 +69,10 @@ nickname management on client.
|
|
69
69
|
|
70
70
|
Ruby's by cho45
|
71
71
|
|
72
|
+
## 備考
|
73
|
+
|
74
|
+
このクライアントで 1000speakers への応募はできません。lingr.com から行ってください。
|
75
|
+
|
72
76
|
=end
|
73
77
|
|
74
78
|
$LOAD_PATH << File.dirname(__FILE__)
|
@@ -79,6 +83,7 @@ require "rubygems"
|
|
79
83
|
require "lingr"
|
80
84
|
require "net/irc"
|
81
85
|
require "pit"
|
86
|
+
require "mutex_m"
|
82
87
|
|
83
88
|
|
84
89
|
class LingrIrcGateway < Net::IRC::Server::Session
|
@@ -93,11 +98,12 @@ class LingrIrcGateway < Net::IRC::Server::Session
|
|
93
98
|
def initialize(*args)
|
94
99
|
super
|
95
100
|
@channels = {}
|
101
|
+
@channels.extend(Mutex_m)
|
96
102
|
end
|
97
103
|
|
98
104
|
def on_user(m)
|
99
105
|
super
|
100
|
-
@real,
|
106
|
+
@real, *@copts = @real.split(/\s+/)
|
101
107
|
@copts ||= []
|
102
108
|
|
103
109
|
# Tiarra sends prev nick when reconnects.
|
@@ -111,11 +117,35 @@ class LingrIrcGateway < Net::IRC::Server::Session
|
|
111
117
|
@lingr = Lingr::Client.new(@opts.api_key)
|
112
118
|
@lingr.create_session('human')
|
113
119
|
@lingr.login(@real, @pass)
|
120
|
+
@session_observer = Thread.start do
|
121
|
+
loop do
|
122
|
+
begin
|
123
|
+
@log.info "Verifying session..."
|
124
|
+
@log.info "Verifed session => #{@lingr.verify_session.inspect}"
|
125
|
+
rescue Lingr::Client::APIError => e
|
126
|
+
@log.info "Verify session raised APIError<#{e.code}:#{e.message}>. Try to re-create session."
|
127
|
+
@lingr.create_session('human')
|
128
|
+
@lingr.login(@real, @pass)
|
129
|
+
rescue Exception => e
|
130
|
+
@log.info "Error on verify_session: #{e.inspect}"
|
131
|
+
end
|
132
|
+
sleep 9 * 60
|
133
|
+
end
|
134
|
+
end
|
114
135
|
@user_info = @lingr.get_user_info
|
115
136
|
|
116
137
|
prefix = make_ids(@user_info)
|
117
138
|
@user_info["prefix"] = prefix
|
118
139
|
post @prefix, NICK, prefix.nick
|
140
|
+
|
141
|
+
rescue Lingr::Client::APIError => e
|
142
|
+
case e.code
|
143
|
+
when 105
|
144
|
+
post nil, ERR_PASSWDMISMATCH, @nick, "Password incorrect"
|
145
|
+
else
|
146
|
+
log "Error: #{e.code}: #{e.message}"
|
147
|
+
end
|
148
|
+
finish
|
119
149
|
end
|
120
150
|
|
121
151
|
def on_privmsg(m)
|
@@ -127,7 +157,12 @@ class LingrIrcGateway < Net::IRC::Server::Session
|
|
127
157
|
end
|
128
158
|
rescue Lingr::Client::APIError => e
|
129
159
|
log "Error: #{e.code}: #{e.message}"
|
130
|
-
log "Coundn't say to #{
|
160
|
+
log "Coundn't say to #{target}."
|
161
|
+
on_join(Message.new(nil, "JOIN", [target])) if e.code == 102 # invalid session
|
162
|
+
end
|
163
|
+
|
164
|
+
def on_notice(m)
|
165
|
+
on_privmsg(m)
|
131
166
|
end
|
132
167
|
|
133
168
|
def on_whois(m)
|
@@ -148,7 +183,7 @@ class LingrIrcGateway < Net::IRC::Server::Session
|
|
148
183
|
real_name = info["description"].to_s
|
149
184
|
server_info = "Lingr: type:#{info["client_type"]} source:#{info["source"]}"
|
150
185
|
channels = [info["client_type"] == "human" ? "@#{chan}" : chan]
|
151
|
-
me = @user_info["
|
186
|
+
me = @user_info["prefix"]
|
152
187
|
|
153
188
|
post nil, RPL_WHOISUSER, me.nick, prefix.nick, prefix.user, prefix.host, "*", real_name
|
154
189
|
post nil, RPL_WHOISSERVER, me.nick, prefix.nick, prefix.host, server_info
|
@@ -159,13 +194,18 @@ class LingrIrcGateway < Net::IRC::Server::Session
|
|
159
194
|
else
|
160
195
|
post nil, ERR_NOSUCHNICK, me.nick, nick, "No such nick/channel"
|
161
196
|
end
|
197
|
+
rescue Exception => e
|
198
|
+
@log.error e.inspect
|
199
|
+
e.backtrace.each do |l|
|
200
|
+
@log.error "\t#{l}"
|
201
|
+
end
|
162
202
|
end
|
163
203
|
|
164
204
|
def on_who(m)
|
165
205
|
channel = m.params[0]
|
166
206
|
return unless channel
|
167
207
|
|
168
|
-
info = @channels[channel.downcase]
|
208
|
+
info = @channels.synchronize { @channels[channel.downcase] }
|
169
209
|
me = @user_info["prefix"]
|
170
210
|
res = @lingr.get_room_info(info[:chan_id], nil, info[:password])
|
171
211
|
res["occupants"].each do |o|
|
@@ -189,10 +229,16 @@ class LingrIrcGateway < Net::IRC::Server::Session
|
|
189
229
|
res = @lingr.enter_room(channel.sub(/^#/, ""), @nick, password)
|
190
230
|
res["password"] = password
|
191
231
|
|
192
|
-
|
232
|
+
@channels.synchronize do
|
233
|
+
create_observer(channel, res)
|
234
|
+
end
|
193
235
|
rescue Lingr::Client::APIError => e
|
194
236
|
log "Error: #{e.code}: #{e.message}"
|
195
237
|
log "Coundn't join to #{channel}."
|
238
|
+
if e.code == 102
|
239
|
+
log "Invalid session... prompt the client to reconnect"
|
240
|
+
finish
|
241
|
+
end
|
196
242
|
rescue Exception => e
|
197
243
|
@log.error e.inspect
|
198
244
|
e.backtrace.each do |l|
|
@@ -216,6 +262,22 @@ class LingrIrcGateway < Net::IRC::Server::Session
|
|
216
262
|
else
|
217
263
|
post nil, ERR_NOSUCHCHANNEL, prefix.nick, channel, "No such channel"
|
218
264
|
end
|
265
|
+
rescue Lingr::Client::APIError => e
|
266
|
+
unless e.code == 102
|
267
|
+
log "Error: #{e.code}: #{e.message}"
|
268
|
+
log "Coundn't say to #{target}."
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def on_disconnected
|
273
|
+
@channels.each do |k, info|
|
274
|
+
info[:observer].kill
|
275
|
+
end
|
276
|
+
@session_observer.kill rescue nil
|
277
|
+
begin
|
278
|
+
@lingr.destroy_session
|
279
|
+
rescue
|
280
|
+
end
|
219
281
|
end
|
220
282
|
|
221
283
|
private
|
@@ -223,10 +285,12 @@ class LingrIrcGateway < Net::IRC::Server::Session
|
|
223
285
|
def create_observer(channel, response)
|
224
286
|
Thread.start(channel, response) do |chan, res|
|
225
287
|
myprefix = @user_info["prefix"]
|
226
|
-
|
288
|
+
if @channels[chan.downcase]
|
289
|
+
@channels[chan.downcase][:observer].kill rescue nil
|
290
|
+
end
|
227
291
|
@channels[chan.downcase] = {
|
228
292
|
:ticket => res["ticket"],
|
229
|
-
:counter => res["counter"],
|
293
|
+
:counter => res["room"]["counter"],
|
230
294
|
:o_id => res["occupant_id"],
|
231
295
|
:chan_id => res["room"]["id"],
|
232
296
|
:password => res["password"],
|
@@ -237,6 +301,8 @@ class LingrIrcGateway < Net::IRC::Server::Session
|
|
237
301
|
:hcounter => 0,
|
238
302
|
:observer => Thread.current,
|
239
303
|
}
|
304
|
+
|
305
|
+
post server_name, TOPIC, chan, "#{res["room"]["url"]} #{res["room"]["description"]}"
|
240
306
|
post myprefix, JOIN, channel
|
241
307
|
post server_name, MODE, channel, "+o", myprefix.nick
|
242
308
|
post nil, RPL_NAMREPLY, myprefix.nick, "=", chan, @channels[chan.downcase][:users].map{|k,v|
|
@@ -244,12 +310,11 @@ class LingrIrcGateway < Net::IRC::Server::Session
|
|
244
310
|
}.join(" ")
|
245
311
|
post nil, RPL_ENDOFNAMES, myprefix.nick, chan, "End of NAMES list"
|
246
312
|
|
247
|
-
first = true
|
248
313
|
info = @channels[chan.downcase]
|
249
314
|
while true
|
250
315
|
begin
|
316
|
+
@log.debug "observe_room<#{info[:counter]}><#{chan}> start <- #{myprefix}"
|
251
317
|
res = @lingr.observe_room info[:ticket], info[:counter]
|
252
|
-
@log.debug "observe_room<#{chan}> returned"
|
253
318
|
|
254
319
|
info[:counter] = res["counter"] if res["counter"]
|
255
320
|
|
@@ -260,13 +325,9 @@ class LingrIrcGateway < Net::IRC::Server::Session
|
|
260
325
|
|
261
326
|
case m["type"]
|
262
327
|
when "user"
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
# Don't send my messages.
|
267
|
-
unless info[:o_id] == o_id
|
268
|
-
post prefix, PRIVMSG, chan, m["text"]
|
269
|
-
end
|
328
|
+
# Don't send my messages.
|
329
|
+
unless info[:o_id] == o_id
|
330
|
+
post prefix, PRIVMSG, chan, m["text"]
|
270
331
|
end
|
271
332
|
when "private"
|
272
333
|
# TODO not sent from lingr?
|
@@ -330,7 +391,6 @@ class LingrIrcGateway < Net::IRC::Server::Session
|
|
330
391
|
end
|
331
392
|
|
332
393
|
|
333
|
-
first = false
|
334
394
|
rescue Lingr::Client::APIError => e
|
335
395
|
case e.code
|
336
396
|
when 100
|
@@ -343,21 +403,29 @@ class LingrIrcGateway < Net::IRC::Server::Session
|
|
343
403
|
@log.fatal "BUG: API returns invalid response format. JSON is unsupported?"
|
344
404
|
exit 1
|
345
405
|
when 109
|
346
|
-
@log.error "
|
347
|
-
on_part(Message.new(
|
406
|
+
@log.error "Error: API returns invalid ticket. Rejoin this channel..."
|
407
|
+
on_part(Message.new(nil, PART, [chan, res["error"]["message"]]))
|
408
|
+
on_join(Message.new(nil, JOIN, [chan, info["password"]]))
|
348
409
|
when 114
|
349
410
|
@log.fatal "BUG: API returns no counter parameter."
|
350
411
|
exit 1
|
351
412
|
when 120
|
352
|
-
@log.error "
|
413
|
+
@log.error "Error: API returns invalid encoding. But continues."
|
353
414
|
when 122
|
354
|
-
@log.
|
355
|
-
|
415
|
+
@log.error "Error: API returns repeated counter. But continues."
|
416
|
+
info[:counter] += 10
|
417
|
+
log "Error: repeated counter. Some message may be ignored..."
|
356
418
|
else
|
357
419
|
# may be socket error?
|
358
420
|
@log.debug "observe failed : #{res.inspect}"
|
359
421
|
log "Error: #{e.code}: #{e.message}"
|
360
422
|
end
|
423
|
+
rescue Timeout::Error
|
424
|
+
# pass
|
425
|
+
rescue JSON::ParserError => e
|
426
|
+
@log.error e
|
427
|
+
info[:counter] += 10
|
428
|
+
log "Error: JSON::ParserError Some message may be ignored..."
|
361
429
|
rescue Exception => e
|
362
430
|
@log.error e.inspect
|
363
431
|
e.backtrace.each do |l|
|
@@ -403,6 +471,7 @@ if __FILE__ == $0
|
|
403
471
|
:host => "localhost",
|
404
472
|
:log => nil,
|
405
473
|
:debug => false,
|
474
|
+
:foreground => false,
|
406
475
|
}
|
407
476
|
|
408
477
|
OptionParser.new do |parser|
|
@@ -436,6 +505,11 @@ if __FILE__ == $0
|
|
436
505
|
opts[:debug] = true
|
437
506
|
end
|
438
507
|
|
508
|
+
on("-f", "--foreground", "run foreground") do |foreground|
|
509
|
+
opts[:log] = $stdout
|
510
|
+
opts[:foreground] = true
|
511
|
+
end
|
512
|
+
|
439
513
|
parse!(ARGV)
|
440
514
|
end
|
441
515
|
end
|
@@ -443,14 +517,14 @@ if __FILE__ == $0
|
|
443
517
|
opts[:logger] = Logger.new(opts[:log], "daily")
|
444
518
|
opts[:logger].level = opts[:debug] ? Logger::DEBUG : Logger::INFO
|
445
519
|
|
446
|
-
def daemonize(
|
447
|
-
|
520
|
+
def daemonize(foreground=false)
|
521
|
+
trap("SIGINT") { exit! 0 }
|
522
|
+
trap("SIGTERM") { exit! 0 }
|
523
|
+
trap("SIGHUP") { exit! 0 }
|
524
|
+
return yield if $DEBUG || foreground
|
448
525
|
Process.fork do
|
449
526
|
Process.setsid
|
450
527
|
Dir.chdir "/"
|
451
|
-
trap("SIGINT") { exit! 0 }
|
452
|
-
trap("SIGTERM") { exit! 0 }
|
453
|
-
trap("SIGHUP") { exit! 0 }
|
454
528
|
File.open("/dev/null") {|f|
|
455
529
|
STDIN.reopen f
|
456
530
|
STDOUT.reopen f
|
@@ -465,7 +539,7 @@ if __FILE__ == $0
|
|
465
539
|
"api_key" => "API key of Lingr"
|
466
540
|
})["api_key"] unless opts[:api_key]
|
467
541
|
|
468
|
-
daemonize(opts[:debug]) do
|
542
|
+
daemonize(opts[:debug] || opts[:foreground]) do
|
469
543
|
Net::IRC::Server.new(opts[:host], opts[:port], LingrIrcGateway, opts).start
|
470
544
|
end
|
471
545
|
|
data/examples/lingr.rb
CHANGED
@@ -21,6 +21,7 @@ require "rubygems"
|
|
21
21
|
require "net/http"
|
22
22
|
require "json"
|
23
23
|
require "uri"
|
24
|
+
require "timeout"
|
24
25
|
|
25
26
|
module Lingr
|
26
27
|
class Client
|
@@ -49,7 +50,7 @@ module Lingr
|
|
49
50
|
@api_key = api_key
|
50
51
|
@host = hostname
|
51
52
|
@verbosity = verbosity
|
52
|
-
@timeout =
|
53
|
+
@timeout = 60
|
53
54
|
end
|
54
55
|
|
55
56
|
# Create a new API session
|
@@ -243,7 +244,9 @@ module Lingr
|
|
243
244
|
raise ClientError, "not in a session"
|
244
245
|
end
|
245
246
|
|
246
|
-
response =
|
247
|
+
response = Timeout.timeout(@timeout) {
|
248
|
+
JSON.parse(self.send(method, url_for(path), parameters.merge({ :format => 'json' })))
|
249
|
+
}
|
247
250
|
|
248
251
|
unless success?(response)
|
249
252
|
raise APIError, response["error"]
|
@@ -262,27 +265,17 @@ module Lingr
|
|
262
265
|
q = params.inject("?") {|s, p| s << "#{p[0].to_s}=#{URI.encode(p[1].to_s, /./)}&"}.chop
|
263
266
|
path << q if q.length > 0
|
264
267
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
parse_result http.request(req)
|
271
|
-
end
|
272
|
-
rescue Exception
|
273
|
-
warn "exception on HTTP GET: #{$!}"
|
274
|
-
nil
|
268
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
269
|
+
http.read_timeout = @timeout
|
270
|
+
req = Net::HTTP::Get.new(path)
|
271
|
+
req.basic_auth(uri.user, uri.password) if uri.user
|
272
|
+
parse_result http.request(req)
|
275
273
|
end
|
276
274
|
end
|
277
275
|
|
278
276
|
def post(url, params)
|
279
277
|
if !params.find {|p| p[1].is_a?(Hash)}
|
280
|
-
|
281
|
-
parse_result Net::HTTP.post_form(URI.parse(url), params)
|
282
|
-
rescue Exception
|
283
|
-
warn "exception on HTTP POST: #{$!}"
|
284
|
-
nil
|
285
|
-
end
|
278
|
+
parse_result Net::HTTP.post_form(URI.parse(url), params)
|
286
279
|
else
|
287
280
|
boundary = 'lingr-api-client' + (0x1000000 + rand(0x1000000).to_s(16))
|
288
281
|
|
@@ -305,29 +298,29 @@ module Lingr
|
|
305
298
|
}.join('') + "--#{boundary}--\r\n"
|
306
299
|
|
307
300
|
uri = URI.parse(url)
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
parse_result http.post2(uri.path, query, "Content-Type" => "multipart/form-data; boundary=#{boundary}")
|
312
|
-
end
|
313
|
-
rescue Exception
|
314
|
-
warn "exception on multipart POST: #{$!}"
|
315
|
-
nil
|
301
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
302
|
+
http.read_timeout = @timeout
|
303
|
+
parse_result http.post2(uri.path, query, "Content-Type" => "multipart/form-data; boundary=#{boundary}")
|
316
304
|
end
|
317
305
|
end
|
318
306
|
end
|
319
307
|
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
308
|
+
def parse_result(result)
|
309
|
+
return nil if !result || result.code != '200' || (!result['Content-Type'] || result['Content-Type'].index('text/javascript') != 0)
|
310
|
+
# puts
|
311
|
+
# puts
|
312
|
+
# puts result.body
|
313
|
+
# puts
|
314
|
+
# puts
|
315
|
+
result.body
|
316
|
+
end
|
324
317
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
318
|
+
def success?(response)
|
319
|
+
return false if !response
|
320
|
+
response["status"] and response["status"] == 'ok'
|
321
|
+
end
|
329
322
|
|
330
323
|
|
331
|
-
|
332
|
-
|
324
|
+
@@PATH_BASE = 'api/'
|
325
|
+
end
|
333
326
|
end
|