net-irc 0.0.1 → 0.0.2

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/examples/tig.rb CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby -Ku
1
+ #!/usr/bin/env ruby
2
2
  =begin
3
3
 
4
4
  # tig.rb
@@ -6,33 +6,53 @@
6
6
  Ruby version of TwitterIrcGateway
7
7
  ( http://www.misuzilla.org/dist/net/twitterircgateway/ )
8
8
 
9
+ ## Launch
9
10
 
10
- ## Client opts
11
+ $ ruby tig.rb # daemonized
12
+
13
+ If you want to help:
14
+
15
+ $ ruby tig.rb --help
16
+
17
+ ## Configuration
11
18
 
12
19
  Options specified by after irc realname.
13
20
 
14
- Configuration example for tiarra ( http://coderepos.org/share/wiki/Tiarra ).
21
+ Configuration example for Tiarra ( http://coderepos.org/share/wiki/Tiarra ).
15
22
 
16
23
  twitter {
17
24
  host: localhost
18
25
  port: 16668
19
26
  name: username@example.com athack
20
- password: password on twitter
27
+ password: password on Twitter
21
28
  in-encoding: utf8
22
29
  out-encoding: utf8
23
30
  }
24
31
 
25
32
  ### athack
26
33
 
27
- If `athack` client options specified,
34
+ If `athack` client option specified,
28
35
  all nick in join message is leading with @.
29
36
 
30
- So if you complemente nicks (ex. irssi),
31
- it's good for twitter like reply command (@nick).
37
+ So if you complemente nicks (ex. Irssi),
38
+ it's good for Twitter like reply command (@nick).
32
39
 
33
40
  In this case, you will see torrent of join messages after connected,
34
41
  because NAMES list can't send @ leading nick (it interpreted op.)
35
42
 
43
+ ### jabber=<jid>:<pass>
44
+
45
+ If `jabber=<jid>:<pass>` option specified,
46
+ use jabber to get friends timeline.
47
+
48
+ You must setup im notifing settings in the site and
49
+ install 'xmpp4r-simple' gem.
50
+
51
+ $ sudo gem install xmpp4r-simple
52
+
53
+ Be careful for managing password.
54
+
55
+
36
56
  ## Licence
37
57
 
38
58
  Ruby's by cho45
@@ -55,6 +75,7 @@ require "logger"
55
75
  require "yaml"
56
76
  require "pathname"
57
77
  require "digest/md5"
78
+ require "cgi"
58
79
 
59
80
  Net::HTTP.version_1_2
60
81
 
@@ -72,7 +93,15 @@ class TwitterIrcGateway < Net::IRC::Server::Session
72
93
  end
73
94
 
74
95
  def api_base
75
- @api_base ||= URI("http://twitter.com/")
96
+ URI("http://twitter.com/")
97
+ end
98
+
99
+ def api_source
100
+ "tigrb"
101
+ end
102
+
103
+ def jabber_bot_id
104
+ "twitter@twitter.com"
76
105
  end
77
106
 
78
107
  class ApiFailed < StandardError; end
@@ -81,15 +110,38 @@ class TwitterIrcGateway < Net::IRC::Server::Session
81
110
  super
82
111
  @groups = {}
83
112
  @channels = [] # join channels (groups)
113
+ @user_agent = "#{self.class}/#{server_version} (tig.rb)"
84
114
  @config = Pathname.new(ENV["HOME"]) + ".tig"
85
115
  load_config
86
116
  end
87
117
 
88
118
  def on_user(m)
89
119
  super
90
- post @mask, JOIN, main_channel
91
- @real, @opts = @real.split(/\s/)
120
+ post @prefix, JOIN, main_channel
121
+ post server_name, MODE, main_channel, "+o", @prefix.nick
122
+
123
+ @real, *@opts = @real.split(/\s+/)
92
124
  @opts ||= []
125
+
126
+ jabber = @opts.find {|i| i =~ /^jabber=(\S+?):(\S+)/ }
127
+ if jabber
128
+ jid, pass = Regexp.last_match.captures
129
+ jabber.replace("jabber=#{jid}:********")
130
+ if jabber_bot_id
131
+ begin
132
+ require "xmpp4r-simple"
133
+ start_jabber(jid, pass)
134
+ rescue LoadError
135
+ log "Failed to start Jabber."
136
+ log "Installl 'xmpp4r-simple' gem or check your id/pass."
137
+ finish
138
+ end
139
+ else
140
+ jabber = nil
141
+ log "This gateway does not support Jabber bot."
142
+ end
143
+ end
144
+
93
145
  @log.info "Client Options: #{@opts.inspect}"
94
146
 
95
147
  @timeline = []
@@ -100,13 +152,18 @@ class TwitterIrcGateway < Net::IRC::Server::Session
100
152
  rescue ApiFailed => e
101
153
  @log.error e.inspect
102
154
  rescue Exception => e
103
- puts e
104
- puts e.backtrace
155
+ @log.error e.inspect
156
+ e.backtrace.each do |l|
157
+ @log.error "\t#{l}"
158
+ end
105
159
  end
106
160
  sleep 10 * 60
107
161
  end
108
162
  end
109
163
  sleep 3
164
+
165
+ return if jabber
166
+
110
167
  Thread.start do
111
168
  loop do
112
169
  begin
@@ -115,8 +172,10 @@ class TwitterIrcGateway < Net::IRC::Server::Session
115
172
  rescue ApiFailed => e
116
173
  @log.error e.inspect
117
174
  rescue Exception => e
118
- puts e
119
- puts e.backtrace
175
+ @log.error e.inspect
176
+ e.backtrace.each do |l|
177
+ @log.error "\t#{l}"
178
+ end
120
179
  end
121
180
  sleep 90
122
181
  end
@@ -129,10 +188,10 @@ class TwitterIrcGateway < Net::IRC::Server::Session
129
188
  target, message = *m.params
130
189
  begin
131
190
  if target =~ /^#/
132
- ret = api("statuses/update.json", {"status" => message})
191
+ ret = api("statuses/update", {"status" => message})
133
192
  else
134
193
  # direct message
135
- ret = api("direct_messages/new.json", {"user" => target, "text" => message})
194
+ ret = api("direct_messages/new", {"user" => target, "text" => message})
136
195
  end
137
196
  raise ApiFailed, "api failed" unless ret
138
197
  log "Status Updated"
@@ -152,10 +211,10 @@ class TwitterIrcGateway < Net::IRC::Server::Session
152
211
  nick = m.params[0]
153
212
  f = (@friends || []).find {|i| i["screen_name"] == nick }
154
213
  if f
155
- post nil, RPL_WHOISUSER, nick, nick, nick, api_base.host, "*", NKF.nkf("-j", "#{f["name"]} / #{f["description"]}")
156
- post nil, RPL_WHOISSERVER, nick, api_base.host, api_base.to_s
157
- post nil, RPL_WHOISIDLE, nick, "0", "seconds idle"
158
- post nil, RPL_ENDOFWHOIS, nick, "End of WHOIS list"
214
+ post nil, RPL_WHOISUSER, @nick, nick, nick, api_base.host, "*", "#{f["name"]} / #{f["description"]}"
215
+ post nil, RPL_WHOISSERVER, @nick, nick, api_base.host, api_base.to_s
216
+ post nil, RPL_WHOISIDLE, @nick, nick, "0", "seconds idle"
217
+ post nil, RPL_ENDOFWHOIS, @nick, nick, "End of WHOIS list"
159
218
  else
160
219
  post nil, ERR_NOSUCHNICK, nick, "No such nick/channel"
161
220
  end
@@ -165,27 +224,27 @@ class TwitterIrcGateway < Net::IRC::Server::Session
165
224
  channel = m.params[0]
166
225
  case
167
226
  when channel == main_channel
168
- # "<channel> <user> <host> <server> <nick>
169
- # ( "H" / "G" > ["*"] [ ( "@" / "+" ) ]
227
+ # "<channel> <user> <host> <server> <nick>
228
+ # ( "H" / "G" > ["*"] [ ( "@" / "+" ) ]
170
229
  # :<hopcount> <real name>"
171
230
  @friends.each do |f|
172
231
  user = nick = f["screen_name"]
173
232
  host = serv = api_base.host
174
233
  real = f["name"]
175
- post nil, RPL_WHOREPLY, channel, user, host, serv, nick, "H", "0 #{real}"
234
+ post nil, RPL_WHOREPLY, @nick, channel, user, host, serv, nick, "H*@", "0 #{real}"
176
235
  end
177
- post nil, RPL_ENDOFWHO, channel
236
+ post nil, RPL_ENDOFWHO, @nick, channel
178
237
  when @groups.key?(channel)
179
238
  @groups[channel].each do |name|
180
239
  f = @friends.find {|i| i["screen_name"] == name }
181
240
  user = nick = f["screen_name"]
182
241
  host = serv = api_base.host
183
242
  real = f["name"]
184
- post nil, RPL_WHOREPLY, channel, user, host, serv, nick, "H", "0 #{real}"
243
+ post nil, RPL_WHOREPLY, @nick, channel, user, host, serv, nick, "H*@", "0 #{real}"
185
244
  end
186
- post nil, RPL_ENDOFWHO, channel
245
+ post nil, RPL_ENDOFWHO, @nick, channel
187
246
  else
188
- post nil, ERR_NOSUCHNICK, nick, "No such nick/channel"
247
+ post nil, ERR_NOSUCHNICK, @nick, nick, "No such nick/channel"
189
248
  end
190
249
  end
191
250
 
@@ -197,6 +256,7 @@ class TwitterIrcGateway < Net::IRC::Server::Session
197
256
  @channels << channel
198
257
  @channels.uniq!
199
258
  post "#{@nick}!#{@nick}@#{api_base.host}", JOIN, channel
259
+ post server_name, MODE, channel, "+o", @nick
200
260
  save_config
201
261
  end
202
262
  end
@@ -216,6 +276,7 @@ class TwitterIrcGateway < Net::IRC::Server::Session
216
276
  if (@friends || []).find {|i| i["screen_name"] == nick }
217
277
  ((@groups[channel] ||= []) << nick).uniq!
218
278
  post "#{nick}!#{nick}@#{api_base.host}", JOIN, channel
279
+ post server_name, MODE, channel, "+o", nick
219
280
  save_config
220
281
  else
221
282
  post ERR_NOSUCHNICK, nil, nick, "No such nick/channel"
@@ -239,17 +300,21 @@ class TwitterIrcGateway < Net::IRC::Server::Session
239
300
  def check_timeline
240
301
  first = true unless @prev_time
241
302
  @prev_time = Time.at(0) if first
242
- api("statuses/friends_timeline.json", {"since" => [@prev_time.httpdate] }).reverse_each do |s|
303
+ api("statuses/friends_timeline", {"since" => [@prev_time.httpdate]}).reverse_each do |s|
243
304
  nick = s["user"]["screen_name"]
244
305
  mesg = s["text"]
245
- time = Time.parse(s["created_at"]) rescue Time.now
306
+ # display photo url(wassr only)
307
+ if s.has_key?('photo_url')
308
+ mesg += " #{s['photo_url']}"
309
+ end
310
+ # time = Time.parse(s["created_at"]) rescue Time.now
246
311
  m = { "&quot;" => "\"", "&lt;"=> "<", "&gt;"=> ">", "&amp;"=> "&", "\n" => " "}
247
312
  mesg.gsub!(/(#{m.keys.join("|")})/) { m[$1] }
248
313
 
249
314
  digest = Digest::MD5.hexdigest("#{nick}::#{mesg}")
250
315
  unless @timeline.include?(digest)
251
316
  @timeline << digest
252
- @log.debug [nick, mesg, time].inspect
317
+ @log.debug [nick, mesg]
253
318
  if nick == @nick # 自分のときは topic に
254
319
  post nick, TOPIC, main_channel, mesg
255
320
  else
@@ -262,6 +327,7 @@ class TwitterIrcGateway < Net::IRC::Server::Session
262
327
  end
263
328
  end
264
329
  end
330
+ @log.debug "@timeline.size = #{@timeline.size}"
265
331
  @timeline = @timeline.last(100)
266
332
  @prev_time = Time.now
267
333
  end
@@ -269,7 +335,7 @@ class TwitterIrcGateway < Net::IRC::Server::Session
269
335
  def check_direct_messages
270
336
  first = true unless @prev_time_d
271
337
  @prev_time_d = Time.now if first
272
- api("direct_messages.json", {"since" => [@prev_time_d.httpdate] }).reverse_each do |s|
338
+ api("direct_messages", {"since" => [@prev_time_d.httpdate] }).reverse_each do |s|
273
339
  nick = s["sender_screen_name"]
274
340
  mesg = s["text"]
275
341
  time = Time.parse(s["created_at"])
@@ -282,11 +348,11 @@ class TwitterIrcGateway < Net::IRC::Server::Session
282
348
  def check_friends
283
349
  first = true unless @friends
284
350
  @friends ||= []
285
- friends = api("statuses/friends.json")
351
+ friends = api("statuses/friends")
286
352
  if first && !@opts.include?("athack")
287
353
  @friends = friends
288
- post nil, RPL_NAMREPLY, server_name, @nick, "=", main_channel, @friends.map{|i| i["screen_name"] }.join(" ")
289
- post nil, RPL_ENDOFNAMES, server_name, @nick, main_channel, "End of NAMES list"
354
+ post nil, RPL_NAMREPLY, @nick, "=", main_channel, @friends.map{|i| "@#{i["screen_name"]}" }.join(" ")
355
+ post nil, RPL_ENDOFNAMES, @nick, main_channel, "End of NAMES list"
290
356
  else
291
357
  prv_friends = @friends.map {|i| i["screen_name"] }
292
358
  now_friends = friends.map {|i| i["screen_name"] }
@@ -302,6 +368,37 @@ class TwitterIrcGateway < Net::IRC::Server::Session
302
368
  end
303
369
  end
304
370
 
371
+ def start_jabber(jid, pass)
372
+ @log.info "Logging-in with #{jid} -> jabber_bot_id: #{jabber_bot_id}"
373
+ im = Jabber::Simple.new(jid, pass)
374
+ im.add(jabber_bot_id)
375
+ Thread.start do
376
+ loop do
377
+ begin
378
+ im.received_messages.each do |msg|
379
+ @log.debug [msg.from, msg.body]
380
+ if msg.from.strip == jabber_bot_id
381
+ # twitter -> 'id: msg'
382
+ # wassr -> 'nick(id): msg'
383
+ body = msg.body.sub(/^(.+?)(?:\((.+?)\))?: /, "")
384
+ if Regexp.last_match
385
+ nick, id = Regexp.last_match.captures
386
+ body = CGI.unescapeHTML(body)
387
+ message(id || nick, main_channel, body)
388
+ end
389
+ end
390
+ end
391
+ rescue Exception => e
392
+ @log.error "Error on Jabber loop: #{e.inspect}"
393
+ e.backtrace.each do |l|
394
+ @log.error "\t#{l}"
395
+ end
396
+ end
397
+ sleep 1
398
+ end
399
+ end
400
+ end
401
+
305
402
  def save_config
306
403
  config = {
307
404
  :channels => @channels,
@@ -323,16 +420,20 @@ class TwitterIrcGateway < Net::IRC::Server::Session
323
420
 
324
421
  def api(path, q={})
325
422
  ret = {}
326
- q["source"] = "tigrb"
423
+ path = path.sub(%r{^/*}, '/') << '.json'
424
+ q["source"] = api_source
327
425
  q = q.inject([]) {|r,(k,v)| v.inject(r) {|r,i| r << "#{k}=#{URI.escape(i, /[^-.!~*'()\w]/n)}" } }.join("&")
328
- uri = api_base + "/#{path}?#{q}"
426
+ uri = api_base.dup
427
+ uri.path = path
428
+ uri.query = q
329
429
  @log.debug uri.inspect
330
430
  Net::HTTP.start(uri.host, uri.port) do |http|
331
431
  header = {
332
432
  'Authorization' => "Basic " + ["#{@real}:#{@pass}"].pack("m"),
433
+ 'User-Agent' => @user_agent,
333
434
  }
334
435
  case path
335
- when "statuses/update.json", "direct_messages/new.json"
436
+ when "/statuses/update.json", "/direct_messages/new.json"
336
437
  ret = http.post(uri.request_uri, q, header)
337
438
  else
338
439
  ret = http.get(uri.request_uri, header)
@@ -341,7 +442,7 @@ class TwitterIrcGateway < Net::IRC::Server::Session
341
442
  @log.debug ret.inspect
342
443
  case ret.code
343
444
  when "200"
344
- JSON.parse(ret.body)
445
+ JSON.parse(ret.body.gsub(/'(y(?:es)?|n(?:o)?|true|false|null)'/, '"\1"'))
345
446
  when "304"
346
447
  []
347
448
  else
@@ -366,10 +467,16 @@ class TwitterIrcGateway < Net::IRC::Server::Session
366
467
  end
367
468
 
368
469
  def untinyurl(text)
369
- text.gsub(%r|http://tinyurl.com/[0-9a-z=]+|i) {|m|
470
+ text.gsub(%r|http://(preview\.)?tinyurl\.com/[0-9a-z=]+|i) {|m|
370
471
  uri = URI(m)
472
+ uri.host = uri.host.sub($1, '') if $1
371
473
  Net::HTTP.start(uri.host, uri.port) {|http|
372
- http.head(uri.request_uri)["Location"]
474
+ http.open_timeout = 3
475
+ begin
476
+ http.head(uri.request_uri, { 'User-Agent' => @user_agent })["Location"]
477
+ rescue Timeout::Error
478
+ m
479
+ end
373
480
  }
374
481
  }
375
482
  end
@@ -379,11 +486,10 @@ if __FILE__ == $0
379
486
  require "optparse"
380
487
 
381
488
  opts = {
382
- :port => 16668,
383
- :host => "localhost",
384
- :debug => false,
385
- :log => nil,
386
- :debug => false,
489
+ :port => 16668,
490
+ :host => "localhost",
491
+ :log => nil,
492
+ :debug => false,
387
493
  }
388
494
 
389
495
  OptionParser.new do |parser|
@@ -396,11 +502,11 @@ if __FILE__ == $0
396
502
  separator ""
397
503
 
398
504
  separator "Options:"
399
- on("-p", "--port [PORT=#{opts[:port]}]", "listen port number") do |port|
505
+ on("-p", "--port [PORT=#{opts[:port]}]", "port number to listen") do |port|
400
506
  opts[:port] = port
401
507
  end
402
508
 
403
- on("-h", "--host [HOST=#{opts[:host]}]", "listen host") do |host|
509
+ on("-h", "--host [HOST=#{opts[:host]}]", "host name or IP address to listen") do |host|
404
510
  opts[:host] = host
405
511
  end
406
512
 
@@ -443,4 +549,3 @@ if __FILE__ == $0
443
549
  end
444
550
  end
445
551
 
446
-
data/examples/wig.rb CHANGED
@@ -5,33 +5,53 @@
5
5
 
6
6
  Wassr IRC Gateway
7
7
 
8
+ ## Launch
8
9
 
9
- ## Client opts
10
+ $ ruby wig.rb # daemonized
11
+
12
+ If you want to help:
13
+
14
+ $ ruby wig.rb --help
15
+
16
+ ## Configuration
10
17
 
11
18
  Options specified by after irc realname.
12
19
 
13
- Configuration example for tiarra ( http://coderepos.org/share/wiki/Tiarra ).
20
+ Configuration example for Tiarra ( http://coderepos.org/share/wiki/Tiarra ).
14
21
 
15
22
  wassr {
16
23
  host: localhost
17
24
  port: 16670
18
25
  name: username@example.com athack
19
- password: password on wassr
26
+ password: password on Wassr
20
27
  in-encoding: utf8
21
28
  out-encoding: utf8
22
29
  }
23
30
 
24
31
  ### athack
25
32
 
26
- If `athack` client options specified,
33
+ If `athack` client option specified,
27
34
  all nick in join message is leading with @.
28
35
 
29
- So if you complemente nicks (ex. irssi),
36
+ So if you complemente nicks (ex. Irssi),
30
37
  it's good for twitter like reply command (@nick).
31
38
 
32
39
  In this case, you will see torrent of join messages after connected,
33
40
  because NAMES list can't send @ leading nick (it interpreted op.)
34
41
 
42
+
43
+ ### jabber=<jid>:<pass>
44
+
45
+ If `jabber=<jid>:<pass>` option specified,
46
+ use jabber to get friends timeline.
47
+
48
+ You must setup im notifing settings in the site and
49
+ install 'xmpp4r-simple' gem.
50
+
51
+ $ sudo gem install xmpp4r-simple
52
+
53
+ Be careful for managing password.
54
+
35
55
  ## Licence
36
56
 
37
57
  Ruby's by cho45
@@ -56,7 +76,15 @@ class WassrIrcGateway < TwitterIrcGateway
56
76
  end
57
77
 
58
78
  def api_base
59
- @api_base ||= URI("http://api.wassr.jp/")
79
+ URI("http://api.wassr.jp/")
80
+ end
81
+
82
+ def api_source
83
+ "wig.rb"
84
+ end
85
+
86
+ def jabber_bot_id
87
+ "wassr-bot@wassr.jp"
60
88
  end
61
89
  end
62
90
 
@@ -64,11 +92,10 @@ if __FILE__ == $0
64
92
  require "optparse"
65
93
 
66
94
  opts = {
67
- :port => 16670,
68
- :host => "localhost",
69
- :debug => false,
70
- :log => nil,
71
- :debug => false,
95
+ :port => 16670,
96
+ :host => "localhost",
97
+ :log => nil,
98
+ :debug => false,
72
99
  }
73
100
 
74
101
  OptionParser.new do |parser|
@@ -81,11 +108,11 @@ if __FILE__ == $0
81
108
  separator ""
82
109
 
83
110
  separator "Options:"
84
- on("-p", "--port [PORT=#{opts[:port]}]", "listen port number") do |port|
111
+ on("-p", "--port [PORT=#{opts[:port]}]", "port number to listen") do |port|
85
112
  opts[:port] = port
86
113
  end
87
114
 
88
- on("-h", "--host [HOST=#{opts[:host]}]", "listen host") do |host|
115
+ on("-h", "--host [HOST=#{opts[:host]}]", "host name or IP address to listen") do |host|
89
116
  opts[:host] = host
90
117
  end
91
118
 
@@ -128,5 +155,3 @@ if __FILE__ == $0
128
155
  end
129
156
  end
130
157
 
131
-
132
-