[project @ 2005-06-30 02:51:27 by unknown_lamer]
[clinton/bobotpp.git] / source / Channel.C
1 // Channel.C -*- C++ -*-
2 // Copyright (c) 1997, 1998 Etienne BERNARD
3 // Copyright (C) 2002,2005 Clinton Ebadi
4
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // any later version.
9
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301, USA.
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "Macros.H"
25 #include "Utils.H"
26 #include "Channel.H"
27 #include "StringTokenizer.H"
28 #ifdef USESCRIPTS
29 #include "Interp.H"
30 #endif
31
32 Channel::Channel(ServerConnection *c,
33 String name, String wanted = "")
34 : channelName(name.toLower()), channelTopic(""),
35 lockedTopic(false), channelMode(0), channelLimit(0),
36 channelKey(""), keepModes(DEFAULT_KEEPMODES), wantedModes(wanted), count(0),
37 countOp(0), joined(false), doMode(true), gotWho(false), cnx(c)
38 {
39 #ifdef HAVE_STL_CLEAR
40 channelMemory.clear();
41 channelBanlist.clear();
42 #endif
43 if (c->bot->wantedChannels[channelName])
44 {
45 if (c->bot->wantedChannels[channelName]->keep != "")
46 keepModes = c->bot->wantedChannels[channelName]->keep;
47
48 if (c->bot->wantedChannels[channelName]->mode != "")
49 wantedModes = c->bot->wantedChannels[channelName]->mode;
50 }
51 }
52
53 Channel::~Channel()
54 {
55 User *u;
56 std::map<String, User *, std::less<String> >::iterator it;
57
58 while (channelMemory.size() != 0) {
59 it = channelMemory.begin();
60 u = (*it).second;
61 if (u && u->userListItem && u->userListItem->identified > 0)
62 u->userListItem->identified--;
63 channelMemory.erase(it);
64 delete u;
65 }
66
67 BanEntry *b;
68 std::vector<BanEntry *>::iterator it2;
69
70 while (channelBanlist.size() != 0) {
71 it2 = channelBanlist.begin();
72 b = *it2;
73 channelBanlist.erase(it2);
74 delete b;
75 }
76 }
77
78 void
79 Channel::addNick(String n, String uh, int mode, UserList *ul,
80 bool names)
81 {
82 if (User * u = getUser(n.toLower())) {
83 count--;
84 if (u->mode & User::OP_MODE)
85 countOp--;
86 channelMemory.erase(n.toLower());
87 delete u;
88 }
89
90 User *u;
91
92 if (names)
93 u = new User(n, mode);
94 else
95 u = new User(n, uh, channelName, mode, ul);
96
97 channelMemory[n.toLower()] = u;
98
99 if (u->userListItem) {
100 if (u->userListItem->identified)
101 u->userListItem->identified++;
102 else {
103 if (u->userListItem->passwd == "")
104 u->userListItem->identified = 1;
105 }
106 }
107
108 count++;
109 if (u->mode & User::OP_MODE)
110 countOp++;
111 }
112
113 void
114 Channel::delNick(String n)
115 {
116 n = n.toLower();
117 User *u = getUser(n);
118
119 if (!u)
120 return;
121
122 if (channelMemory[n]!=0) {
123 channelMemory.erase(n);
124 }
125
126 count--;
127 if (u->mode & User::OP_MODE)
128 countOp--;
129 if (u->userListItem && u->userListItem->identified > 0)
130 u->userListItem->identified--;
131 delete u;
132 }
133
134 void
135 Channel::changeNick(String on, String nn)
136 {
137 on = on.toLower();
138 User *u = getUser(on);
139 channelMemory.erase(on);
140 channelMemory[nn.toLower()] = u;
141 }
142
143 bool
144 Channel::hasNick(String n)
145 {
146 return getUser(n.toLower()) != 0;
147 }
148
149 User *
150 Channel::getUser(String n)
151 {
152 User *u;
153
154 n = n.toLower();
155
156 if ((u = channelMemory[n]) == 0) {
157 channelMemory.erase(n);
158 return 0;
159 }
160
161 return u;
162 }
163
164 void
165 Channel::addBan(String mask, std::time_t expiration)
166 {
167 for (std::vector<BanEntry *>::iterator it = channelBanlist.begin();
168 it != channelBanlist.end(); ++it)
169 if ((*it)->getMask() == mask) {
170 if (expiration > (*it)->getExpirationDate())
171 (*it)->setExpirationDate(expiration);
172 return;
173 }
174 channelBanlist.push_back(new BanEntry(mask, expiration));
175 }
176
177 void
178 Channel::delBan(String mask)
179 {
180 for (std::vector<BanEntry *>::iterator it = channelBanlist.begin();
181 it != channelBanlist.end(); ++it)
182 if (mask == (*it)->getMask()) {
183 BanEntry *b = *it;
184 channelBanlist.erase(it);
185 delete b;
186 break;
187 }
188 }
189
190 void
191 Channel::resynchModes()
192 {
193 cnx->queue->sendChannelMode(String("MODE ") + channelName +
194 " +" + cnx->bot->wantedChannels[channelName]->mode);
195 }
196
197 void
198 Channel::parseMode(Person *from, String mode)
199 {
200 char sign = '-';
201 StringTokenizer st(mode);
202 String m = st.next_token(), n;
203 User *u = 0;
204 if (from)
205 u = getUser(from->getNick());
206 // u == 0 if it's a server mode
207 bool doNotObey = !u || (u->getProt() <= User::NO_PROT);
208 if (!gotWho)
209 doNotObey = false;
210
211 for (int i = 0; i < m.length(); i++)
212 switch(m[i]) {
213 case '+':
214 case '-':
215 sign = m[i];
216 break;
217 case 'p': sign =='+' ? channelMode |= PRIVATE :
218 channelMode &= ~PRIVATE;
219 if (keepModes.find('p') != -1 && doNotObey) {
220 if (sign == '-' && wantedModes.find('p') != -1)
221 cnx->queue->sendChannelMode(channelName, "+p", "");
222 else
223 cnx->queue->sendChannelMode(channelName, "-p", "");
224 }
225 break;
226 case 's': sign =='+' ? channelMode |= SECRET :
227 channelMode &= ~SECRET;
228 if (keepModes.find('s') != -1 && doNotObey) {
229 if (sign == '-' && wantedModes.find('s') != -1)
230 cnx->queue->sendChannelMode(channelName, "+s", "");
231 else
232 cnx->queue->sendChannelMode(channelName, "-s", "");
233 }
234 break;
235 case 'i': sign =='+' ? channelMode |= INVITE_ONLY :
236 channelMode &= ~INVITE_ONLY;
237 if (keepModes.find('i') != -1 && doNotObey) {
238 if (sign == '-' && wantedModes.find('i') != -1)
239 cnx->queue->sendChannelMode(channelName, "+i", "");
240 else
241 cnx->queue->sendChannelMode(channelName, "-i", "");
242 }
243 break;
244 case 't': sign =='+' ? channelMode |= TOPIC_RESTRICTED :
245 channelMode &= ~TOPIC_RESTRICTED;
246 if (keepModes.find('t') != -1 && doNotObey) {
247 if (sign == '-' && wantedModes.find('t') != -1)
248 cnx->queue->sendChannelMode(channelName, "+t", "");
249 else
250 cnx->queue->sendChannelMode(channelName, "-t", "");
251 }
252 break;
253 case 'n': sign =='+' ? channelMode |= EXTMSG_RESTRICTED :
254 channelMode &= ~EXTMSG_RESTRICTED;
255 if (keepModes.find('n') != -1 && doNotObey) {
256 if (sign == '-' && wantedModes.find('n') != -1)
257 cnx->queue->sendChannelMode(channelName, "+n", "");
258 else
259 cnx->queue->sendChannelMode(channelName, "-n", "");
260 }
261 break;
262 case 'm': sign =='+' ? channelMode |= MODERATED :
263 channelMode &= ~MODERATED;
264 if (keepModes.find('m') != -1 && doNotObey) {
265 if (sign == '-' && wantedModes.find('m') != -1)
266 cnx->queue->sendChannelMode(channelName, "+m", "");
267 else
268 cnx->queue->sendChannelMode(channelName, "-m", "");
269 }
270 break;
271 case 'l':
272 if (keepModes.find('l') != -1 && doNotObey) {
273 if (sign == '-' && wantedModes.find('l') != -1)
274 cnx->queue->sendChannelMode(channelName, "+l",
275 String((long)channelLimit));
276 else
277 cnx->queue->sendChannelMode(channelName, "-l", "");
278 }
279 channelLimit = (sign == '+' ? std::atoi(st.next_token().c_str()) :
280 channelLimit = 0);
281 break;
282 case 'k':
283 channelKey = st.next_token();
284 if (keepModes.find('k') != -1 && doNotObey) {
285 if (sign == '-' && wantedModes.find('k') != -1)
286 cnx->queue->sendChannelMode(channelName, "+k", channelKey);
287 else
288 cnx->queue->sendChannelMode(channelName, "-k", channelKey);
289 }
290 cnx->bot->wantedChannels[channelName]->key = (sign == '+' ? channelKey :
291 String(""));
292 break;
293 case 'o':
294 n = st.next_token();
295 u = getUser(n);
296 if (joined)
297 sign == '+' ? countOp++ : countOp--;
298 if (!u)
299 break;
300 sign == '+' ? (u->mode |= User::OP_MODE) :
301 (u->mode &= ~User::OP_MODE);
302 if (sign == '-' && u->getProt() >= User::NO_DEOP) {
303 String fromNick = from->getNick();
304 User * v = getUser(fromNick);
305 if (u == v)
306 return;
307 if (v->getProt() < User::NO_DEOP)
308 cnx->queue->sendChannelMode(channelName, "-o", fromNick);
309 cnx->queue->sendChannelMode(channelName, "+o", n);
310 }
311 if (sign == '+') {
312 if (doNotObey && !from &&
313 u->getProt() < User::NO_DEOP && !u->getAop())
314 cnx->queue->sendChannelMode(channelName, "-o", n);
315 ShitEntry * se =
316 cnx->bot->shitList->getShit(n+"!"+cnx->bot->getUserhost(channelName, n),
317 channelName);
318 if (se && se->isStillValid() &&
319 se->getShitLevel() >= ShitEntry::SHIT_NOOP)
320 cnx->queue->sendChannelMode(channelName, "-o", n);
321 if (n.toLower() == cnx->bot->nickName.toLower() && doMode) {
322 doMode = false;
323 resynchModes();
324 }
325 }
326 break;
327 case 'v':
328 u = getUser(st.next_token());
329 u->mode = (sign == '+' ? u->mode |= User::VOICE_MODE :
330 u->mode &= ~User::VOICE_MODE);
331 break;
332 case 'b':
333 String m = st.next_token();
334 sign == '+' ? addBan(m) : delBan(m);
335 if (sign == '-') {
336 ShitEntry * se =
337 cnx->bot->shitList->getShit(m, channelName);
338 if (se && se->isStillValid() &&
339 se->getShitLevel() >= ShitEntry::SHIT_NODEBAN)
340 cnx->queue->sendChannelMode(channelName, "+b", m);
341 }
342 }
343 }