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