1 // ScriptCommands.C -*- C++ -*-
2 // Copyright (c) 1998 Etienne BERNARD
3 // Copyright (C) 2002,2005,2008 Clinton Ebadi
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
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.
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
28 #include "ServerList.H"
29 #include "ServerQueue.H"
30 #include "ScriptCommands.H"
32 #include "DCCPerson.H"
33 #include "DCCManager.H"
39 #define VERIFY_STRING(par) if (!scm_is_string((par))) \
40 return scm_from_int(-17)
42 #define VERIFY_NUMBER(par) if (!SCM_NUMBERP((par))) \
43 return scm_from_int(-17)
46 ScriptCommands::Action(SCM channel, SCM message)
48 VERIFY_STRING(channel);
49 VERIFY_STRING(message);
50 Message m = Commands::Action(Interp::bot, Utils::scm2str(channel),
51 Utils::scm2str(message));
52 return scm_from_int(m.getCode());
56 ScriptCommands::AddUser(SCM who, SCM maskChannel, SCM level,
57 SCM prot, SCM aop, SCM expire, SCM password)
59 // It segfaults when not online, but otherwise appears to work
61 VERIFY_STRING (maskChannel);
62 VERIFY_NUMBER (level);
64 String wwho = Utils::scm2str (who);
65 String mask = Utils::scm2str (maskChannel);
69 if (SCM_UNBNDP (password))
73 VERIFY_STRING (password);
74 passwd = Utils::scm2str (password);
76 if (SCM_UNBNDP (expire))
80 VERIFY_STRING (expire);
81 eexpire = Utils::str2time (Utils::scm2str (expire));
82 if (!eexpire) eexpire = -1;
85 int protect = scm_to_int (prot);
86 bool aaop = scm_is_true (aop);
87 int llevel = scm_to_int (level);
89 Message m = Commands::AddUser (Interp::bot, wwho, mask, llevel,
90 protect, aaop, eexpire, passwd);
92 return scm_from_int(m.getCode ());
96 ScriptCommands::AddServer(SCM servername, SCM port)
99 if (SCM_NUMBERP(port))
100 p = scm_to_int (port);
101 Message m = Commands::AddServer(Interp::bot,
102 Utils::scm2str(servername),
104 return scm_from_int(m.getCode());
108 ScriptCommands::AddShit(SCM mask, SCM maskChannel, SCM level,
109 SCM expiration, SCM reason)
111 // This appears to work...not much testing though
112 VERIFY_STRING (mask);
113 VERIFY_STRING (maskChannel);
114 VERIFY_NUMBER (level);
115 String mmask = Utils::scm2str (mask);
116 String mmaskChannel = Utils::scm2str (maskChannel);
117 int llevel = scm_to_int (level);
121 if (SCM_UNBNDP (expiration))
125 VERIFY_STRING (expiration);
126 expire = Utils::str2time (Utils::scm2str (expiration));
127 if (!expire) expire = -1;
129 if (SCM_UNBNDP (reason))
130 rreason = "You're on my shitlist, lamer";
133 VERIFY_STRING (reason);
134 rreason = Utils::scm2str (reason);
136 Message m = Commands::AddShit (Interp::bot, mmask, mmaskChannel,
137 llevel, expire, rreason);
139 return scm_from_int(m.getCode ());
143 ScriptCommands::Ban(SCM channel, SCM who)
145 VERIFY_STRING(channel);
147 Message m = Commands::Ban(Interp::bot, Utils::scm2str(channel),
148 Utils::scm2str(who));
149 return scm_from_int(m.getCode());
153 ScriptCommands::ChangeCommandLevel(SCM command, SCM level)
155 VERIFY_STRING (command);
156 VERIFY_NUMBER (level);
158 std::string ccommand = scm_to_locale_string (command);
159 unsigned int llevel = scm_to_uint (level);
164 std::map<std::string, class userFunction*,
165 std::less<std::string> >::const_iterator uf_iter
166 = Interp::bot->userFunctions.find (ccommand);
167 userFunction * f = 0;
169 if (uf_iter != Interp::bot->userFunctions.end ())
174 f->minLevel = llevel;
179 ScriptCommands::CTCP(SCM to, SCM command , SCM message)
182 VERIFY_STRING(command);
183 VERIFY_STRING(message);
185 Commands::CTCP (Interp::bot, Utils::scm2str (to),
186 Utils::scm2str (command),
187 Utils::scm2str (message));
189 return SCM_UNSPECIFIED;
193 ScriptCommands::CTCPReply (SCM to, SCM command , SCM message)
196 VERIFY_STRING(command);
197 VERIFY_STRING(message);
199 Commands::CTCPReply (Interp::bot, Utils::scm2str (to),
200 Utils::scm2str (command),
201 Utils::scm2str (message));
203 return SCM_UNSPECIFIED;
207 ScriptCommands::Cycle(SCM channel)
209 VERIFY_STRING(channel);
210 Message m = Commands::Cycle(Interp::bot, Utils::scm2str(channel));
211 return scm_from_int(m.getCode());
215 ScriptCommands::Deban(SCM channel, SCM who)
217 VERIFY_STRING(channel);
219 Message m = Commands::Deban(Interp::bot, Utils::scm2str(channel),
220 Utils::scm2str(who));
221 return scm_from_int(m.getCode());
225 ScriptCommands::DelServer(SCM number)
227 VERIFY_NUMBER(number);
228 Message m = Commands::DelServer(Interp::bot, scm_to_int (number));
229 return scm_from_int(m.getCode());
233 ScriptCommands::DelUser(SCM who, SCM maskChannel)
236 VERIFY_STRING(maskChannel);
237 Message m = Commands::DelUser(Interp::bot, Utils::scm2str(who),
238 Utils::scm2str(maskChannel));
239 return scm_from_int(m.getCode());
243 ScriptCommands::DelShit(SCM who, SCM maskChannel)
246 VERIFY_STRING(maskChannel);
247 Message m = Commands::DelShit(Interp::bot, Utils::scm2str(who),
248 Utils::scm2str(maskChannel));
249 return scm_from_int(m.getCode());
253 ScriptCommands::Deop(SCM channel, SCM who)
255 VERIFY_STRING(channel);
257 Message m = Commands::Deop(Interp::bot, Utils::scm2str(channel),
258 Utils::scm2str(who));
259 return scm_from_int(m.getCode());
263 ScriptCommands::Die(SCM reason)
265 String r = "Leaving";
266 if (scm_is_string(reason))
267 r = Utils::scm2str(reason);
268 Message m = Commands::Die(Interp::bot, r);
269 return scm_from_int(m.getCode());
273 ScriptCommands::Do(SCM command)
275 VERIFY_STRING(command);
276 Message m = Commands::Do(Interp::bot, Utils::scm2str(command));
277 return scm_from_int(m.getCode());
281 ScriptCommands::Invite(SCM channel, SCM who)
283 VERIFY_STRING(channel);
285 Message m = Commands::Invite(Interp::bot, Utils::scm2str(channel),
286 Utils::scm2str(who));
287 return scm_from_int(m.getCode());
291 ScriptCommands::Join(SCM channel, SCM key)
293 VERIFY_STRING(channel);
295 if (scm_is_string(key))
296 k = Utils::scm2str(key);
297 Message m = Commands::Join(Interp::bot, Utils::scm2str(channel),
299 return scm_from_int(m.getCode());
303 ScriptCommands::Keep(SCM channel, SCM modes)
305 VERIFY_STRING(channel);
306 VERIFY_STRING(modes);
307 Message m = Commands::Keep(Interp::bot, Utils::scm2str(channel),
308 Utils::scm2str(modes));
309 return scm_from_int(m.getCode());
313 ScriptCommands::Kick(SCM channel, SCM who, SCM reason)
315 VERIFY_STRING(channel);
319 if (scm_is_string(reason))
320 r = Utils::scm2str(reason);
322 Message m = Commands::Kick(Interp::bot, Utils::scm2str(channel),
323 Utils::scm2str(who), r);
324 return scm_from_int(m.getCode());
328 ScriptCommands::KickBan(SCM channel, SCM who, SCM reason)
330 VERIFY_STRING(channel);
333 if (scm_is_string(reason))
334 r = Utils::scm2str(reason);
335 Message m = Commands::KickBan(Interp::bot, Utils::scm2str(channel),
336 Utils::scm2str(who), r);
337 return scm_from_int(m.getCode());
341 ScriptCommands::Lock(SCM channel)
343 VERIFY_STRING(channel);
344 Message m = Commands::Lock(Interp::bot, Utils::scm2str(channel));
345 return scm_from_int(m.getCode());
349 ScriptCommands::LogPort(void)
351 return Interp::bot->botInterp->logPort;
355 ScriptCommands::Mode(SCM channel, SCM mode)
357 VERIFY_STRING(channel);
359 Message m = Commands::Mode(Interp::bot, Utils::scm2str(channel),
360 Utils::scm2str(mode));
361 return scm_from_int(m.getCode());
365 ScriptCommands::Msg(SCM nick, SCM message)
368 VERIFY_STRING(message);
369 Message m = Commands::Msg(Interp::bot, Utils::scm2str(nick),
370 Utils::scm2str(message));
371 return scm_from_int(m.getCode());
376 ScriptCommands::NextServer(void)
378 Message m = Commands::NextServer(Interp::bot);
379 return scm_from_int(m.getCode());
383 ScriptCommands::Nick(SCM nick)
386 Message m = Commands::Nick(Interp::bot, Utils::scm2str(nick));
387 return scm_from_int(m.getCode());
391 ScriptCommands::Notice (SCM to, SCM message)
394 VERIFY_STRING (message);
397 (Commands::Notice (Interp::bot,
399 Utils::scm2str (message)).getCode ()));
404 ScriptCommands::Op(SCM channel, SCM who)
406 VERIFY_STRING(channel);
408 Message m = Commands::Op(Interp::bot, Utils::scm2str(channel),
409 Utils::scm2str(who));
410 return scm_from_int(m.getCode());
414 ScriptCommands::Part(SCM channel)
416 VERIFY_STRING(channel);
417 Message m = Commands::Part(Interp::bot, Utils::scm2str(channel));
418 return scm_from_int(m.getCode());
422 ScriptCommands::Reconnect(void)
424 Message m = Commands::Reconnect(Interp::bot);
425 return scm_from_int(m.getCode());
429 ScriptCommands::Say(SCM channel, SCM message)
431 VERIFY_STRING(channel);
432 VERIFY_STRING(message);
433 Message m = Commands::Say(Interp::bot, Utils::scm2str(channel),
434 Utils::scm2str(message));
435 return scm_from_int(m.getCode());
439 ScriptCommands::Server(SCM number)
441 VERIFY_NUMBER(number);
442 Message m = Commands::Server(Interp::bot, scm_to_int(number));
443 return scm_from_int(m.getCode());
447 ScriptCommands::SetFloodRate(SCM rate)
450 Message m = Commands::SetFloodRate(Interp::bot, scm_to_uint (rate));
451 return scm_from_int(m.getCode());
455 ScriptCommands::SetVersion(SCM version)
457 Message m = Commands::SetVersion(Interp::bot, Utils::scm2str(version));
458 return scm_from_int(m.getCode());
462 ScriptCommands::TBan(SCM channel, SCM who, SCM seconds)
464 VERIFY_STRING(channel);
466 VERIFY_NUMBER(seconds);
467 Message m = Commands::TBan(Interp::bot, Utils::scm2str(channel),
468 Utils::scm2str(who), scm_to_int(seconds));
469 return scm_from_int(m.getCode());
473 ScriptCommands::TKBan(SCM channel, SCM who, SCM seconds, SCM reason)
475 VERIFY_STRING(channel);
477 VERIFY_NUMBER(seconds);
479 if (scm_is_string(reason))
480 r = Utils::scm2str(reason);
481 Message m = Commands::TKBan(Interp::bot, Utils::scm2str(channel),
483 scm_to_int(seconds), r);
484 return scm_from_int(m.getCode());
488 ScriptCommands::Topic(SCM channel, SCM topic)
490 VERIFY_STRING(channel);
491 VERIFY_STRING(topic);
492 Message m = Commands::Topic(Interp::bot, Utils::scm2str(channel),
493 Utils::scm2str(topic));
494 return scm_from_int(m.getCode());
498 ScriptCommands::Unlock(SCM channel)
500 VERIFY_STRING(channel);
501 Message m = Commands::Unlock(Interp::bot, Utils::scm2str(channel));
502 return scm_from_int(m.getCode());
506 ScriptCommands::Who (SCM target)
508 VERIFY_STRING (target);
510 Message m = Commands::Who (Interp::bot, Utils::scm2str (target));
512 return scm_from_int (m.getCode ());
516 ScriptCommands::Whois (SCM nick)
518 VERIFY_STRING (nick);
520 Message m = Commands::Whois (Interp::bot, Utils::scm2str (nick));
522 return scm_from_int (m.getCode ());
526 ScriptCommands::getNickname(void)
528 return Utils::str2scm(Interp::bot->nickName);
532 ScriptCommands::getServer(void)
534 ::Server *serv = Interp::bot->serverList->currentServer();
535 int serverNumber = Interp::bot->serverList->currentNumber;
537 return scm_list_n(scm_from_int(serverNumber),
538 Utils::str2scm(serv->getHostName()),
539 scm_from_int(serv->getPort()),
540 Utils::str2scm(serv->getPassword()),
545 ScriptCommands::getServerList(void)
547 SCM res = scm_list_n(SCM_UNDEFINED);
550 std::vector<class Server *>::iterator it =
551 Interp::bot->serverList->begin();
553 for ( ; it != Interp::bot->serverList->end(); ++it) {
558 scm_list_n(scm_list_n(scm_from_int(i++),
559 Utils::str2scm(s->getHostName()),
560 scm_from_int(s->getPort()),
561 Utils::str2scm(s->getPassword()),
562 SCM_UNDEFINED), SCM_UNDEFINED)));
568 ScriptCommands::flushQueue(void)
570 if (!Interp::bot->serverConnection)
572 Interp::bot->serverConnection->queue->flush();
577 ScriptCommands::flushPort(void)
579 scm_flush(Interp::bot->botInterp->logPort);
584 ScriptCommands::random(SCM scm_max)
588 if (SCM_NUMBERP(scm_max))
589 max = scm_to_int(scm_max);
590 return scm_from_int(max ? rand() % max : 0);
594 ScriptCommands::addCommand(SCM scm_commandName, SCM scm_function,
595 SCM scm_needsChannel, SCM scm_args,
598 // We check that commandName is a string
599 if (!scm_is_string(scm_commandName))
602 // We check that the command does not exist
603 String commandName = Utils::to_upper (Utils::scm2str(scm_commandName));
604 if (Interp::bot->userFunctions[commandName])
607 // Next we check that needsChannel is a boolean
608 if (!scm_is_bool (scm_needsChannel))
610 bool needsChannel = scm_to_bool(scm_needsChannel);
612 // We check that minLevel is an integer and that it's
614 if (!SCM_NUMBERP(scm_minLevel))
617 int minLevel = scm_to_int(scm_minLevel);
618 if (minLevel < User::NONE || minLevel > User::MASTER)
621 // We check that "scm_function" is a Scheme procedure
622 if (!scm_is_true (scm_procedure_p(scm_function)))
625 // We check that args is an integer and is between 0 and 20 (arbitrary limit)
626 if (!SCM_NUMBERP(scm_args))
629 int args = scm_to_int(scm_args);
630 if (args < 0 || args > 20)
633 // We add the command in the commands list
634 Interp::bot->userFunctions[commandName] =
635 new userFunction(0, minLevel, needsChannel, args, scm_function);
641 ScriptCommands::delCommand(SCM scm_commandName)
643 // We check that commandName is a string
644 if (!scm_is_string(scm_commandName))
647 // We check that the command does exist
648 String commandName = Utils::to_upper (Utils::scm2str(scm_commandName));
649 if (!Interp::bot->userFunctions[commandName])
652 // We delete the command
653 Interp::bot->userFunctions.erase(commandName);
659 ScriptCommands::AddHook(SCM type, SCM regex, SCM function, SCM pri, SCM fall,
663 bool fallt = true; // does this hook fall through?
664 String rname = "DEFAULT";
666 if (!SCM_UNBNDP (pri))
667 priority = scm_to_int (pri);
668 if (!SCM_UNBNDP (fall))
669 fallt = scm_is_true (fall);
670 if (!SCM_UNBNDP (name))
671 rname = Utils::scm2str (name);
672 return scm_from_bool (Interp::bot->botInterp->AddHook(scm_to_int(type),
674 priority, fallt, rname));
678 ScriptCommands::AddTimer(SCM when, SCM function)
680 return Interp::bot->botInterp->AddTimer(scm_to_int(when), function);
684 ScriptCommands::DelTimer(SCM timer)
686 return scm_from_bool (Interp::bot->botInterp->DelTimer(timer));
690 ScriptCommands::sendDCCChatMessage (SCM to, SCM message)
693 return scm_from_bool (Interp::bot->dccConnections->sendMessage
694 (Utils::scm2str (to),
695 Utils::scm2str (message)));