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