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