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 CHANGED
@@ -1,18 +1,29 @@
1
- ChangeLog of http://svn.coderepos.org/share/lang/ruby/net-irc/trunk
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
- Fix to destroy closed stream.
17
+ Fixed to destroy closed stream.
7
18
 
8
19
  2008-01-31 cho45
9
20
 
10
21
  * [new] @5939:
11
- Add client example.
22
+ Added client example.
12
23
 
13
24
  * [new] @5929:
14
- Update tests.
15
- Allow lame prefix in RPL_WELCOME (like freenode)
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
- Release 0.0.1
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, @copts = @real.split(/\s+/)
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 #{channel}."
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["nick"]
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
- create_observer(channel, res)
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
- post server_name, TOPIC, chan, "#{res["room"]["url"]} #{res["room"]["description"]}"
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
- if first
264
- post prefix, NOTICE, chan, m["text"]
265
- else
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 "BUG: API returns invalid ticket. Part this channel..."
347
- on_part(Message.new("", PART, [chan, res["error"]["message"]]))
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 "BUG: API returns invalid encoding. But continues."
413
+ @log.error "Error: API returns invalid encoding. But continues."
353
414
  when 122
354
- @log.fatal "BUG: API returns repeated counter"
355
- exit 1
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(debug=false)
447
- return yield if $DEBUG || debug
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 = 120
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 = JSON.parse(self.send(method, url_for(path), parameters.merge({ :format => 'json' })))
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
- begin
266
- Net::HTTP.start(uri.host, uri.port) do |http|
267
- http.read_timeout = @timeout
268
- req = Net::HTTP::Get.new(path)
269
- req.basic_auth(uri.user, uri.password) if uri.user
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
- begin
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
- begin
309
- Net::HTTP.start(uri.host, uri.port) do |http|
310
- http.read_timeout = @timeout
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
- def parse_result(result)
321
- return nil if !result || result.code != '200' || (!result['Content-Type'] || result['Content-Type'].index('text/javascript') != 0)
322
- result.body
323
- end
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
- def success?(response)
326
- return false if !response
327
- response["status"] and response["status"] == 'ok'
328
- end
318
+ def success?(response)
319
+ return false if !response
320
+ response["status"] and response["status"] == 'ok'
321
+ end
329
322
 
330
323
 
331
- @@PATH_BASE = 'api/'
332
- end
324
+ @@PATH_BASE = 'api/'
325
+ end
333
326
  end