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