]> git.lizzy.rs Git - luairc.git/blob - src/irc/channel.lua
clean up some docs
[luairc.git] / src / irc / channel.lua
1 ---
2 -- Implementation of the Channel class
3
4 -- initialization {{{
5 local base =   _G
6 local irc =    require 'irc'
7 local misc =   require 'irc.misc'
8 local socket = require 'socket'
9 local table =  require 'table'
10 -- }}}
11
12 ---
13 -- This module implements a channel object representing a single channel we
14 -- have joined.
15 module 'irc.channel'
16
17 -- object metatable {{{
18 -- TODO: this <br /> shouldn't be necessary - bug in luadoc
19 ---
20 -- An object of the Channel class represents a single joined channel. It has
21 -- several table fields, and can be used in string contexts (returning the
22 -- channel name).<br />
23 -- @class table
24 -- @name Channel
25 -- @field name     Name of the channel (read only)
26 -- @field topic    Channel topic, if set (read/write, writing to this sends a
27 --                 topic change request to the server for this channel)
28 -- @field chanmode Channel mode (public/private/secret) (read only)
29 -- @field members  Array of all members of this channel
30 local mt = {
31     -- __index() {{{
32     __index =    function(self, key)
33                      if key == "name" then
34                          return self._name
35                      elseif key == "topic" then
36                          return self._topic
37                      elseif key == "chanmode" then
38                          return self._chanmode
39                      else
40                          return _M[key]
41                      end
42                  end,
43     -- }}}
44     -- __newindex() {{{
45     __newindex = function(self, key, value)
46                      if key == "name" then
47                          return
48                      elseif key == "topic" then
49                          irc.send("TOPIC", self._name, value)
50                      elseif key == "chanmode" then
51                          return
52                      else
53                          base.rawset(self, key, value)
54                      end
55                  end,
56     -- }}}
57     -- __concat() {{{
58     __concat =   function(first, second)
59                      local first_str, second_str
60
61                      if base.type(first) == "table" then
62                          first_str = first._name
63                      else
64                          first_str = first
65                      end
66                      if base.type(second) == "table" then
67                          second_str = second._name
68                      else
69                          second_str = second
70                      end
71
72                      return first_str .. second_str
73                  end,
74     -- }}}
75     -- __tostring() {{{
76     __tostring = function(self)
77                      return self._name
78                  end
79     -- }}}
80 }
81 -- }}}
82
83 -- private methods {{{
84 -- set_basic_mode {{{
85 --
86 -- Sets a no-arg mode on a channel.
87 -- @name chan:set_basic_mode
88 -- @param self   Channel object
89 -- @param set    True to set the mode, false to unset it
90 -- @param letter Letter of the mode
91 local function set_basic_mode(self, set, letter)
92     if set then
93         irc.send("MODE", self.name, "+" .. letter)
94     else
95         irc.send("MODE", self.name, "-" .. letter)
96     end
97 end
98 -- }}}
99 -- }}}
100
101 -- constructor {{{
102 ---
103 -- Creates a new Channel object.
104 -- @param chan Name of the new channel
105 -- @return The new channel instance
106 function new(chan)
107     return base.setmetatable({_name = chan, _topic = {}, _chanmode = "",
108                               _members = {}}, mt)
109 end
110 -- }}}
111
112 -- public methods {{{
113 -- iterators {{{
114 -- each_op {{{
115 ---
116 -- Iterator over the ops in the channel
117 -- @param self Channel object
118 function each_op(self)
119     return function(state, arg)
120                return misc.value_iter(state, arg,
121                                       function(v)
122                                           return v:sub(1, 1) == "@"
123                                       end)
124            end,
125            self._members,
126            nil
127 end
128 -- }}}
129
130 -- each_voice {{{
131 ---
132 -- Iterator over the voiced users in the channel
133 -- @param self Channel object
134 function each_voice(self)
135     return function(state, arg)
136                return misc.value_iter(state, arg,
137                                       function(v)
138                                           return v:sub(1, 1) == "+"
139                                       end)
140            end,
141            self._members,
142            nil
143 end
144 -- }}}
145
146 -- each_user {{{
147 ---
148 -- Iterator over the normal users in the channel
149 -- @param self Channel object
150 function each_user(self)
151     return function(state, arg)
152                return misc.value_iter(state, arg,
153                                       function(v)
154                                           return v:sub(1, 1) ~= "@" and
155                                                  v:sub(1, 1) ~= "+"
156                                       end)
157            end,
158            self._members,
159            nil
160 end
161 -- }}}
162
163 -- each_member {{{
164 ---
165 -- Iterator over all users in the channel
166 -- @param self Channel object
167 function each_member(self)
168     return misc.value_iter, self._members, nil
169 end
170 -- }}}
171 -- }}}
172
173 -- return tables of users {{{
174 -- ops {{{
175 ---
176 -- Gets an array of all the ops in the channel.
177 -- @param self Channel object
178 -- @return Array of channel ops
179 function ops(self)
180     local ret = {}
181     for nick in self:each_op() do
182         table.insert(ret, nick)
183     end
184     return ret
185 end
186 -- }}}
187
188 -- voices {{{
189 ---
190 -- Gets an array of all the voiced users in the channel.
191 -- @param self Channel object
192 -- @return Array of channel voiced users
193 function voices(self)
194     local ret = {}
195     for nick in self:each_voice() do
196         table.insert(ret, nick)
197     end
198     return ret
199 end
200 -- }}}
201
202 -- users {{{
203 ---
204 -- Gets an array of all the normal users in the channel.
205 -- @param self Channel object
206 -- @return Array of channel normal users
207 function users(self)
208     local ret = {}
209     for nick in self:each_user() do
210         table.insert(ret, nick)
211     end
212     return ret
213 end
214 -- }}}
215
216 -- members {{{
217 ---
218 -- Gets an array of all the users in the channel.
219 -- @param self Channel object
220 -- @return Array of channel users
221 function members(self)
222     local ret = {}
223     -- not just returning self._members, since the return value shouldn't be
224     -- modifiable
225     for nick in self:each_member() do
226         table.insert(ret, nick)
227     end
228     return ret
229 end
230 -- }}}
231 -- }}}
232
233 -- setting modes {{{
234 -- ban {{{
235 -- TODO: hmmm, this probably needs an appropriate mask, rather than a nick
236 ---
237 -- Ban a user from a channel.
238 -- @param self Channel object
239 -- @param name User to ban
240 function ban(self, name)
241     irc.send("MODE", self.name, "+b", name)
242 end
243 -- }}}
244
245 -- unban {{{
246 -- TODO: same here
247 ---
248 -- Remove a ban on a user.
249 -- @param self Channel object
250 -- @param name User to unban
251 function unban(self, name)
252     irc.send("MODE", self.name, "-b", name)
253 end
254 -- }}}
255
256 -- voice {{{
257 ---
258 -- Give a user voice on a channel.
259 -- @param self Channel object
260 -- @param name User to give voice to
261 function voice(self, name)
262     irc.send("MODE", self.name, "+v", name)
263 end
264 -- }}}
265
266 -- devoice {{{
267 ---
268 -- Remove voice from a user.
269 -- @param self Channel object
270 -- @param name User to remove voice from
271 function devoice(self, name)
272     irc.send("MODE", self.name, "-v", name)
273 end
274 -- }}}
275
276 -- op {{{
277 ---
278 -- Give a user ops on a channel.
279 -- @param self Channel object
280 -- @param name User to op
281 function op(self, name)
282     irc.send("MODE", self.name, "+o", name)
283 end
284 -- }}}
285
286 -- deop {{{
287 ---
288 -- Remove ops from a user.
289 -- @param self Channel object
290 -- @param name User to remove ops from
291 function deop(self, name)
292     irc.send("MODE", self.name, "-o", name)
293 end
294 -- }}}
295
296 -- set_limit {{{
297 ---
298 -- Set a channel limit.
299 -- @param self      Channel object
300 -- @param new_limit New value for the channel limit (optional; limit is unset
301 --                  if this argument isn't passed)
302 function set_limit(self, new_limit)
303     if new_limit then
304         irc.send("MODE", self.name, "+l", new_limit)
305     else
306         irc.send("MODE", self.name, "-l")
307     end
308 end
309 -- }}}
310
311 -- set_key {{{
312 ---
313 -- Set a channel password.
314 -- @param self Channel object
315 -- @param key  New channel password (optional; password is unset if this
316 --             argument isn't passed)
317 function set_key(self, key)
318     if key then
319         irc.send("MODE", self.name, "+k", key)
320     else
321         irc.send("MODE", self.name, "-k")
322     end
323 end
324 -- }}}
325
326 -- set_private() {{{
327 ---
328 -- Set the private state of a channel.
329 -- @param self Channel object
330 -- @param set  True to set the channel as private, false to unset it
331 function set_private(self, set)
332     set_basic_mode(self, set, "p")
333 end
334 -- }}}
335
336 -- set_secret {{{
337 ---
338 -- Set the secret state of a channel.
339 -- @param self Channel object
340 -- @param set  True to set the channel as secret, false to unset it
341 function set_secret(self, set)
342     set_basic_mode(self, set, "s")
343 end
344 -- }}}
345
346 -- set_invite_only {{{
347 ---
348 -- Set whether joining the channel requires an invite.
349 -- @param self Channel object
350 -- @param set  True to set the channel invite only, false to unset it
351 function set_invite_only(self, set)
352     set_basic_mode(self, set, "i")
353 end
354 -- }}}
355
356 -- set_topic_lock {{{
357 ---
358 -- If true, the topic can only be changed by an op.
359 -- @param self Channel object
360 -- @param set  True to lock the topic, false to unlock it
361 function set_topic_lock(self, set)
362     set_basic_mode(self, set, "t")
363 end
364 -- }}}
365
366 -- set_no_outside_messages {{{
367 ---
368 -- If true, users must be in the channel to send messages to it.
369 -- @param self Channel object
370 -- @param set  True to require users to be in the channel to send messages to
371 --             it, false to remove this restriction
372 function set_no_outside_messages(self, set)
373     set_basic_mode(self, set, "n")
374 end
375 -- }}}
376
377 -- set moderated {{{
378 ---
379 -- Set whether voice is required to speak.
380 -- @param self Channel object
381 -- @param set  True to set the channel as moderated, false to unset it
382 function set_moderated(self, set)
383     set_basic_mode(self, set, "m")
384 end
385 -- }}}
386 -- }}}
387
388 -- accessors {{{
389 -- contains {{{
390 ---
391 -- Test if a user is in the channel.
392 -- @param self Channel object
393 -- @param nick Nick to search for
394 -- @return True if the nick is in the channel, false otherwise
395 function contains(self, nick)
396     for member in self:each_member() do
397         local member_nick = member:gsub('@+', '')
398         if member_nick == nick then
399             return true
400         end
401     end
402     return false
403 end
404 -- }}}
405
406 -- TODO: these four need to be made private at minimum (they are here for the
407 -- main irc module to access things), but they really should probably be
408 -- refactored out or something. definitely shouldn't be part of the public
409 -- interface.
410 -- add_user() {{{
411 function add_user(self, user, mode)
412     mode = mode or ''
413     self._members[user] = mode .. user
414 end
415 -- }}}
416
417 -- remove_user() {{{
418 function remove_user(self, user)
419     self._members[user] = nil
420 end
421 -- }}}
422
423 -- change_status() {{{
424 function change_status(self, user, on, mode)
425     if on then
426         if mode == 'o' then
427             self._members[user] = '@' .. user
428         elseif mode == 'v' then
429             self._members[user] = '+' .. user
430         end
431     else
432         if (mode == 'o' and self._members[user]:sub(1, 1) == '@') or
433            (mode == 'v' and self._members[user]:sub(1, 1) == '+') then
434             self._members[user] = user
435         end
436     end
437 end
438 -- }}}
439
440 -- change_nick {{{
441 function change_nick(self, old_nick, new_nick)
442     for member in self:each_member() do
443         local member_nick = member:gsub('@+', '')
444         if member_nick == old_nick then
445             local mode = self._members[old_nick]:sub(1, 1)
446             if mode ~= '@' and mode ~= '+' then mode = "" end
447             self._members[old_nick] = nil
448             self._members[new_nick] = mode .. new_nick
449             break
450         end
451     end
452 end
453 -- }}}
454 -- }}}
455 -- }}}