cb21075d |
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; |
439869bf |
575 | bool fallt = true; // does this hook fall through? |
cb21075d |
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 |