[project @ 2005-06-28 03:16:45 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 02110-1301, 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"
28 #include "ServerQueue.H"
29 #include "ScriptCommands.H"
30 #include "Interp.H"
31 #include "DCCPerson.H"
32 #include "DCCManager.H"
33 #include "Parser.H"
34 #include "Commands.H"
35 #include "Message.H"
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
44 SCM
45 ScriptCommands::Action(SCM channel, SCM message)
46 {
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());
52 }
53
54 SCM
55 ScriptCommands::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
63 String wwho = Utils::scm2str (who);
64 String mask = Utils::scm2str (maskChannel);
65 String passwd;
66 std::time_t eexpire;
67
68 if (SCM_UNBNDP (password))
69 passwd = "";
70 else
71 {
72 VERIFY_STRING (password);
73 passwd = Utils::scm2str (password);
74 }
75 if (SCM_UNBNDP (expire))
76 eexpire = -1;
77 else
78 {
79 VERIFY_STRING (expire);
80 eexpire = Utils::str2time (Utils::scm2str (expire));
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
95 SCM
96 ScriptCommands::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,
102 Utils::scm2str(servername),
103 p);
104 return scm_long2num(m.getCode());
105 }
106
107 SCM
108 ScriptCommands::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);
115 String mmask = Utils::scm2str (mask);
116 String mmaskChannel = Utils::scm2str (maskChannel);
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);
126 expire = Utils::str2time (Utils::scm2str (expiration));
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);
134 rreason = Utils::scm2str (reason);
135 }
136 Message m = Commands::AddShit (Interp::bot, mmask, mmaskChannel,
137 llevel, expire, rreason);
138
139 return scm_long2num(m.getCode ());
140 }
141
142 SCM
143 ScriptCommands::Ban(SCM channel, SCM who)
144 {
145 VERIFY_STRING(channel);
146 VERIFY_STRING(who);
147 Message m = Commands::Ban(Interp::bot, Utils::scm2str(channel),
148 Utils::scm2str(who));
149 return scm_long2num(m.getCode());
150 }
151
152 SCM
153 ScriptCommands::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
179 SCM
180 ScriptCommands::Cycle(SCM channel)
181 {
182 VERIFY_STRING(channel);
183 Message m = Commands::Cycle(Interp::bot, Utils::scm2str(channel));
184 return scm_long2num(m.getCode());
185 }
186
187 SCM
188 ScriptCommands::Deban(SCM channel, SCM who)
189 {
190 VERIFY_STRING(channel);
191 VERIFY_STRING(who);
192 Message m = Commands::Deban(Interp::bot, Utils::scm2str(channel),
193 Utils::scm2str(who));
194 return scm_long2num(m.getCode());
195 }
196
197 SCM
198 ScriptCommands::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
207 SCM
208 ScriptCommands::DelUser(SCM who, SCM maskChannel)
209 {
210 VERIFY_STRING(who);
211 VERIFY_STRING(maskChannel);
212 Message m = Commands::DelUser(Interp::bot, Utils::scm2str(who),
213 Utils::scm2str(maskChannel));
214 return scm_long2num(m.getCode());
215 }
216
217 SCM
218 ScriptCommands::DelShit(SCM who, SCM maskChannel)
219 {
220 VERIFY_STRING(who);
221 VERIFY_STRING(maskChannel);
222 Message m = Commands::DelShit(Interp::bot, Utils::scm2str(who),
223 Utils::scm2str(maskChannel));
224 return scm_long2num(m.getCode());
225 }
226
227 SCM
228 ScriptCommands::Deop(SCM channel, SCM who)
229 {
230 VERIFY_STRING(channel);
231 VERIFY_STRING(who);
232 Message m = Commands::Deop(Interp::bot, Utils::scm2str(channel),
233 Utils::scm2str(who));
234 return scm_long2num(m.getCode());
235 }
236
237 SCM
238 ScriptCommands::Die(SCM reason)
239 {
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());
245 }
246
247 SCM
248 ScriptCommands::Do(SCM command)
249 {
250 VERIFY_STRING(command);
251 Message m = Commands::Do(Interp::bot, Utils::scm2str(command));
252 return scm_long2num(m.getCode());
253 }
254
255 SCM
256 ScriptCommands::Invite(SCM channel, SCM who)
257 {
258 VERIFY_STRING(channel);
259 VERIFY_STRING(who);
260 Message m = Commands::Invite(Interp::bot, Utils::scm2str(channel),
261 Utils::scm2str(who));
262 return scm_long2num(m.getCode());
263 }
264
265 SCM
266 ScriptCommands::Join(SCM channel, SCM key)
267 {
268 VERIFY_STRING(channel);
269 String k = "";
270 if (SCM_STRINGP(key))
271 k = Utils::scm2str(key);
272 Message m = Commands::Join(Interp::bot, Utils::scm2str(channel),
273 k);
274 return scm_long2num(m.getCode());
275 }
276
277 SCM
278 ScriptCommands::Keep(SCM channel, SCM modes)
279 {
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());
285 }
286
287 SCM
288 ScriptCommands::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))
295 r = Utils::scm2str(reason);
296
297 Message m = Commands::Kick(Interp::bot, Utils::scm2str(channel),
298 Utils::scm2str(who), r);
299 return scm_long2num(m.getCode());
300 }
301
302 SCM
303 ScriptCommands::KickBan(SCM channel, SCM who, SCM reason)
304 {
305 VERIFY_STRING(channel);
306 VERIFY_STRING(who);
307 String r = "";
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());
313 }
314
315 SCM
316 ScriptCommands::Lock(SCM channel)
317 {
318 VERIFY_STRING(channel);
319 Message m = Commands::Lock(Interp::bot, Utils::scm2str(channel));
320 return scm_long2num(m.getCode());
321 }
322
323 SCM
324 ScriptCommands::LogPort(void)
325 {
326 return Interp::bot->botInterp->logPort;
327 }
328
329 SCM
330 ScriptCommands::Mode(SCM channel, SCM mode)
331 {
332 VERIFY_STRING(channel);
333 VERIFY_STRING(mode);
334 Message m = Commands::Mode(Interp::bot, Utils::scm2str(channel),
335 Utils::scm2str(mode));
336 return scm_long2num(m.getCode());
337 }
338
339 SCM
340 ScriptCommands::Msg(SCM nick, SCM message)
341 {
342 VERIFY_STRING(nick);
343 VERIFY_STRING(message);
344 Message m = Commands::Msg(Interp::bot, Utils::scm2str(nick),
345 Utils::scm2str(message));
346 return scm_long2num(m.getCode());
347
348 }
349
350 SCM
351 ScriptCommands::NextServer(void)
352 {
353 Message m = Commands::NextServer(Interp::bot);
354 return scm_long2num(m.getCode());
355 }
356
357 SCM
358 ScriptCommands::Nick(SCM nick)
359 {
360 VERIFY_STRING(nick);
361 Message m = Commands::Nick(Interp::bot, Utils::scm2str(nick));
362 return scm_long2num(m.getCode());
363 }
364
365 SCM
366 ScriptCommands::Op(SCM channel, SCM who)
367 {
368 VERIFY_STRING(channel);
369 VERIFY_STRING(who);
370 Message m = Commands::Op(Interp::bot, Utils::scm2str(channel),
371 Utils::scm2str(who));
372 return scm_long2num(m.getCode());
373 }
374
375 SCM
376 ScriptCommands::Part(SCM channel)
377 {
378 VERIFY_STRING(channel);
379 Message m = Commands::Part(Interp::bot, Utils::scm2str(channel));
380 return scm_long2num(m.getCode());
381 }
382
383 SCM
384 ScriptCommands::Reconnect(void)
385 {
386 Message m = Commands::Reconnect(Interp::bot);
387 return scm_long2num(m.getCode());
388 }
389
390 SCM
391 ScriptCommands::Say(SCM channel, SCM message)
392 {
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());
398 }
399
400 SCM
401 ScriptCommands::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
408 SCM
409 ScriptCommands::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
417 SCM
418 ScriptCommands::SetVersion(SCM version)
419 {
420 Message m = Commands::SetVersion(Interp::bot, Utils::scm2str(version));
421 return scm_long2num(m.getCode());
422 }
423
424 SCM
425 ScriptCommands::TBan(SCM channel, SCM who, SCM seconds)
426 {
427 VERIFY_STRING(channel);
428 VERIFY_STRING(who);
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());
433 }
434
435 SCM
436 ScriptCommands::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))
443 r = Utils::scm2str(reason);
444 Message m = Commands::TKBan(Interp::bot, Utils::scm2str(channel),
445 Utils::scm2str(who),
446 gh_scm2long(seconds), r);
447 return scm_long2num(m.getCode());
448 }
449
450 SCM
451 ScriptCommands::Topic(SCM channel, SCM topic)
452 {
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());
458 }
459
460 SCM
461 ScriptCommands::Unlock(SCM channel)
462 {
463 VERIFY_STRING(channel);
464 Message m = Commands::Unlock(Interp::bot, Utils::scm2str(channel));
465 return scm_long2num(m.getCode());
466 }
467
468 SCM
469 ScriptCommands::getNickname(void)
470 {
471 return Utils::str2scm(Interp::bot->nickName);
472 }
473
474 SCM
475 ScriptCommands::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),
481 Utils::str2scm(serv->getHostName()),
482 scm_long2num(serv->getPort()),
483 Utils::str2scm(serv->getPassword()),
484 SCM_UNDEFINED);
485 }
486
487 SCM
488 ScriptCommands::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++),
499 Utils::str2scm(s->getHostName()),
500 scm_long2num(s->getPort()),
501 Utils::str2scm(s->getPassword()),
502 SCM_UNDEFINED), SCM_UNDEFINED));
503 }
504 return res;
505 }
506
507 SCM
508 ScriptCommands::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
516 SCM
517 ScriptCommands::flushPort(void)
518 {
519 scm_flush(Interp::bot->botInterp->logPort);
520 return SCM_BOOL_T;
521 }
522
523 SCM
524 ScriptCommands::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
533 SCM
534 ScriptCommands::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
543 String commandName = Utils::to_upper (Utils::scm2str(scm_commandName));
544 if (Interp::bot->userFunctions[commandName])
545 return SCM_BOOL_F;
546
547 // Next we check that needsChannel is a boolean
548 if (!gh_boolean_p(scm_needsChannel))
549 return SCM_BOOL_F;
550 bool needsChannel = gh_scm2bool(scm_needsChannel);
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
574 Interp::bot->userFunctions[commandName] =
575 new userFunction(0, minLevel, needsChannel, args, scm_function);
576
577 return SCM_BOOL_T;
578 }
579
580 SCM
581 ScriptCommands::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
588 String commandName = Utils::to_upper (Utils::scm2str(scm_commandName));
589 if (!Interp::bot->userFunctions[commandName])
590 return SCM_BOOL_F;
591
592 // We delete the command
593 Interp::bot->userFunctions.erase(commandName);
594
595 return SCM_BOOL_T;
596 }
597
598 SCM
599 ScriptCommands::AddHook(SCM type, SCM regex, SCM function, SCM pri, SCM fall,
600 SCM name)
601 {
602 int priority = 0;
603 bool fallt = true; // does this hook fall through?
604 String rname = "DEFAULT";
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);
610 if (!SCM_UNBNDP (name))
611 rname = Utils::scm2str (name);
612 return SCM_BOOL (Interp::bot->botInterp->AddHook(gh_scm2long(type),
613 regex, function,
614 priority, fallt, rname));
615 }
616
617 SCM
618 ScriptCommands::AddTimer(SCM when, SCM function)
619 {
620 return Interp::bot->botInterp->AddTimer(gh_scm2long(when), function);
621 }
622
623 SCM
624 ScriptCommands::DelTimer(SCM timer)
625 {
626 return SCM_BOOL (Interp::bot->botInterp->DelTimer(timer));
627 }
628
629 SCM
630 ScriptCommands::sendDCCChatMessage (SCM to, SCM message)
631 {
632
633 return SCM_BOOL (Interp::bot->dccConnections->sendMessage
634 (Utils::scm2str (to),
635 Utils::scm2str (message)));
636 }
637
638 // Message sending
639 // FIXME: write these
640
641 #define IQUEUE Interp::bot->serverConnection->queue
642
643 SCM
644 ScriptCommands::sendCTCP(SCM to, SCM command , SCM message)
645 {
646 VERIFY_STRING(to);
647 VERIFY_STRING(command);
648 VERIFY_STRING(message);
649
650 IQUEUE->sendCTCP (Utils::scm2str (to), Utils::scm2str (command),
651 Utils::scm2str (message));
652
653 return SCM_UNSPECIFIED;
654 }
655
656 SCM
657 ScriptCommands::sendNotice (SCM to, SCM message)
658 {
659 VERIFY_STRING (to);
660 VERIFY_STRING (message);
661
662 return (scm_long2num
663 (Commands::Notice (Interp::bot,
664 Utils::scm2str (to),
665 Utils::scm2str (message)).getCode ()));
666
667 }
668 #endif