1 // ScriptCommands.C -*- C++ -*-
2 // Copyright (c) 1998 Etienne BERNARD
3 // Copyright (C) 2002,2005,2008,2009 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
26 #include "ScriptCommands.H"
31 #include "BotInterp.H"
32 #include "ChannelList.H"
34 #include "DCCManager.H"
35 #include "DCCPerson.H"
40 #include "ServerConnection.H"
41 #include "ServerList.H"
42 #include "ServerQueue.H"
46 #define VERIFY_STRING(par) if (!scm_is_string((par))) \
47 return scm_from_int(-17)
49 #define VERIFY_NUMBER(par) if (!SCM_NUMBERP((par))) \
50 return scm_from_int(-17)
53 ScriptCommands::Action(SCM channel, SCM message)
55 VERIFY_STRING(channel);
56 VERIFY_STRING(message);
57 Message m = Commands::Action(Interp::bot, Utils::scm2str(channel),
58 Utils::scm2str(message));
59 return scm_from_int(m.getCode());
63 ScriptCommands::AddUser(SCM who, SCM maskChannel, SCM level,
64 SCM prot, SCM aop, SCM expire, SCM password)
66 // It segfaults when not online, but otherwise appears to work
68 VERIFY_STRING (maskChannel);
69 VERIFY_NUMBER (level);
71 String wwho = Utils::scm2str (who);
72 String mask = Utils::scm2str (maskChannel);
76 if (SCM_UNBNDP (password))
80 VERIFY_STRING (password);
81 passwd = Utils::scm2str (password);
83 if (SCM_UNBNDP (expire))
87 VERIFY_STRING (expire);
88 eexpire = Utils::str2time (Utils::scm2str (expire));
89 if (!eexpire) eexpire = -1;
92 int protect = scm_to_int (prot);
93 bool aaop = scm_is_true (aop);
94 int llevel = scm_to_int (level);
96 Message m = Commands::AddUser (Interp::bot, wwho, mask, llevel,
97 protect, aaop, eexpire, passwd);
99 return scm_from_int(m.getCode ());
103 ScriptCommands::AddServer(SCM servername, SCM port)
106 if (SCM_NUMBERP(port))
107 p = scm_to_int (port);
108 Message m = Commands::AddServer(Interp::bot,
109 Utils::scm2str(servername),
111 return scm_from_int(m.getCode());
115 ScriptCommands::AddShit(SCM mask, SCM maskChannel, SCM level,
116 SCM expiration, SCM reason)
118 // This appears to work...not much testing though
119 VERIFY_STRING (mask);
120 VERIFY_STRING (maskChannel);
121 VERIFY_NUMBER (level);
122 String mmask = Utils::scm2str (mask);
123 String mmaskChannel = Utils::scm2str (maskChannel);
124 int llevel = scm_to_int (level);
128 if (SCM_UNBNDP (expiration))
132 VERIFY_STRING (expiration);
133 expire = Utils::str2time (Utils::scm2str (expiration));
134 if (!expire) expire = -1;
136 if (SCM_UNBNDP (reason))
137 rreason = "You're on my shitlist, lamer";
140 VERIFY_STRING (reason);
141 rreason = Utils::scm2str (reason);
143 Message m = Commands::AddShit (Interp::bot, mmask, mmaskChannel,
144 llevel, expire, rreason);
146 return scm_from_int(m.getCode ());
150 ScriptCommands::Ban(SCM channel, SCM who)
152 VERIFY_STRING(channel);
154 Message m = Commands::Ban(Interp::bot, Utils::scm2str(channel),
155 Utils::scm2str(who));
156 return scm_from_int(m.getCode());
160 ScriptCommands::ChangeCommandLevel(SCM command, SCM level)
162 VERIFY_STRING (command);
163 VERIFY_NUMBER (level);
165 std::string ccommand = scm_to_locale_string (command);
166 unsigned int llevel = scm_to_uint (level);
171 std::map<std::string, class userFunction*,
172 std::less<std::string> >::const_iterator uf_iter
173 = Interp::bot->userFunctions.find (ccommand);
174 userFunction * f = 0;
176 if (uf_iter != Interp::bot->userFunctions.end ())
181 f->minLevel = llevel;
187 ScriptCommands::collect_channel_users::operator() (SCM *list, User user)
190 *list = scm_cons (scm_list_n (Utils::str2scm (user.get_nick()),
191 Utils::str2scm (user.get_userhost ()),
192 scm_from_int (user.get_mode ()),
198 ScriptCommands::ChannelUsers (SCM channel_name)
200 VERIFY_STRING (channel_name);
202 Channel *channel = Interp::bot->channelList->getChannel (Utils::scm2str (channel_name));
207 SCM* list = (SCM*)scm_gc_malloc (sizeof (SCM), "ScriptCommands::ChannelUsers");
210 collect_channel_users c;
212 channel->for_each_channel_users (std::bind1st (c, list));
214 scm_remember_upto_here_1 (list);
215 return scm_reverse_x (*list, SCM_UNDEFINED);
219 ScriptCommands::CTCP(SCM to, SCM command , SCM message)
222 VERIFY_STRING(command);
223 VERIFY_STRING(message);
225 Commands::CTCP (Interp::bot, Utils::scm2str (to),
226 Utils::scm2str (command),
227 Utils::scm2str (message));
229 return SCM_UNSPECIFIED;
233 ScriptCommands::CTCPReply (SCM to, SCM command , SCM message)
236 VERIFY_STRING(command);
237 VERIFY_STRING(message);
239 Commands::CTCPReply (Interp::bot, Utils::scm2str (to),
240 Utils::scm2str (command),
241 Utils::scm2str (message));
243 return SCM_UNSPECIFIED;
247 ScriptCommands::Cycle(SCM channel)
249 VERIFY_STRING(channel);
250 Message m = Commands::Cycle(Interp::bot, Utils::scm2str(channel));
251 return scm_from_int(m.getCode());
255 ScriptCommands::Deban(SCM channel, SCM who)
257 VERIFY_STRING(channel);
259 Message m = Commands::Deban(Interp::bot, Utils::scm2str(channel),
260 Utils::scm2str(who));
261 return scm_from_int(m.getCode());
265 ScriptCommands::DelServer(SCM number)
267 VERIFY_NUMBER(number);
268 Message m = Commands::DelServer(Interp::bot, scm_to_int (number));
269 return scm_from_int(m.getCode());
273 ScriptCommands::DelUser(SCM who, SCM maskChannel)
276 VERIFY_STRING(maskChannel);
277 Message m = Commands::DelUser(Interp::bot, Utils::scm2str(who),
278 Utils::scm2str(maskChannel));
279 return scm_from_int(m.getCode());
283 ScriptCommands::DelShit(SCM who, SCM maskChannel)
286 VERIFY_STRING(maskChannel);
287 Message m = Commands::DelShit(Interp::bot, Utils::scm2str(who),
288 Utils::scm2str(maskChannel));
289 return scm_from_int(m.getCode());
293 ScriptCommands::Deop(SCM channel, SCM who)
295 VERIFY_STRING(channel);
297 Message m = Commands::Deop(Interp::bot, Utils::scm2str(channel),
298 Utils::scm2str(who));
299 return scm_from_int(m.getCode());
303 ScriptCommands::Die(SCM reason)
305 String r = "Leaving";
306 if (scm_is_string(reason))
307 r = Utils::scm2str(reason);
308 Message m = Commands::Die(Interp::bot, r);
309 return scm_from_int(m.getCode());
313 ScriptCommands::Do(SCM command)
315 VERIFY_STRING(command);
316 Message m = Commands::Do(Interp::bot, Utils::scm2str(command));
317 return scm_from_int(m.getCode());
321 ScriptCommands::Invite(SCM channel, SCM who)
323 VERIFY_STRING(channel);
325 Message m = Commands::Invite(Interp::bot, Utils::scm2str(channel),
326 Utils::scm2str(who));
327 return scm_from_int(m.getCode());
331 ScriptCommands::Join(SCM channel, SCM key)
333 VERIFY_STRING(channel);
335 if (scm_is_string(key))
336 k = Utils::scm2str(key);
337 Message m = Commands::Join(Interp::bot, Utils::scm2str(channel),
339 return scm_from_int(m.getCode());
343 ScriptCommands::Keep(SCM channel, SCM modes)
345 VERIFY_STRING(channel);
346 VERIFY_STRING(modes);
347 Message m = Commands::Keep(Interp::bot, Utils::scm2str(channel),
348 Utils::scm2str(modes));
349 return scm_from_int(m.getCode());
353 ScriptCommands::Kick(SCM channel, SCM who, SCM reason)
355 VERIFY_STRING(channel);
359 if (scm_is_string(reason))
360 r = Utils::scm2str(reason);
362 Message m = Commands::Kick(Interp::bot, Utils::scm2str(channel),
363 Utils::scm2str(who), r);
364 return scm_from_int(m.getCode());
368 ScriptCommands::KickBan(SCM channel, SCM who, SCM reason)
370 VERIFY_STRING(channel);
373 if (scm_is_string(reason))
374 r = Utils::scm2str(reason);
375 Message m = Commands::KickBan(Interp::bot, Utils::scm2str(channel),
376 Utils::scm2str(who), r);
377 return scm_from_int(m.getCode());
381 ScriptCommands::Lock(SCM channel)
383 VERIFY_STRING(channel);
384 Message m = Commands::Lock(Interp::bot, Utils::scm2str(channel));
385 return scm_from_int(m.getCode());
389 ScriptCommands::LogPort(void)
391 return Interp::bot->botInterp->logPort;
395 ScriptCommands::Mode(SCM channel, SCM mode)
397 VERIFY_STRING(channel);
399 Message m = Commands::Mode(Interp::bot, Utils::scm2str(channel),
400 Utils::scm2str(mode));
401 return scm_from_int(m.getCode());
405 ScriptCommands::Msg(SCM nick, SCM message)
408 VERIFY_STRING(message);
409 Message m = Commands::Msg(Interp::bot, Utils::scm2str(nick),
410 Utils::scm2str(message));
411 return scm_from_int(m.getCode());
416 ScriptCommands::NextServer(void)
418 Message m = Commands::NextServer(Interp::bot);
419 return scm_from_int(m.getCode());
423 ScriptCommands::Nick(SCM nick)
426 Message m = Commands::Nick(Interp::bot, Utils::scm2str(nick));
427 return scm_from_int(m.getCode());
431 ScriptCommands::Notice (SCM to, SCM message)
434 VERIFY_STRING (message);
437 (Commands::Notice (Interp::bot,
439 Utils::scm2str (message)).getCode ()));
444 ScriptCommands::Op(SCM channel, SCM who)
446 VERIFY_STRING(channel);
448 Message m = Commands::Op(Interp::bot, Utils::scm2str(channel),
449 Utils::scm2str(who));
450 return scm_from_int(m.getCode());
454 ScriptCommands::Part(SCM channel)
456 VERIFY_STRING(channel);
457 Message m = Commands::Part(Interp::bot, Utils::scm2str(channel));
458 return scm_from_int(m.getCode());
462 ScriptCommands::Reconnect(void)
464 Message m = Commands::Reconnect(Interp::bot);
465 return scm_from_int(m.getCode());
469 ScriptCommands::Say(SCM channel, SCM message)
471 VERIFY_STRING(channel);
472 VERIFY_STRING(message);
473 Message m = Commands::Say(Interp::bot, Utils::scm2str(channel),
474 Utils::scm2str(message));
475 return scm_from_int(m.getCode());
479 ScriptCommands::Server(SCM number)
481 VERIFY_NUMBER(number);
482 Message m = Commands::Server(Interp::bot, scm_to_int(number));
483 return scm_from_int(m.getCode());
487 ScriptCommands::SetFloodRate(SCM rate)
490 Message m = Commands::SetFloodRate(Interp::bot, scm_to_uint (rate));
491 return scm_from_int(m.getCode());
495 ScriptCommands::SetVersion(SCM version)
497 Message m = Commands::SetVersion(Interp::bot, Utils::scm2str(version));
498 return scm_from_int(m.getCode());
502 ScriptCommands::TBan(SCM channel, SCM who, SCM seconds)
504 VERIFY_STRING(channel);
506 VERIFY_NUMBER(seconds);
507 Message m = Commands::TBan(Interp::bot, Utils::scm2str(channel),
508 Utils::scm2str(who), scm_to_int(seconds));
509 return scm_from_int(m.getCode());
513 ScriptCommands::TKBan(SCM channel, SCM who, SCM seconds, SCM reason)
515 VERIFY_STRING(channel);
517 VERIFY_NUMBER(seconds);
519 if (scm_is_string(reason))
520 r = Utils::scm2str(reason);
521 Message m = Commands::TKBan(Interp::bot, Utils::scm2str(channel),
523 scm_to_int(seconds), r);
524 return scm_from_int(m.getCode());
528 ScriptCommands::Topic(SCM channel, SCM topic)
530 VERIFY_STRING(channel);
531 VERIFY_STRING(topic);
532 Message m = Commands::Topic(Interp::bot, Utils::scm2str(channel),
533 Utils::scm2str(topic));
534 return scm_from_int(m.getCode());
538 ScriptCommands::Unlock(SCM channel)
540 VERIFY_STRING(channel);
541 Message m = Commands::Unlock(Interp::bot, Utils::scm2str(channel));
542 return scm_from_int(m.getCode());
546 ScriptCommands::Who (SCM target)
548 VERIFY_STRING (target);
550 Message m = Commands::Who (Interp::bot, Utils::scm2str (target));
552 return scm_from_int (m.getCode ());
556 ScriptCommands::Whois (SCM nick)
558 VERIFY_STRING (nick);
560 Message m = Commands::Whois (Interp::bot, Utils::scm2str (nick));
562 return scm_from_int (m.getCode ());
566 ScriptCommands::getNickname(void)
568 return Utils::str2scm(Interp::bot->nickName);
572 ScriptCommands::getServer(void)
574 ::Server *serv = Interp::bot->serverList->currentServer();
575 int serverNumber = Interp::bot->serverList->currentNumber;
577 return scm_list_n(scm_from_int(serverNumber),
578 Utils::str2scm(serv->getHostName()),
579 scm_from_int(serv->getPort()),
580 Utils::str2scm(serv->getPassword()),
585 ScriptCommands::getServerList(void)
587 SCM res = scm_list_n(SCM_UNDEFINED);
590 std::vector<class Server *>::iterator it =
591 Interp::bot->serverList->begin();
593 for ( ; it != Interp::bot->serverList->end(); ++it) {
598 scm_list_n(scm_list_n(scm_from_int(i++),
599 Utils::str2scm(s->getHostName()),
600 scm_from_int(s->getPort()),
601 Utils::str2scm(s->getPassword()),
602 SCM_UNDEFINED), SCM_UNDEFINED)));
608 ScriptCommands::flushQueue(void)
610 if (!Interp::bot->serverConnection)
612 Interp::bot->serverConnection->queue->flush();
617 ScriptCommands::flushPort(void)
619 scm_flush(Interp::bot->botInterp->logPort);
624 ScriptCommands::random(SCM scm_max)
628 if (SCM_NUMBERP(scm_max))
629 max = scm_to_int(scm_max);
630 return scm_from_int(max ? rand() % max : 0);
634 ScriptCommands::addCommand(SCM scm_commandName, SCM scm_function,
635 SCM scm_needsChannel, SCM scm_args,
638 // We check that commandName is a string
639 if (!scm_is_string(scm_commandName))
642 // We check that the command does not exist
643 String commandName = Utils::to_upper (Utils::scm2str(scm_commandName));
644 if (Interp::bot->userFunctions[commandName])
647 // Next we check that needsChannel is a boolean
648 if (!scm_is_bool (scm_needsChannel))
650 bool needsChannel = scm_to_bool(scm_needsChannel);
652 // We check that minLevel is an integer and that it's
654 if (!SCM_NUMBERP(scm_minLevel))
657 int minLevel = scm_to_int(scm_minLevel);
658 if (minLevel < User::NONE || minLevel > User::MASTER)
661 // We check that "scm_function" is a Scheme procedure
662 if (!scm_is_true (scm_procedure_p(scm_function)))
665 // We check that args is an integer and is between 0 and 20 (arbitrary limit)
666 if (!SCM_NUMBERP(scm_args))
669 int args = scm_to_int(scm_args);
670 if (args < 0 || args > 20)
673 // We add the command in the commands list
674 Interp::bot->userFunctions[commandName] =
675 new userFunction(0, minLevel, needsChannel, args, scm_function);
681 ScriptCommands::delCommand(SCM scm_commandName)
683 // We check that commandName is a string
684 if (!scm_is_string(scm_commandName))
687 // We check that the command does exist
688 String commandName = Utils::to_upper (Utils::scm2str(scm_commandName));
689 if (!Interp::bot->userFunctions[commandName])
692 // We delete the command
693 Interp::bot->userFunctions.erase(commandName);
699 ScriptCommands::AddHook(SCM type, SCM regex, SCM function, SCM pri, SCM fall,
703 bool fallt = true; // does this hook fall through?
704 String rname = "DEFAULT";
706 if (!SCM_UNBNDP (pri))
707 priority = scm_to_int (pri);
708 if (!SCM_UNBNDP (fall))
709 fallt = scm_is_true (fall);
710 if (!SCM_UNBNDP (name))
711 rname = Utils::scm2str (name);
712 return scm_from_bool (Interp::bot->botInterp->AddHook(scm_to_int(type),
714 priority, fallt, rname));
718 ScriptCommands::AddTimer(SCM when, SCM function)
720 return Interp::bot->botInterp->AddTimer(scm_to_int(when), function);
724 ScriptCommands::DelTimer(SCM timer)
726 return scm_from_bool (Interp::bot->botInterp->DelTimer(timer));
730 ScriptCommands::sendDCCChatMessage (SCM to, SCM message)
733 return scm_from_bool (Interp::bot->dccConnections->sendMessage
734 (Utils::scm2str (to),
735 Utils::scm2str (message)));