failirc 0.0.1
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/bin/failbot +162 -0
- data/bin/failircd +61 -0
- data/lib/failirc.rb +25 -0
- data/lib/failirc/client.rb +227 -0
- data/lib/failirc/client/channel.rb +98 -0
- data/lib/failirc/client/channels.rb +85 -0
- data/lib/failirc/client/client.rb +59 -0
- data/lib/failirc/client/clients.rb +43 -0
- data/lib/failirc/client/dispatcher.rb +209 -0
- data/lib/failirc/client/dispatcher/connectiondispatcher.rb +410 -0
- data/lib/failirc/client/dispatcher/event.rb +113 -0
- data/lib/failirc/client/dispatcher/eventdispatcher.rb +203 -0
- data/lib/failirc/client/module.rb +103 -0
- data/lib/failirc/client/modules/Base.rb +361 -0
- data/lib/failirc/client/modules/Logger.rb +89 -0
- data/lib/failirc/client/server.rb +89 -0
- data/lib/failirc/client/user.rb +66 -0
- data/lib/failirc/client/users.rb +100 -0
- data/lib/failirc/errors.rb +339 -0
- data/lib/failirc/extensions.rb +124 -0
- data/lib/failirc/mask.rb +117 -0
- data/lib/failirc/modes.rb +54 -0
- data/lib/failirc/responses.rb +360 -0
- data/lib/failirc/server.rb +266 -0
- data/lib/failirc/server/channel.rb +122 -0
- data/lib/failirc/server/channels.rb +84 -0
- data/lib/failirc/server/client.rb +100 -0
- data/lib/failirc/server/clients.rb +54 -0
- data/lib/failirc/server/dispatcher.rb +219 -0
- data/lib/failirc/server/dispatcher/connectiondispatcher.rb +477 -0
- data/lib/failirc/server/dispatcher/event.rb +113 -0
- data/lib/failirc/server/dispatcher/eventdispatcher.rb +196 -0
- data/lib/failirc/server/link.rb +50 -0
- data/lib/failirc/server/links.rb +49 -0
- data/lib/failirc/server/module.rb +103 -0
- data/lib/failirc/server/modules/Base.rb +2545 -0
- data/lib/failirc/server/modules/Cloaking.rb +170 -0
- data/lib/failirc/server/modules/Firewall.rb +104 -0
- data/lib/failirc/server/modules/Netlog.rb +67 -0
- data/lib/failirc/server/modules/Roulette.rb +78 -0
- data/lib/failirc/server/modules/TinyURL.rb +98 -0
- data/lib/failirc/server/modules/Translate.rb +62 -0
- data/lib/failirc/server/modules/WordFilter.rb +144 -0
- data/lib/failirc/server/user.rb +72 -0
- data/lib/failirc/server/users.rb +103 -0
- data/lib/failirc/sslutils.rb +74 -0
- data/lib/failirc/utils.rb +53 -0
- metadata +107 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
# failirc, a fail IRC library.
|
2
|
+
#
|
3
|
+
# Copyleft meh. [http://meh.doesntexist.org | meh.ffff@gmail.com]
|
4
|
+
#
|
5
|
+
# This file is part of failirc.
|
6
|
+
#
|
7
|
+
# failirc is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Affero General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# failirc is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Affero General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Affero General Public License
|
18
|
+
# along with failirc. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require 'failirc/server/module'
|
21
|
+
|
22
|
+
module IRC
|
23
|
+
|
24
|
+
class Server
|
25
|
+
|
26
|
+
module Modules
|
27
|
+
|
28
|
+
class Translate < Module
|
29
|
+
def initialize (server)
|
30
|
+
@aliases = {
|
31
|
+
:input => {
|
32
|
+
:TRANSLATE => /^TRANSLATE( |$)/i,
|
33
|
+
},
|
34
|
+
}
|
35
|
+
|
36
|
+
@events = {
|
37
|
+
:custom => {
|
38
|
+
:message => Event::Callback.new(self.method(:netlog), -50),
|
39
|
+
},
|
40
|
+
|
41
|
+
:input => {
|
42
|
+
:TRANSLATE => self.method(:set),
|
43
|
+
},
|
44
|
+
}
|
45
|
+
|
46
|
+
super(server)
|
47
|
+
end
|
48
|
+
|
49
|
+
def translate (chain, from, to, message, level)
|
50
|
+
if chain == :input
|
51
|
+
|
52
|
+
elsif chain == :output
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# failirc, a fail IRC library.
|
2
|
+
#
|
3
|
+
# Copyleft meh. [http://meh.doesntexist.org | meh.ffff@gmail.com]
|
4
|
+
#
|
5
|
+
# This file is part of failirc.
|
6
|
+
#
|
7
|
+
# failirc is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Affero General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# failirc is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Affero General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Affero General Public License
|
18
|
+
# along with failirc. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require 'failirc/extensions'
|
21
|
+
require 'failirc/modes'
|
22
|
+
|
23
|
+
require 'failirc/server/module'
|
24
|
+
|
25
|
+
module IRC
|
26
|
+
|
27
|
+
class Server
|
28
|
+
|
29
|
+
module Modules
|
30
|
+
|
31
|
+
class WordFilter < Module
|
32
|
+
def initialize (server)
|
33
|
+
@events = {
|
34
|
+
:custom => {
|
35
|
+
:message => Event::Callback.new(self.method(:filter), -1),
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
super(server)
|
40
|
+
end
|
41
|
+
|
42
|
+
def rehash
|
43
|
+
# config for the rainbow filter
|
44
|
+
if tmp = @server.config.elements['config/modules/module[@name="WordFilter"]/rainbow']
|
45
|
+
@rainbow = tmp.text
|
46
|
+
else
|
47
|
+
@rainbow = 'rrRRyyYYGGggccCCBBppPP'
|
48
|
+
end
|
49
|
+
|
50
|
+
# config for the replaces filter
|
51
|
+
@replaces = []
|
52
|
+
|
53
|
+
if tmp = @server.config.elements['config/modules/module[@name="WordFilter"]/replaces']
|
54
|
+
tmp.elements.each('replace') {|element|
|
55
|
+
@replaces.push({ :from => element.attributes['word'], :to => element.attributes['with'] })
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def filter (chain, fromRef, toRef, message, level=nil)
|
61
|
+
if chain != :input
|
62
|
+
return
|
63
|
+
end
|
64
|
+
|
65
|
+
from = fromRef.value
|
66
|
+
to = toRef.value
|
67
|
+
|
68
|
+
if to.is_a?(Channel)
|
69
|
+
channel = to.modes
|
70
|
+
|
71
|
+
if user = to.user(from)
|
72
|
+
user = user.modes
|
73
|
+
else
|
74
|
+
user = Modes.new
|
75
|
+
end
|
76
|
+
else
|
77
|
+
channel = Modes.new
|
78
|
+
user = Modes.new
|
79
|
+
end
|
80
|
+
|
81
|
+
client = from.modes
|
82
|
+
|
83
|
+
if channel[:extended][:gay] || client[:extended][:gay] || user[:extended][:gay]
|
84
|
+
rainbow(message, 'rrRRyyYYGGggccCCBBppPP')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def rainbow (string, pattern=@rainbow)
|
89
|
+
string.gsub!(/\x03((\d{1,2})?(,\d{1,2})?)?/, '')
|
90
|
+
|
91
|
+
result = ''
|
92
|
+
position = 0
|
93
|
+
|
94
|
+
string.each_char {|char|
|
95
|
+
if position >= pattern.length
|
96
|
+
position = 0
|
97
|
+
end
|
98
|
+
|
99
|
+
result << WordFilter.color(pattern[position, 1]) << char
|
100
|
+
position += 1
|
101
|
+
}
|
102
|
+
|
103
|
+
string.replace result
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.color (char)
|
107
|
+
if !char
|
108
|
+
return ''
|
109
|
+
end
|
110
|
+
|
111
|
+
color = @@colors[char.to_sym]
|
112
|
+
|
113
|
+
if color
|
114
|
+
return "\x03#{'%02d' % color}"
|
115
|
+
else
|
116
|
+
return "\x03"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
@@colors = {
|
121
|
+
:w => 15,
|
122
|
+
:W => 0,
|
123
|
+
:n => 1,
|
124
|
+
:N => 14,
|
125
|
+
:b => 2,
|
126
|
+
:B => 12,
|
127
|
+
:g => 3,
|
128
|
+
:G => 9,
|
129
|
+
:r => 5,
|
130
|
+
:R => 4,
|
131
|
+
:c => 10,
|
132
|
+
:C => 11,
|
133
|
+
:p => 6,
|
134
|
+
:P => 13,
|
135
|
+
:y => 7,
|
136
|
+
:Y => 8,
|
137
|
+
}
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# failirc, a fail IRC library.
|
2
|
+
#
|
3
|
+
# Copyleft meh. [http://meh.doesntexist.org | meh.ffff@gmail.com]
|
4
|
+
#
|
5
|
+
# This file is part of failirc.
|
6
|
+
#
|
7
|
+
# failirc is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Affero General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# failirc is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Affero General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Affero General Public License
|
18
|
+
# along with failirc. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
module IRC
|
21
|
+
|
22
|
+
class Server
|
23
|
+
|
24
|
+
class User
|
25
|
+
attr_reader :client, :channel, :modes
|
26
|
+
|
27
|
+
def initialize (client, channel, modes=Modes.new)
|
28
|
+
@client = client
|
29
|
+
@channel = channel
|
30
|
+
@modes = modes
|
31
|
+
end
|
32
|
+
|
33
|
+
def mask
|
34
|
+
@client.mask
|
35
|
+
end
|
36
|
+
|
37
|
+
def server
|
38
|
+
@client.server
|
39
|
+
end
|
40
|
+
|
41
|
+
def nick
|
42
|
+
@client.nick
|
43
|
+
end
|
44
|
+
|
45
|
+
def user
|
46
|
+
@client.user
|
47
|
+
end
|
48
|
+
|
49
|
+
def host
|
50
|
+
@client.host
|
51
|
+
end
|
52
|
+
|
53
|
+
def realName
|
54
|
+
@client.realName
|
55
|
+
end
|
56
|
+
|
57
|
+
def send (type, *args)
|
58
|
+
@client.send(type, *args)
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_s
|
62
|
+
return "#{modes[:level]}#{nick}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def inspect
|
66
|
+
return "#<User: #{client.inspect} #{channel.inspect} #{modes.inspect}>"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# failirc, a fail IRC library.
|
2
|
+
#
|
3
|
+
# Copyleft meh. [http://meh.doesntexist.org | meh.ffff@gmail.com]
|
4
|
+
#
|
5
|
+
# This file is part of failirc.
|
6
|
+
#
|
7
|
+
# failirc is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Affero General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# failirc is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Affero General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Affero General Public License
|
18
|
+
# along with failirc. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require 'failirc/extensions'
|
21
|
+
|
22
|
+
require 'failirc/server/user'
|
23
|
+
|
24
|
+
module IRC
|
25
|
+
|
26
|
+
class Server
|
27
|
+
|
28
|
+
class Users < ThreadSafeHash
|
29
|
+
attr_reader :server, :channel
|
30
|
+
|
31
|
+
def initialize (channel, *args)
|
32
|
+
@server = channel.server
|
33
|
+
@channel = channel
|
34
|
+
|
35
|
+
super(*args)
|
36
|
+
end
|
37
|
+
|
38
|
+
def server
|
39
|
+
@channel.server
|
40
|
+
end
|
41
|
+
|
42
|
+
alias __get []
|
43
|
+
|
44
|
+
def [] (user)
|
45
|
+
if user.is_a?(Client) || user.is_a?(User)
|
46
|
+
user = user.nick
|
47
|
+
end
|
48
|
+
|
49
|
+
__get(user)
|
50
|
+
end
|
51
|
+
|
52
|
+
alias __set []=
|
53
|
+
|
54
|
+
def []= (user, value)
|
55
|
+
if user.is_a?(Client) || user.is_a?(User)
|
56
|
+
user = user.nick
|
57
|
+
end
|
58
|
+
|
59
|
+
__set(user, value)
|
60
|
+
end
|
61
|
+
|
62
|
+
alias __delete delete
|
63
|
+
|
64
|
+
def delete (key)
|
65
|
+
if key.is_a?(User) || key.is_a?(Client)
|
66
|
+
key = key.nick
|
67
|
+
end
|
68
|
+
|
69
|
+
key = key.downcase
|
70
|
+
|
71
|
+
user = self[key]
|
72
|
+
|
73
|
+
if user
|
74
|
+
__delete(key)
|
75
|
+
|
76
|
+
if channel.empty?
|
77
|
+
server.channels.delete(channel)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
return user
|
82
|
+
end
|
83
|
+
|
84
|
+
def add (user)
|
85
|
+
if user.is_a?(Client)
|
86
|
+
self[user.nick] = User.new(user, @channel)
|
87
|
+
elsif user.is_a?(User)
|
88
|
+
self[user.nick] = user
|
89
|
+
else
|
90
|
+
raise 'You can only add Client or User.'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def send (*args)
|
95
|
+
each_value {|user|
|
96
|
+
user.send(*args)
|
97
|
+
}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# failirc, a fail IRC library.
|
2
|
+
#
|
3
|
+
# Copyleft meh. [http://meh.doesntexist.org | meh.ffff@gmail.com]
|
4
|
+
#
|
5
|
+
# This file is part of failirc.
|
6
|
+
#
|
7
|
+
# failirc is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Affero General Public License as published
|
9
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# failirc is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Affero General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Affero General Public License
|
18
|
+
# along with failirc. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require 'openssl'
|
21
|
+
|
22
|
+
module IRC
|
23
|
+
|
24
|
+
module SSLUtils
|
25
|
+
def self.selfSignedCertificate (bits, comment)
|
26
|
+
rsa = OpenSSL::PKey::RSA.new(bits)
|
27
|
+
|
28
|
+
cert = OpenSSL::X509::Certificate.new
|
29
|
+
cert.version = 3
|
30
|
+
cert.serial = 0
|
31
|
+
name = OpenSSL::X509::Name.new
|
32
|
+
cert.subject = name
|
33
|
+
cert.issuer = name
|
34
|
+
cert.not_before = Time.now
|
35
|
+
cert.not_after = Time.now + (365*24*60*60)
|
36
|
+
cert.public_key = rsa.public_key
|
37
|
+
|
38
|
+
ef = OpenSSL::X509::ExtensionFactory.new(nil, cert)
|
39
|
+
ef.issuer_certificate = cert
|
40
|
+
|
41
|
+
cert.extensions = [
|
42
|
+
ef.create_extension('basicConstraints', 'CA:FALSE'),
|
43
|
+
ef.create_extension('keyUsage', 'keyEncipherment'),
|
44
|
+
ef.create_extension('subjectKeyIdentifier', 'hash'),
|
45
|
+
ef.create_extension('extendedKeyUsage', 'serverAuth'),
|
46
|
+
ef.create_extension('nsComment', comment),
|
47
|
+
]
|
48
|
+
|
49
|
+
aki = ef.create_extension('authorityKeyIdentifier', 'keyid:always,issuer:always')
|
50
|
+
cert.add_extension(aki)
|
51
|
+
cert.sign(rsa, OpenSSL::Digest::SHA1.new)
|
52
|
+
|
53
|
+
return [cert, rsa]
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.context (cert, key)
|
57
|
+
context = OpenSSL::SSL::SSLContext.new
|
58
|
+
|
59
|
+
if !cert
|
60
|
+
comment = 'Generated by Ruby/OpenSSL'
|
61
|
+
cert, key = self.selfSignedCertificate(1024, comment)
|
62
|
+
else
|
63
|
+
cert = OpenSSL::X509::Certificate.new(cert.is_a?(File) ? cert.read : File.read(cert))
|
64
|
+
key = OpenSSL::PKey::RSA.new(key.is_a?(File) ? key.read : File.read(key))
|
65
|
+
end
|
66
|
+
|
67
|
+
context.cert = cert
|
68
|
+
context.key = key
|
69
|
+
|
70
|
+
return context
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|