net-irc 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +6 -0
- data/README +14 -15
- data/Rakefile +1 -1
- data/examples/client.rb +1 -1
- data/examples/echo_bot.rb +1 -1
- data/examples/gmail.rb +2 -1
- data/examples/hatena-star-stream.rb +56 -11
- data/examples/hig.rb +54 -22
- data/examples/iig.rb +63 -86
- data/examples/ircd.rb +358 -0
- data/examples/mixi.rb +2 -1
- data/examples/sig.rb +2 -1
- data/examples/tig.rb +1671 -524
- data/examples/wig.rb +27 -27
- data/lib/net/irc.rb +36 -21
- data/lib/net/irc/client.rb +8 -2
- data/lib/net/irc/client/channel_manager.rb +13 -13
- data/lib/net/irc/constants.rb +2 -2
- data/lib/net/irc/message.rb +17 -10
- data/lib/net/irc/message/modeparser.rb +5 -5
- data/lib/net/irc/message/serverconfig.rb +3 -3
- data/lib/net/irc/pattern.rb +2 -2
- data/lib/net/irc/server.rb +8 -5
- data/spec/net-irc_spec.rb +33 -8
- metadata +16 -18
- data/examples/lig.rb +0 -551
- data/examples/lingr.rb +0 -327
- data/examples/nig.rb +0 -154
data/examples/wig.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
#
|
2
|
+
# vim:fileencoding=UTF-8:
|
3
3
|
=begin
|
4
4
|
|
5
5
|
# wig.rb
|
@@ -93,7 +93,7 @@ Ruby's by cho45
|
|
93
93
|
$LOAD_PATH << "lib"
|
94
94
|
$LOAD_PATH << "../lib"
|
95
95
|
|
96
|
-
$KCODE = "u" # json use this
|
96
|
+
$KCODE = "u" if RUBY_VERSION < "1.9" # json use this
|
97
97
|
|
98
98
|
require "rubygems"
|
99
99
|
require "net/irc"
|
@@ -145,7 +145,6 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
145
145
|
super
|
146
146
|
@channels = {}
|
147
147
|
@user_agent = "#{self.class}/#{server_version} (wig.rb)"
|
148
|
-
@map = nil
|
149
148
|
@counters = {} # for jabber fav
|
150
149
|
end
|
151
150
|
|
@@ -182,7 +181,7 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
182
181
|
log "Client Options: #{@opts.inspect}"
|
183
182
|
@log.info "Client Options: #{@opts.inspect}"
|
184
183
|
|
185
|
-
@ratio
|
184
|
+
@ratio = Struct.new(:timeline, :friends, :channel).new(*(@opts["ratio"] || "10:3:5").split(":").map {|ratio| ratio.to_f })
|
186
185
|
@footing = @ratio.inject {|r,i| r + i }
|
187
186
|
|
188
187
|
@timeline = []
|
@@ -251,7 +250,7 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
251
250
|
end
|
252
251
|
|
253
252
|
def on_privmsg(m)
|
254
|
-
return on_ctcp(m[0],
|
253
|
+
return m[1].ctcps.each {|ctcp| on_ctcp(m[0], ctcp) } if m.ctcp?
|
255
254
|
retry_count = 3
|
256
255
|
ret = nil
|
257
256
|
target, message = *m.params
|
@@ -259,7 +258,10 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
259
258
|
if target =~ /^#(.+)/
|
260
259
|
channel = Regexp.last_match[1]
|
261
260
|
reply = message[/\s+>(.+)$/, 1]
|
262
|
-
|
261
|
+
if @utf7
|
262
|
+
message = Iconv.iconv("UTF-7", "UTF-8", message).join
|
263
|
+
message = message.force_encoding("ASCII-8BIT") if message.respond_to?(:force_encoding)
|
264
|
+
end
|
263
265
|
if !reply && @opts.key?("alwaysim") && @im && @im.connected? # in jabber mode, using jabber post
|
264
266
|
message = "##{channel} #{message}" unless "##{channel}" == main_channel
|
265
267
|
ret = @im.deliver(jabber_bot_id, message)
|
@@ -314,8 +316,8 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
314
316
|
end
|
315
317
|
when "fav"
|
316
318
|
target = args[0]
|
317
|
-
st
|
318
|
-
id
|
319
|
+
st = @tmap[target]
|
320
|
+
id = rid_for(target)
|
319
321
|
if st || id
|
320
322
|
unless id
|
321
323
|
if @im && @im.connected?
|
@@ -357,7 +359,7 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
357
359
|
end
|
358
360
|
rescue ApiFailed => e
|
359
361
|
log e.inspect
|
360
|
-
end
|
362
|
+
end; private :on_ctcp
|
361
363
|
|
362
364
|
def on_whois(m)
|
363
365
|
nick = m.params[0]
|
@@ -482,8 +484,8 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
482
484
|
|
483
485
|
begin
|
484
486
|
require 'iconv'
|
485
|
-
mesg
|
486
|
-
mesg
|
487
|
+
mesg = mesg.sub(/^.+ > |^.+/) {|str| Iconv.iconv("UTF-8", "UTF-7", str).join }
|
488
|
+
mesg = "[utf7]: #{mesg}" if mesg =~ /[^a-z0-9\s]/i
|
487
489
|
rescue LoadError
|
488
490
|
rescue Iconv::IllegalSequence
|
489
491
|
end
|
@@ -575,8 +577,8 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
575
577
|
body = CGI.unescapeHTML(body)
|
576
578
|
begin
|
577
579
|
require 'iconv'
|
578
|
-
body
|
579
|
-
body
|
580
|
+
body = body.sub(/^.+ > |^.+/) {|str| Iconv.iconv("UTF-8", "UTF-7", str).join }
|
581
|
+
body = "[utf7]: #{body}" if body =~ /[^a-z0-9\s]/i
|
580
582
|
rescue LoadError
|
581
583
|
rescue Iconv::IllegalSequence
|
582
584
|
end
|
@@ -646,7 +648,7 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
646
648
|
|
647
649
|
case ret
|
648
650
|
when Net::HTTPOK # 200
|
649
|
-
ret = JSON.parse(ret.body
|
651
|
+
ret = JSON.parse(ret.body)
|
650
652
|
raise ApiFailed, "Server Returned Error: #{ret["error"]}" if ret.kind_of?(Hash) && ret["error"]
|
651
653
|
ret
|
652
654
|
when Net::HTTPNotModified # 304
|
@@ -700,20 +702,18 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
700
702
|
end
|
701
703
|
|
702
704
|
class TypableMap < Hash
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
when
|
708
|
-
|
709
|
-
else
|
710
|
-
%w|a i u e o|
|
705
|
+
Roman = %w[
|
706
|
+
k g ky gy s z sh j t d ch n ny h b p hy by py m my y r ry w v q
|
707
|
+
].unshift("").map do |consonant|
|
708
|
+
case consonant
|
709
|
+
when "y", /\A.{2}/ then %w|a u o|
|
710
|
+
when "q" then %w|a i e o|
|
711
|
+
else %w|a i u e o|
|
711
712
|
end.map {|vowel| "#{consonant}#{vowel}" }
|
712
|
-
|
713
|
+
end.flatten
|
713
714
|
|
714
|
-
def initialize(size=1)
|
715
|
-
@seq =
|
716
|
-
@map = {}
|
715
|
+
def initialize(size = 1)
|
716
|
+
@seq = Roman
|
717
717
|
@n = 0
|
718
718
|
@size = size
|
719
719
|
end
|
@@ -731,7 +731,7 @@ class WassrIrcGateway < Net::IRC::Server::Session
|
|
731
731
|
id = generate(@n)
|
732
732
|
self[id] = obj
|
733
733
|
@n += 1
|
734
|
-
@n
|
734
|
+
@n %= @seq.size ** @size
|
735
735
|
id
|
736
736
|
end
|
737
737
|
alias << push
|
data/lib/net/irc.rb
CHANGED
@@ -2,22 +2,21 @@
|
|
2
2
|
|
3
3
|
require "ostruct"
|
4
4
|
require "socket"
|
5
|
-
require "thread"
|
6
5
|
require "logger"
|
7
6
|
require "monitor"
|
8
7
|
|
9
8
|
module Net; end
|
10
9
|
|
11
10
|
module Net::IRC
|
12
|
-
VERSION = "0.0.
|
11
|
+
VERSION = "0.0.8".freeze
|
13
12
|
class IRCException < StandardError; end
|
14
13
|
|
15
14
|
require "net/irc/constants"
|
16
15
|
require "net/irc/pattern"
|
17
16
|
|
18
|
-
autoload :Message,
|
19
|
-
autoload :Client,
|
20
|
-
autoload :Server,
|
17
|
+
autoload :Message, "net/irc/message"
|
18
|
+
autoload :Client, "net/irc/client"
|
19
|
+
autoload :Server, "net/irc/server"
|
21
20
|
|
22
21
|
class Prefix < String
|
23
22
|
def nick
|
@@ -32,28 +31,44 @@ module Net::IRC
|
|
32
31
|
extract[2]
|
33
32
|
end
|
34
33
|
|
35
|
-
# Extract
|
34
|
+
# Extract Prefix String to [nick, user, host] Array.
|
36
35
|
def extract
|
37
|
-
_, *ret = *self.match(
|
36
|
+
_, *ret = *self.match(/\A([^\s!]+)(?:!([^\s@]+)@(\S+))?\z/)
|
38
37
|
ret
|
39
38
|
end
|
40
39
|
end
|
41
40
|
|
42
|
-
#
|
43
|
-
def
|
44
|
-
str
|
45
|
-
str = str.gsub(/\x10/, "\x10\x10").gsub(/\x00/, "\x10\x30").gsub(/\x0d/, "\x10r").gsub(/\x0a/, "\x10n")
|
46
|
-
"\x01#{str}\x01"
|
41
|
+
# Encode to CTCP message. Prefix and postfix \x01.
|
42
|
+
def ctcp_encode(str)
|
43
|
+
"\x01#{ctcp_quote(str)}\x01"
|
47
44
|
end
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
str
|
54
|
-
|
55
|
-
|
45
|
+
#alias :ctcp_encoding :ctcp_encode
|
46
|
+
module_function :ctcp_encode #, :ctcp_encoding
|
47
|
+
|
48
|
+
# Decode from CTCP message delimited with \x01.
|
49
|
+
def ctcp_decode(str)
|
50
|
+
ctcp_dequote(str.delete("\x01"))
|
51
|
+
end
|
52
|
+
#alias :ctcp_decoding :ctcp_decode
|
53
|
+
module_function :ctcp_decode #, :ctcp_decoding
|
54
|
+
|
55
|
+
def ctcp_quote(str)
|
56
|
+
low_quote(str.gsub("\\", "\\\\\\\\").gsub("\x01", "\\a"))
|
57
|
+
end
|
58
|
+
module_function :ctcp_quote
|
59
|
+
|
60
|
+
def ctcp_dequote(str)
|
61
|
+
low_dequote(str).gsub("\\a", "\x01").gsub(/\\(.|\z)/m, "\\1")
|
62
|
+
end
|
63
|
+
module_function :ctcp_dequote
|
64
|
+
|
65
|
+
private
|
66
|
+
def low_quote(str)
|
67
|
+
str.gsub("\x10", "\x10\x10").gsub("\x00", "\x10\x30").gsub("\r", "\x10r").gsub("\n", "\x10n")
|
68
|
+
end
|
69
|
+
|
70
|
+
def low_dequote(str)
|
71
|
+
str.gsub("\x10n", "\n").gsub("\x10r", "\r").gsub("\x10\x30", "\x00").gsub("\x10\x10", "\x10")
|
56
72
|
end
|
57
|
-
module_function :ctcp_decoding
|
58
73
|
end
|
59
74
|
|
data/lib/net/irc/client.rb
CHANGED
@@ -66,7 +66,7 @@ class Net::IRC::Client
|
|
66
66
|
# Default RPL_WELCOME callback.
|
67
67
|
# This sets @prefix from the message.
|
68
68
|
def on_rpl_welcome(m)
|
69
|
-
@prefix = Prefix.new(m[1][/\S
|
69
|
+
@prefix = Prefix.new(m[1][/\S+\z/])
|
70
70
|
end
|
71
71
|
|
72
72
|
# Default RPL_ISUPPORT callback.
|
@@ -102,7 +102,13 @@ class Net::IRC::Client
|
|
102
102
|
# post PRIVMSG, "#channel", "foobar"
|
103
103
|
def post(command, *params)
|
104
104
|
m = Message.new(nil, command, params.map {|s|
|
105
|
-
|
105
|
+
if s
|
106
|
+
s.force_encoding("ASCII-8BIT") if s.respond_to? :force_encoding
|
107
|
+
#s.gsub(/\r\n|[\r\n]/, " ")
|
108
|
+
s.tr("\r\n", " ")
|
109
|
+
else
|
110
|
+
""
|
111
|
+
end
|
106
112
|
})
|
107
113
|
|
108
114
|
@log.debug "SEND: #{m.to_s.chomp}"
|
@@ -7,12 +7,12 @@ module Net::IRC::Client::ChannelManager
|
|
7
7
|
init_channel(channel)
|
8
8
|
|
9
9
|
@channels.synchronize do
|
10
|
-
m[3].split(
|
11
|
-
_, mode, nick = *u.match(
|
10
|
+
m[3].split(" ").each do |u|
|
11
|
+
_, mode, nick = *u.match(/\A([@+]?)(.+)/)
|
12
12
|
|
13
13
|
@channels[channel][:users] << nick
|
14
14
|
@channels[channel][:users].uniq!
|
15
|
-
|
15
|
+
|
16
16
|
op = @server_config.mode_parser.mark_to_op(mode)
|
17
17
|
if op
|
18
18
|
@channels[channel][:modes] << [op, nick]
|
@@ -64,10 +64,10 @@ module Net::IRC::Client::ChannelManager
|
|
64
64
|
|
65
65
|
# For managing channel
|
66
66
|
def on_kick(m)
|
67
|
-
users = m[1].split(
|
67
|
+
users = m[1].split(",")
|
68
68
|
|
69
69
|
@channels.synchronize do
|
70
|
-
m[0].split(
|
70
|
+
m[0].split(",").each do |chan|
|
71
71
|
init_channel(chan)
|
72
72
|
info = @channels[chan]
|
73
73
|
if info
|
@@ -105,8 +105,8 @@ module Net::IRC::Client::ChannelManager
|
|
105
105
|
info[:users].map! {|i|
|
106
106
|
(i == oldnick) ? newnick : i
|
107
107
|
}
|
108
|
-
info[:modes].map! {|
|
109
|
-
(target == oldnick) ? [
|
108
|
+
info[:modes].map! {|mode, target|
|
109
|
+
(target == oldnick) ? [mode, newnick] : [mode, target]
|
110
110
|
}
|
111
111
|
end
|
112
112
|
end
|
@@ -118,17 +118,17 @@ module Net::IRC::Client::ChannelManager
|
|
118
118
|
@channels.synchronize do
|
119
119
|
init_channel(channel)
|
120
120
|
|
121
|
-
|
122
|
-
|
123
|
-
@channels[channel][:modes].delete(
|
121
|
+
modes = @server_config.mode_parser.parse(m)
|
122
|
+
modes[:negative].each do |mode|
|
123
|
+
@channels[channel][:modes].delete(mode)
|
124
124
|
end
|
125
125
|
|
126
|
-
|
127
|
-
@channels[channel][:modes] <<
|
126
|
+
modes[:positive].each do |mode|
|
127
|
+
@channels[channel][:modes] << mode
|
128
128
|
end
|
129
129
|
|
130
130
|
@channels[channel][:modes].uniq!
|
131
|
-
[
|
131
|
+
[modes[:negative], modes[:positive]]
|
132
132
|
end
|
133
133
|
end
|
134
134
|
|
data/lib/net/irc/constants.rb
CHANGED
@@ -208,7 +208,7 @@ module Net::IRC::Constants # :nodoc:
|
|
208
208
|
ISON = 'ISON'
|
209
209
|
end
|
210
210
|
|
211
|
-
Net::IRC::COMMANDS = Net::IRC::Constants.constants.inject({}) {|r,i| # :nodoc:
|
212
|
-
r.update(Net::IRC::Constants.const_get(i).to_s => i.to_s)
|
211
|
+
Net::IRC::COMMANDS = Net::IRC::Constants.constants.inject({}) {|r, i| # :nodoc:
|
212
|
+
r.update(Net::IRC::Constants.const_get(i).to_s => i.to_s.freeze)
|
213
213
|
}
|
214
214
|
|
data/lib/net/irc/message.rb
CHANGED
@@ -58,13 +58,10 @@ class Net::IRC::Message
|
|
58
58
|
if @params
|
59
59
|
f = false
|
60
60
|
@params.each do |param|
|
61
|
+
f = !f && (param.empty? || param[0] == ?: || param.include?(" "))
|
61
62
|
str << " "
|
62
|
-
|
63
|
-
|
64
|
-
f = true
|
65
|
-
else
|
66
|
-
str << param
|
67
|
-
end
|
63
|
+
str << ":" if f
|
64
|
+
str << param
|
68
65
|
end
|
69
66
|
end
|
70
67
|
|
@@ -81,12 +78,22 @@ class Net::IRC::Message
|
|
81
78
|
|
82
79
|
# If the message is CTCP, return true.
|
83
80
|
def ctcp?
|
84
|
-
message = @params[1]
|
85
|
-
message[0] == ?\01 && message[
|
81
|
+
#message = @params[1]
|
82
|
+
#message[0] == ?\01 && message[-1] == ?\01
|
83
|
+
/\x01(?>[^\x00\x01\r\n]*)\x01/ === @params[1]
|
84
|
+
end
|
85
|
+
|
86
|
+
def ctcps
|
87
|
+
messages = []
|
88
|
+
@params[1].gsub!(/\x01(?>[^\x00\x01\r\n]*)\x01/) do
|
89
|
+
messages << ctcp_decode($&)
|
90
|
+
""
|
91
|
+
end
|
92
|
+
messages
|
86
93
|
end
|
87
94
|
|
88
95
|
def inspect
|
89
|
-
|
96
|
+
"#<%s:0x%x prefix:%s command:%s params:%s>" % [
|
90
97
|
self.class,
|
91
98
|
self.object_id,
|
92
99
|
@prefix,
|
@@ -97,6 +104,6 @@ class Net::IRC::Message
|
|
97
104
|
|
98
105
|
autoload :ModeParser, "net/irc/message/modeparser"
|
99
106
|
autoload :ServerConfig, "net/irc/message/serverconfig"
|
100
|
-
autoload :ISupportModeParser, "net/irc/message/isupportmodeparser"
|
107
|
+
#autoload :ISupportModeParser, "net/irc/message/isupportmodeparser"
|
101
108
|
end # Message
|
102
109
|
|
@@ -6,7 +6,7 @@ class Net::IRC::Message::ModeParser
|
|
6
6
|
NO_PARAM = 3
|
7
7
|
|
8
8
|
def initialize
|
9
|
-
@modes
|
9
|
+
@modes = {}
|
10
10
|
@op_to_mark_map = {}
|
11
11
|
@mark_to_op_map = {}
|
12
12
|
|
@@ -14,7 +14,7 @@ class Net::IRC::Message::ModeParser
|
|
14
14
|
set(:CHANMODES, 'beIR,k,l,imnpstaqr')
|
15
15
|
set(:PREFIX, '(ov)@+')
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def mark_to_op(mark)
|
19
19
|
mark.empty? ? nil : @mark_to_op_map[mark.to_sym]
|
20
20
|
end
|
@@ -22,7 +22,7 @@ class Net::IRC::Message::ModeParser
|
|
22
22
|
def set(key, value)
|
23
23
|
case key
|
24
24
|
when :PREFIX
|
25
|
-
if value =~
|
25
|
+
if value =~ /\A\(([a-zA-Z]+)\)(.+)\z/
|
26
26
|
@op_to_mark_map = {}
|
27
27
|
key, value = Regexp.last_match[1], Regexp.last_match[2]
|
28
28
|
key.scan(/./).zip(value.scan(/./)) {|pair|
|
@@ -32,7 +32,7 @@ class Net::IRC::Message::ModeParser
|
|
32
32
|
end
|
33
33
|
when :CHANMODES
|
34
34
|
@modes = {}
|
35
|
-
value.split(
|
35
|
+
value.split(",").each_with_index do |s, kind|
|
36
36
|
s.scan(/./).each {|c|
|
37
37
|
@modes[c.to_sym] = kind
|
38
38
|
}
|
@@ -41,7 +41,7 @@ class Net::IRC::Message::ModeParser
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def parse(arg)
|
44
|
-
params = arg.kind_of?(Net::IRC::Message) ? arg.to_a : arg.split(
|
44
|
+
params = arg.kind_of?(Net::IRC::Message) ? arg.to_a : arg.split(" ")
|
45
45
|
params.shift
|
46
46
|
|
47
47
|
ret = {
|
@@ -7,13 +7,13 @@ class Net::IRC::Message::ServerConfig
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def set(arg)
|
10
|
-
params = arg.kind_of?(Net::IRC::Message) ? arg.to_a : arg.split(
|
10
|
+
params = arg.kind_of?(Net::IRC::Message) ? arg.to_a : arg.split(" ")
|
11
11
|
|
12
12
|
params[1..-1].each do |s|
|
13
13
|
case s
|
14
|
-
when
|
14
|
+
when /\A:?are supported by this server\z/
|
15
15
|
# Ignore
|
16
|
-
when
|
16
|
+
when /\A([^=]+)=(.*)\z/
|
17
17
|
key = Regexp.last_match[1].to_sym
|
18
18
|
value = Regexp.last_match[2]
|
19
19
|
@config[key] = value
|
data/lib/net/irc/pattern.rb
CHANGED
@@ -6,7 +6,7 @@ module Net::IRC::PATTERN # :nodoc:
|
|
6
6
|
# special = %x5B-60 / %x7B-7D
|
7
7
|
# ; "[", "]", "\", "`", "_", "^", "{", "|", "}"
|
8
8
|
LETTER = 'A-Za-z'
|
9
|
-
DIGIT = '
|
9
|
+
DIGIT = '0-9'
|
10
10
|
HEXDIGIT = "#{DIGIT}A-Fa-f"
|
11
11
|
SPECIAL = '\x5B-\x60\x7B-\x7D'
|
12
12
|
|
@@ -21,7 +21,7 @@ module Net::IRC::PATTERN # :nodoc:
|
|
21
21
|
SERVERNAME = HOSTNAME
|
22
22
|
|
23
23
|
# nickname = ( letter / special ) *8( letter / digit / special / "-" )
|
24
|
-
#NICKNAME = "[#{LETTER}#{SPECIAL}
|
24
|
+
#NICKNAME = "[#{LETTER}#{SPECIAL}#{DIGIT}_][-#{LETTER}#{DIGIT}#{SPECIAL}]*"
|
25
25
|
NICKNAME = "\\S+" # for multibytes
|
26
26
|
|
27
27
|
# user = 1*( %x01-09 / %x0B-0C / %x0E-1F / %x21-3F / %x41-FF )
|