net-irc 0.0.2 → 0.0.3
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 +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
|