forked from ldilley/rubircd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
channel.rb
231 lines (207 loc) · 6.64 KB
/
channel.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# RubIRCd - An IRC server written in Ruby
# Copyright (C) 2013 Lloyd Dilley (see authors.txt for details)
# http://www.rubircd.rocks/
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# Represents a ban record
class Ban
def initialize(creator, mask, reason)
@creator = creator
@mask = mask
@reason = reason
@create_timestamp = Time.now.to_i
end
attr_reader :creator, :mask, :reason, :create_timestamp
end
# Contains the properties of an IRC channel along
# with some static utility methods
class Channel
MODE_ADMIN = 'a' # server administrator
FLAG_ADMIN = '&'
MODE_OPER = 'z' # IRC operator
FLAG_OPER = '!'
MODE_CHANOP = 'o' # channel operator
FLAG_CHANOP = '@'
MODE_HALFOP = 'h' # half operator
FLAG_HALFOP = '%'
MODE_VOICE = 'v' # can chat in moderated channels
FLAG_VOICE = '+'
MODE_FOUNDER = 'f' # if nick is registered and is founder of the channel
FLAG_FOUNDER = '~'
MODE_BAN = 'b' # ban
MODE_INVITE = 'i' # invite only
MODE_LOCKED = 'k' # key set
MODE_LIMIT = 'l' # limit set
MODE_MODERATED = 'm' # only voiced users can chat
MODE_NOEXTERN = 'n' # no external PRIVMSG
MODE_PRIVATE = 'p' # will not show up in LIST output
MODE_REGISTERED = 'r' # channel is registered
MODE_SECRET = 's' # will not show up in LIST or WHOIS output
MODE_TOPIC = 't' # only channel operators can change topic
CHANNEL_MODES = 'abfhiklmnoprstvz'
ISUPPORT_CHANNEL_MODES = 'b,k,l,imnprst' # comma-separated modes that accept arguments -- needed for numeric 005 (RPL_ISUPPORT)
ISUPPORT_PREFIX = '(azfohv)&!~@%+'
def initialize(name, founder)
@bans = []
@name = name
@key = nil
@limit = nil
@modes = []
@modes.push('n')
@modes.push('t')
@topic = ''
@topic_author = nil
@topic_time = nil
@users = []
@invisible_users = [] # users who IJOIN
@url = nil
@founder = founder
@registered = false
@create_timestamp = Time.now.to_i
return unless Options.io_type.to_s == 'thread'
@bans_lock = Mutex.new
@modes_lock = Mutex.new
@topic_lock = Mutex.new
@users_lock = Mutex.new
end
def key=(key)
@mode_lock.lock if Options.io_type.to_s == 'thread'
@key = key
@mode_lock.unlock if Options.io_type.to_s == 'thread'
end
def limit=(limit)
@mode_lock.lock if Options.io_type.to_s == 'thread'
@limit = limit
@mode_lock.unlock if Options.io_type.to_s == 'thread'
end
def self.valid_channel_name?(channel)
if channel =~ /^[#][A-Za-z0-9_!-]*$/
return true
else
return false
end
end
def self.valid_ban?(ban_mask)
# TODO: Validate ban masks
end
def add_ban(creator, mask, reason)
@bans_lock.lock if Options.io_type.to_s == 'thread'
ban = Ban.new(creator, mask, reason)
@bans.push(ban)
@bans_lock.unlock if Options.io_type.to_s == 'thread'
end
def remove_ban(mask)
@bans_lock.lock if Options.io_type.to_s == 'thread'
@bans.each do |ban|
next unless ban.mask == mask
@bans.delete(ban)
# TODO: else send appropriate RPL
end
@bans_lock.unlock if Options.io_type.to_s == 'thread'
end
def add_mode(mode)
@modes_lock.lock if Options.io_type.to_s == 'thread'
@modes.push(mode)
@modes_lock.unlock if Options.io_type.to_s == 'thread'
end
def remove_mode(mode)
@modes_lock.lock if Options.io_type.to_s == 'thread'
@modes.delete(mode)
@modes_lock.unlock if Options.io_type.to_s == 'thread'
end
def clear_modes
@modes_lock.lock if Options.io_type.to_s == 'thread'
@modes.clear
@modes_lock.unlock if Options.io_type.to_s == 'thread'
end
def mode?(mode)
if Options.io_type.to_s == 'thread'
@modes_lock.synchronize { @modes.include?(mode) }
else
@modes.include?(mode)
end
end
def set_topic(user, new_topic)
@topic_lock.lock if Options.io_type.to_s == 'thread'
@topic_author = "#{user.nick}!#{user.ident}@#{user.hostname}"
@topic = new_topic
@topic_time = Time.now.to_i
@topic_lock.unlock if Options.io_type.to_s == 'thread'
end
def registered=(registered)
@modes_lock.lock if Options.io_type.to_s == 'thread'
@registered = registered
@modes_lock.unlock if Options.io_type.to_s == 'thread'
end
def clear_topic
@topic_lock.lock if Options.io_type.to_s == 'thread'
@topic_author = ''
@topic = ''
@topic_time = ''
@topic_lock.unlock if Options.io_type.to_s == 'thread'
end
def nick_in_channel?(nick)
if Options.io_type.to_s == 'thread'
@users_lock.synchronize do
@users.each do |u|
return true if u.nick.casecmp(nick) == 0
end
end
return false
else
@users.each do |u|
return true if u.nick.casecmp(nick) == 0
end
return false
end
end
def invisible_nick_in_channel?(nick)
if Options.io_type.to_s == 'thread'
@users_lock.synchronize do
@invisible_users.each do |iu|
return true if iu.nick.casecmp(nick) == 0
end
end
return false
else
@invisible_users.each do |iu|
return true if iu.nick.casecmp(nick) == 0
end
return false
end
end
def add_user(user)
@users_lock.lock if Options.io_type.to_s == 'thread'
user_ref = user
@users.push(user_ref)
@users_lock.unlock if Options.io_type.to_s == 'thread'
end
def remove_user(user)
@users_lock.lock if Options.io_type.to_s == 'thread'
@users.delete(user)
@users_lock.unlock if Options.io_type.to_s == 'thread'
end
def add_invisible_user(user)
@users_lock.lock if Options.io_type.to_s == 'thread'
@invisible_users << user
@users_lock.unlock if Options.io_type.to_s == 'thread'
end
def remove_invisible_user(user)
@users_lock.lock if Options.io_type.to_s == 'thread'
@invisible_users.delete(user)
@users_lock.unlock if Options.io_type.to_s == 'thread'
end
attr_reader :bans, :name, :key, :limit, :modes, :topic, :topic_author, :topic_time, :users, :invisible_users, :url, :founder, :registered, :create_timestamp
end