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