net-irc 0.0.8 → 0.0.9
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 +9 -0
- data/Rakefile +10 -19
- data/examples/2ch.rb +225 -0
- data/examples/2ig.rb +267 -0
- data/examples/echo_bot.rb +1 -1
- data/examples/gmail.rb +2 -2
- data/examples/hatena-star-stream.rb +10 -4
- data/examples/hig.rb +9 -4
- data/examples/iig.rb +3 -3
- data/examples/ircd.rb +1 -1
- data/examples/lig.rb +551 -0
- data/examples/lingr.rb +327 -0
- data/examples/mixi.rb +2 -2
- data/examples/sig.rb +2 -2
- data/examples/tig.rb +552 -386
- data/examples/wig.rb +11 -4
- data/lib/net/irc.rb +1 -1
- data/lib/net/irc/server.rb +1 -0
- data/spec/channel_manager_spec.rb +4 -1
- data/spec/net-irc_spec.rb +4 -2
- metadata +12 -11
data/examples/echo_bot.rb
CHANGED
data/examples/gmail.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# vim:
|
2
|
+
# vim:encoding=UTF-8:
|
3
3
|
|
4
4
|
$LOAD_PATH << "lib"
|
5
5
|
$LOAD_PATH << "../lib"
|
6
6
|
|
7
|
-
$KCODE = "u"
|
7
|
+
$KCODE = "u" unless defined? ::Encoding
|
8
8
|
|
9
9
|
require "rubygems"
|
10
10
|
require "net/irc"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# vim:
|
2
|
+
# vim:encoding=UTF-8:
|
3
3
|
=begin
|
4
4
|
|
5
5
|
## Licence
|
@@ -11,7 +11,7 @@ Ruby's by cho45
|
|
11
11
|
$LOAD_PATH << "lib"
|
12
12
|
$LOAD_PATH << "../lib"
|
13
13
|
|
14
|
-
$KCODE = "u"
|
14
|
+
$KCODE = "u" unless defined? ::Encoding # json use this
|
15
15
|
|
16
16
|
require "rubygems"
|
17
17
|
require "json"
|
@@ -48,7 +48,10 @@ class HatenaStarStream < Net::IRC::Server::Session
|
|
48
48
|
post server_name, MODE, main_channel, "+o", @prefix.nick
|
49
49
|
|
50
50
|
@real, *@opts = @opts.name || @real.split(/\s+/)
|
51
|
-
@opts
|
51
|
+
@opts = @opts.inject({}) {|r,i|
|
52
|
+
key, value = i.split("=")
|
53
|
+
r.update(key => value)
|
54
|
+
}
|
52
55
|
|
53
56
|
start_observer
|
54
57
|
end
|
@@ -115,7 +118,10 @@ class HatenaStarStream < Net::IRC::Server::Session
|
|
115
118
|
end
|
116
119
|
}
|
117
120
|
|
118
|
-
post server_name, NOTICE, main_channel, "
|
121
|
+
post server_name, NOTICE, main_channel, "#{entry} #{title(entry)}" if s.length > 0
|
122
|
+
if @opts.key?("metadata")
|
123
|
+
post "metadata", NOTICE, main_channel, JSON.generate({ "uri" => entry })
|
124
|
+
end
|
119
125
|
|
120
126
|
s.each do |star|
|
121
127
|
post server_name, NOTICE, main_channel, "id:%s \x03%d%s%s\x030 %s" % [
|
data/examples/hig.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# vim:
|
2
|
+
# vim:encoding=UTF-8:
|
3
3
|
=begin
|
4
4
|
# hig.rb
|
5
5
|
|
@@ -90,7 +90,7 @@ Ruby's by cho45
|
|
90
90
|
$LOAD_PATH << "lib"
|
91
91
|
$LOAD_PATH << "../lib"
|
92
92
|
|
93
|
-
$KCODE = "u"
|
93
|
+
$KCODE = "u" unless defined? ::Encoding # json use this
|
94
94
|
|
95
95
|
require "rubygems"
|
96
96
|
require "net/irc"
|
@@ -227,7 +227,7 @@ class HaikuIrcGateway < Net::IRC::Server::Session
|
|
227
227
|
end
|
228
228
|
|
229
229
|
def on_privmsg(m)
|
230
|
-
return m
|
230
|
+
return m.ctcps.each {|ctcp| on_ctcp(m[0], ctcp) } if m.ctcp?
|
231
231
|
retry_count = 3
|
232
232
|
ret = nil
|
233
233
|
target, message = *m.params
|
@@ -316,7 +316,7 @@ class HaikuIrcGateway < Net::IRC::Server::Session
|
|
316
316
|
tid = args[0]
|
317
317
|
st = @tmap[tid]
|
318
318
|
if st
|
319
|
-
st["link"] = (api_base + "/#{st["user"]["screen_name"]}
|
319
|
+
st["link"] = (api_base + "/#{st["user"]["screen_name"]}/#{st["id"]}").to_s unless st["link"]
|
320
320
|
post nil, NOTICE, main_channel, st["link"]
|
321
321
|
else
|
322
322
|
post nil, NOTICE, main_channel, "No such id #{tid}"
|
@@ -343,6 +343,7 @@ class HaikuIrcGateway < Net::IRC::Server::Session
|
|
343
343
|
end
|
344
344
|
|
345
345
|
def on_join(m)
|
346
|
+
return ### なんかしらんけど何度も入ってしまってうざいので……
|
346
347
|
channels = m.params[0].split(/\s*,\s*/)
|
347
348
|
channels.each do |channel|
|
348
349
|
next if channel == main_channel
|
@@ -426,6 +427,10 @@ class HaikuIrcGateway < Net::IRC::Server::Session
|
|
426
427
|
else
|
427
428
|
message(nick, channel, "%s" % [mesg, tid])
|
428
429
|
end
|
430
|
+
|
431
|
+
if @opts.key?("metadata")
|
432
|
+
post "metadata", NOTICE, channel, JSON.generate({ "uri" => (api_base + "/#{s["user"]["screen_name"]}/#{s["id"]}").to_s })
|
433
|
+
end
|
429
434
|
end
|
430
435
|
rescue => e
|
431
436
|
@log.debug "Error: %p" % e
|
data/examples/iig.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# vim:
|
2
|
+
# vim:encoding=UTF-8:
|
3
|
+
$KCODE = "u" unless defined? ::Encoding # json use this
|
3
4
|
=begin
|
4
5
|
|
5
6
|
# iig.rb
|
@@ -100,7 +101,6 @@ Ruby's by cho45
|
|
100
101
|
=end
|
101
102
|
|
102
103
|
$LOAD_PATH << "lib" << "../lib"
|
103
|
-
$KCODE = "u" if RUBY_VERSION < "1.9" # json use this
|
104
104
|
|
105
105
|
require "rubygems"
|
106
106
|
require "net/irc"
|
@@ -241,7 +241,7 @@ class IdenticaIrcGateway < Net::IRC::Server::Session
|
|
241
241
|
end
|
242
242
|
|
243
243
|
def on_privmsg(m)
|
244
|
-
return m
|
244
|
+
return m.ctcps.each {|ctcp| on_ctcp(m[0], ctcp) } if m.ctcp?
|
245
245
|
retry_count = 3
|
246
246
|
ret = nil
|
247
247
|
target, message = *m.params
|
data/examples/ircd.rb
CHANGED
data/examples/lig.rb
ADDED
@@ -0,0 +1,551 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
=begin
|
3
|
+
|
4
|
+
# lig.rb
|
5
|
+
|
6
|
+
Lingr IRC Gateway - IRC Gateway to Lingr ( http://www.lingr.com/ )
|
7
|
+
|
8
|
+
## Launch
|
9
|
+
|
10
|
+
$ ruby lig.rb # daemonized
|
11
|
+
|
12
|
+
If you want to help:
|
13
|
+
|
14
|
+
$ ruby lig.rb --help
|
15
|
+
Usage: examples/lig.rb [opts]
|
16
|
+
|
17
|
+
|
18
|
+
Options:
|
19
|
+
-p, --port [PORT=16669] port number to listen
|
20
|
+
-h, --host [HOST=localhost] host name or IP address to listen
|
21
|
+
-l, --log LOG log file
|
22
|
+
-a, --api_key API_KEY Your api key on Lingr
|
23
|
+
--debug Enable debug mode
|
24
|
+
|
25
|
+
## Configuration
|
26
|
+
|
27
|
+
Configuration example for Tiarra ( http://coderepos.org/share/wiki/Tiarra ).
|
28
|
+
|
29
|
+
lingr {
|
30
|
+
host: localhost
|
31
|
+
port: 16669
|
32
|
+
name: username@example.com (Email on Lingr)
|
33
|
+
password: password on Lingr
|
34
|
+
in-encoding: utf8
|
35
|
+
out-encoding: utf8
|
36
|
+
}
|
37
|
+
|
38
|
+
Set your email as IRC 'real name' field, and password as server password.
|
39
|
+
This does not allow anonymous connection to Lingr.
|
40
|
+
You must create a account on Lingr and get API key (ask it first time).
|
41
|
+
|
42
|
+
## Client
|
43
|
+
|
44
|
+
This gateway sends multibyte nicknames at Lingr rooms as-is.
|
45
|
+
So you should use a client which treats it correctly.
|
46
|
+
|
47
|
+
Recommended:
|
48
|
+
|
49
|
+
* LimeChat for OSX ( http://limechat.sourceforge.net/ )
|
50
|
+
* Irssi ( http://irssi.org/ )
|
51
|
+
* (gateway) Tiarra ( http://coderepos.org/share/wiki/Tiarra )
|
52
|
+
|
53
|
+
## Nickname/Mask
|
54
|
+
|
55
|
+
nick -> nickname in a room.
|
56
|
+
o_id -> occupant_id (unique id in a room)
|
57
|
+
u_id -> user_id (unique user id in Lingr)
|
58
|
+
|
59
|
+
* Anonymous User: <nick>|<o_id>!anon@lingr.com
|
60
|
+
* Logged-in User: <nick>|<o_id>!<u_id>@lingr.com
|
61
|
+
* Your: <nick>|<u_id>!<u_id>@lingr.com
|
62
|
+
|
63
|
+
So you can see some nicknames in same user, but it is needed for
|
64
|
+
nickname management on client.
|
65
|
+
|
66
|
+
(Lingr allows different nicknames between rooms in a same user, but IRC not)
|
67
|
+
|
68
|
+
## Licence
|
69
|
+
|
70
|
+
Ruby's by cho45
|
71
|
+
|
72
|
+
## 備考
|
73
|
+
|
74
|
+
このクライアントで 1000speakers への応募はできません。lingr.com から行ってください。
|
75
|
+
|
76
|
+
=end
|
77
|
+
|
78
|
+
$LOAD_PATH << File.dirname(__FILE__)
|
79
|
+
$LOAD_PATH << "lib"
|
80
|
+
$LOAD_PATH << "../lib"
|
81
|
+
|
82
|
+
require "rubygems"
|
83
|
+
require "lingr"
|
84
|
+
require "net/irc"
|
85
|
+
require "pit"
|
86
|
+
require "mutex_m"
|
87
|
+
|
88
|
+
|
89
|
+
class LingrIrcGateway < Net::IRC::Server::Session
|
90
|
+
def server_name
|
91
|
+
"lingrgw"
|
92
|
+
end
|
93
|
+
|
94
|
+
def server_version
|
95
|
+
"0.0.0"
|
96
|
+
end
|
97
|
+
|
98
|
+
def initialize(*args)
|
99
|
+
super
|
100
|
+
@channels = {}
|
101
|
+
@channels.extend(Mutex_m)
|
102
|
+
end
|
103
|
+
|
104
|
+
def on_user(m)
|
105
|
+
super
|
106
|
+
@real, *@copts = @real.split(/\s+/)
|
107
|
+
@copts ||= []
|
108
|
+
|
109
|
+
# Tiarra sends prev nick when reconnects.
|
110
|
+
@nick.sub!(/\|.+$/, "")
|
111
|
+
|
112
|
+
log "Hello #{@nick}, this is Lingr IRC Gateway."
|
113
|
+
log "Client Option: #{@copts.join(", ")}"
|
114
|
+
@log.info "Client Option: #{@copts.join(", ")}"
|
115
|
+
@log.info "Client initialization is completed."
|
116
|
+
|
117
|
+
@lingr = Lingr::Client.new(@opts.api_key)
|
118
|
+
@lingr.create_session('human')
|
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
|
135
|
+
@user_info = @lingr.get_user_info
|
136
|
+
|
137
|
+
prefix = make_ids(@user_info)
|
138
|
+
@user_info["prefix"] = prefix
|
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
|
149
|
+
end
|
150
|
+
|
151
|
+
def on_privmsg(m)
|
152
|
+
target, message = *m.params
|
153
|
+
if @channels.key?(target.downcase)
|
154
|
+
@lingr.say(@channels[target.downcase][:ticket], message)
|
155
|
+
else
|
156
|
+
post nil, ERR_NOSUCHNICK, @user_info["prefix"].nick, target, "No such nick/channel"
|
157
|
+
end
|
158
|
+
rescue Lingr::Client::APIError => e
|
159
|
+
log "Error: #{e.code}: #{e.message}"
|
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)
|
166
|
+
end
|
167
|
+
|
168
|
+
def on_whois(m)
|
169
|
+
nick = m.params[0]
|
170
|
+
chan = nil
|
171
|
+
info = nil
|
172
|
+
|
173
|
+
@channels.each do |k, v|
|
174
|
+
if v[:users].key?(nick)
|
175
|
+
chan = k
|
176
|
+
info = v[:users][nick]
|
177
|
+
break
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
if chan
|
182
|
+
prefix = info["prefix"]
|
183
|
+
real_name = info["description"].to_s
|
184
|
+
server_info = "Lingr: type:#{info["client_type"]} source:#{info["source"]}"
|
185
|
+
channels = [info["client_type"] == "human" ? "@#{chan}" : chan]
|
186
|
+
me = @user_info["prefix"]
|
187
|
+
|
188
|
+
post nil, RPL_WHOISUSER, me.nick, prefix.nick, prefix.user, prefix.host, "*", real_name
|
189
|
+
post nil, RPL_WHOISSERVER, me.nick, prefix.nick, prefix.host, server_info
|
190
|
+
# post nil, RPL_WHOISOPERATOR, me.nick, prefix.nick, "is an IRC operator"
|
191
|
+
# post nil, RPL_WHOISIDLE, me.nick, prefix.nick, idle, "seconds idle"
|
192
|
+
post nil, RPL_WHOISCHANNELS, me.nick, prefix.nick, channels.join(" ")
|
193
|
+
post nil, RPL_ENDOFWHOIS, me.nick, prefix.nick, "End of WHOIS list"
|
194
|
+
else
|
195
|
+
post nil, ERR_NOSUCHNICK, me.nick, nick, "No such nick/channel"
|
196
|
+
end
|
197
|
+
rescue Exception => e
|
198
|
+
@log.error e.inspect
|
199
|
+
e.backtrace.each do |l|
|
200
|
+
@log.error "\t#{l}"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def on_who(m)
|
205
|
+
channel = m.params[0]
|
206
|
+
return unless channel
|
207
|
+
|
208
|
+
info = @channels.synchronize { @channels[channel.downcase] }
|
209
|
+
me = @user_info["prefix"]
|
210
|
+
res = @lingr.get_room_info(info[:chan_id], nil, info[:password])
|
211
|
+
res["occupants"].each do |o|
|
212
|
+
next unless o["nickname"]
|
213
|
+
u_id, o_id, prefix = *make_ids(o, true)
|
214
|
+
op = (o["client_type"] == "human") ? "@" : ""
|
215
|
+
post nil, RPL_WHOREPLY, me.nick, channel, o_id, "lingr.com", "lingr.com", prefix.nick, "H*#{op}", "0 #{o["description"].to_s.gsub(/\s+/, " ")}"
|
216
|
+
end
|
217
|
+
post nil, RPL_ENDOFWHO, me.nick, channel
|
218
|
+
rescue Lingr::Client::APIError => e
|
219
|
+
log "Maybe gateway don't know password for channel #{channel}. Please part and join."
|
220
|
+
end
|
221
|
+
|
222
|
+
def on_join(m)
|
223
|
+
channels = m.params[0].split(/\s*,\s*/)
|
224
|
+
password = m.params[1]
|
225
|
+
channels.each do |channel|
|
226
|
+
next if @channels.key? channel.downcase
|
227
|
+
begin
|
228
|
+
@log.debug "Enter room -> #{channel}"
|
229
|
+
res = @lingr.enter_room(channel.sub(/^#/, ""), @nick, password)
|
230
|
+
res["password"] = password
|
231
|
+
|
232
|
+
@channels.synchronize do
|
233
|
+
create_observer(channel, res)
|
234
|
+
end
|
235
|
+
rescue Lingr::Client::APIError => e
|
236
|
+
log "Error: #{e.code}: #{e.message}"
|
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
|
242
|
+
rescue Exception => e
|
243
|
+
@log.error e.inspect
|
244
|
+
e.backtrace.each do |l|
|
245
|
+
@log.error "\t#{l}"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def on_part(m)
|
252
|
+
channel = m.params[0]
|
253
|
+
info = @channels[channel.downcase]
|
254
|
+
prefix = @user_info["prefix"]
|
255
|
+
|
256
|
+
if info
|
257
|
+
info[:observer].kill
|
258
|
+
@lingr.exit_room(info[:ticket])
|
259
|
+
@channels.delete(channel.downcase)
|
260
|
+
|
261
|
+
post prefix, PART, channel, "Parted"
|
262
|
+
else
|
263
|
+
post nil, ERR_NOSUCHCHANNEL, prefix.nick, channel, "No such channel"
|
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
|
+
|
270
|
+
@channels.delete(channel.downcase)
|
271
|
+
post prefix, PART, channel, "Parted"
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def on_disconnected
|
276
|
+
@channels.each do |k, info|
|
277
|
+
info[:observer].kill
|
278
|
+
end
|
279
|
+
@session_observer.kill rescue nil
|
280
|
+
begin
|
281
|
+
@lingr.destroy_session
|
282
|
+
rescue
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
private
|
287
|
+
|
288
|
+
def create_observer(channel, response)
|
289
|
+
Thread.start(channel, response) do |chan, res|
|
290
|
+
myprefix = @user_info["prefix"]
|
291
|
+
if @channels[chan.downcase]
|
292
|
+
@channels[chan.downcase][:observer].kill rescue nil
|
293
|
+
end
|
294
|
+
@channels[chan.downcase] = {
|
295
|
+
:ticket => res["ticket"],
|
296
|
+
:counter => res["room"]["counter"],
|
297
|
+
:o_id => res["occupant_id"],
|
298
|
+
:chan_id => res["room"]["id"],
|
299
|
+
:password => res["password"],
|
300
|
+
:users => res["occupants"].reject {|i| i["nickname"].nil? }.inject({}) {|r,i|
|
301
|
+
i["prefix"] = make_ids(i)
|
302
|
+
r.update(i["prefix"].nick => i)
|
303
|
+
},
|
304
|
+
:hcounter => 0,
|
305
|
+
:observer => Thread.current,
|
306
|
+
}
|
307
|
+
|
308
|
+
post server_name, TOPIC, chan, "#{res["room"]["url"]} #{res["room"]["description"]}"
|
309
|
+
post myprefix, JOIN, channel
|
310
|
+
post server_name, MODE, channel, "+o", myprefix.nick
|
311
|
+
post nil, RPL_NAMREPLY, myprefix.nick, "=", chan, @channels[chan.downcase][:users].map{|k,v|
|
312
|
+
v["client_type"] == "human" ? "@#{k}" : k
|
313
|
+
}.join(" ")
|
314
|
+
post nil, RPL_ENDOFNAMES, myprefix.nick, chan, "End of NAMES list"
|
315
|
+
|
316
|
+
info = @channels[chan.downcase]
|
317
|
+
while true
|
318
|
+
begin
|
319
|
+
@log.debug "observe_room<#{info[:counter]}><#{chan}> start <- #{myprefix}"
|
320
|
+
res = @lingr.observe_room info[:ticket], info[:counter]
|
321
|
+
|
322
|
+
info[:counter] = res["counter"] if res["counter"]
|
323
|
+
|
324
|
+
(res["messages"] || []).each do |m|
|
325
|
+
next if m["id"].to_i <= info[:hcounter]
|
326
|
+
|
327
|
+
u_id, o_id, prefix = *make_ids(m, true)
|
328
|
+
|
329
|
+
case m["type"]
|
330
|
+
when "user"
|
331
|
+
# Don't send my messages.
|
332
|
+
unless info[:o_id] == o_id
|
333
|
+
post prefix, PRIVMSG, chan, m["text"]
|
334
|
+
end
|
335
|
+
when "private"
|
336
|
+
# TODO not sent from lingr?
|
337
|
+
post prefix, PRIVMSG, chan, ctcp_encoding("ACTION Sent private: #{m["text"]}")
|
338
|
+
|
339
|
+
# system:{enter,leave,nickname_changed} should not be used for nick management.
|
340
|
+
# when "system:enter"
|
341
|
+
# post prefix, PRIVMSG, chan, ctcp_encoding("ACTION #{m["text"]}")
|
342
|
+
# when "system:leave"
|
343
|
+
# post prefix, PRIVMSG, chan, ctcp_encoding("ACTION #{m["text"]}")
|
344
|
+
# when "system:nickname_change"
|
345
|
+
# post prefix, PRIVMSG, chan, ctcp_encoding("ACTION #{m["text"]}")
|
346
|
+
when "system:broadcast"
|
347
|
+
post "system.broadcast", NOTICE, chan, m["text"]
|
348
|
+
end
|
349
|
+
|
350
|
+
info[:hcounter] = m["id"].to_i if m["id"]
|
351
|
+
end
|
352
|
+
|
353
|
+
if res["occupants"]
|
354
|
+
enter = [], leave = []
|
355
|
+
newusers = res["occupants"].reject {|i| i["nickname"].nil? }.inject({}) {|r,i|
|
356
|
+
i["prefix"] = make_ids(i)
|
357
|
+
r.update(i["prefix"].nick => i)
|
358
|
+
}
|
359
|
+
|
360
|
+
|
361
|
+
nickchange = newusers.inject({:new => [], :old => []}) {|r,(k,new)|
|
362
|
+
old = info[:users].find {|l,old|
|
363
|
+
# same occupant_id and different nickname
|
364
|
+
# when nickname was changed and when un-authed user promoted to authed user.
|
365
|
+
new["prefix"] != old["prefix"] && new["id"] == old["id"]
|
366
|
+
}
|
367
|
+
if old
|
368
|
+
old = old[1]
|
369
|
+
post old["prefix"], NICK, new["prefix"].nick
|
370
|
+
r[:old] << old["prefix"].nick
|
371
|
+
r[:new] << new["prefix"].nick
|
372
|
+
end
|
373
|
+
r
|
374
|
+
}
|
375
|
+
|
376
|
+
entered = newusers.keys - info[:users].keys - nickchange[:new]
|
377
|
+
leaved = info[:users].keys - newusers.keys - entered - nickchange[:old]
|
378
|
+
|
379
|
+
leaved.each do |leave|
|
380
|
+
leave = info[:users][leave]
|
381
|
+
post leave["prefix"], PART, chan, ""
|
382
|
+
end
|
383
|
+
|
384
|
+
entered.each do |enter|
|
385
|
+
enter = newusers[enter]
|
386
|
+
prefix = enter["prefix"]
|
387
|
+
post prefix, JOIN, chan
|
388
|
+
if enter["client_type"] == "human"
|
389
|
+
post server_name, MODE, chan, "+o", prefix.nick
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
info[:users] = newusers
|
394
|
+
end
|
395
|
+
|
396
|
+
|
397
|
+
rescue Lingr::Client::APIError => e
|
398
|
+
case e.code
|
399
|
+
when 100
|
400
|
+
@log.fatal "BUG: API returns invalid HTTP method"
|
401
|
+
exit 1
|
402
|
+
when 102
|
403
|
+
@log.error "BUG: API returns invalid session. Prompt the client to reconnect."
|
404
|
+
finish
|
405
|
+
when 104
|
406
|
+
@log.fatal "BUG: API returns invalid response format. JSON is unsupported?"
|
407
|
+
exit 1
|
408
|
+
when 109
|
409
|
+
@log.error "Error: API returns invalid ticket. Rejoin this channel..."
|
410
|
+
on_part(Message.new(nil, PART, [chan, res["error"]["message"]]))
|
411
|
+
on_join(Message.new(nil, JOIN, [chan, info["password"]]))
|
412
|
+
when 114
|
413
|
+
@log.fatal "BUG: API returns no counter parameter."
|
414
|
+
exit 1
|
415
|
+
when 120
|
416
|
+
@log.error "Error: API returns invalid encoding. But continues."
|
417
|
+
when 122
|
418
|
+
@log.error "Error: API returns repeated counter. But continues."
|
419
|
+
info[:counter] += 10
|
420
|
+
log "Error: repeated counter. Some message may be ignored..."
|
421
|
+
else
|
422
|
+
# may be socket error?
|
423
|
+
@log.debug "observe failed : #{res.inspect}"
|
424
|
+
log "Error: #{e.code}: #{e.message}"
|
425
|
+
end
|
426
|
+
rescue Timeout::Error
|
427
|
+
# pass
|
428
|
+
rescue JSON::ParserError => e
|
429
|
+
@log.error e
|
430
|
+
info[:counter] += 10
|
431
|
+
log "Error: JSON::ParserError Some message may be ignored..."
|
432
|
+
rescue Exception => e
|
433
|
+
@log.error e.inspect
|
434
|
+
e.backtrace.each do |l|
|
435
|
+
@log.error "\t#{l}"
|
436
|
+
end
|
437
|
+
end
|
438
|
+
sleep 1
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
def log(str)
|
444
|
+
str.gsub!(/\s/, " ")
|
445
|
+
begin
|
446
|
+
post nil, NOTICE, @user_info["prefix"].nick, str
|
447
|
+
rescue
|
448
|
+
post nil, NOTICE, @nick, str
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
def make_ids(o, ext=false)
|
453
|
+
u_id = o["user_id"] || "anon"
|
454
|
+
o_id = o["occupant_id"] || o["id"]
|
455
|
+
nick = (o["default_nickname"] || o["nickname"]).gsub(/\s+/, "")
|
456
|
+
if o["user_id"] == @user_info["user_id"]
|
457
|
+
nick << "|#{o["user_id"]}"
|
458
|
+
else
|
459
|
+
nick << "|#{o["user_id"] ? o_id : "_"+o_id}"
|
460
|
+
end
|
461
|
+
pref = Prefix.new("#{nick}!#{u_id}@lingr.com")
|
462
|
+
ext ? [u_id, o_id, pref] : pref
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
|
467
|
+
if __FILE__ == $0
|
468
|
+
require "rubygems"
|
469
|
+
require "optparse"
|
470
|
+
require "pit"
|
471
|
+
|
472
|
+
opts = {
|
473
|
+
:port => 16669,
|
474
|
+
:host => "localhost",
|
475
|
+
:log => nil,
|
476
|
+
:debug => false,
|
477
|
+
:foreground => false,
|
478
|
+
}
|
479
|
+
|
480
|
+
OptionParser.new do |parser|
|
481
|
+
parser.instance_eval do
|
482
|
+
self.banner = <<-EOB.gsub(/^\t+/, "")
|
483
|
+
Usage: #{$0} [opts]
|
484
|
+
|
485
|
+
EOB
|
486
|
+
|
487
|
+
separator ""
|
488
|
+
|
489
|
+
separator "Options:"
|
490
|
+
on("-p", "--port [PORT=#{opts[:port]}]", "port number to listen") do |port|
|
491
|
+
opts[:port] = port
|
492
|
+
end
|
493
|
+
|
494
|
+
on("-h", "--host [HOST=#{opts[:host]}]", "host name or IP address to listen") do |host|
|
495
|
+
opts[:host] = host
|
496
|
+
end
|
497
|
+
|
498
|
+
on("-l", "--log LOG", "log file") do |log|
|
499
|
+
opts[:log] = log
|
500
|
+
end
|
501
|
+
|
502
|
+
on("-a", "--api_key API_KEY", "Your api key on Lingr") do |key|
|
503
|
+
opts[:api_key] = key
|
504
|
+
end
|
505
|
+
|
506
|
+
on("--debug", "Enable debug mode") do |debug|
|
507
|
+
opts[:log] = $stdout
|
508
|
+
opts[:debug] = true
|
509
|
+
end
|
510
|
+
|
511
|
+
on("-f", "--foreground", "run foreground") do |foreground|
|
512
|
+
opts[:log] = $stdout
|
513
|
+
opts[:foreground] = true
|
514
|
+
end
|
515
|
+
|
516
|
+
parse!(ARGV)
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
opts[:logger] = Logger.new(opts[:log], "daily")
|
521
|
+
opts[:logger].level = opts[:debug] ? Logger::DEBUG : Logger::INFO
|
522
|
+
|
523
|
+
def daemonize(foreground=false)
|
524
|
+
[:INT, :TERM, :HUP].each do |sig|
|
525
|
+
Signal.trap sig, "EXIT"
|
526
|
+
end
|
527
|
+
return yield if $DEBUG || foreground
|
528
|
+
Process.fork do
|
529
|
+
Process.setsid
|
530
|
+
Dir.chdir "/"
|
531
|
+
File.open("/dev/null") {|f|
|
532
|
+
STDIN.reopen f
|
533
|
+
STDOUT.reopen f, "w"
|
534
|
+
STDERR.reopen f, "w"
|
535
|
+
}
|
536
|
+
yield
|
537
|
+
end
|
538
|
+
exit! 0
|
539
|
+
end
|
540
|
+
|
541
|
+
opts[:api_key] = Pit.get("lig.rb", :require => {
|
542
|
+
"api_key" => "API key of Lingr"
|
543
|
+
})["api_key"] unless opts[:api_key]
|
544
|
+
|
545
|
+
daemonize(opts[:debug] || opts[:foreground]) do
|
546
|
+
Net::IRC::Server.new(opts[:host], opts[:port], LingrIrcGateway, opts).start
|
547
|
+
end
|
548
|
+
|
549
|
+
end
|
550
|
+
|
551
|
+
|