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 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