]> jfr.im git - irc/quakenet/newserv.git/blame - lua/luacommands.c
Add to regexgline.
[irc/quakenet/newserv.git] / lua / luacommands.c
CommitLineData
d0d1e2a3 1/* Copyright (C) Chris Porter 2005-2006 */
2da56f0d
CP
2/* ALL RIGHTS RESERVED. */
3/* Don't put this into the SVN repo. */
4
d0d1e2a3
CP
5/*
6 @todo
7 - Write a nick printf type thing for pcalled functions.
8 - Make commands register as apposed to blinding calling.
9 - Use numerics instead of huge structures, and add lookup functions.
10*/
11
2da56f0d
CP
12#include "../channel/channel.h"
13#include "../control/control.h"
14#include "../nick/nick.h"
15#include "../localuser/localuser.h"
16#include "../localuser/localuserchannel.h"
17#include "../lib/irc_string.h"
18
19#include "lua.h"
20#include "luabot.h"
21
22#include <stdarg.h>
30a59b87 23#include <stddef.h>
2da56f0d 24
9887536a 25#ifdef LUA_USEJIT
6269435f
CP
26#include <luajit.h>
27#endif
28
ec91b2e4
CP
29#define MAX_PUSHER 50
30
2da56f0d
CP
31static int lua_smsg(lua_State *ps);
32static int lua_skill(lua_State *ps);
33
ec91b2e4 34typedef struct lua_pusher {
30a59b87
CP
35 short argtype;
36 short offset;
37 const char *structname;
ec91b2e4
CP
38} lua_pusher;
39
40struct lua_pusher nickpusher[MAX_PUSHER];
41struct lua_pusher chanpusher[MAX_PUSHER];
42
43void lua_setuppusher(struct lua_pusher *pusherlist, lua_State *l, int index, struct lua_pusher **lp, int max);
30a59b87
CP
44
45void lua_initnickpusher(void);
ec91b2e4
CP
46INLINE int lua_usepusher(lua_State *l, struct lua_pusher **lp, void *np);
47
48void lua_initchanpusher(void);
49INLINE int lua_usechanpusher(lua_State *l, struct lua_pusher **lp, nick *np);
50
51#define lua_setupnickpusher(L2, I2, P2, M2) lua_setuppusher(&nickpusher[0], L2, I2, P2, M2)
52#define lua_setupchanpusher(L2, I2, P2, M2) lua_setuppusher(&chanpusher[0], L2, I2, P2, M2)
30a59b87 53
2da56f0d
CP
54int lua_lineok(const char *data) {
55 if(strchr(data, '\r') || strchr(data, '\n'))
56 return 0;
57 return 1;
58}
59
60int lua_cmsg(char *channell, char *message, ...) {
61 char buf[512];
62 va_list va;
63 channel *cp;
64
65 va_start(va, message);
66 vsnprintf(buf, sizeof(buf), message, va);
67 va_end(va);
68
69 cp = findchannel(channell);
70 if(!cp)
71 return LUA_FAIL;
72
73 if(!lua_lineok(buf))
74 return LUA_FAIL;
75
76 lua_channelmessage(cp, "%s", buf);
77
78 return LUA_OK;
79}
80
81static int lua_chanmsg(lua_State *ps) {
82 if(!lua_isstring(ps, 1))
83 LUA_RETURN(ps, LUA_FAIL);
84
85 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua: %s", lua_tostring(ps, 1)));
86}
87
88static int lua_scripterror(lua_State *ps) {
89 if(!lua_isstring(ps, 1))
90 LUA_RETURN(ps, LUA_FAIL);
91
92 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-error: %s", lua_tostring(ps, 1)));
93}
94
95static int lua_ctcp(lua_State *ps) {
96 const char *n, *msg;
97 nick *np;
98
99 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
100 LUA_RETURN(ps, LUA_FAIL);
101
102 n = lua_tostring(ps, 1);
103 msg = lua_tostring(ps, 2);
104
105 np = getnickbynick(n);
106 if(!np || !lua_lineok(msg))
107 LUA_RETURN(ps, LUA_FAIL);
108
109 lua_message(np, "\001%s\001", msg);
110
111 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-ctcp: %s (%s)", np->nick, msg));
112}
113
114static int lua_noticecmd(lua_State *ps) {
115 const char *n, *msg;
116 nick *np;
117
118 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
119 LUA_RETURN(ps, LUA_FAIL);
120
121 n = lua_tostring(ps, 1);
122 msg = lua_tostring(ps, 2);
123
124 np = getnickbynick(n);
125 if(!np || !lua_lineok(msg))
126 LUA_RETURN(ps, LUA_FAIL);
127
128 lua_notice(np, "%s", msg);
129
130 LUA_RETURN(ps, LUA_OK);
131}
132
133static int lua_kill(lua_State *ps) {
134 const char *n, *msg;
135 nick *np;
136
137 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
138 LUA_RETURN(ps, LUA_FAIL);
139
140 n = lua_tostring(ps, 1);
141 msg = lua_tostring(ps, 2);
142
143 np = getnickbynick(n);
144 if(!np)
145 LUA_RETURN(ps, LUA_FAIL);
146
147 if(IsOper(np) || IsService(np) || IsXOper(np))
148 LUA_RETURN(ps, LUA_FAIL);
149
150 if(!lua_lineok(msg))
151 LUA_RETURN(ps, LUA_FAIL);
152
153 killuser(lua_nick, np, "%s", msg);
154
155 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-KILL: %s (%s)", np->nick, msg));
156}
157
511316a4
CP
158static int lua_kick(lua_State *ps) {
159 const char *n, *msg, *chan;
160 nick *np;
161 channel *cp;
46751959 162 int dochecks = 1;
511316a4
CP
163
164 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3))
165 LUA_RETURN(ps, LUA_FAIL);
166
167 chan = lua_tostring(ps, 1);
168 n = lua_tostring(ps, 2);
169 msg = lua_tostring(ps, 3);
170
46751959
CP
171 if(lua_isboolean(ps, 4) && !lua_toboolean(ps, 4))
172 dochecks = 0;
173
511316a4
CP
174 np = getnickbynick(n);
175 if(!np)
176 LUA_RETURN(ps, LUA_FAIL);
177
46751959
CP
178 if(dochecks && (IsOper(np) || IsXOper(np) || IsService(np)))
179 LUA_RETURN(ps, LUA_FAIL);
180
511316a4
CP
181 cp = findchannel((char *)chan);
182 if(!cp)
183 LUA_RETURN(ps, LUA_FAIL);
184
185 if(!lua_lineok(msg))
186 LUA_RETURN(ps, LUA_FAIL);
187
188 localkickuser(lua_nick, cp, np, msg);
189
190 LUA_RETURN(ps, LUA_OK);
191}
192
193static int lua_invite(lua_State *ps) {
194 nick *np;
195 channel *cp;
196
197 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
198 LUA_RETURN(ps, LUA_FAIL);
199
200 np = getnickbynick((char *)lua_tostring(ps, 1));
201 if(!np)
202 LUA_RETURN(ps, LUA_FAIL);
203
204 cp = findchannel((char *)lua_tostring(ps, 2));
205 if(!cp)
206 LUA_RETURN(ps, LUA_FAIL);
207
208 localinvite(lua_nick, cp, np);
209
210 LUA_RETURN(ps, LUA_OK);
211}
212
2da56f0d
CP
213static int lua_gline(lua_State *ps) {
214 const char *reason;
215 nick *target;
216 char mask[512];
217 int duration, usercount = 0;
218 host *hp;
219
220 if(!lua_isstring(ps, 1) || !lua_isint(ps, 2) || !lua_isstring(ps, 3))
221 LUA_RETURN(ps, LUA_FAIL);
222
223 duration = lua_toint(ps, 2);
ec91b2e4 224 if((duration < 1) || (duration > 7 * 86400))
2da56f0d
CP
225 LUA_RETURN(ps, LUA_FAIL);
226
227 reason = lua_tostring(ps, 3);
228 if(!lua_lineok(reason) || !reason)
229 LUA_RETURN(ps, LUA_FAIL);
230
231 target = getnickbynick(lua_tostring(ps, 1));
232 if(!target || (IsOper(target) || IsXOper(target) || IsService(target)))
233 LUA_RETURN(ps, LUA_FAIL);
234
235 hp = target->host;
236 if(!hp)
237 LUA_RETURN(ps, LUA_FAIL);
238
239 usercount = hp->clonecount;
240 if(usercount > 10) { /* (decent) trusted host */
241 int j;
242 nick *np;
243
244 usercount = 0;
245
246 for (j=0;j<NICKHASHSIZE;j++)
247 for (np=nicktable[j];np;np=np->next)
248 if (np && (np->host == hp) && (!ircd_strcmp(np->ident, target->ident)))
249 usercount++;
250
251 if(usercount > 50)
252 LUA_RETURN(ps, LUA_FAIL);
253
254 snprintf(mask, sizeof(mask), "*%s@%s", target->ident, IPtostr(target->ipaddress));
255 } else {
256 snprintf(mask, sizeof(mask), "*@%s", IPtostr(target->ipaddress));
257 }
258
b822d7a4 259 irc_send("%s GL * +%s %d :%s", mynumeric->content, mask, duration, reason);
2da56f0d
CP
260 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-GLINE: %s (%d users, %d seconds -- %s)", mask, usercount, duration, reason));
261}
262
263static int lua_getchaninfo(lua_State *ps) {
264 channel *cp;
265
266 if(!lua_isstring(ps, 1))
267 return 0;
268
269 cp = findchannel((char *)lua_tostring(ps, 1));
270 if(!cp)
271 return 0;
272
273 LUA_PUSHCHAN(ps, cp);
274
275 return 1;
276}
277
278static int lua_opchan(lua_State *ps) {
279 channel *cp;
280 nick *np;
281
282 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
283 LUA_RETURN(ps, LUA_FAIL);
284
285 cp = findchannel((char *)lua_tostring(ps, 1));
286 if(!cp)
287 LUA_RETURN(ps, LUA_FAIL);
288
289 np = getnickbynick((char *)lua_tostring(ps, 2));
290 if(!np)
291 LUA_RETURN(ps, LUA_FAIL);
292
293 localsetmodes(lua_nick, cp, np, MC_OP);
294 LUA_RETURN(ps, LUA_OK);
295}
296
d6998bd1
CP
297static int lua_deopchan(lua_State *ps) {
298 channel *cp;
299 nick *np;
300
301 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
302 LUA_RETURN(ps, LUA_FAIL);
303
304 cp = findchannel((char *)lua_tostring(ps, 1));
305 if(!cp)
306 LUA_RETURN(ps, LUA_FAIL);
307
308 np = getnickbynick((char *)lua_tostring(ps, 2));
309 if(!np)
310 LUA_RETURN(ps, LUA_FAIL);
311
312 localsetmodes(lua_nick, cp, np, MC_DEOP);
313 LUA_RETURN(ps, LUA_OK);
314}
315
2da56f0d
CP
316static int lua_voicechan(lua_State *ps) {
317 channel *cp;
318 nick *np;
319
320 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
321 LUA_RETURN(ps, LUA_FAIL);
322
323 cp = findchannel((char *)lua_tostring(ps, 1));
324 if(!cp)
325 LUA_RETURN(ps, LUA_FAIL);
326
327 np = getnickbynick((char *)lua_tostring(ps, 2));
328 if(!np)
329 LUA_RETURN(ps, LUA_FAIL);
330
331 localsetmodes(lua_nick, cp, np, MC_VOICE);
332 LUA_RETURN(ps, LUA_OK);
333}
334
335static int lua_counthost(lua_State *ps) {
336 long numeric;
337 nick *np;
338
339 if(!lua_islong(ps, 1))
340 return 0;
341
342 numeric = lua_tolong(ps, 1);
343
344 np = getnickbynumeric(numeric);
345 if(!np)
346 return 0;
347
348 lua_pushint(ps, np->host->clonecount);
349 return 1;
350}
351
352static int lua_versioninfo(lua_State *ps) {
353 lua_pushstring(ps, LUA_VERSION);
354 lua_pushstring(ps, LUA_BOTVERSION);
355 lua_pushstring(ps, __DATE__);
356 lua_pushstring(ps, __TIME__);
357
9887536a 358#ifdef LUA_USEJIT
6269435f
CP
359 lua_pushstring(ps, " + " LUAJIT_VERSION);
360#else
361 lua_pushstring(ps, "");
362#endif
363
364 return 5;
365}
366
367static int lua_basepath(lua_State *ps) {
368 lua_pushfstring(ps, "%s/", cpath->content);
369
370 return 1;
2da56f0d
CP
371}
372
373/* O(n) */
374static int lua_getuserbyauth(lua_State *l) {
375 const char *acc;
376 nick *np;
377 int i, found = 0;
378
379 if(!lua_isstring(l, 1))
380 return 0;
381
1fbb1306
CP
382 acc = lua_tostring(l, 1);
383
2da56f0d
CP
384 for(i=0;i<NICKHASHSIZE;i++) {
385 for(np=nicktable[i];np;np=np->next) {
386 if(np && np->authname && !ircd_strcmp(np->authname, acc)) {
387 LUA_PUSHNICK(l, np);
388 found++;
389 }
390 }
391 }
392
393 return found;
394}
395
396static int lua_getnickchans(lua_State *l) {
397 nick *np;
398 int i;
399 channel **channels;
400
401 if(!lua_islong(l, 1))
402 return 0;
403
404 np = getnickbynumeric(lua_tolong(l, 1));
405 if(!np)
406 return 0;
407
408 channels = (channel **)np->channels->content;
409 for(i=0;i<np->channels->cursi;i++)
410 lua_pushstring(l, channels[i]->index->name->content);
411
412 return np->channels->cursi;
413}
414
4561a594
CP
415static int lua_getnickchanindex(lua_State *l) {
416 nick *np;
417 int offset;
418
419 if(!lua_islong(l, 1) || !lua_isint(l, 2))
420 return 0;
421
422 np = getnickbynumeric(lua_tolong(l, 1));
423 if(!np)
424 return 0;
425
426 offset = lua_toint(l, 2);
427 if((offset < 0) || (offset >= np->channels->cursi))
428 return 0;
429
430 lua_pushstring(l, ((channel **)np->channels->content)[offset]->index->name->content);
431
432 return 1;
433}
434
c5706d5b
CP
435int hashindex;
436nick *lasthashnick;
437
ec91b2e4 438struct lua_pusher *nickhashpusher[MAX_PUSHER];
30a59b87 439
c5706d5b
CP
440static int lua_getnextnick(lua_State *l) {
441 if(!lasthashnick && (hashindex != -1))
442 return 0;
443
444 do {
445 if(!lasthashnick) {
446 hashindex++;
447 if(hashindex >= NICKHASHSIZE)
448 return 0;
449 lasthashnick = nicktable[hashindex];
450 } else {
451 lasthashnick = lasthashnick->next;
452 }
453 } while(!lasthashnick);
454
ec91b2e4 455 return lua_usepusher(l, nickhashpusher, lasthashnick);
c5706d5b
CP
456}
457
458static int lua_getfirstnick(lua_State *l) {
c5706d5b
CP
459 hashindex = -1;
460 lasthashnick = NULL;
461
ec91b2e4 462 lua_setupnickpusher(l, 1, nickhashpusher, MAX_PUSHER);
30a59b87 463
c5706d5b
CP
464 return lua_getnextnick(l);
465}
466
ec91b2e4
CP
467int chanhashindex;
468chanindex *lasthashchan;
469
470struct lua_pusher *chanhashpusher[MAX_PUSHER];
471
472static int lua_getnextchan(lua_State *l) {
473 if(!lasthashchan && (chanhashindex != -1))
474 return 0;
475
476 do {
477 if(!lasthashchan) {
478 chanhashindex++;
479 if(chanhashindex >= CHANNELHASHSIZE)
480 return 0;
481 lasthashchan = chantable[chanhashindex];
482 } else {
483 lasthashchan = lasthashchan->next;
484 }
485 } while(!lasthashchan || !lasthashchan->channel);
486
487 return lua_usepusher(l, chanhashpusher, lasthashchan);
488}
489
490static int lua_getfirstchan(lua_State *l) {
491 chanhashindex = -1;
492 lasthashchan = NULL;
493
494 lua_setupchanpusher(l, 1, chanhashpusher, MAX_PUSHER);
495
496 return lua_getnextchan(l);
497}
498
8ac8cd09
CP
499static int lua_getnickchancount(lua_State *l) {
500 nick *np;
501
502 if(!lua_islong(l, 1))
503 return 0;
504
505 np = getnickbynumeric(lua_tolong(l, 1));
506 if(!np)
507 return 0;
508
509 lua_pushint(l, np->channels->cursi);
510
511 return 1;
512}
513
2da56f0d
CP
514static int lua_gethostusers(lua_State *l) {
515 nick *np;
516 int count;
517
518 if(!lua_islong(l, 1))
519 return 0;
520
521 np = getnickbynumeric(lua_tolong(l, 1));
522 if(!np || !np->host || !np->host->nicks)
523 return 0;
524
525 np = np->host->nicks;
526 count = np->host->clonecount;
527
528 do {
529 LUA_PUSHNICK(l, np);
530 np = np->nextbyhost;
531 } while(np);
532
533 return count;
534}
535
46751959
CP
536static int lua_getnickcountry(lua_State *l) {
537 nick *np;
538 int ext;
539
540 ext = findnickext("geoip");
541 if(ext == -1)
542 return 0;
543
544 if(!lua_islong(l, 1))
545 return 0;
546
547 np = getnickbynumeric(lua_tolong(l, 1));
548 if(!np)
549 return 0;
550
551 lua_pushint(l, (int)np->exts[ext]);
552 return 1;
553}
554
ebe20bb8
CP
555static int lua_chanfix(lua_State *ps) {
556 channel *cp;
557 nick *np;
558
559 if(!lua_isstring(ps, 1))
560 LUA_RETURN(ps, LUA_FAIL);
561
562 cp = findchannel((char *)lua_tostring(ps, 1));
563 if(!cp)
564 LUA_RETURN(ps, LUA_FAIL);
565
566 np = getnickbynick(LUA_CHANFIXBOT);
567 if(!np)
568 LUA_RETURN(ps, LUA_FAIL);
569
570 lua_message(np, "chanfix %s", cp->index->name->content);
571
572 LUA_RETURN(ps, LUA_OK);
573}
574
575static int lua_clearmode(lua_State *ps) {
576 channel *cp;
577 int i;
578 nick *np;
579 unsigned long *lp;
580 modechanges changes;
581
582 if(!lua_isstring(ps, 1))
583 LUA_RETURN(ps, LUA_FAIL);
584
585 cp = findchannel((char *)lua_tostring(ps, 1));
586 if(!cp)
587 LUA_RETURN(ps, LUA_FAIL);
588
589 localsetmodeinit(&changes, cp, lua_nick);
590
591 localdosetmode_key(&changes, NULL, MCB_DEL);
592 localdosetmode_simple(&changes, 0, CHANMODE_INVITEONLY | CHANMODE_LIMIT);
593
594 while(cp->bans)
595 localdosetmode_ban(&changes, bantostring(cp->bans), MCB_DEL);
596
597 for(i=0,lp=cp->users->content;i<cp->users->hashsize;i++,lp++)
598 if((*lp != nouser) && (*lp & CUMODE_OP)) {
599 np = getnickbynumeric(*lp);
600 if(np && !IsService(np))
601 localdosetmode_nick(&changes, np, MC_DEOP);
602 }
603
604 localsetmodeflush(&changes, 1);
605
606 LUA_RETURN(ps, LUA_OK);
607}
608
46751959
CP
609static int lua_ban(lua_State *ps) {
610 channel *cp;
611 const char *mask;
612 modechanges changes;
613 int dir = MCB_ADD;
614
615 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
616 LUA_RETURN(ps, LUA_FAIL);
617
618 if(lua_isboolean(ps, 3) && lua_toboolean(ps, 3))
619 dir = MCB_DEL;
620
621 cp = findchannel((char *)lua_tostring(ps, 1));
622 if(!cp)
623 LUA_RETURN(ps, LUA_FAIL);
624
625 mask = lua_tostring(ps, 2);
626 if(!mask || !mask[0] || !lua_lineok(mask))
627 LUA_RETURN(ps, LUA_FAIL);
628
629 localsetmodeinit(&changes, cp, lua_nick);
630 localdosetmode_ban(&changes, mask, dir);
631 localsetmodeflush(&changes, 1);
632
633 LUA_RETURN(ps, LUA_OK);
634}
635
d0d1e2a3
CP
636static int lua_topic(lua_State *ps) {
637 channel *cp;
638 char *topic;
639
640 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
641 LUA_RETURN(ps, LUA_FAIL);
642
643 cp = findchannel((char *)lua_tostring(ps, 1));
644 if(!cp)
645 LUA_RETURN(ps, LUA_FAIL);
646
647 topic = (char *)lua_tostring(ps, 2);
648 if(!topic || !lua_lineok(topic))
649 LUA_RETURN(ps, LUA_FAIL);
650
651 localsettopic(lua_nick, cp, topic);
652
653 LUA_RETURN(ps, LUA_OK);
654}
655
656static int lua_getuserchanmodes(lua_State *l) {
657 nick *np;
658 channel *cp;
659 unsigned long *lp;
660
661 if(!lua_islong(l, 1) || !lua_isstring(l, 2))
662 return 0;
663
664 np = getnickbynumeric(lua_tolong(l, 1));
665 if(!np)
666 return 0;
667
668 cp = findchannel((char *)lua_tostring(l, 2));
669 if(!cp)
670 return 0;
671
672 lp = getnumerichandlefromchanhash(cp->users, np->numeric);
673 if(!lp)
674 return 0;
675
676 LUA_PUSHNICKCHANMODES(l, lp);
677 return 1;
678}
679
680static int lua_getnickbynick(lua_State *l) {
681 nick *np;
682
683 if(!lua_isstring(l, 1))
684 return 0;
685
686 np = getnickbynick(lua_tostring(l, 1));
687 if(!np)
688 return 0;
689
690 LUA_PUSHNICK(l, np);
691 return 1;
692}
693
d4aef858
CP
694static int lua_getnickbynumeric(lua_State *l) {
695 nick *np;
696
697 if(!lua_islong(l, 1))
698 return 0;
699
700 np = getnickbynumeric(lua_tolong(l, 1));
701 if(!np)
702 return 0;
703
704 LUA_PUSHNICK(l, np);
705 return 1;
706}
707
2da56f0d
CP
708void lua_registercommands(lua_State *l) {
709 lua_register(l, "irc_smsg", lua_smsg);
710 lua_register(l, "irc_skill", lua_skill);
711
712 lua_register(l, "chanmsg", lua_chanmsg);
713 lua_register(l, "scripterror", lua_scripterror);
714 lua_register(l, "versioninfo", lua_versioninfo);
6269435f 715 lua_register(l, "basepath", lua_basepath);
2da56f0d
CP
716
717 lua_register(l, "irc_report", lua_chanmsg);
718 lua_register(l, "irc_ctcp", lua_ctcp);
719 lua_register(l, "irc_kill", lua_kill);
511316a4
CP
720 lua_register(l, "irc_kick", lua_kick);
721 lua_register(l, "irc_invite", lua_invite);
2da56f0d
CP
722 lua_register(l, "irc_gline", lua_gline);
723 lua_register(l, "irc_getchaninfo", lua_getchaninfo);
724 lua_register(l, "irc_counthost", lua_counthost);
725 lua_register(l, "irc_getuserbyauth", lua_getuserbyauth);
726 lua_register(l, "irc_notice", lua_noticecmd);
727 lua_register(l, "irc_opchan", lua_opchan);
728 lua_register(l, "irc_voicechan", lua_voicechan);
ebe20bb8
CP
729 lua_register(l, "irc_chanfix", lua_chanfix);
730 lua_register(l, "irc_clearmode", lua_clearmode);
46751959 731 lua_register(l, "irc_ban", lua_ban);
d6998bd1 732 lua_register(l, "irc_deopchan", lua_deopchan);
d0d1e2a3
CP
733 lua_register(l, "irc_topic", lua_topic);
734
735 lua_register(l, "irc_getnickbynick", lua_getnickbynick);
d4aef858 736 lua_register(l, "irc_getnickbynumeric", lua_getnickbynumeric);
d0d1e2a3
CP
737 lua_register(l, "irc_getfirstnick", lua_getfirstnick);
738 lua_register(l, "irc_getnextnick", lua_getnextnick);
2da56f0d
CP
739
740 lua_register(l, "irc_getnickchans", lua_getnickchans);
4561a594 741 lua_register(l, "irc_getnickchanindex", lua_getnickchanindex);
8ac8cd09 742 lua_register(l, "irc_getnickchancount", lua_getnickchancount);
c5706d5b 743
d0d1e2a3
CP
744 lua_register(l, "irc_getuserchanmodes", lua_getuserchanmodes);
745
c5706d5b 746
2da56f0d 747 lua_register(l, "irc_gethostusers", lua_gethostusers);
46751959 748 lua_register(l, "irc_getnickcountry", lua_getnickcountry);
ec91b2e4
CP
749
750 lua_register(l, "irc_getfirstchan", lua_getfirstchan);
751 lua_register(l, "irc_getnextchan", lua_getnextchan);
2da56f0d
CP
752}
753
754/* --- */
755
756static int lua_smsg(lua_State *ps) {
757 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
758 LUA_RETURN(ps, LUA_FAIL);
759
760 LUA_RETURN(ps, lua_cmsg((char *)lua_tostring(ps, 2), "%s", lua_tostring(ps, 1)));
761}
762
763static int lua_skill(lua_State *ps) {
764 const char *n, *msg;
765 nick *np;
766
767 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
768 LUA_RETURN(ps, LUA_FAIL);
769
770 n = lua_tostring(ps, 1);
771 msg = lua_tostring(ps, 2);
772
773 np = getnickbynick(n);
774 if(!np)
775 LUA_RETURN(ps, LUA_FAIL);
776
777 if(IsOper(np) || IsService(np) || IsXOper(np))
778 LUA_RETURN(ps, LUA_FAIL);
779
780 if(!lua_lineok(msg))
781 LUA_RETURN(ps, LUA_FAIL);
782
783 killuser(lua_nick, np, "%s", msg);
784
785 LUA_RETURN(ps, LUA_OK);
786}
787
30a59b87 788#define PUSHER_STRING 1
eebdff1f 789#define PUSHER_REALNAME 2
30a59b87
CP
790#define PUSHER_IP 3
791#define PUSHER_LONG 4
eebdff1f
CP
792#define PUSHER_HOSTNAME 5
793#define PUSHER_SSTRING 6
ec91b2e4
CP
794#define PUSHER_TOTALUSERS 7
795#define PUSHER_TOPIC 8
30a59b87
CP
796
797void lua_initnickpusher(void) {
798 int i = 0;
799
800#define PUSH_NICKPUSHER(F2, O2) nickpusher[i].argtype = F2; nickpusher[i].structname = #O2; nickpusher[i].offset = offsetof(nick, O2); i++;
801
802 PUSH_NICKPUSHER(PUSHER_STRING, nick);
803 PUSH_NICKPUSHER(PUSHER_STRING, ident);
eebdff1f
CP
804 PUSH_NICKPUSHER(PUSHER_HOSTNAME, host);
805 PUSH_NICKPUSHER(PUSHER_REALNAME, realname);
30a59b87
CP
806 PUSH_NICKPUSHER(PUSHER_STRING, authname);
807 PUSH_NICKPUSHER(PUSHER_IP, ipaddress);
808 PUSH_NICKPUSHER(PUSHER_LONG, numeric);
809
810 nickpusher[i].argtype = 0;
811}
812
ec91b2e4 813void lua_setuppusher(struct lua_pusher *pusherlist, lua_State *l, int index, struct lua_pusher **lp, int max) {
30a59b87 814 int current = 0;
ec91b2e4 815 struct lua_pusher *f;
30a59b87
CP
816
817 if(max > 0)
818 lp[0] = NULL;
819
820 if(!lua_istable(l, -1) || (max < 2))
821 return;
822
823 lua_pushnil(l);
824
825 max--;
826
827 while (lua_next(l, index)) {
828 if(lua_isstring(l, -1)) {
829 char *name = (char *)lua_tostring(l, -1);
830
ec91b2e4 831 for(f=pusherlist;f->argtype;f++)
30a59b87
CP
832 if(!strcmp(f->structname, name))
833 break;
834
835 if(f->argtype)
836 lp[current++] = f;
837 }
838
839 lua_pop(l, 1);
840
841 if(current == max)
842 break;
843 }
844
845 lp[current] = NULL;
846}
847
ec91b2e4 848INLINE int lua_usepusher(lua_State *l, struct lua_pusher **lp, void *np) {
1f38b1d7
CP
849 int i = 0;
850
30a59b87
CP
851 while(*lp) {
852 void *offset = (void *)np + (*lp)->offset;
853
30a59b87
CP
854 switch((*lp)->argtype) {
855 case PUSHER_STRING:
856 lua_pushstring(l, (char *)offset);
857 break;
eebdff1f
CP
858 case PUSHER_HOSTNAME:
859 lua_pushstring(l, (*(host **)offset)->name->content);
860 break;
861 case PUSHER_REALNAME:
862 lua_pushstring(l, (*(realname **)offset)->name->content);
863 break;
30a59b87 864 case PUSHER_SSTRING:
ec91b2e4 865 lua_pushstring(l, (*((sstring **)offset))->content);
30a59b87
CP
866 break;
867 case PUSHER_LONG:
868 lua_pushlong(l, *((long *)offset));
869 break;
870 case PUSHER_IP:
871 lua_pushstring(l, IPtostr(*((long *)offset)));
872 break;
ec91b2e4
CP
873 case PUSHER_TOTALUSERS:
874 lua_pushint(l, (*((channel **)offset))->users->totalusers);
875 break;
876 case PUSHER_TOPIC:
877 if((*((channel **)offset))->topic) {
878 lua_pushstring(l, (*((channel **)offset))->topic->content);
879 } else {
880 lua_pushnil(l);
881 }
882 break;
30a59b87
CP
883 }
884
1f38b1d7 885 i++;
30a59b87
CP
886 lp++;
887 }
1f38b1d7
CP
888
889 return i;
30a59b87 890}
24da5817 891
ec91b2e4
CP
892void lua_initchanpusher(void) {
893 int i = 0;
894
895#define PUSH_CHANPUSHER(F2, O2, N2) chanpusher[i].argtype = F2; chanpusher[i].structname = N2; chanpusher[i].offset = offsetof(chanindex, O2); i++;
896
897 PUSH_CHANPUSHER(PUSHER_SSTRING, name, "name");
898 PUSH_CHANPUSHER(PUSHER_TOTALUSERS, channel, "totalusers");
899 PUSH_CHANPUSHER(PUSHER_TOPIC, channel, "topic");
900
901 chanpusher[i].argtype = 0;
902}