1 // ScriptCommands.C -*- C++ -*-
2 // Copyright (c) 1998 Etienne BERNARD
3 // Copyright (C) 2002,2005 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 02110-1301, USA.
27 #include "ServerList.H"
28 #include "ServerQueue.H"
29 #include "ScriptCommands.H"
31 #include "DCCPerson.H"
32 #include "DCCManager.H"
38 #define VERIFY_STRING(par) if (!SCM_STRINGP((par))) \
39 return scm_long2num(-17)
41 #define VERIFY_NUMBER(par) if (!SCM_NUMBERP((par))) \
42 return scm_long2num(-17)
45 ScriptCommands::Action(SCM channel, SCM message)
47 VERIFY_STRING(channel);
48 VERIFY_STRING(message);
49 Message m = Commands::Action(Interp::bot, Utils::scm2str(channel),
50 Utils::scm2str(message));
51 return scm_long2num(m.getCode());
55 ScriptCommands::AddUser(SCM who, SCM maskChannel, SCM level,
56 SCM prot, SCM aop, SCM expire, SCM password)
58 // It segfaults when not online, but otherwise appears to work
60 VERIFY_STRING (maskChannel);
61 VERIFY_NUMBER (level);
63 String wwho = Utils::scm2str (who);
64 String mask = Utils::scm2str (maskChannel);
68 if (SCM_UNBNDP (password))
72 VERIFY_STRING (password);
73 passwd = Utils::scm2str (password);
75 if (SCM_UNBNDP (expire))
79 VERIFY_STRING (expire);
80 eexpire = Utils::str2time (Utils::scm2str (expire));
81 if (!eexpire) eexpire = -1;
84 int protect = scm_num2int (prot, SCM_ARG1, "ScriptCommands::AddUser");
85 bool aaop = SCM_NFALSEP (aop);
86 int llevel = scm_num2int (level, SCM_ARG1,
87 "ScriptCommands::AddUser");
89 Message m = Commands::AddUser (Interp::bot, wwho, mask, llevel,
90 protect, aaop, eexpire, passwd);
92 return scm_long2num(m.getCode ());
96 ScriptCommands::AddServer(SCM servername, SCM port)
99 if (SCM_NUMBERP(port))
100 p = scm_num2long(port, SCM_ARG1, "ScriptCommands::AddServer");
101 Message m = Commands::AddServer(Interp::bot,
102 Utils::scm2str(servername),
104 return scm_long2num(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_num2int (level, SCM_ARG1, "ScriptCommands::AddShit");
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_long2num(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_long2num(m.getCode());
153 ScriptCommands::ChangeCommandLevel(SCM command, SCM level)
155 VERIFY_STRING (command);
156 VERIFY_NUMBER (level);
158 SCM_STRING_COERCE_0TERMINATION_X (command);
159 std::string ccommand = SCM_STRING_CHARS (command);
160 unsigned int llevel = scm_num2uint (level, 0, "ScriptCommands::ChangeCommandLevel");
165 std::map<std::string, class userFunction*,
166 std::less<std::string> >::const_iterator uf_iter
167 = Interp::bot->userFunctions.find (ccommand);
168 userFunction * f = 0;
170 if (uf_iter != Interp::bot->userFunctions.end ())
175 f->minLevel = llevel;
180 ScriptCommands::Cycle(SCM channel)
182 VERIFY_STRING(channel);
183 Message m = Commands::Cycle(Interp::bot, Utils::scm2str(channel));
184 return scm_long2num(m.getCode());
188 ScriptCommands::Deban(SCM channel, SCM who)
190 VERIFY_STRING(channel);
192 Message m = Commands::Deban(Interp::bot, Utils::scm2str(channel),
193 Utils::scm2str(who));
194 return scm_long2num(m.getCode());
198 ScriptCommands::DelServer(SCM number)
200 VERIFY_NUMBER(number);
201 Message m = Commands::DelServer(Interp::bot,
202 scm_num2long(number, SCM_ARG1,
203 "ScriptCommands::DelServer"));
204 return scm_long2num(m.getCode());
208 ScriptCommands::DelUser(SCM who, SCM maskChannel)
211 VERIFY_STRING(maskChannel);
212 Message m = Commands::DelUser(Interp::bot, Utils::scm2str(who),
213 Utils::scm2str(maskChannel));
214 return scm_long2num(m.getCode());
218 ScriptCommands::DelShit(SCM who, SCM maskChannel)
221 VERIFY_STRING(maskChannel);
222 Message m = Commands::DelShit(Interp::bot, Utils::scm2str(who),
223 Utils::scm2str(maskChannel));
224 return scm_long2num(m.getCode());
228 ScriptCommands::Deop(SCM channel, SCM who)
230 VERIFY_STRING(channel);
232 Message m = Commands::Deop(Interp::bot, Utils::scm2str(channel),
233 Utils::scm2str(who));
234 return scm_long2num(m.getCode());
238 ScriptCommands::Die(SCM reason)
240 String r = "Leaving";
241 if (SCM_STRINGP(reason))
242 r = Utils::scm2str(reason);
243 Message m = Commands::Die(Interp::bot, r);
244 return scm_long2num(m.getCode());
248 ScriptCommands::Do(SCM command)
250 VERIFY_STRING(command);
251 Message m = Commands::Do(Interp::bot, Utils::scm2str(command));
252 return scm_long2num(m.getCode());
256 ScriptCommands::Invite(SCM channel, SCM who)
258 VERIFY_STRING(channel);
260 Message m = Commands::Invite(Interp::bot, Utils::scm2str(channel),
261 Utils::scm2str(who));
262 return scm_long2num(m.getCode());
266 ScriptCommands::Join(SCM channel, SCM key)
268 VERIFY_STRING(channel);
270 if (SCM_STRINGP(key))
271 k = Utils::scm2str(key);
272 Message m = Commands::Join(Interp::bot, Utils::scm2str(channel),
274 return scm_long2num(m.getCode());
278 ScriptCommands::Keep(SCM channel, SCM modes)
280 VERIFY_STRING(channel);
281 VERIFY_STRING(modes);
282 Message m = Commands::Keep(Interp::bot, Utils::scm2str(channel),
283 Utils::scm2str(modes));
284 return scm_long2num(m.getCode());
288 ScriptCommands::Kick(SCM channel, SCM who, SCM reason)
290 VERIFY_STRING(channel);
294 if (SCM_STRINGP(reason))
295 r = Utils::scm2str(reason);
297 Message m = Commands::Kick(Interp::bot, Utils::scm2str(channel),
298 Utils::scm2str(who), r);
299 return scm_long2num(m.getCode());
303 ScriptCommands::KickBan(SCM channel, SCM who, SCM reason)
305 VERIFY_STRING(channel);
308 if (SCM_STRINGP(reason))
309 r = Utils::scm2str(reason);
310 Message m = Commands::KickBan(Interp::bot, Utils::scm2str(channel),
311 Utils::scm2str(who), r);
312 return scm_long2num(m.getCode());
316 ScriptCommands::Lock(SCM channel)
318 VERIFY_STRING(channel);
319 Message m = Commands::Lock(Interp::bot, Utils::scm2str(channel));
320 return scm_long2num(m.getCode());
324 ScriptCommands::LogPort(void)
326 return Interp::bot->botInterp->logPort;
330 ScriptCommands::Mode(SCM channel, SCM mode)
332 VERIFY_STRING(channel);
334 Message m = Commands::Mode(Interp::bot, Utils::scm2str(channel),
335 Utils::scm2str(mode));
336 return scm_long2num(m.getCode());
340 ScriptCommands::Msg(SCM nick, SCM message)
343 VERIFY_STRING(message);
344 Message m = Commands::Msg(Interp::bot, Utils::scm2str(nick),
345 Utils::scm2str(message));
346 return scm_long2num(m.getCode());
351 ScriptCommands::NextServer(void)
353 Message m = Commands::NextServer(Interp::bot);
354 return scm_long2num(m.getCode());
358 ScriptCommands::Nick(SCM nick)
361 Message m = Commands::Nick(Interp::bot, Utils::scm2str(nick));
362 return scm_long2num(m.getCode());
366 ScriptCommands::Op(SCM channel, SCM who)
368 VERIFY_STRING(channel);
370 Message m = Commands::Op(Interp::bot, Utils::scm2str(channel),
371 Utils::scm2str(who));
372 return scm_long2num(m.getCode());
376 ScriptCommands::Part(SCM channel)
378 VERIFY_STRING(channel);
379 Message m = Commands::Part(Interp::bot, Utils::scm2str(channel));
380 return scm_long2num(m.getCode());
384 ScriptCommands::Reconnect(void)
386 Message m = Commands::Reconnect(Interp::bot);
387 return scm_long2num(m.getCode());
391 ScriptCommands::Say(SCM channel, SCM message)
393 VERIFY_STRING(channel);
394 VERIFY_STRING(message);
395 Message m = Commands::Say(Interp::bot, Utils::scm2str(channel),
396 Utils::scm2str(message));
397 return scm_long2num(m.getCode());
401 ScriptCommands::Server(SCM number)
403 VERIFY_NUMBER(number);
404 Message m = Commands::Server(Interp::bot, gh_scm2long(number));
405 return scm_long2num(m.getCode());
409 ScriptCommands::SetFloodRate(SCM rate)
412 Message m = Commands::SetFloodRate(Interp::bot, scm_num2uint
413 (rate, 0, "SetFloodRate"));
414 return scm_long2num(m.getCode());
418 ScriptCommands::SetVersion(SCM version)
420 Message m = Commands::SetVersion(Interp::bot, Utils::scm2str(version));
421 return scm_long2num(m.getCode());
425 ScriptCommands::TBan(SCM channel, SCM who, SCM seconds)
427 VERIFY_STRING(channel);
429 VERIFY_NUMBER(seconds);
430 Message m = Commands::TBan(Interp::bot, Utils::scm2str(channel),
431 Utils::scm2str(who), gh_scm2long(seconds));
432 return scm_long2num(m.getCode());
436 ScriptCommands::TKBan(SCM channel, SCM who, SCM seconds, SCM reason)
438 VERIFY_STRING(channel);
440 VERIFY_NUMBER(seconds);
442 if (SCM_STRINGP(reason))
443 r = Utils::scm2str(reason);
444 Message m = Commands::TKBan(Interp::bot, Utils::scm2str(channel),
446 gh_scm2long(seconds), r);
447 return scm_long2num(m.getCode());
451 ScriptCommands::Topic(SCM channel, SCM topic)
453 VERIFY_STRING(channel);
454 VERIFY_STRING(topic);
455 Message m = Commands::Topic(Interp::bot, Utils::scm2str(channel),
456 Utils::scm2str(topic));
457 return scm_long2num(m.getCode());
461 ScriptCommands::Unlock(SCM channel)
463 VERIFY_STRING(channel);
464 Message m = Commands::Unlock(Interp::bot, Utils::scm2str(channel));
465 return scm_long2num(m.getCode());
469 ScriptCommands::getNickname(void)
471 return Utils::str2scm(Interp::bot->nickName);
475 ScriptCommands::getServer(void)
477 ::Server *serv = Interp::bot->serverList->currentServer();
478 int serverNumber = Interp::bot->serverList->currentNumber;
480 return gh_list(scm_long2num(serverNumber),
481 Utils::str2scm(serv->getHostName()),
482 scm_long2num(serv->getPort()),
483 Utils::str2scm(serv->getPassword()),
488 ScriptCommands::getServerList(void)
490 SCM res = gh_list(SCM_UNDEFINED);
493 std::vector<class Server *>::iterator it = Interp::bot->serverList->begin();
495 for ( ; it != Interp::bot->serverList->end(); ++it) {
497 res = gh_append2(res,
498 gh_list(gh_list(scm_long2num(i++),
499 Utils::str2scm(s->getHostName()),
500 scm_long2num(s->getPort()),
501 Utils::str2scm(s->getPassword()),
502 SCM_UNDEFINED), SCM_UNDEFINED));
508 ScriptCommands::flushQueue(void)
510 if (!Interp::bot->serverConnection)
512 Interp::bot->serverConnection->queue->flush();
517 ScriptCommands::flushPort(void)
519 scm_flush(Interp::bot->botInterp->logPort);
524 ScriptCommands::random(SCM scm_max)
528 if (SCM_NUMBERP(scm_max))
529 max = gh_scm2int(scm_max);
530 return scm_long2num(max ? rand() % max : 0);
534 ScriptCommands::addCommand(SCM scm_commandName, SCM scm_function,
535 SCM scm_needsChannel, SCM scm_args,
538 // We check that commandName is a string
539 if (!SCM_STRINGP(scm_commandName))
542 // We check that the command does not exist
543 String commandName = Utils::to_upper (Utils::scm2str(scm_commandName));
544 if (Interp::bot->userFunctions[commandName])
547 // Next we check that needsChannel is a boolean
548 if (!gh_boolean_p(scm_needsChannel))
550 bool needsChannel = gh_scm2bool(scm_needsChannel);
552 // We check that minLevel is an integer and that it's
554 if (!SCM_NUMBERP(scm_minLevel))
557 int minLevel = gh_scm2long(scm_minLevel);
558 if (minLevel < User::NONE || minLevel > User::MASTER)
561 // We check that "scm_function" is a Scheme procedure
562 if (!gh_procedure_p(scm_function))
565 // We check that args is an integer and is between 0 and 20 (arbitrary limit)
566 if (!SCM_NUMBERP(scm_args))
569 int args = gh_scm2long(scm_args);
570 if (args < 0 || args > 20)
573 // We add the command in the commands list
574 Interp::bot->userFunctions[commandName] =
575 new userFunction(0, minLevel, needsChannel, args, scm_function);
581 ScriptCommands::delCommand(SCM scm_commandName)
583 // We check that commandName is a string
584 if (!SCM_STRINGP(scm_commandName))
587 // We check that the command does exist
588 String commandName = Utils::to_upper (Utils::scm2str(scm_commandName));
589 if (!Interp::bot->userFunctions[commandName])
592 // We delete the command
593 Interp::bot->userFunctions.erase(commandName);
599 ScriptCommands::AddHook(SCM type, SCM regex, SCM function, SCM pri, SCM fall,
603 bool fallt = true; // does this hook fall through?
604 String rname = "DEFAULT";
606 if (!SCM_UNBNDP (pri))
607 priority = scm_num2int (pri, SCM_ARG1, "ScriptCommands::AddHook");
608 if (!SCM_UNBNDP (fall))
609 fallt = SCM_NFALSEP (fall);
610 if (!SCM_UNBNDP (name))
611 rname = Utils::scm2str (name);
612 return SCM_BOOL (Interp::bot->botInterp->AddHook(gh_scm2long(type),
614 priority, fallt, rname));
618 ScriptCommands::AddTimer(SCM when, SCM function)
620 return Interp::bot->botInterp->AddTimer(gh_scm2long(when), function);
624 ScriptCommands::DelTimer(SCM timer)
626 return SCM_BOOL (Interp::bot->botInterp->DelTimer(timer));
630 ScriptCommands::sendDCCChatMessage (SCM to, SCM message)
633 return SCM_BOOL (Interp::bot->dccConnections->sendMessage
634 (Utils::scm2str (to),
635 Utils::scm2str (message)));
639 // FIXME: write these
641 #define IQUEUE Interp::bot->serverConnection->queue
644 ScriptCommands::sendCTCP(SCM to, SCM command , SCM message)
647 VERIFY_STRING(command);
648 VERIFY_STRING(message);
650 IQUEUE->sendCTCP (Utils::scm2str (to), Utils::scm2str (command),
651 Utils::scm2str (message));
653 return SCM_UNSPECIFIED;
657 ScriptCommands::sendNotice (SCM to, SCM message)
660 VERIFY_STRING (message);
663 (Commands::Notice (Interp::bot,
665 Utils::scm2str (message)).getCode ()));