]> git.lizzy.rs Git - luairc.git/blob - src/irc/channel.lua
start documenting the channel class
[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 -- @release 0.02
16 module 'irc.channel'
17
18 -- object metatable {{{
19 -- TODO: this <br /> shouldn't be necessary - bug in luadoc
20 ---
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 />
24 -- @class table
25 -- @name Channel
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
31 local mt = {
32     -- __index() {{{
33     __index =    function(self, key)
34                      if key == "name" then
35                          return self._name
36                      elseif key == "topic" then
37                          return self._topic
38                      elseif key == "chanmode" then
39                          return self._chanmode
40                      else
41                          return _M[key]
42                      end
43                  end,
44     -- }}}
45     -- __newindex() {{{
46     __newindex = function(self, key, value)
47                      if key == "name" then
48                          return
49                      elseif key == "topic" then
50                          irc.send("TOPIC", self._name, value)
51                      elseif key == "chanmode" then
52                          return
53                      else
54                          base.rawset(self, key, value)
55                      end
56                  end,
57     -- }}}
58     -- __concat() {{{
59     __concat =   function(first, second)
60                      local first_str, second_str
61
62                      if base.type(first) == "table" then
63                          first_str = first._name
64                      else
65                          first_str = first
66                      end
67                      if base.type(second) == "table" then
68                          second_str = second._name
69                      else
70                          second_str = second
71                      end
72
73                      return first_str .. second_str
74                  end,
75     -- }}}
76     -- __tostring() {{{
77     __tostring = function(self)
78                      return self._name
79                  end
80     -- }}}
81 }
82 -- }}}
83
84 -- private methods {{{
85 -- set_basic_mode {{{
86 --
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)
93     if set then
94         irc.send("MODE", self.name, "+" .. letter)
95     else
96         irc.send("MODE", self.name, "-" .. letter)
97     end
98 end
99 -- }}}
100 -- }}}
101
102 -- constructor {{{
103 ---
104 -- Creates a new Channel object.
105 -- @param chan Name of the new channel
106 -- @return The new channel instance
107 function new(chan)
108     return base.setmetatable({_name = chan, _topic = {}, _chanmode = "",
109                               _members = {}}, mt)
110 end
111 -- }}}
112
113 -- public methods {{{
114 -- iterators {{{
115 -- each_op {{{
116 ---
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,
122                                       function(v)
123                                           return v:sub(1, 1) == "@"
124                                       end)
125            end,
126            self._members,
127            nil
128 end
129 -- }}}
130
131 -- each_voice {{{
132 ---
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,
138                                       function(v)
139                                           return v:sub(1, 1) == "+"
140                                       end)
141            end,
142            self._members,
143            nil
144 end
145 -- }}}
146
147 -- each_user {{{
148 ---
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,
154                                       function(v)
155                                           return v:sub(1, 1) ~= "@" and
156                                                  v:sub(1, 1) ~= "+"
157                                       end)
158            end,
159            self._members,
160            nil
161 end
162 -- }}}
163
164 -- each_member {{{
165 ---
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
170 end
171 -- }}}
172 -- }}}
173
174 -- return tables of users {{{
175 -- ops {{{
176 ---
177 -- Gets an array of all the ops in the channel.
178 -- @param self Channel object
179 -- @return Array of channel ops
180 function ops(self)
181     local ret = {}
182     for nick in self:each_op() do
183         table.insert(ret, nick)
184     end
185     return ret
186 end
187 -- }}}
188
189 -- voices {{{
190 ---
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)
195     local ret = {}
196     for nick in self:each_voice() do
197         table.insert(ret, nick)
198     end
199     return ret
200 end
201 -- }}}
202
203 -- users {{{
204 ---
205 -- Gets an array of all the normal users in the channel.
206 -- @param self Channel object
207 -- @return Array of channel normal users
208 function users(self)
209     local ret = {}
210     for nick in self:each_user() do
211         table.insert(ret, nick)
212     end
213     return ret
214 end
215 -- }}}
216
217 -- members {{{
218 ---
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)
223     local ret = {}
224     -- not just returning self._members, since the return value shouldn't be
225     -- modifiable
226     for nick in self:each_member() do
227         table.insert(ret, nick)
228     end
229     return ret
230 end
231 -- }}}
232 -- }}}
233
234 -- setting modes {{{
235 -- ban() - ban a user from a channel {{{
236 -- TODO: hmmm, this probably needs an appropriate mask, rather than a nick
237 function ban(self, name)
238     irc.send("MODE", self.name, "+b", name)
239 end
240 -- }}}
241
242 -- unban() - remove a ban on a user {{{
243 -- TODO: same here
244 function unban(self, name)
245     irc.send("MODE", self.name, "-b", name)
246 end
247 -- }}}
248
249 -- voice() - give a user voice on a channel {{{
250 function voice(self, name)
251     irc.send("MODE", self.name, "+v", name)
252 end
253 -- }}}
254
255 -- devoice() - remove voice from a user {{{
256 function devoice(self, name)
257     irc.send("MODE", self.name, "-v", name)
258 end
259 -- }}}
260
261 -- op() - give a user ops on a channel {{{
262 function op(self, name)
263     irc.send("MODE", self.name, "+o", name)
264 end
265 -- }}}
266
267 -- deop() - remove ops from a user {{{
268 function deop(self, name)
269     irc.send("MODE", self.name, "-o", name)
270 end
271 -- }}}
272
273 -- set_limit() - set a channel limit {{{
274 function set_limit(self, new_limit)
275     if new_limit then
276         irc.send("MODE", self.name, "+l", new_limit)
277     else
278         irc.send("MODE", self.name, "-l")
279     end
280 end
281 -- }}}
282
283 -- set_key() - set a channel password {{{
284 function set_key(self, key)
285     if key then
286         irc.send("MODE", self.name, "+k", key)
287     else
288         irc.send("MODE", self.name, "-k")
289     end
290 end
291 -- }}}
292
293 -- set_private() - set the private state of a channel {{{
294 function set_private(self, set)
295     set_basic_mode(self, set, "p")
296 end
297 -- }}}
298
299 -- set_secret() - set the secret state of a channel {{{
300 function set_secret(self, set)
301     set_basic_mode(self, set, "s")
302 end
303 -- }}}
304
305 -- set_invite_only() - set whether joining the channel requires an invite {{{
306 function set_invite_only(self, set)
307     set_basic_mode(self, set, "i")
308 end
309 -- }}}
310
311 -- set_topic_lock() - if true, the topic can only be changed by an op {{{
312 function set_topic_lock(self, set)
313     set_basic_mode(self, set, "t")
314 end
315 -- }}}
316
317 -- set_no_outside_messages() - if true, users must be in the channel to send messages to it {{{
318 function set_no_outside_messages(self, set)
319     set_basic_mode(self, set, "n")
320 end
321 -- }}}
322
323 -- set moderated() - set whether voice is required to speak {{{
324 function set_moderated(self, set)
325     set_basic_mode(self, set, "m")
326 end
327 -- }}}
328 -- }}}
329
330 -- accessors {{{
331 -- add_user() {{{
332 function add_user(self, user, mode)
333     mode = mode or ''
334     self._members[user] = mode .. user
335 end
336 -- }}}
337
338 -- remove_user() {{{
339 function remove_user(self, user)
340     self._members[user] = nil
341 end
342 -- }}}
343
344 -- change_status() {{{
345 function change_status(self, user, on, mode)
346     if on then
347         if mode == 'o' then
348             self._members[user] = '@' .. user
349         elseif mode == 'v' then
350             self._members[user] = '+' .. user
351         end
352     else
353         if (mode == 'o' and self._members[user]:sub(1, 1) == '@') or
354            (mode == 'v' and self._members[user]:sub(1, 1) == '+') then
355             self._members[user] = user
356         end
357     end
358 end
359 -- }}}
360
361 -- contains() {{{
362 function contains(self, nick)
363     for member in self:each_member() do
364         local member_nick = member:gsub('@+', '')
365         if member_nick == nick then
366             return true
367         end
368     end
369     return false
370 end
371 -- }}}
372
373 -- change_nick {{{
374 function change_nick(self, old_nick, new_nick)
375     for member in self:each_member() do
376         local member_nick = member:gsub('@+', '')
377         if member_nick == old_nick then
378             local mode = self._members[old_nick]:sub(1, 1)
379             if mode ~= '@' and mode ~= '+' then mode = "" end
380             self._members[old_nick] = nil
381             self._members[new_nick] = mode .. new_nick
382             break
383         end
384     end
385 end
386 -- }}}
387 -- }}}
388 -- }}}