]> jfr.im git - irc/quakenet/newserv.git/blame - lua/luacommands.c
More small error fixes.
[irc/quakenet/newserv.git] / lua / luacommands.c
CommitLineData
2da56f0d
CP
1/* Copyright (C) Chris Porter 2005 */
2/* ALL RIGHTS RESERVED. */
3/* Don't put this into the SVN repo. */
4
5#include "../channel/channel.h"
6#include "../control/control.h"
7#include "../nick/nick.h"
8#include "../localuser/localuser.h"
9#include "../localuser/localuserchannel.h"
10#include "../lib/irc_string.h"
11
12#include "lua.h"
13#include "luabot.h"
14
15#include <stdarg.h>
16
6269435f
CP
17#ifdef LUA_JITLIBNAME
18#include <luajit.h>
19#endif
20
2da56f0d
CP
21static int lua_smsg(lua_State *ps);
22static int lua_skill(lua_State *ps);
23
24int lua_lineok(const char *data) {
25 if(strchr(data, '\r') || strchr(data, '\n'))
26 return 0;
27 return 1;
28}
29
30int lua_cmsg(char *channell, char *message, ...) {
31 char buf[512];
32 va_list va;
33 channel *cp;
34
35 va_start(va, message);
36 vsnprintf(buf, sizeof(buf), message, va);
37 va_end(va);
38
39 cp = findchannel(channell);
40 if(!cp)
41 return LUA_FAIL;
42
43 if(!lua_lineok(buf))
44 return LUA_FAIL;
45
46 lua_channelmessage(cp, "%s", buf);
47
48 return LUA_OK;
49}
50
51static int lua_chanmsg(lua_State *ps) {
52 if(!lua_isstring(ps, 1))
53 LUA_RETURN(ps, LUA_FAIL);
54
55 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua: %s", lua_tostring(ps, 1)));
56}
57
58static int lua_scripterror(lua_State *ps) {
59 if(!lua_isstring(ps, 1))
60 LUA_RETURN(ps, LUA_FAIL);
61
62 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-error: %s", lua_tostring(ps, 1)));
63}
64
65static int lua_ctcp(lua_State *ps) {
66 const char *n, *msg;
67 nick *np;
68
69 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
70 LUA_RETURN(ps, LUA_FAIL);
71
72 n = lua_tostring(ps, 1);
73 msg = lua_tostring(ps, 2);
74
75 np = getnickbynick(n);
76 if(!np || !lua_lineok(msg))
77 LUA_RETURN(ps, LUA_FAIL);
78
79 lua_message(np, "\001%s\001", msg);
80
81 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-ctcp: %s (%s)", np->nick, msg));
82}
83
84static int lua_noticecmd(lua_State *ps) {
85 const char *n, *msg;
86 nick *np;
87
88 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
89 LUA_RETURN(ps, LUA_FAIL);
90
91 n = lua_tostring(ps, 1);
92 msg = lua_tostring(ps, 2);
93
94 np = getnickbynick(n);
95 if(!np || !lua_lineok(msg))
96 LUA_RETURN(ps, LUA_FAIL);
97
98 lua_notice(np, "%s", msg);
99
100 LUA_RETURN(ps, LUA_OK);
101}
102
103static int lua_kill(lua_State *ps) {
104 const char *n, *msg;
105 nick *np;
106
107 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
108 LUA_RETURN(ps, LUA_FAIL);
109
110 n = lua_tostring(ps, 1);
111 msg = lua_tostring(ps, 2);
112
113 np = getnickbynick(n);
114 if(!np)
115 LUA_RETURN(ps, LUA_FAIL);
116
117 if(IsOper(np) || IsService(np) || IsXOper(np))
118 LUA_RETURN(ps, LUA_FAIL);
119
120 if(!lua_lineok(msg))
121 LUA_RETURN(ps, LUA_FAIL);
122
123 killuser(lua_nick, np, "%s", msg);
124
125 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-KILL: %s (%s)", np->nick, msg));
126}
127
511316a4
CP
128static int lua_kick(lua_State *ps) {
129 const char *n, *msg, *chan;
130 nick *np;
131 channel *cp;
46751959 132 int dochecks = 1;
511316a4
CP
133
134 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3))
135 LUA_RETURN(ps, LUA_FAIL);
136
137 chan = lua_tostring(ps, 1);
138 n = lua_tostring(ps, 2);
139 msg = lua_tostring(ps, 3);
140
46751959
CP
141 if(lua_isboolean(ps, 4) && !lua_toboolean(ps, 4))
142 dochecks = 0;
143
511316a4
CP
144 np = getnickbynick(n);
145 if(!np)
146 LUA_RETURN(ps, LUA_FAIL);
147
46751959
CP
148 if(dochecks && (IsOper(np) || IsXOper(np) || IsService(np)))
149 LUA_RETURN(ps, LUA_FAIL);
150
511316a4
CP
151 cp = findchannel((char *)chan);
152 if(!cp)
153 LUA_RETURN(ps, LUA_FAIL);
154
155 if(!lua_lineok(msg))
156 LUA_RETURN(ps, LUA_FAIL);
157
158 localkickuser(lua_nick, cp, np, msg);
159
160 LUA_RETURN(ps, LUA_OK);
161}
162
163static int lua_invite(lua_State *ps) {
164 nick *np;
165 channel *cp;
166
167 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
168 LUA_RETURN(ps, LUA_FAIL);
169
170 np = getnickbynick((char *)lua_tostring(ps, 1));
171 if(!np)
172 LUA_RETURN(ps, LUA_FAIL);
173
174 cp = findchannel((char *)lua_tostring(ps, 2));
175 if(!cp)
176 LUA_RETURN(ps, LUA_FAIL);
177
178 localinvite(lua_nick, cp, np);
179
180 LUA_RETURN(ps, LUA_OK);
181}
182
2da56f0d
CP
183static int lua_gline(lua_State *ps) {
184 const char *reason;
185 nick *target;
186 char mask[512];
187 int duration, usercount = 0;
188 host *hp;
189
190 if(!lua_isstring(ps, 1) || !lua_isint(ps, 2) || !lua_isstring(ps, 3))
191 LUA_RETURN(ps, LUA_FAIL);
192
193 duration = lua_toint(ps, 2);
194 if((duration < 1) || (duration > 86400))
195 LUA_RETURN(ps, LUA_FAIL);
196
197 reason = lua_tostring(ps, 3);
198 if(!lua_lineok(reason) || !reason)
199 LUA_RETURN(ps, LUA_FAIL);
200
201 target = getnickbynick(lua_tostring(ps, 1));
202 if(!target || (IsOper(target) || IsXOper(target) || IsService(target)))
203 LUA_RETURN(ps, LUA_FAIL);
204
205 hp = target->host;
206 if(!hp)
207 LUA_RETURN(ps, LUA_FAIL);
208
209 usercount = hp->clonecount;
210 if(usercount > 10) { /* (decent) trusted host */
211 int j;
212 nick *np;
213
214 usercount = 0;
215
216 for (j=0;j<NICKHASHSIZE;j++)
217 for (np=nicktable[j];np;np=np->next)
218 if (np && (np->host == hp) && (!ircd_strcmp(np->ident, target->ident)))
219 usercount++;
220
221 if(usercount > 50)
222 LUA_RETURN(ps, LUA_FAIL);
223
224 snprintf(mask, sizeof(mask), "*%s@%s", target->ident, IPtostr(target->ipaddress));
225 } else {
226 snprintf(mask, sizeof(mask), "*@%s", IPtostr(target->ipaddress));
227 }
228
b822d7a4 229 irc_send("%s GL * +%s %d :%s", mynumeric->content, mask, duration, reason);
2da56f0d
CP
230 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-GLINE: %s (%d users, %d seconds -- %s)", mask, usercount, duration, reason));
231}
232
233static int lua_getchaninfo(lua_State *ps) {
234 channel *cp;
235
236 if(!lua_isstring(ps, 1))
237 return 0;
238
239 cp = findchannel((char *)lua_tostring(ps, 1));
240 if(!cp)
241 return 0;
242
243 LUA_PUSHCHAN(ps, cp);
244
245 return 1;
246}
247
248static int lua_opchan(lua_State *ps) {
249 channel *cp;
250 nick *np;
251
252 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
253 LUA_RETURN(ps, LUA_FAIL);
254
255 cp = findchannel((char *)lua_tostring(ps, 1));
256 if(!cp)
257 LUA_RETURN(ps, LUA_FAIL);
258
259 np = getnickbynick((char *)lua_tostring(ps, 2));
260 if(!np)
261 LUA_RETURN(ps, LUA_FAIL);
262
263 localsetmodes(lua_nick, cp, np, MC_OP);
264 LUA_RETURN(ps, LUA_OK);
265}
266
d6998bd1
CP
267static int lua_deopchan(lua_State *ps) {
268 channel *cp;
269 nick *np;
270
271 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
272 LUA_RETURN(ps, LUA_FAIL);
273
274 cp = findchannel((char *)lua_tostring(ps, 1));
275 if(!cp)
276 LUA_RETURN(ps, LUA_FAIL);
277
278 np = getnickbynick((char *)lua_tostring(ps, 2));
279 if(!np)
280 LUA_RETURN(ps, LUA_FAIL);
281
282 localsetmodes(lua_nick, cp, np, MC_DEOP);
283 LUA_RETURN(ps, LUA_OK);
284}
285
2da56f0d
CP
286static int lua_voicechan(lua_State *ps) {
287 channel *cp;
288 nick *np;
289
290 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
291 LUA_RETURN(ps, LUA_FAIL);
292
293 cp = findchannel((char *)lua_tostring(ps, 1));
294 if(!cp)
295 LUA_RETURN(ps, LUA_FAIL);
296
297 np = getnickbynick((char *)lua_tostring(ps, 2));
298 if(!np)
299 LUA_RETURN(ps, LUA_FAIL);
300
301 localsetmodes(lua_nick, cp, np, MC_VOICE);
302 LUA_RETURN(ps, LUA_OK);
303}
304
305static int lua_counthost(lua_State *ps) {
306 long numeric;
307 nick *np;
308
309 if(!lua_islong(ps, 1))
310 return 0;
311
312 numeric = lua_tolong(ps, 1);
313
314 np = getnickbynumeric(numeric);
315 if(!np)
316 return 0;
317
318 lua_pushint(ps, np->host->clonecount);
319 return 1;
320}
321
322static int lua_versioninfo(lua_State *ps) {
323 lua_pushstring(ps, LUA_VERSION);
324 lua_pushstring(ps, LUA_BOTVERSION);
325 lua_pushstring(ps, __DATE__);
326 lua_pushstring(ps, __TIME__);
327
6269435f
CP
328#ifdef LUAJIT_VERSION
329 lua_pushstring(ps, " + " LUAJIT_VERSION);
330#else
331 lua_pushstring(ps, "");
332#endif
333
334 return 5;
335}
336
337static int lua_basepath(lua_State *ps) {
338 lua_pushfstring(ps, "%s/", cpath->content);
339
340 return 1;
2da56f0d
CP
341}
342
343/* O(n) */
344static int lua_getuserbyauth(lua_State *l) {
345 const char *acc;
346 nick *np;
347 int i, found = 0;
348
349 if(!lua_isstring(l, 1))
350 return 0;
351
1fbb1306
CP
352 acc = lua_tostring(l, 1);
353
2da56f0d
CP
354 for(i=0;i<NICKHASHSIZE;i++) {
355 for(np=nicktable[i];np;np=np->next) {
356 if(np && np->authname && !ircd_strcmp(np->authname, acc)) {
357 LUA_PUSHNICK(l, np);
358 found++;
359 }
360 }
361 }
362
363 return found;
364}
365
366static int lua_getnickchans(lua_State *l) {
367 nick *np;
368 int i;
369 channel **channels;
370
371 if(!lua_islong(l, 1))
372 return 0;
373
374 np = getnickbynumeric(lua_tolong(l, 1));
375 if(!np)
376 return 0;
377
378 channels = (channel **)np->channels->content;
379 for(i=0;i<np->channels->cursi;i++)
380 lua_pushstring(l, channels[i]->index->name->content);
381
382 return np->channels->cursi;
383}
384
4561a594
CP
385static int lua_getnickchanindex(lua_State *l) {
386 nick *np;
387 int offset;
388
389 if(!lua_islong(l, 1) || !lua_isint(l, 2))
390 return 0;
391
392 np = getnickbynumeric(lua_tolong(l, 1));
393 if(!np)
394 return 0;
395
396 offset = lua_toint(l, 2);
397 if((offset < 0) || (offset >= np->channels->cursi))
398 return 0;
399
400 lua_pushstring(l, ((channel **)np->channels->content)[offset]->index->name->content);
401
402 return 1;
403}
404
c5706d5b
CP
405int hashindex;
406nick *lasthashnick;
407
408static int lua_getnextnick(lua_State *l) {
409 if(!lasthashnick && (hashindex != -1))
410 return 0;
411
412 do {
413 if(!lasthashnick) {
414 hashindex++;
415 if(hashindex >= NICKHASHSIZE)
416 return 0;
417 lasthashnick = nicktable[hashindex];
418 } else {
419 lasthashnick = lasthashnick->next;
420 }
421 } while(!lasthashnick);
422
026b1c90 423 LUA_PUSHNICK(l, lasthashnick);
c5706d5b
CP
424 return 1;
425}
426
427static int lua_getfirstnick(lua_State *l) {
c5706d5b
CP
428 hashindex = -1;
429 lasthashnick = NULL;
430
431 return lua_getnextnick(l);
432}
433
8ac8cd09
CP
434static int lua_getnickchancount(lua_State *l) {
435 nick *np;
436
437 if(!lua_islong(l, 1))
438 return 0;
439
440 np = getnickbynumeric(lua_tolong(l, 1));
441 if(!np)
442 return 0;
443
444 lua_pushint(l, np->channels->cursi);
445
446 return 1;
447}
448
2da56f0d
CP
449static int lua_gethostusers(lua_State *l) {
450 nick *np;
451 int count;
452
453 if(!lua_islong(l, 1))
454 return 0;
455
456 np = getnickbynumeric(lua_tolong(l, 1));
457 if(!np || !np->host || !np->host->nicks)
458 return 0;
459
460 np = np->host->nicks;
461 count = np->host->clonecount;
462
463 do {
464 LUA_PUSHNICK(l, np);
465 np = np->nextbyhost;
466 } while(np);
467
468 return count;
469}
470
46751959
CP
471static int lua_getnickcountry(lua_State *l) {
472 nick *np;
473 int ext;
474
475 ext = findnickext("geoip");
476 if(ext == -1)
477 return 0;
478
479 if(!lua_islong(l, 1))
480 return 0;
481
482 np = getnickbynumeric(lua_tolong(l, 1));
483 if(!np)
484 return 0;
485
486 lua_pushint(l, (int)np->exts[ext]);
487 return 1;
488}
489
2da56f0d
CP
490/*
491static int lua_iteratenickhash(lua_State *l) {
492 nick *np;
493 int i, top;
494 void *fp;
495
496 if(!lua_isfunction(l, 1))
497 LUA_RETURN(LUA_FAIL);
498
499 fp = lua_touserdata(l, 1);
500 if(!fp)
501 LUA_RETURN(LUA_FAIL);
502
503 for(i=0;i<NICKHASHSIZE;i++) {
504 for(np=nicktable[i];np;np=np->next) {
505 if(np) {
506 top = lua_gettop(l);
507
508 lua_getglobal(l, "scripterror");
509 lua_insert
510
511 LUA_PUSHNICK(l, np);
512 lua_pcall(l, 1, 0, top + 1);
513
514 lua_settop(l, top);
515 }
516 }
517 }
518
519 LUA_RETURN(LUA_OK);
520}
521*/
522
ebe20bb8
CP
523static int lua_chanfix(lua_State *ps) {
524 channel *cp;
525 nick *np;
526
527 if(!lua_isstring(ps, 1))
528 LUA_RETURN(ps, LUA_FAIL);
529
530 cp = findchannel((char *)lua_tostring(ps, 1));
531 if(!cp)
532 LUA_RETURN(ps, LUA_FAIL);
533
534 np = getnickbynick(LUA_CHANFIXBOT);
535 if(!np)
536 LUA_RETURN(ps, LUA_FAIL);
537
538 lua_message(np, "chanfix %s", cp->index->name->content);
539
540 LUA_RETURN(ps, LUA_OK);
541}
542
543static int lua_clearmode(lua_State *ps) {
544 channel *cp;
545 int i;
546 nick *np;
547 unsigned long *lp;
548 modechanges changes;
549
550 if(!lua_isstring(ps, 1))
551 LUA_RETURN(ps, LUA_FAIL);
552
553 cp = findchannel((char *)lua_tostring(ps, 1));
554 if(!cp)
555 LUA_RETURN(ps, LUA_FAIL);
556
557 localsetmodeinit(&changes, cp, lua_nick);
558
559 localdosetmode_key(&changes, NULL, MCB_DEL);
560 localdosetmode_simple(&changes, 0, CHANMODE_INVITEONLY | CHANMODE_LIMIT);
561
562 while(cp->bans)
563 localdosetmode_ban(&changes, bantostring(cp->bans), MCB_DEL);
564
565 for(i=0,lp=cp->users->content;i<cp->users->hashsize;i++,lp++)
566 if((*lp != nouser) && (*lp & CUMODE_OP)) {
567 np = getnickbynumeric(*lp);
568 if(np && !IsService(np))
569 localdosetmode_nick(&changes, np, MC_DEOP);
570 }
571
572 localsetmodeflush(&changes, 1);
573
574 LUA_RETURN(ps, LUA_OK);
575}
576
46751959
CP
577static int lua_ban(lua_State *ps) {
578 channel *cp;
579 const char *mask;
580 modechanges changes;
581 int dir = MCB_ADD;
582
583 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
584 LUA_RETURN(ps, LUA_FAIL);
585
586 if(lua_isboolean(ps, 3) && lua_toboolean(ps, 3))
587 dir = MCB_DEL;
588
589 cp = findchannel((char *)lua_tostring(ps, 1));
590 if(!cp)
591 LUA_RETURN(ps, LUA_FAIL);
592
593 mask = lua_tostring(ps, 2);
594 if(!mask || !mask[0] || !lua_lineok(mask))
595 LUA_RETURN(ps, LUA_FAIL);
596
597 localsetmodeinit(&changes, cp, lua_nick);
598 localdosetmode_ban(&changes, mask, dir);
599 localsetmodeflush(&changes, 1);
600
601 LUA_RETURN(ps, LUA_OK);
602}
603
2da56f0d
CP
604void lua_registercommands(lua_State *l) {
605 lua_register(l, "irc_smsg", lua_smsg);
606 lua_register(l, "irc_skill", lua_skill);
607
608 lua_register(l, "chanmsg", lua_chanmsg);
609 lua_register(l, "scripterror", lua_scripterror);
610 lua_register(l, "versioninfo", lua_versioninfo);
6269435f 611 lua_register(l, "basepath", lua_basepath);
2da56f0d
CP
612
613 lua_register(l, "irc_report", lua_chanmsg);
614 lua_register(l, "irc_ctcp", lua_ctcp);
615 lua_register(l, "irc_kill", lua_kill);
511316a4
CP
616 lua_register(l, "irc_kick", lua_kick);
617 lua_register(l, "irc_invite", lua_invite);
2da56f0d
CP
618 lua_register(l, "irc_gline", lua_gline);
619 lua_register(l, "irc_getchaninfo", lua_getchaninfo);
620 lua_register(l, "irc_counthost", lua_counthost);
621 lua_register(l, "irc_getuserbyauth", lua_getuserbyauth);
622 lua_register(l, "irc_notice", lua_noticecmd);
623 lua_register(l, "irc_opchan", lua_opchan);
624 lua_register(l, "irc_voicechan", lua_voicechan);
ebe20bb8
CP
625 lua_register(l, "irc_chanfix", lua_chanfix);
626 lua_register(l, "irc_clearmode", lua_clearmode);
46751959 627 lua_register(l, "irc_ban", lua_ban);
d6998bd1 628 lua_register(l, "irc_deopchan", lua_deopchan);
2da56f0d
CP
629
630 lua_register(l, "irc_getnickchans", lua_getnickchans);
4561a594 631 lua_register(l, "irc_getnickchanindex", lua_getnickchanindex);
8ac8cd09 632 lua_register(l, "irc_getnickchancount", lua_getnickchancount);
c5706d5b
CP
633
634 lua_register(l, "irc_getfirstnick", lua_getfirstnick);
635 lua_register(l, "irc_getnextnick", lua_getnextnick);
636
2da56f0d 637 lua_register(l, "irc_gethostusers", lua_gethostusers);
46751959 638 lua_register(l, "irc_getnickcountry", lua_getnickcountry);
2da56f0d
CP
639
640/* lua_register(l, "irc_iteratenickhash", lua_iteratenickhash); */
641}
642
643/* --- */
644
645static int lua_smsg(lua_State *ps) {
646 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
647 LUA_RETURN(ps, LUA_FAIL);
648
649 LUA_RETURN(ps, lua_cmsg((char *)lua_tostring(ps, 2), "%s", lua_tostring(ps, 1)));
650}
651
652static int lua_skill(lua_State *ps) {
653 const char *n, *msg;
654 nick *np;
655
656 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
657 LUA_RETURN(ps, LUA_FAIL);
658
659 n = lua_tostring(ps, 1);
660 msg = lua_tostring(ps, 2);
661
662 np = getnickbynick(n);
663 if(!np)
664 LUA_RETURN(ps, LUA_FAIL);
665
666 if(IsOper(np) || IsService(np) || IsXOper(np))
667 LUA_RETURN(ps, LUA_FAIL);
668
669 if(!lua_lineok(msg))
670 LUA_RETURN(ps, LUA_FAIL);
671
672 killuser(lua_nick, np, "%s", msg);
673
674 LUA_RETURN(ps, LUA_OK);
675}
676