cb21075d |
1 | // Bot.C -*- C++ -*- |
2 | // Copyright (c) 1997, 1998 Etienne BERNARD |
a6339323 |
3 | // Copyright (C) 2002,2003,2005 Clinton Ebadi |
cb21075d |
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 |
133eff7a |
17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
18 | // 02110-1301, USA. |
cb21075d |
19 | |
cb21075d |
20 | #include <cstring> |
21 | #include <cstdlib> |
22 | #include <cstdio> |
cfa82921 |
23 | |
24 | #include <fstream> |
25 | #include <algorithm> |
26 | #include <iomanip> |
27 | |
b0e3551b |
28 | #include <dirent.h> |
cb21075d |
29 | #include <sys/time.h> |
30 | #include <sys/types.h> |
b0e3551b |
31 | #include <sys/stat.h> |
cb21075d |
32 | #include <unistd.h> |
33 | |
cfa82921 |
34 | #ifdef USESCRIPTS |
35 | #include <libguile.h> |
36 | #endif |
37 | |
cb21075d |
38 | #include "Bot.H" |
39 | #include "DCCConnection.H" |
4edefeb6 |
40 | #include "DCCChatConnection.H" |
cfa82921 |
41 | #include "ChannelList.H" |
42 | #include "DCCManager.H" |
43 | #include "DCCPerson.H" |
44 | #include "Parser.H" |
45 | #include "Person.H" |
46 | #include "Server.H" |
cb21075d |
47 | #include "ServerConnection.H" |
cfa82921 |
48 | #include "ServerList.H" |
49 | #include "ShitList.H" |
50 | #include "StringTokenizer.H" |
cfa82921 |
51 | #include "User.H" |
e07b6b46 |
52 | #include "UserCommands.H" |
cfa82921 |
53 | #include "UserList.H" |
54 | #include "Utils.H" |
55 | |
cb21075d |
56 | |
cfa82921 |
57 | #ifdef USESCRIPTS |
58 | #include "BotInterp.H" |
59 | #include "Interp.H" |
60 | #endif |
e171dcce |
61 | |
62 | unsigned int Bot::MAX_MESSAGES = 2; |
6b7614a8 |
63 | unsigned int Bot::MAX_NICKLENGTH = 9; |
e171dcce |
64 | |
cb21075d |
65 | #define DEFAULT_NICKNAME "Bobot" |
66 | #define DEFAULT_USERNAME "bobot" |
67 | #define DEFAULT_IRCNAME "I'm a bobot++!" |
68 | #define DEFAULT_COMMANDCHAR '!' |
69 | #define DEFAULT_USERLISTFILENAME "bot.users" |
70 | #define DEFAULT_SHITLISTFILENAME "bot.shit" |
71 | #define DEFAULT_HELPFILENAME "bot.help" |
72 | #define DEFAULT_SCRIPTLOGFILENAME "script.log" |
73 | #define DEFAULT_LOGFILENAME "bot.log" |
439869bf |
74 | #define DEFAULT_LOGDIR getenv ("HOME") + String("/.bobotpp/logs/") |
cb21075d |
75 | #define DEFAULT_INITFILENAME "bot.init" |
76 | #ifdef USESCRIPTS |
77 | #define DEFAULT_AUTOEXECFILENAME "bot.autoexec" |
78 | #endif |
79 | |
80 | Bot::Bot(String filename, bool debug_on) |
81 | : nickName(DEFAULT_NICKNAME), |
82 | wantedNickName(DEFAULT_NICKNAME), |
83 | userName(DEFAULT_USERNAME), |
84 | ircName(DEFAULT_IRCNAME), |
85 | versionString(VERSION_STRING), |
86 | userHost(""), |
87 | localIP(""), |
88 | commandChar(DEFAULT_COMMANDCHAR), |
cb21075d |
89 | userListFileName(DEFAULT_USERLISTFILENAME), |
90 | shitListFileName(DEFAULT_SHITLISTFILENAME), |
cb21075d |
91 | helpFileName(DEFAULT_HELPFILENAME), |
92 | initFileName(DEFAULT_INITFILENAME), |
cf8ea873 |
93 | connected(false), |
94 | debug(debug_on), |
95 | stop(false), |
96 | sentPing(false), |
97 | startTime(time(NULL)), |
98 | currentTime(startTime), |
99 | lastNickNameChange(startTime), |
100 | lastChannelJoin(startTime), |
101 | serverConnection(0), |
102 | sentUserhostID(0), |
103 | receivedUserhostID(0), |
104 | logFileName(DEFAULT_LOGFILENAME), |
105 | logs_dir (DEFAULT_LOGDIR), |
4679dc8b |
106 | configFileName (filename) |
cb21075d |
107 | #ifdef USESCRIPTS |
4679dc8b |
108 | ,scriptLogFileName(DEFAULT_SCRIPTLOGFILENAME), |
cf8ea873 |
109 | autoexecFileName(DEFAULT_AUTOEXECFILENAME) |
cb21075d |
110 | #endif |
cb21075d |
111 | { |
cb21075d |
112 | #ifdef HAVE_STL_CLEAR |
113 | wantedChannels.clear(); |
114 | ignoredUserhosts.clear(); |
115 | spyList.clear(); |
116 | userhostMap.clear(); |
117 | #endif |
118 | |
e07b6b46 |
119 | init_user_functions (); |
cb21075d |
120 | |
be3612f3 |
121 | set_log_dir (logs_dir); |
122 | set_log_file (logFileName); |
123 | |
124 | |
cb21075d |
125 | channelList = new ChannelList(); |
126 | serverList = new ServerList(); |
127 | readConfig(); |
128 | userList = new UserList(userListFileName); |
129 | shitList = new ShitList(shitListFileName); |
6530edbf |
130 | dccConnections = new DCCManager (); |
cb21075d |
131 | |
132 | // Let's read the alias file |
815a1816 |
133 | std::ifstream initFile(initFileName.c_str ()); |
cb21075d |
134 | |
0316e2c1 |
135 | if (initFile) |
136 | { |
137 | // FIXME: these variables are current String instead of |
138 | // std::string because String>> reads an entire line. This code |
139 | // needs to be rewritten to use std::string and std::getline (or |
140 | // better yet, be removed entirely once BotConfig is in place) |
141 | String temp, alias, command; |
142 | int line = 0; |
143 | |
144 | while (initFile >> temp, temp.length() != 0) |
e07b6b46 |
145 | { |
0316e2c1 |
146 | StringTokenizer st(temp); |
147 | |
148 | line++; |
149 | temp = Utils::trim_str (temp); |
150 | |
151 | if (temp[0]=='#') |
152 | { |
153 | continue; |
154 | } |
155 | |
156 | if (st.count_tokens (' ') != 2) |
157 | { |
158 | std::cerr << "Error when reading alias file (" << initFileName |
159 | << ") line " << line << "...\n"; |
160 | continue; |
161 | } |
162 | |
163 | alias = Utils::to_upper (st.next_token()); |
164 | command = Utils::to_upper (st.next_token()); |
165 | |
166 | // Does the function already exist ? |
167 | if (!userFunctions[alias]) |
168 | { |
169 | if (userFunction *u = userFunctions[command]) |
170 | userFunctions[alias] = |
171 | new |
172 | userFunction(u->function, |
173 | u->minLevel, |
174 | u->needsChannelName); |
175 | } |
e07b6b46 |
176 | } |
cb21075d |
177 | } |
cb21075d |
178 | |
e07b6b46 |
179 | |
cb21075d |
180 | std::srand (std::time (0)); // srand for bot-random |
0316e2c1 |
181 | |
cb21075d |
182 | #ifdef USESCRIPTS |
439869bf |
183 | botInterp = new BotInterp(this, logs_dir + scriptLogFileName); |
db098a03 |
184 | Interp::Startup2 (this); |
cb21075d |
185 | botInterp->LoadScript(autoexecFileName); |
186 | #endif |
187 | } |
188 | |
189 | Bot::~Bot() |
190 | { |
cb21075d |
191 | Person *p; |
192 | while (spyList.size() != 0) { |
193 | p = (*spyList.begin()).second; |
194 | spyList.erase(spyList.begin()); |
195 | delete p; |
196 | } |
6530edbf |
197 | delete dccConnections; |
e07b6b46 |
198 | destroy_user_functions (); |
199 | |
cb21075d |
200 | wantedChannel *w; |
201 | while (wantedChannels.size() != 0) { |
202 | w = (*wantedChannels.begin()).second; |
203 | wantedChannels.erase(wantedChannels.begin()); |
204 | delete w; |
205 | } |
206 | userList->save(); |
207 | shitList->save(); |
208 | delete channelList; |
209 | delete userList; |
cb21075d |
210 | delete serverList; |
211 | delete shitList; |
212 | delete serverConnection; |
213 | logLine("Stopping log."); |
214 | logFile.close(); |
215 | } |
216 | |
217 | void |
218 | Bot::logLine(String line) |
219 | { |
220 | tm *d; |
221 | std::time_t current_time = time(0); |
222 | |
223 | d = localtime(¤t_time); |
224 | logFile << "[" << std::setfill('0') << std::setw(2) |
225 | << d->tm_mday << "/" << std::setfill('0') << std::setw(2) |
226 | << d->tm_mon + 1 << "/" |
227 | << d->tm_year + 1900 << " - " << std::setfill('0') << std::setw(2) |
228 | << d->tm_hour << ":" << std::setfill('0') << std::setw(2) |
229 | << d->tm_min << ":" << std::setfill('0') << std::setw(2) |
230 | << d->tm_sec << "] " |
231 | << line |
232 | << std::endl; |
233 | } |
234 | |
235 | void |
236 | Bot::readConfig() |
237 | { |
815a1816 |
238 | std::ifstream file(configFileName.c_str ()); |
cb21075d |
239 | String temp; |
240 | int line = 1; |
241 | |
242 | if (!file) { |
243 | logLine(String("I cannot find the file ") + configFileName); |
244 | return; |
245 | } |
246 | |
247 | while (!file.eof()) { |
248 | |
249 | file >> temp; |
250 | |
cf8ea873 |
251 | if (temp.length() == 0 || temp[(unsigned int)0] == '#') { |
cb21075d |
252 | line++; |
253 | continue; |
254 | } |
255 | |
256 | StringTokenizer st(temp); |
a6339323 |
257 | String command = Utils::to_upper (Utils::trim_str (st.next_token('='))); |
258 | String parameters = Utils::trim_str (st.next_token('=')); |
cb21075d |
259 | |
260 | if (command == "NICK" || command == "NICKNAME") |
261 | nickName = wantedNickName = parameters; |
262 | else if (command == "USERNAME") |
263 | userName = parameters; |
264 | else if (command == "IRCNAME" || command == "REALNAME") |
265 | ircName = parameters; |
266 | else if (command == "CMDCHAR" || command == "COMMAND") |
cf8ea873 |
267 | commandChar = parameters[(unsigned int)0]; |
cb21075d |
268 | else if (command == "USERLIST") |
269 | userListFileName = parameters; |
270 | else if (command == "SHITLIST") |
271 | shitListFileName = parameters; |
272 | else if (command == "CHANNEL") { |
273 | if (parameters.indexOf(':') == -1) { |
274 | std::cout << "Warning. The 'channel' syntax has changed." |
275 | << " Please see the README file for more information." |
276 | << " I will use compatibility mode, but you're really" |
277 | << " missing something.\n"; |
278 | StringTokenizer st2(parameters); |
a6339323 |
279 | String name = Utils::to_lower (st2.next_token()); |
280 | String key = st2.next_token(); |
cb21075d |
281 | wantedChannels[name] = new wantedChannel("", "", key); |
282 | } else { |
283 | StringTokenizer st2(parameters); |
a6339323 |
284 | String name = Utils::to_lower (st2.next_token(':')); |
285 | String mode = st2.next_token(':'); |
286 | String keep = st2.next_token(':'); |
287 | String key = st2.next_token(':'); |
cb21075d |
288 | wantedChannels[name] = new wantedChannel(mode, keep, key); |
289 | } |
290 | } |
291 | else if (command == "LOGFILE") |
be3612f3 |
292 | { |
fd7440f1 |
293 | if (parameters != logFileName) |
be3612f3 |
294 | { |
cf8ea873 |
295 | if (parameters[(unsigned int)0] == '/') |
fd7440f1 |
296 | { |
d3f0798d |
297 | StringTokenizer log_st (parameters); |
298 | std::string log_dir = "/"; |
299 | |
300 | for (unsigned int m = log_st.count_tokens ('/'); |
301 | --m; |
302 | m > 0) |
303 | { |
304 | log_dir += log_st.next_token ('/') + "/"; |
305 | } |
306 | |
307 | std::cerr << "==" << log_dir << std::endl; |
308 | |
309 | set_log_dir (log_dir); |
310 | set_log_file (log_st.rest ()); |
fd7440f1 |
311 | } |
312 | else |
313 | set_log_file (parameters); |
be3612f3 |
314 | } |
be3612f3 |
315 | } |
cb21075d |
316 | #ifdef USESCRIPTS |
317 | else if (command == "SCRIPTLOGFILE") |
318 | scriptLogFileName = parameters; |
319 | else if (command == "AUTOEXECFILE") |
320 | autoexecFileName = parameters; |
321 | #endif |
322 | else if (command == "INITFILE") |
323 | initFileName = parameters; |
324 | else if (command == "LOCALIP") |
325 | localIP = parameters; |
6b7614a8 |
326 | else if (command == "MAXNICKLENGTH") |
815a1816 |
327 | MAX_NICKLENGTH = std::atoi (parameters.c_str ()); |
cb21075d |
328 | else if (command == "SERVER") { |
329 | if (parameters.indexOf(' ') == -1) |
330 | serverList->addServer(new Server(parameters)); |
331 | else { |
332 | StringTokenizer st2(parameters); |
a6339323 |
333 | String name = st2.next_token(); |
334 | int port = std::atoi(st2.next_token().c_str()); |
cb21075d |
335 | serverList->addServer(new Server(name, |
336 | port, |
a6339323 |
337 | st2.next_token())); |
cb21075d |
338 | } |
339 | } |
b0e3551b |
340 | else if (command == "") |
341 | { |
342 | // do nothing |
343 | } |
cb21075d |
344 | else { |
345 | logLine(String("Syntax error in file ") + configFileName + |
346 | ", line " + String((long)line)); |
347 | file.close(); |
348 | std::exit(1); |
349 | } |
350 | |
351 | line++; |
352 | } |
353 | |
354 | file.close(); |
355 | } |
356 | |
357 | void |
358 | Bot::run() |
359 | { |
360 | nextServer(); |
361 | |
1520dfbd |
362 | while (!stop) |
363 | { |
364 | waitForInput(); // This is the main event loop |
365 | dccConnections->checkStale (); |
366 | |
367 | if (!serverConnection->queue->flush()) |
368 | { |
369 | // Disconnected |
370 | #ifdef USESCRIPTS |
ae97d6ec |
371 | // Run hooks/disconnect |
1520dfbd |
372 | this->botInterp->RunHooks |
373 | (Hook::DISCONNECT, |
374 | serverConnection->server->getHostName (), |
375 | scm_list_n |
ae97d6ec |
376 | (Utils::str2scm (serverConnection->server->getHostName ()), |
377 | SCM_BOOL_F)); |
1520dfbd |
378 | #endif |
379 | nextServer(); |
380 | } |
381 | } |
cb21075d |
382 | } |
383 | |
384 | void |
385 | Bot::waitForInput() |
386 | { |
387 | #ifdef _HPUX_SOURCE |
388 | int rd; |
389 | #else |
390 | fd_set rd; |
391 | #endif |
392 | struct timeval timer; |
393 | |
394 | int sock = serverConnection->getFileDescriptor(); |
395 | int maxSocketNumber = sock; |
396 | |
397 | #ifdef _HPUX_SOURCE |
398 | rd = sock; |
399 | #else |
400 | FD_ZERO(&rd); |
401 | FD_SET(sock, &rd); |
402 | #endif |
403 | |
c3ecc559 |
404 | DCC_MAP* dccmap = &dccConnections->dcc_map; |
6530edbf |
405 | for (DCC_MAP::iterator it = dccmap->begin (); |
406 | it != dccmap->end(); ++it) { |
c3ecc559 |
407 | int s = it->second->dcc->getFileDescriptor(); |
cb21075d |
408 | #ifdef _HPUX_SOURCE |
409 | rd |= s; |
410 | #else |
411 | FD_SET(s, &rd); |
412 | #endif |
413 | if (s > maxSocketNumber) |
414 | maxSocketNumber = s; |
415 | } |
416 | |
417 | timer.tv_sec = 1; |
418 | timer.tv_usec = 0; |
419 | |
420 | switch (select(maxSocketNumber + 1, &rd, NULL, NULL, &timer)) { |
421 | case 0: /* timeout */ |
422 | break; |
423 | case -1: /* error */ |
424 | break; |
425 | default: /* normal */ |
426 | #ifdef _HPUX_SOURCE |
427 | if (rd & sock) |
428 | #else |
429 | if (FD_ISSET(sock, &rd)) |
430 | #endif |
431 | if (serverConnection->handleInput()) |
432 | nextServer(); |
433 | |
6530edbf |
434 | dccConnections->checkInput (rd); |
cb21075d |
435 | } |
436 | |
feb33b96 |
437 | if (currentTime < std::time(0)) { // Actions that we do each second |
438 | currentTime = std::time(0); |
cb21075d |
439 | for (std::map<String, unsigned int, std::less<String> >::iterator |
440 | it = ignoredUserhosts.begin(); |
441 | it != ignoredUserhosts.end(); ++it) |
442 | if ((*it).second > 0) |
443 | (*it).second--; |
444 | |
f9723c92 |
445 | for (std::map<String, Channel *, std::less<String> >::iterator it = channelList->begin (); |
446 | it != channelList->end (); |
447 | ++it) |
448 | { |
449 | it->second->purge_expired_bans (); |
450 | } |
cb21075d |
451 | #ifdef USESCRIPTS |
452 | botInterp->RunTimers(currentTime); |
cb21075d |
453 | |
cb21075d |
454 | tm *thisTime = localtime(¤tTime); |
e171dcce |
455 | if (thisTime->tm_sec == 0) |
456 | { |
457 | char s[6]; |
a756c916 |
458 | std::snprintf(s, 6, "%02d:%02d", thisTime->tm_hour, thisTime->tm_min); |
0316e2c1 |
459 | |
e171dcce |
460 | botInterp->RunHooks(Hook::TIMER, String(s), |
0316e2c1 |
461 | scm_list_n (Utils::str2scm (std::string (s)), |
462 | SCM_UNDEFINED)); |
e171dcce |
463 | } |
cb21075d |
464 | #endif |
465 | |
466 | } |
467 | |
468 | if (currentTime >= (time_t)(lastNickNameChange + Bot::NICK_CHANGE) && |
469 | nickName != wantedNickName) { |
470 | lastNickNameChange = currentTime; |
471 | serverConnection->queue->sendNick(wantedNickName); |
472 | } |
473 | |
474 | if (currentTime >= (std::time_t)(lastChannelJoin + Bot::CHANNEL_JOIN)) { |
475 | lastChannelJoin = currentTime; |
476 | for (std::map<String, wantedChannel *, std::less<String> >::iterator it = |
477 | wantedChannels.begin(); it != wantedChannels.end(); |
478 | ++it) |
479 | if (channelList->getChannel((*it).first) == 0) |
480 | serverConnection->queue->sendJoin((*it).first, (*it).second->key); |
481 | } |
482 | |
0316e2c1 |
483 | if (currentTime >= (std::time_t)(serverConnection->serverLastSpoken |
484 | + Bot::PING_TIME) && !sentPing) |
485 | { |
486 | serverConnection->queue->sendPing("Testing connection"); |
487 | sentPing = true; |
488 | } |
cb21075d |
489 | |
0316e2c1 |
490 | if (currentTime >= (std::time_t)(serverConnection->serverLastSpoken |
491 | + Bot::TIMEOUT)) |
492 | { |
493 | sentPing = false; |
494 | nextServer(); |
495 | } |
cb21075d |
496 | } |
497 | |
498 | // We can change server if we will not lose op on a channel |
499 | bool |
500 | Bot::canChangeServer() |
501 | { |
502 | String channel; |
503 | Channel *c; |
504 | |
505 | for (std::map<String, Channel *, std::less<String> >::iterator it = |
506 | channelList->begin(); |
507 | it != channelList->end(); ++it) { |
508 | channel = (*it).first; |
509 | c = channelList->getChannel(channel); |
510 | if (c->countOp == 1 && |
511 | c->count > 1 && this->iAmOp(channel)) |
512 | return false; |
513 | } |
514 | return true; |
515 | } |
516 | |
517 | void |
518 | Bot::nextServer() |
519 | { |
520 | bool cont = false; |
521 | |
522 | if (channelList) |
523 | channelList->clear(); |
524 | |
525 | if (serverConnection) |
526 | userList->removeFirst(); |
527 | |
528 | delete serverConnection; |
529 | |
530 | do { |
531 | Server * s = serverList->nextServer(); |
532 | if (!s) { |
533 | std::cout << "No server found. Exiting..." << std::endl; |
534 | std::exit(1); |
535 | } |
536 | serverConnection = new ServerConnection(this, s, localIP); |
537 | if (!serverConnection->connect()) { |
538 | cont = true; |
539 | // We sleep 10 seconds, to avoid connection flood |
540 | sleep(10); |
541 | delete serverConnection; |
542 | } else { |
543 | cont = false; |
544 | } |
545 | } while (cont); |
546 | } |
547 | |
548 | void |
549 | Bot::reconnect() |
550 | { |
551 | if (channelList) |
552 | channelList->clear(); |
553 | |
554 | userList->removeFirst(); |
555 | |
556 | delete serverConnection; |
557 | |
558 | serverConnection = |
559 | new ServerConnection(this, serverList->currentServer(), localIP); |
560 | |
561 | serverConnection->connect(); |
562 | } |
563 | |
564 | void |
565 | Bot::connect(int serverNumber) |
566 | { |
567 | if (channelList) |
568 | channelList->clear(); |
569 | |
570 | userList->removeFirst(); |
571 | |
572 | delete serverConnection; |
573 | |
574 | serverConnection = |
575 | new ServerConnection(this, serverList->get(serverNumber), localIP); |
576 | |
577 | serverConnection->connect(); |
578 | } |
579 | |
580 | void |
4edefeb6 |
581 | Bot::addDCC(Person * from, unsigned long address, int port, int type) |
cb21075d |
582 | { |
4edefeb6 |
583 | DCCConnection *d = 0; |
584 | |
585 | if (type == CHAT) |
0316e2c1 |
586 | { |
587 | d = new DCCChatConnection(this, from->getAddress (), |
588 | address, port); |
589 | } |
4edefeb6 |
590 | else |
0316e2c1 |
591 | { |
592 | return; |
593 | } |
cb21075d |
594 | |
595 | if (!d->connect()) |
fd7440f1 |
596 | { |
597 | logLine ("DCC Connection failed from " + from->getAddress ()); |
598 | return; |
599 | } |
0316e2c1 |
600 | |
fed59248 |
601 | logLine ("DCC CHAT accepted from" + from->getAddress ()); |
6530edbf |
602 | dccConnections->addConnection (d); |
cb21075d |
603 | } |
604 | |
605 | void |
606 | Bot::rehash() |
607 | { |
fed59248 |
608 | for (std::map<String, Channel *, std::less<String> >::iterator it = |
609 | channelList->begin(); |
cb21075d |
610 | it != channelList->end(); ++it) |
611 | serverConnection->queue->sendWho((*it).first); |
612 | } |
613 | |
614 | String |
615 | Bot::getUserhost(String channel, String nick) |
616 | { |
617 | Channel *c; |
618 | |
619 | if (channel == "") |
620 | c = 0; |
621 | else |
622 | c = channelList->getChannel(channel); |
623 | |
624 | nick = nick.toLower(); |
625 | |
626 | |
627 | if (c && c->hasNick(nick)) |
628 | return c->getUser(nick)->userhost; |
629 | |
630 | unsigned long num = sentUserhostID++; |
631 | |
632 | serverConnection->queue->sendUserhost(nick); |
633 | userhostMap[num] = "+"; |
634 | |
635 | while (userhostMap[num] == "+") { |
636 | waitForInput(); |
637 | serverConnection->queue->flush(); |
638 | } |
639 | |
640 | // We have got our answer |
641 | String res = userhostMap[num]; |
642 | userhostMap.erase(num); |
643 | |
644 | return res; |
645 | } |
646 | |
647 | bool |
648 | Bot::iAmOp(String channel) |
649 | { |
650 | User * me = channelList->getChannel(channel)->getUser(nickName); |
651 | return (me->mode & User::OP_MODE); |
652 | } |
e07b6b46 |
653 | |
654 | void |
655 | Bot::init_user_functions () |
656 | { |
657 | // User Functions |
658 | #define uf(f, l, b) new userFunction (f, l, b); |
659 | userFunctions["ACTION"] = uf (UserCommands::Action, User::USER, true); |
660 | userFunctions["ADDUSER"] = uf (UserCommands::AddUser, User::FRIEND, false); |
661 | userFunctions["ADDSERVER"] = uf (UserCommands::AddServer, User::FRIEND, |
662 | false); |
663 | userFunctions["ADDSHIT"] = uf (UserCommands::AddShit, User::FRIEND, false); |
664 | userFunctions["ALIAS"] = uf (UserCommands::Alias, User::MASTER, false); |
665 | userFunctions["BAN"] = uf (UserCommands::Ban, User::USER, true); |
666 | userFunctions["BANLIST"] = uf (UserCommands::BanList, User::USER, true); |
667 | userFunctions["CHANNELS"] = |
668 | uf (UserCommands::Channels, User::FRIEND, false); |
669 | userFunctions["CYCLE"] = uf (UserCommands::Cycle, User::FRIEND, true); |
670 | userFunctions["DCCLIST"] = uf (UserCommands::DCCList, User::FRIEND, false); |
671 | userFunctions["DEBAN"] = uf (UserCommands::Deban, User::USER, true); |
672 | userFunctions["DELSERVER"] = uf (UserCommands::DelServer, User::FRIEND, |
673 | false); |
674 | userFunctions["DELUSER"] = uf (UserCommands::DelUser, User::FRIEND, false); |
675 | userFunctions["DELSHIT"] = uf (UserCommands::DelShit, User::FRIEND, false); |
676 | userFunctions["DEOP"] = uf (UserCommands::Deop, User::TRUSTED_USER, true); |
677 | userFunctions["DIE"] = uf (UserCommands::Die, User::MASTER, false); |
678 | userFunctions["DO"] = uf (UserCommands::Do, User::MASTER, false); |
679 | #ifdef USESCRIPTS |
680 | userFunctions["EXECUTE"] = uf (UserCommands::Execute, User::MASTER, false); |
681 | #endif |
682 | userFunctions["HELP"] = uf (UserCommands::Help, User::NONE, false); |
683 | userFunctions["IDENT"] = uf (UserCommands::Ident, User::NONE, true); |
684 | userFunctions["INVITE"] = uf (UserCommands::Invite, User::USER, true); |
685 | userFunctions["JOIN"] = uf (UserCommands::Join, User::FRIEND, false); |
686 | userFunctions["KEEP"] = uf (UserCommands::Keep, User::FRIEND, true); |
687 | userFunctions["KICK"] = uf (UserCommands::Kick, User::USER, true); |
688 | userFunctions["KICKBAN"] = uf (UserCommands::KickBan, User::USER, true); |
689 | userFunctions["LOAD"] = uf (UserCommands::Load, User::FRIEND, false); |
690 | #ifdef USESCRIPTS |
691 | userFunctions["LOADSCRIPT"] = uf (UserCommands::LoadScript, User::MASTER, |
692 | false); |
693 | #endif |
694 | userFunctions["LOCK"] = uf (UserCommands::Lock, User::FRIEND, true); |
695 | userFunctions["MODE"] = uf (UserCommands::Mode, User::FRIEND, true); |
696 | userFunctions["MSG"] = uf (UserCommands::Msg, User::USER, false); |
697 | userFunctions["NAMES"] = uf (UserCommands::Names, User::USER, true); |
698 | userFunctions["NEXTSERVER"] = uf (UserCommands::NextServer, User::FRIEND, |
699 | false); |
700 | userFunctions["NICK"] = uf (UserCommands::Nick, User::FRIEND, false); |
701 | userFunctions["NSLOOKUP"] = uf (UserCommands::NsLookup, User::USER, false); |
702 | userFunctions["OP"] = uf (UserCommands::Op, User::TRUSTED_USER, true); |
703 | userFunctions["PART"] = uf (UserCommands::Part, User::FRIEND, true); |
704 | userFunctions["PASSWORD"] = uf (UserCommands::Password, User::USER, true); |
705 | userFunctions["RECONNECT"] = |
706 | uf (UserCommands::Reconnect, User::FRIEND, false); |
707 | userFunctions["RSPYMESSAGE"] = |
708 | uf (UserCommands::RSpyMessage, User::USER, false); |
709 | userFunctions["SAVE"] = uf (UserCommands::Save, User::FRIEND, false); |
710 | userFunctions["SAY"] = uf (UserCommands::Say, User::USER, true); |
711 | userFunctions["SERVER"] = uf (UserCommands::Server, User::FRIEND, false); |
712 | userFunctions["SERVERLIST"] = |
713 | uf (UserCommands::ServerList, User::FRIEND, false); |
e171dcce |
714 | userFunctions["SETFLOODRATE"] = |
715 | uf (UserCommands::SetFloodRate, User::MASTER, false); |
e07b6b46 |
716 | userFunctions["SETVERSION"] = |
717 | uf (UserCommands::SetVersion, User::MASTER, false); |
718 | userFunctions["SHITLIST"] = |
719 | uf (UserCommands::ShitList, User::FRIEND, false); |
720 | userFunctions["SPYLIST"] = uf (UserCommands::SpyList, User::USER, false); |
721 | userFunctions["SPYMESSAGE"] = |
722 | uf (UserCommands::SpyMessage, User::USER, false); |
723 | userFunctions["STATS"] = uf (UserCommands::Stats, User::FRIEND, true); |
724 | userFunctions["TBAN"] = uf (UserCommands::TBan, User::USER, true); |
725 | userFunctions["TKBAN"] = uf (UserCommands::TKBan, User::USER, true); |
726 | userFunctions["TOPIC"] = uf (UserCommands::Topic, User::USER, true); |
727 | userFunctions["UNLOCK"] = uf (UserCommands::Unlock, User::FRIEND, true); |
728 | userFunctions["USERLIST"] = |
729 | uf (UserCommands::UserList, User::FRIEND, false); |
730 | userFunctions["WHO"] = uf (UserCommands::Who, User::NONE, true); |
731 | userFunctions["WHOIS"] = uf (UserCommands::Whois, User::FRIEND, true); |
732 | #undef uf |
733 | } |
734 | |
735 | namespace |
736 | { |
737 | void erase_userf (std::pair<std::string, class userFunction*> it) |
738 | { |
739 | delete it.second; |
740 | } |
741 | } |
742 | |
743 | void |
744 | Bot::destroy_user_functions () |
745 | { |
91dddabd |
746 | std::for_each (userFunctions.begin (), |
e07b6b46 |
747 | userFunctions.end (), |
748 | erase_userf); |
749 | userFunctions.erase (userFunctions.begin (), |
750 | userFunctions.end ()); |
751 | } |
be3612f3 |
752 | |
753 | void |
754 | Bot::set_log_file (String name) |
755 | { |
815a1816 |
756 | logFileName = logs_dir + name; |
fd7440f1 |
757 | logFile.close (); |
758 | logFile.clear (); |
be3612f3 |
759 | #if HAVE_IOSBASE |
815a1816 |
760 | logFile.open(logFileName.c_str (), std::ios_base::out | |
be3612f3 |
761 | std::ios_base::ate | std::ios_base::app); |
762 | #else |
815a1816 |
763 | logFile.open(logFileName.c_str (), ios::out | ios::ate |
be3612f3 |
764 | | ios::app); |
765 | #endif |
766 | |
767 | logLine("Starting log."); |
768 | } |
769 | |
770 | void |
771 | Bot::set_log_dir (String dir) |
772 | { |
773 | logs_dir = dir; |
b0e3551b |
774 | |
815a1816 |
775 | DIR *temp = opendir (logs_dir.c_str ()); |
b0e3551b |
776 | |
777 | if (!temp) |
778 | { |
815a1816 |
779 | mkdir (logs_dir.c_str (), S_IRWXU); |
b0e3551b |
780 | } |
781 | else |
782 | { |
783 | closedir (temp); |
784 | } |
be3612f3 |
785 | } |