2 -- Implementation of the Channel class
6 local irc = require 'irc'
7 local misc = require 'irc.misc'
8 local socket = require 'socket'
9 local table = require 'table'
13 -- This module implements a channel object representing a single channel we
18 -- object metatable {{{
19 -- TODO: this <br /> shouldn't be necessary - bug in luadoc
21 -- An object of the Channel class represents a single joined channel. It has
22 -- several table fields, and can be used in string contexts (returning the
23 -- channel name).<br />
26 -- @field name Name of the channel (read only)
27 -- @field topic Channel topic, if set (read/write, writing to this sends a
28 -- topic change request to the server for this channel)
29 -- @field chanmode Channel mode (public/private/secret) (read only)
30 -- @field members Array of all members of this channel
33 __index = function(self, key)
36 elseif key == "topic" then
38 elseif key == "chanmode" then
46 __newindex = function(self, key, value)
49 elseif key == "topic" then
50 irc.send("TOPIC", self._name, value)
51 elseif key == "chanmode" then
54 base.rawset(self, key, value)
59 __concat = function(first, second)
60 local first_str, second_str
62 if base.type(first) == "table" then
63 first_str = first._name
67 if base.type(second) == "table" then
68 second_str = second._name
73 return first_str .. second_str
77 __tostring = function(self)
84 -- private methods {{{
87 -- Sets a no-arg mode on a channel.
88 -- @name chan:set_basic_mode
89 -- @param self Channel object
90 -- @param set True to set the mode, false to unset it
91 -- @param letter Letter of the mode
92 local function set_basic_mode(self, set, letter)
94 irc.send("MODE", self.name, "+" .. letter)
96 irc.send("MODE", self.name, "-" .. letter)
104 -- Creates a new Channel object.
105 -- @param chan Name of the new channel
106 -- @return The new channel instance
108 return base.setmetatable({_name = chan, _topic = {}, _chanmode = "",
113 -- public methods {{{
117 -- Iterator over the ops in the channel
118 -- @param self Channel object
119 function each_op(self)
120 return function(state, arg)
121 return misc.value_iter(state, arg,
123 return v:sub(1, 1) == "@"
133 -- Iterator over the voiced users in the channel
134 -- @param self Channel object
135 function each_voice(self)
136 return function(state, arg)
137 return misc.value_iter(state, arg,
139 return v:sub(1, 1) == "+"
149 -- Iterator over the normal users in the channel
150 -- @param self Channel object
151 function each_user(self)
152 return function(state, arg)
153 return misc.value_iter(state, arg,
155 return v:sub(1, 1) ~= "@" and
166 -- Iterator over all users in the channel
167 -- @param self Channel object
168 function each_member(self)
169 return misc.value_iter, self._members, nil
174 -- return tables of users {{{
177 -- Gets an array of all the ops in the channel.
178 -- @param self Channel object
179 -- @return Array of channel ops
182 for nick in self:each_op() do
183 table.insert(ret, nick)
191 -- Gets an array of all the voiced users in the channel.
192 -- @param self Channel object
193 -- @return Array of channel voiced users
194 function voices(self)
196 for nick in self:each_voice() do
197 table.insert(ret, nick)
205 -- Gets an array of all the normal users in the channel.
206 -- @param self Channel object
207 -- @return Array of channel normal users
210 for nick in self:each_user() do
211 table.insert(ret, nick)
219 -- Gets an array of all the users in the channel.
220 -- @param self Channel object
221 -- @return Array of channel users
222 function members(self)
224 -- not just returning self._members, since the return value shouldn't be
226 for nick in self:each_member() do
227 table.insert(ret, nick)
236 -- TODO: hmmm, this probably needs an appropriate mask, rather than a nick
238 -- Ban a user from a channel.
239 -- @param self Channel object
240 -- @param name User to ban
241 function ban(self, name)
242 irc.send("MODE", self.name, "+b", name)
249 -- Remove a ban on a user.
250 -- @param self Channel object
251 -- @param name User to unban
252 function unban(self, name)
253 irc.send("MODE", self.name, "-b", name)
259 -- Give a user voice on a channel.
260 -- @param self Channel object
261 -- @param name User to give voice to
262 function voice(self, name)
263 irc.send("MODE", self.name, "+v", name)
269 -- Remove voice from a user.
270 -- @param self Channel object
271 -- @param name User to remove voice from
272 function devoice(self, name)
273 irc.send("MODE", self.name, "-v", name)
279 -- Give a user ops on a channel.
280 -- @param self Channel object
281 -- @param name User to op
282 function op(self, name)
283 irc.send("MODE", self.name, "+o", name)
289 -- Remove ops from a user.
290 -- @param self Channel object
291 -- @param name User to remove ops from
292 function deop(self, name)
293 irc.send("MODE", self.name, "-o", name)
299 -- Set a channel limit.
300 -- @param self Channel object
301 -- @param new_limit New value for the channel limit (optional; limit is unset
302 -- if this argument isn't passed)
303 function set_limit(self, new_limit)
305 irc.send("MODE", self.name, "+l", new_limit)
307 irc.send("MODE", self.name, "-l")
314 -- Set a channel password.
315 -- @param self Channel object
316 -- @param key New channel password (optional; password is unset if this
317 -- argument isn't passed)
318 function set_key(self, key)
320 irc.send("MODE", self.name, "+k", key)
322 irc.send("MODE", self.name, "-k")
329 -- Set the private state of a channel.
330 -- @param self Channel object
331 -- @param set True to set the channel as private, false to unset it
332 function set_private(self, set)
333 set_basic_mode(self, set, "p")
339 -- Set the secret state of a channel.
340 -- @param self Channel object
341 -- @param set True to set the channel as secret, false to unset it
342 function set_secret(self, set)
343 set_basic_mode(self, set, "s")
347 -- set_invite_only {{{
349 -- Set whether joining the channel requires an invite.
350 -- @param self Channel object
351 -- @param set True to set the channel invite only, false to unset it
352 function set_invite_only(self, set)
353 set_basic_mode(self, set, "i")
357 -- set_topic_lock {{{
359 -- If true, the topic can only be changed by an op.
360 -- @param self Channel object
361 -- @param set True to lock the topic, false to unlock it
362 function set_topic_lock(self, set)
363 set_basic_mode(self, set, "t")
367 -- set_no_outside_messages {{{
369 -- If true, users must be in the channel to send messages to it.
370 -- @param self Channel object
371 -- @param set True to require users to be in the channel to send messages to
372 -- it, false to remove this restriction
373 function set_no_outside_messages(self, set)
374 set_basic_mode(self, set, "n")
380 -- Set whether voice is required to speak.
381 -- @param self Channel object
382 -- @param set True to set the channel as moderated, false to unset it
383 function set_moderated(self, set)
384 set_basic_mode(self, set, "m")
391 function add_user(self, user, mode)
393 self._members[user] = mode .. user
398 function remove_user(self, user)
399 self._members[user] = nil
403 -- change_status() {{{
404 function change_status(self, user, on, mode)
407 self._members[user] = '@' .. user
408 elseif mode == 'v' then
409 self._members[user] = '+' .. user
412 if (mode == 'o' and self._members[user]:sub(1, 1) == '@') or
413 (mode == 'v' and self._members[user]:sub(1, 1) == '+') then
414 self._members[user] = user
421 function contains(self, nick)
422 for member in self:each_member() do
423 local member_nick = member:gsub('@+', '')
424 if member_nick == nick then
433 function change_nick(self, old_nick, new_nick)
434 for member in self:each_member() do
435 local member_nick = member:gsub('@+', '')
436 if member_nick == old_nick then
437 local mode = self._members[old_nick]:sub(1, 1)
438 if mode ~= '@' and mode ~= '+' then mode = "" end
439 self._members[old_nick] = nil
440 self._members[new_nick] = mode .. new_nick