Remove String->const char* conversion operator in favor of c_str method
[clinton/bobotpp.git] / source / Bot.C
CommitLineData
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
62unsigned int Bot::MAX_MESSAGES = 2;
6b7614a8 63unsigned 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
80Bot::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
189Bot::~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
217void
218Bot::logLine(String line)
219{
220 tm *d;
221 std::time_t current_time = time(0);
222
223 d = localtime(&current_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
235void
236Bot::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
357void
358Bot::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
384void
385Bot::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(&currentTime);
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
499bool
500Bot::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
517void
518Bot::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
548void
549Bot::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
564void
565Bot::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
580void
4edefeb6 581Bot::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
605void
606Bot::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
614String
615Bot::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
647bool
648Bot::iAmOp(String channel)
649{
650 User * me = channelList->getChannel(channel)->getUser(nickName);
651 return (me->mode & User::OP_MODE);
652}
e07b6b46 653
654void
655Bot::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
735namespace
736{
737 void erase_userf (std::pair<std::string, class userFunction*> it)
738 {
739 delete it.second;
740 }
741}
742
743void
744Bot::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
753void
754Bot::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
770void
771Bot::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}