net-irc 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
-