[project @ 2005-01-12 05:36:40 by unknown_lamer]
[clinton/bobotpp.git] / source / ScriptCommands.C
CommitLineData
cb21075d 1// ScriptCommands.C -*- C++ -*-
2// Copyright (c) 1998 Etienne BERNARD
a6339323 3// Copyright (C) 2002,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
17// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
18
19#ifdef HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#ifdef USESCRIPTS
24
25#include "Utils.H"
26#include "Server.H"
27#include "ServerList.H"
e07b6b46 28#include "ServerQueue.H"
cb21075d 29#include "ScriptCommands.H"
30#include "Interp.H"
6530edbf 31#include "DCCPerson.H"
0b7a49e2 32#include "DCCManager.H"
4edefeb6 33#include "Parser.H"
cb21075d 34#include <libguile.h>
35
36#define VERIFY_STRING(par) if (!SCM_STRINGP((par))) \
37 return scm_long2num(-17)
38
39#define VERIFY_NUMBER(par) if (!SCM_NUMBERP((par))) \
40 return scm_long2num(-17)
41
42SCM
43ScriptCommands::Action(SCM channel, SCM message)
44{
45 VERIFY_STRING(channel);
46 VERIFY_STRING(message);
a6339323 47 Message m = Commands::Action(Interp::bot, Utils::scm2str(channel),
48 Utils::scm2str(message));
cb21075d 49 return scm_long2num(m.getCode());
50}
51
52SCM
53ScriptCommands::AddUser(SCM who, SCM maskChannel, SCM level,
54 SCM prot, SCM aop, SCM expire, SCM password)
55{
56 // It segfaults when not online, but otherwise appears to work
57 VERIFY_STRING (who);
58 VERIFY_STRING (maskChannel);
59 VERIFY_NUMBER (level);
60
a6339323 61 String wwho = Utils::scm2str (who);
62 String mask = Utils::scm2str (maskChannel);
cb21075d 63 String passwd;
64 std::time_t eexpire;
65
66 if (SCM_UNBNDP (password))
67 passwd = "";
68 else
69 {
70 VERIFY_STRING (password);
a6339323 71 passwd = Utils::scm2str (password);
cb21075d 72 }
73 if (SCM_UNBNDP (expire))
74 eexpire = -1;
75 else
76 {
77 VERIFY_STRING (expire);
a6339323 78 eexpire = Utils::str2time (Utils::scm2str (expire));
cb21075d 79 if (!eexpire) eexpire = -1;
80 }
81
82 int protect = scm_num2int (prot, SCM_ARG1, "ScriptCommands::AddUser");
83 bool aaop = SCM_NFALSEP (aop);
84 int llevel = scm_num2int (level, SCM_ARG1,
85 "ScriptCommands::AddUser");
86
87 Message m = Commands::AddUser (Interp::bot, wwho, mask, llevel,
88 protect, aaop, eexpire, passwd);
89
90 return scm_long2num(m.getCode ());
91}
92
93SCM
94ScriptCommands::AddServer(SCM servername, SCM port)
95{
96 int p = 6667;
97 if (SCM_NUMBERP(port))
98 p = scm_num2long(port, SCM_ARG1, "ScriptCommands::AddServer");
99 Message m = Commands::AddServer(Interp::bot,
a6339323 100 Utils::scm2str(servername),
cb21075d 101 p);
102 return scm_long2num(m.getCode());
103}
104
105SCM
106ScriptCommands::AddShit(SCM mask, SCM maskChannel, SCM level,
107 SCM expiration, SCM reason)
108{
109 // This appears to work...not much testing though
110 VERIFY_STRING (mask);
111 VERIFY_STRING (maskChannel);
112 VERIFY_NUMBER (level);
a6339323 113 String mmask = Utils::scm2str (mask);
114 String mmaskChannel = Utils::scm2str (maskChannel);
cb21075d 115 int llevel = scm_num2int (level, SCM_ARG1, "ScriptCommands::AddShit");
116 std::time_t expire;
117 String rreason;
118
119 if (SCM_UNBNDP (expiration))
120 expire = -1;
121 else
122 {
123 VERIFY_STRING (expiration);
a6339323 124 expire = Utils::str2time (Utils::scm2str (expiration));
cb21075d 125 if (!expire) expire = -1;
126 }
127 if (SCM_UNBNDP (reason))
128 rreason = "You're on my shitlist, lamer";
129 else
130 {
131 VERIFY_STRING (reason);
a6339323 132 rreason = Utils::scm2str (reason);
cb21075d 133 }
134 Message m = Commands::AddShit (Interp::bot, mmask, mmaskChannel,
135 llevel, expire, rreason);
136
137 return scm_long2num(m.getCode ());
138}
139
140SCM
141ScriptCommands::Ban(SCM channel, SCM who)
142{
143 VERIFY_STRING(channel);
144 VERIFY_STRING(who);
a6339323 145 Message m = Commands::Ban(Interp::bot, Utils::scm2str(channel),
146 Utils::scm2str(who));
cb21075d 147 return scm_long2num(m.getCode());
148}
149
4edefeb6 150SCM
151ScriptCommands::ChangeCommandLevel(SCM command, SCM level)
152{
153 VERIFY_STRING (command);
154 VERIFY_NUMBER (level);
155
156 SCM_STRING_COERCE_0TERMINATION_X (command);
157 std::string ccommand = SCM_STRING_CHARS (command);
158 unsigned int llevel = scm_num2uint (level, 0, "ScriptCommands::ChangeCommandLevel");
159
160 if (llevel > 4)
161 return SCM_BOOL_F;
162
163 std::map<std::string, class userFunction*,
164 std::less<std::string> >::const_iterator uf_iter
165 = Interp::bot->userFunctions.find (ccommand);
166 userFunction * f = 0;
167
168 if (uf_iter != Interp::bot->userFunctions.end ())
169 f = uf_iter->second;
170 else
171 return SCM_BOOL_F;
172
173 f->minLevel = llevel;
174 return SCM_BOOL_T;
175}
176
cb21075d 177SCM
178ScriptCommands::Cycle(SCM channel)
179{
180 VERIFY_STRING(channel);
a6339323 181 Message m = Commands::Cycle(Interp::bot, Utils::scm2str(channel));
cb21075d 182 return scm_long2num(m.getCode());
183}
184
185SCM
186ScriptCommands::Deban(SCM channel, SCM who)
187{
188 VERIFY_STRING(channel);
189 VERIFY_STRING(who);
a6339323 190 Message m = Commands::Deban(Interp::bot, Utils::scm2str(channel),
191 Utils::scm2str(who));
cb21075d 192 return scm_long2num(m.getCode());
193}
194
195SCM
196ScriptCommands::DelServer(SCM number)
197{
198 VERIFY_NUMBER(number);
199 Message m = Commands::DelServer(Interp::bot,
200 scm_num2long(number, SCM_ARG1,
201 "ScriptCommands::DelServer"));
202 return scm_long2num(m.getCode());
203}
204
205SCM
206ScriptCommands::DelUser(SCM who, SCM maskChannel)
207{
208 VERIFY_STRING(who);
209 VERIFY_STRING(maskChannel);
a6339323 210 Message m = Commands::DelUser(Interp::bot, Utils::scm2str(who),
211 Utils::scm2str(maskChannel));
cb21075d 212 return scm_long2num(m.getCode());
213}
214
215SCM
216ScriptCommands::DelShit(SCM who, SCM maskChannel)
217{
218 VERIFY_STRING(who);
219 VERIFY_STRING(maskChannel);
a6339323 220 Message m = Commands::DelShit(Interp::bot, Utils::scm2str(who),
221 Utils::scm2str(maskChannel));
cb21075d 222 return scm_long2num(m.getCode());
223}
224
225SCM
226ScriptCommands::Deop(SCM channel, SCM who)
227{
228 VERIFY_STRING(channel);
229 VERIFY_STRING(who);
a6339323 230 Message m = Commands::Deop(Interp::bot, Utils::scm2str(channel),
231 Utils::scm2str(who));
cb21075d 232 return scm_long2num(m.getCode());
233}
234
235SCM
236ScriptCommands::Die(SCM reason)
237{
238 String r = "Leaving";
239 if (SCM_STRINGP(reason))
a6339323 240 r = Utils::scm2str(reason);
cb21075d 241 Message m = Commands::Die(Interp::bot, r);
242 return scm_long2num(m.getCode());
243}
244
245SCM
246ScriptCommands::Do(SCM command)
247{
248 VERIFY_STRING(command);
a6339323 249 Message m = Commands::Do(Interp::bot, Utils::scm2str(command));
cb21075d 250 return scm_long2num(m.getCode());
251}
252
253SCM
254ScriptCommands::Invite(SCM channel, SCM who)
255{
256 VERIFY_STRING(channel);
257 VERIFY_STRING(who);
a6339323 258 Message m = Commands::Invite(Interp::bot, Utils::scm2str(channel),
259 Utils::scm2str(who));
cb21075d 260 return scm_long2num(m.getCode());
261}
262
263SCM
264ScriptCommands::Join(SCM channel, SCM key)
265{
266 VERIFY_STRING(channel);
267 String k = "";
268 if (SCM_STRINGP(key))
a6339323 269 k = Utils::scm2str(key);
270 Message m = Commands::Join(Interp::bot, Utils::scm2str(channel),
cb21075d 271 k);
272 return scm_long2num(m.getCode());
273}
274
275SCM
276ScriptCommands::Keep(SCM channel, SCM modes)
277{
278 VERIFY_STRING(channel);
279 VERIFY_STRING(modes);
a6339323 280 Message m = Commands::Keep(Interp::bot, Utils::scm2str(channel),
281 Utils::scm2str(modes));
cb21075d 282 return scm_long2num(m.getCode());
283}
284
285SCM
286ScriptCommands::Kick(SCM channel, SCM who, SCM reason)
287{
288 VERIFY_STRING(channel);
289 VERIFY_STRING(who);
290
291 String r = "";
292 if (SCM_STRINGP(reason))
a6339323 293 r = Utils::scm2str(reason);
cb21075d 294
a6339323 295 Message m = Commands::Kick(Interp::bot, Utils::scm2str(channel),
296 Utils::scm2str(who), r);
cb21075d 297 return scm_long2num(m.getCode());
298}
299
300SCM
301ScriptCommands::KickBan(SCM channel, SCM who, SCM reason)
302{
303 VERIFY_STRING(channel);
304 VERIFY_STRING(who);
305 String r = "";
306 if (SCM_STRINGP(reason))
a6339323 307 r = Utils::scm2str(reason);
308 Message m = Commands::KickBan(Interp::bot, Utils::scm2str(channel),
309 Utils::scm2str(who), r);
cb21075d 310 return scm_long2num(m.getCode());
311}
312
313SCM
314ScriptCommands::Lock(SCM channel)
315{
316 VERIFY_STRING(channel);
a6339323 317 Message m = Commands::Lock(Interp::bot, Utils::scm2str(channel));
cb21075d 318 return scm_long2num(m.getCode());
319}
320
321SCM
322ScriptCommands::LogPort(void)
323{
324 return Interp::bot->botInterp->logPort;
325}
326
327SCM
328ScriptCommands::Mode(SCM channel, SCM mode)
329{
330 VERIFY_STRING(channel);
331 VERIFY_STRING(mode);
a6339323 332 Message m = Commands::Mode(Interp::bot, Utils::scm2str(channel),
333 Utils::scm2str(mode));
cb21075d 334 return scm_long2num(m.getCode());
335}
336
337SCM
338ScriptCommands::Msg(SCM nick, SCM message)
339{
340 VERIFY_STRING(nick);
341 VERIFY_STRING(message);
a6339323 342 Message m = Commands::Msg(Interp::bot, Utils::scm2str(nick),
343 Utils::scm2str(message));
cb21075d 344 return scm_long2num(m.getCode());
345
346}
347
348SCM
349ScriptCommands::NextServer(void)
350{
351 Message m = Commands::NextServer(Interp::bot);
352 return scm_long2num(m.getCode());
353}
354
355SCM
356ScriptCommands::Nick(SCM nick)
357{
358 VERIFY_STRING(nick);
a6339323 359 Message m = Commands::Nick(Interp::bot, Utils::scm2str(nick));
cb21075d 360 return scm_long2num(m.getCode());
361}
362
363SCM
364ScriptCommands::Op(SCM channel, SCM who)
365{
366 VERIFY_STRING(channel);
367 VERIFY_STRING(who);
a6339323 368 Message m = Commands::Op(Interp::bot, Utils::scm2str(channel),
369 Utils::scm2str(who));
cb21075d 370 return scm_long2num(m.getCode());
371}
372
373SCM
374ScriptCommands::Part(SCM channel)
375{
376 VERIFY_STRING(channel);
a6339323 377 Message m = Commands::Part(Interp::bot, Utils::scm2str(channel));
cb21075d 378 return scm_long2num(m.getCode());
379}
380
381SCM
382ScriptCommands::Reconnect(void)
383{
384 Message m = Commands::Reconnect(Interp::bot);
385 return scm_long2num(m.getCode());
386}
387
388SCM
389ScriptCommands::Say(SCM channel, SCM message)
390{
391 VERIFY_STRING(channel);
392 VERIFY_STRING(message);
a6339323 393 Message m = Commands::Say(Interp::bot, Utils::scm2str(channel),
394 Utils::scm2str(message));
cb21075d 395 return scm_long2num(m.getCode());
396}
397
398SCM
399ScriptCommands::Server(SCM number)
400{
401 VERIFY_NUMBER(number);
402 Message m = Commands::Server(Interp::bot, gh_scm2long(number));
403 return scm_long2num(m.getCode());
404}
405
e171dcce 406SCM
407ScriptCommands::SetFloodRate(SCM rate)
408{
409 VERIFY_NUMBER(rate);
410 Message m = Commands::SetFloodRate(Interp::bot, scm_num2uint
411 (rate, 0, "SetFloodRate"));
412 return scm_long2num(m.getCode());
413}
414
cb21075d 415SCM
416ScriptCommands::SetVersion(SCM version)
417{
a6339323 418 Message m = Commands::SetVersion(Interp::bot, Utils::scm2str(version));
cb21075d 419 return scm_long2num(m.getCode());
420}
421
422SCM
423ScriptCommands::TBan(SCM channel, SCM who, SCM seconds)
424{
425 VERIFY_STRING(channel);
426 VERIFY_STRING(who);
427 VERIFY_NUMBER(seconds);
a6339323 428 Message m = Commands::TBan(Interp::bot, Utils::scm2str(channel),
429 Utils::scm2str(who), gh_scm2long(seconds));
cb21075d 430 return scm_long2num(m.getCode());
431}
432
433SCM
434ScriptCommands::TKBan(SCM channel, SCM who, SCM seconds, SCM reason)
435{
436 VERIFY_STRING(channel);
437 VERIFY_STRING(who);
438 VERIFY_NUMBER(seconds);
439 String r = "";
440 if (SCM_STRINGP(reason))
a6339323 441 r = Utils::scm2str(reason);
442 Message m = Commands::TKBan(Interp::bot, Utils::scm2str(channel),
443 Utils::scm2str(who),
cb21075d 444 gh_scm2long(seconds), r);
445 return scm_long2num(m.getCode());
446}
447
448SCM
449ScriptCommands::Topic(SCM channel, SCM topic)
450{
451 VERIFY_STRING(channel);
452 VERIFY_STRING(topic);
a6339323 453 Message m = Commands::Topic(Interp::bot, Utils::scm2str(channel),
454 Utils::scm2str(topic));
cb21075d 455 return scm_long2num(m.getCode());
456}
457
458SCM
459ScriptCommands::Unlock(SCM channel)
460{
461 VERIFY_STRING(channel);
a6339323 462 Message m = Commands::Unlock(Interp::bot, Utils::scm2str(channel));
cb21075d 463 return scm_long2num(m.getCode());
464}
465
cb21075d 466SCM
467ScriptCommands::getNickname(void)
468{
a6339323 469 return Utils::str2scm(Interp::bot->nickName);
cb21075d 470}
471
472SCM
473ScriptCommands::getServer(void)
474{
475 ::Server *serv = Interp::bot->serverList->currentServer();
476 int serverNumber = Interp::bot->serverList->currentNumber;
477
478 return gh_list(scm_long2num(serverNumber),
a6339323 479 Utils::str2scm(serv->getHostName()),
cb21075d 480 scm_long2num(serv->getPort()),
a6339323 481 Utils::str2scm(serv->getPassword()),
cb21075d 482 SCM_UNDEFINED);
483}
484
485SCM
486ScriptCommands::getServerList(void)
487{
488 SCM res = gh_list(SCM_UNDEFINED);
489 ::Server *s;
490 int i = 0;
491 std::vector<class Server *>::iterator it = Interp::bot->serverList->begin();
492
493 for ( ; it != Interp::bot->serverList->end(); ++it) {
494 s = (*it);
495 res = gh_append2(res,
496 gh_list(gh_list(scm_long2num(i++),
a6339323 497 Utils::str2scm(s->getHostName()),
cb21075d 498 scm_long2num(s->getPort()),
a6339323 499 Utils::str2scm(s->getPassword()),
cb21075d 500 SCM_UNDEFINED), SCM_UNDEFINED));
501 }
502 return res;
503}
504
505SCM
506ScriptCommands::flushQueue(void)
507{
508 if (!Interp::bot->serverConnection)
509 return SCM_BOOL_F;
510 Interp::bot->serverConnection->queue->flush();
511 return SCM_BOOL_T;
512}
513
514SCM
515ScriptCommands::flushPort(void)
516{
517 scm_flush(Interp::bot->botInterp->logPort);
518 return SCM_BOOL_T;
519}
520
521SCM
522ScriptCommands::random(SCM scm_max)
523{
524 int max = 0;
525 //srand(time(NULL));
526 if (SCM_NUMBERP(scm_max))
527 max = gh_scm2int(scm_max);
528 return scm_long2num(max ? rand() % max : 0);
529}
530
531SCM
532ScriptCommands::addCommand(SCM scm_commandName, SCM scm_function,
533 SCM scm_needsChannel, SCM scm_args,
534 SCM scm_minLevel)
535{
536 // We check that commandName is a string
537 if (!SCM_STRINGP(scm_commandName))
538 return SCM_BOOL_F;
539
540 // We check that the command does not exist
a6339323 541 String commandName = Utils::to_upper (Utils::scm2str(scm_commandName));
e07b6b46 542 if (Interp::bot->userFunctions[commandName])
543 return SCM_BOOL_F;
cb21075d 544
545 // Next we check that needsChannel is a boolean
546 if (!gh_boolean_p(scm_needsChannel))
547 return SCM_BOOL_F;
e07b6b46 548 bool needsChannel = gh_scm2bool(scm_needsChannel);
cb21075d 549
550 // We check that minLevel is an integer and that it's
551 // a valid level
552 if (!SCM_NUMBERP(scm_minLevel))
553 return SCM_BOOL_F;
554
555 int minLevel = gh_scm2long(scm_minLevel);
556 if (minLevel < User::NONE || minLevel > User::MASTER)
557 return SCM_BOOL_F;
558
559 // We check that "scm_function" is a Scheme procedure
560 if (!gh_procedure_p(scm_function))
561 return SCM_BOOL_F;
562
563 // We check that args is an integer and is between 0 and 20 (arbitrary limit)
564 if (!SCM_NUMBERP(scm_args))
565 return SCM_BOOL_F;
566
567 int args = gh_scm2long(scm_args);
568 if (args < 0 || args > 20)
569 return SCM_BOOL_F;
570
571 // We add the command in the commands list
e07b6b46 572 Interp::bot->userFunctions[commandName] =
573 new userFunction(0, minLevel, needsChannel, args, scm_function);
574
cb21075d 575 return SCM_BOOL_T;
576}
577
578SCM
579ScriptCommands::delCommand(SCM scm_commandName)
580{
581 // We check that commandName is a string
582 if (!SCM_STRINGP(scm_commandName))
583 return SCM_BOOL_F;
584
585 // We check that the command does exist
a6339323 586 String commandName = Utils::to_upper (Utils::scm2str(scm_commandName));
e07b6b46 587 if (!Interp::bot->userFunctions[commandName])
cb21075d 588 return SCM_BOOL_F;
589
590 // We delete the command
e07b6b46 591 Interp::bot->userFunctions.erase(commandName);
cb21075d 592
593 return SCM_BOOL_T;
594}
595
596SCM
fd7440f1 597ScriptCommands::AddHook(SCM type, SCM regex, SCM function, SCM pri, SCM fall,
598 SCM name)
cb21075d 599{
600 int priority = 0;
439869bf 601 bool fallt = true; // does this hook fall through?
fd7440f1 602 String rname = "DEFAULT";
cb21075d 603
604 if (!SCM_UNBNDP (pri))
605 priority = scm_num2int (pri, SCM_ARG1, "ScriptCommands::AddHook");
606 if (!SCM_UNBNDP (fall))
607 fallt = SCM_NFALSEP (fall);
fd7440f1 608 if (!SCM_UNBNDP (name))
a6339323 609 rname = Utils::scm2str (name);
cb21075d 610 return SCM_BOOL (Interp::bot->botInterp->AddHook(gh_scm2long(type),
611 regex, function,
fd7440f1 612 priority, fallt, rname));
cb21075d 613}
614
615SCM
616ScriptCommands::AddTimer(SCM when, SCM function)
617{
618 return Interp::bot->botInterp->AddTimer(gh_scm2long(when), function);
619}
620
621SCM
622ScriptCommands::DelTimer(SCM timer)
623{
e07b6b46 624 return SCM_BOOL (Interp::bot->botInterp->DelTimer(timer));
625}
626
0b7a49e2 627SCM
628ScriptCommands::sendDCCChatMessage (SCM to, SCM message)
629{
630
631 return SCM_BOOL (Interp::bot->dccConnections->sendMessage
a6339323 632 (Utils::scm2str (to),
633 Utils::scm2str (message)));
0b7a49e2 634}
635
e07b6b46 636// Message sending
637// FIXME: write these
638
639#define IQUEUE Interp::bot->serverConnection->queue
640
641SCM
642ScriptCommands::sendCTCP(SCM to, SCM command , SCM message)
643{
644 VERIFY_STRING(to);
645 VERIFY_STRING(command);
646 VERIFY_STRING(message);
647
a6339323 648 IQUEUE->sendCTCP (Utils::scm2str (to), Utils::scm2str (command),
649 Utils::scm2str (message));
e07b6b46 650 return SCM_UNSPECIFIED;
cb21075d 651}
cb21075d 652#endif