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