]> jfr.im git - irc/quakenet/newserv.git/blob - lua/luacommands.c
Merge default.
[irc/quakenet/newserv.git] / lua / luacommands.c
1 /* Copyright (C) Chris Porter 2005-2007 */
2 /* ALL RIGHTS RESERVED. */
3 /* Don't put this into the SVN repo. */
4
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
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 #include "../lib/flags.h"
19 #include "../authext/authext.h"
20 #include "../glines/glines.h"
21
22 #include "lua.h"
23 #include "luabot.h"
24
25 #include <stdarg.h>
26 #include <stddef.h>
27
28 #define MAX_PUSHER 50
29
30 static int lua_smsg(lua_State *ps);
31 static int lua_skill(lua_State *ps);
32
33 typedef struct lua_pusher {
34 short argtype;
35 short offset;
36 const char *structname;
37 } lua_pusher;
38
39 struct lua_pusher nickpusher[MAX_PUSHER];
40 struct lua_pusher chanpusher[MAX_PUSHER];
41 int nickpushercount, chanpushercount;
42
43 void lua_setuppusher(struct lua_pusher *pusherlist, lua_State *l, int index, struct lua_pusher **lp, int max, int pcount);
44 int lua_usepusher(lua_State *l, struct lua_pusher **lp, void *np);
45
46 void lua_initnickpusher(void);
47 void lua_initchanpusher(void);
48
49 #define lua_setupnickpusher(L2, I2, P2, M2) lua_setuppusher(&nickpusher[0], L2, I2, P2, M2, nickpushercount)
50 #define lua_setupchanpusher(L2, I2, P2, M2) lua_setuppusher(&chanpusher[0], L2, I2, P2, M2, chanpushercount)
51
52 int lua_cmsg(char *channell, char *message, ...) __attribute__ ((format (printf, 2, 3)));
53
54 int lua_cmsg(char *channell, char *message, ...) {
55 char buf[512];
56 va_list va;
57 channel *cp;
58
59 va_start(va, message);
60 vsnprintf(buf, sizeof(buf), message, va);
61 va_end(va);
62
63 cp = findchannel(channell);
64 if(!cp)
65 return LUA_FAIL;
66
67 if(!lua_lineok(buf))
68 return LUA_FAIL;
69
70 lua_channelmessage(cp, "%s", buf);
71
72 return LUA_OK;
73 }
74
75 static int lua_chanmsg(lua_State *ps) {
76 if(!lua_isstring(ps, 1))
77 LUA_RETURN(ps, LUA_FAIL);
78
79 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua: %s", lua_tostring(ps, 1)));
80 }
81
82 static int lua_ctcp(lua_State *ps) {
83 const char *n, *msg;
84 nick *np;
85
86 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
87 LUA_RETURN(ps, LUA_FAIL);
88
89 n = lua_tostring(ps, 1);
90 msg = lua_tostring(ps, 2);
91
92 np = getnickbynick(n);
93 if(!np || !lua_lineok(msg))
94 LUA_RETURN(ps, LUA_FAIL);
95
96 lua_message(np, "\001%s\001", msg);
97
98 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-ctcp: %s (%s)", np->nick, msg));
99 }
100
101 static int lua_noticecmd(lua_State *ps) {
102 const char *n, *msg;
103 nick *np;
104
105 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
106 LUA_RETURN(ps, LUA_FAIL);
107
108 n = lua_tostring(ps, 1);
109 msg = lua_tostring(ps, 2);
110
111 np = getnickbynick(n);
112 if(!np || !lua_lineok(msg))
113 LUA_RETURN(ps, LUA_FAIL);
114
115 lua_notice(np, "%s", msg);
116
117 LUA_RETURN(ps, LUA_OK);
118 }
119
120 static int lua_privmsgcmd(lua_State *ps) {
121 const char *n, *msg;
122 nick *np;
123
124 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
125 LUA_RETURN(ps, LUA_FAIL);
126
127 n = lua_tostring(ps, 1);
128 msg = lua_tostring(ps, 2);
129
130 np = getnickbynick(n);
131 if(!np || !lua_lineok(msg))
132 LUA_RETURN(ps, LUA_FAIL);
133
134 lua_message(np, "%s", msg);
135
136 LUA_RETURN(ps, LUA_OK);
137 }
138
139 static int lua_kill(lua_State *ps) {
140 const char *n, *msg;
141 nick *np;
142
143 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
144 LUA_RETURN(ps, LUA_FAIL);
145
146 n = lua_tostring(ps, 1);
147 msg = lua_tostring(ps, 2);
148
149 np = getnickbynick(n);
150 if(!np)
151 LUA_RETURN(ps, LUA_FAIL);
152
153 if(IsOper(np) || IsService(np) || IsXOper(np))
154 LUA_RETURN(ps, LUA_FAIL);
155
156 if(!lua_lineok(msg))
157 LUA_RETURN(ps, LUA_FAIL);
158
159 killuser(lua_nick, np, "%s", msg);
160
161 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-KILL: %s (%s)", np->nick, msg));
162 }
163
164 static int lua_kick(lua_State *ps) {
165 const char *n, *msg, *chan;
166 nick *np;
167 channel *cp;
168 int dochecks = 1;
169
170 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3))
171 LUA_RETURN(ps, LUA_FAIL);
172
173 chan = lua_tostring(ps, 1);
174 n = lua_tostring(ps, 2);
175 msg = lua_tostring(ps, 3);
176
177 if(lua_isboolean(ps, 4) && !lua_toboolean(ps, 4))
178 dochecks = 0;
179
180 np = getnickbynick(n);
181 if(!np)
182 LUA_RETURN(ps, LUA_FAIL);
183
184 if(dochecks && (IsOper(np) || IsXOper(np) || IsService(np)))
185 LUA_RETURN(ps, LUA_FAIL);
186
187 cp = findchannel((char *)chan);
188 if(!cp)
189 LUA_RETURN(ps, LUA_FAIL);
190
191 if(!lua_lineok(msg))
192 LUA_RETURN(ps, LUA_FAIL);
193
194 localkickuser(lua_nick, cp, np, msg);
195
196 LUA_RETURN(ps, LUA_OK);
197 }
198
199 static int lua_invite(lua_State *ps) {
200 nick *np;
201 channel *cp;
202
203 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
204 LUA_RETURN(ps, LUA_FAIL);
205
206 np = getnickbynick((char *)lua_tostring(ps, 1));
207 if(!np)
208 LUA_RETURN(ps, LUA_FAIL);
209
210 cp = findchannel((char *)lua_tostring(ps, 2));
211 if(!cp)
212 LUA_RETURN(ps, LUA_FAIL);
213
214 localinvite(lua_nick, cp->index, np);
215
216 LUA_RETURN(ps, LUA_OK);
217 }
218
219 static int lua_gline(lua_State *ps) {
220 const char *reason;
221 nick *target;
222 char mask[512];
223 int duration, usercount = 0;
224 host *hp;
225
226 if(!lua_isstring(ps, 1) || !lua_isint(ps, 2) || !lua_isstring(ps, 3))
227 LUA_RETURN(ps, LUA_FAIL);
228
229 duration = lua_toint(ps, 2);
230 if((duration < 1) || (duration > 31 * 86400))
231 LUA_RETURN(ps, LUA_FAIL);
232
233 reason = lua_tostring(ps, 3);
234 if(!lua_lineok(reason) || !reason)
235 LUA_RETURN(ps, LUA_FAIL);
236
237 target = getnickbynick(lua_tostring(ps, 1));
238 if(!target || (IsOper(target) || IsXOper(target) || IsService(target)))
239 LUA_RETURN(ps, LUA_FAIL);
240
241 if(glinebynick(target, duration, reason, GLINE_SIMULATE) > 50)
242 LUA_RETURN(ps, LUA_FAIL);
243
244 usercount = glinebynick(target, duration, reason, 0);
245 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-GLINE: %s (%d users, %d seconds -- %s)", mask, usercount, duration, reason));
246 }
247
248 static int lua_fastgetchaninfo(lua_State *ps) {
249 static struct lua_pusher *ourpusher[MAX_PUSHER];
250 channel *cp;
251
252 if(!lua_isstring(ps, 1))
253 return 0;
254
255 cp = findchannel((char *)lua_tostring(ps, 1));
256 if(!cp || cp->index->channel != cp)
257 return 0;
258
259 lua_setupchanpusher(ps, 2, ourpusher, MAX_PUSHER);
260 return lua_usepusher(ps, ourpusher, cp->index);
261 }
262
263 static int lua_opchan(lua_State *ps) {
264 channel *cp;
265 nick *np;
266
267 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
268 LUA_RETURN(ps, LUA_FAIL);
269
270 cp = findchannel((char *)lua_tostring(ps, 1));
271 if(!cp)
272 LUA_RETURN(ps, LUA_FAIL);
273
274 np = getnickbynick((char *)lua_tostring(ps, 2));
275 if(!np)
276 LUA_RETURN(ps, LUA_FAIL);
277
278 localsetmodes(lua_nick, cp, np, MC_OP);
279 LUA_RETURN(ps, LUA_OK);
280 }
281
282 static int lua_deopchan(lua_State *ps) {
283 channel *cp;
284 nick *np;
285
286 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
287 LUA_RETURN(ps, LUA_FAIL);
288
289 cp = findchannel((char *)lua_tostring(ps, 1));
290 if(!cp)
291 LUA_RETURN(ps, LUA_FAIL);
292
293 np = getnickbynick((char *)lua_tostring(ps, 2));
294 if(!np)
295 LUA_RETURN(ps, LUA_FAIL);
296
297 localsetmodes(lua_nick, cp, np, MC_DEOP);
298 LUA_RETURN(ps, LUA_OK);
299 }
300
301 static int lua_voicechan(lua_State *ps) {
302 channel *cp;
303 nick *np;
304
305 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
306 LUA_RETURN(ps, LUA_FAIL);
307
308 cp = findchannel((char *)lua_tostring(ps, 1));
309 if(!cp)
310 LUA_RETURN(ps, LUA_FAIL);
311
312 np = getnickbynick((char *)lua_tostring(ps, 2));
313 if(!np)
314 LUA_RETURN(ps, LUA_FAIL);
315
316 localsetmodes(lua_nick, cp, np, MC_VOICE);
317 LUA_RETURN(ps, LUA_OK);
318 }
319
320 static int lua_counthost(lua_State *ps) {
321 long numeric;
322 nick *np;
323
324 if(!lua_islong(ps, 1))
325 return 0;
326
327 numeric = lua_tolong(ps, 1);
328
329 np = getnickbynumeric(numeric);
330 if(!np)
331 return 0;
332
333 lua_pushint(ps, np->host->clonecount);
334 return 1;
335 }
336
337 static int lua_versioninfo(lua_State *ps) {
338 lua_pushstring(ps, LUA_VERSION);
339 lua_pushstring(ps, LUA_BOTVERSION);
340 lua_pushstring(ps, __DATE__);
341 lua_pushstring(ps, __TIME__);
342
343 lua_pushstring(ps, LUA_AUXVERSION);
344
345 return 5;
346 }
347
348 static int lua_basepath(lua_State *ps) {
349 lua_pushfstring(ps, "%s/", cpath->content);
350
351 return 1;
352 }
353
354 static int lua_botnick(lua_State *ps) {
355 lua_pushstring(ps, luabotnick->content);
356
357 return 1;
358 }
359
360 static int lua_numerictobase64(lua_State *ps) {
361 if(!lua_islong(ps, 1))
362 return 0;
363
364 lua_pushstring(ps, longtonumeric(lua_tolong(ps, 1), 5));
365 return 1;
366 }
367
368 static int lua_getuserbyauth(lua_State *l) {
369 nick *np;
370 int found = 0;
371 authname *au;
372
373 if(!lua_isstring(l, 1))
374 return 0;
375
376 au = getauthbyname(lua_tostring(l, 1));
377 if(!au)
378 return 0;
379
380 for(np=au->nicks;np;np=np->nextbyauthname) {
381 lua_pushnumeric(l, np->numeric);
382 found++;
383 }
384
385 return found;
386 }
387
388 static int lua_getnickchans(lua_State *l) {
389 nick *np;
390 int i;
391 channel **channels;
392
393 if(!lua_islong(l, 1))
394 return 0;
395
396 np = getnickbynumeric(lua_tolong(l, 1));
397 if(!np)
398 return 0;
399
400 channels = (channel **)np->channels->content;
401 for(i=0;i<np->channels->cursi;i++)
402 lua_pushstring(l, channels[i]->index->name->content);
403
404 return np->channels->cursi;
405 }
406
407 static int lua_getnickchanindex(lua_State *l) {
408 nick *np;
409 int offset;
410
411 if(!lua_islong(l, 1) || !lua_isint(l, 2))
412 return 0;
413
414 np = getnickbynumeric(lua_tolong(l, 1));
415 if(!np)
416 return 0;
417
418 offset = lua_toint(l, 2);
419 if((offset < 0) || (offset >= np->channels->cursi))
420 return 0;
421
422 lua_pushstring(l, ((channel **)np->channels->content)[offset]->index->name->content);
423
424 return 1;
425 }
426
427 int hashindex;
428 nick *lasthashnick;
429 static int geoipext;
430
431 struct lua_pusher *nickhashpusher[MAX_PUSHER];
432
433 static int lua_getnextnick(lua_State *l) {
434 if(!lasthashnick && (hashindex != -1))
435 return 0;
436
437 do {
438 if(!lasthashnick) {
439 hashindex++;
440 if(hashindex >= NICKHASHSIZE)
441 return 0;
442 lasthashnick = nicktable[hashindex];
443 } else {
444 lasthashnick = lasthashnick->next;
445 }
446 } while(!lasthashnick);
447
448 return lua_usepusher(l, nickhashpusher, lasthashnick);
449 }
450
451 static int lua_getfirstnick(lua_State *l) {
452 hashindex = -1;
453 lasthashnick = NULL;
454
455 lua_setupnickpusher(l, 1, nickhashpusher, MAX_PUSHER);
456 geoipext = findnickext("geoip");
457
458 return lua_getnextnick(l);
459 }
460
461 int chanhashindex;
462 chanindex *lasthashchan;
463
464 struct lua_pusher *chanhashpusher[MAX_PUSHER];
465
466 static int lua_getnextchan(lua_State *l) {
467 if(!lasthashchan && (chanhashindex != -1))
468 return 0;
469
470 do {
471 if(!lasthashchan) {
472 chanhashindex++;
473 if(chanhashindex >= CHANNELHASHSIZE)
474 return 0;
475 lasthashchan = chantable[chanhashindex];
476 } else {
477 lasthashchan = lasthashchan->next;
478 }
479 } while(!lasthashchan || !lasthashchan->channel);
480
481 return lua_usepusher(l, chanhashpusher, lasthashchan);
482 }
483
484 static int lua_getfirstchan(lua_State *l) {
485 chanhashindex = -1;
486 lasthashchan = NULL;
487
488 lua_setupchanpusher(l, 1, chanhashpusher, MAX_PUSHER);
489
490 return lua_getnextchan(l);
491 }
492
493 static int lua_getnickchancount(lua_State *l) {
494 nick *np;
495
496 if(!lua_islong(l, 1))
497 return 0;
498
499 np = getnickbynumeric(lua_tolong(l, 1));
500 if(!np)
501 return 0;
502
503 lua_pushint(l, np->channels->cursi);
504
505 return 1;
506 }
507
508 static int lua_gethostusers(lua_State *l) {
509 nick *np;
510 int count;
511
512 if(!lua_islong(l, 1))
513 return 0;
514
515 np = getnickbynumeric(lua_tolong(l, 1));
516 if(!np || !np->host || !np->host->nicks)
517 return 0;
518
519 np = np->host->nicks;
520 count = np->host->clonecount;
521
522 do {
523 lua_pushnumeric(l, np->numeric);
524 np = np->nextbyhost;
525 } while(np);
526
527 return count;
528 }
529
530 static int lua_getnickcountry(lua_State *l) {
531 nick *np;
532 int ext;
533
534 ext = findnickext("geoip");
535 if(ext == -1)
536 return 0;
537
538 if(!lua_islong(l, 1))
539 return 0;
540
541 np = getnickbynumeric(lua_tolong(l, 1));
542 if(!np)
543 return 0;
544
545 lua_pushint(l, (long)np->exts[ext]);
546 return 1;
547 }
548
549 static int lua_chanfix(lua_State *ps) {
550 channel *cp;
551 nick *np;
552
553 if(!lua_isstring(ps, 1))
554 LUA_RETURN(ps, LUA_FAIL);
555
556 cp = findchannel((char *)lua_tostring(ps, 1));
557 if(!cp || !cp->index)
558 LUA_RETURN(ps, LUA_FAIL);
559
560 np = getnickbynick(LUA_CHANFIXBOT);
561 if(!np)
562 LUA_RETURN(ps, LUA_FAIL);
563
564 lua_message(np, "chanfix %s", cp->index->name->content);
565
566 LUA_RETURN(ps, LUA_OK);
567 }
568
569 static int lua_clearmode(lua_State *ps) {
570 channel *cp;
571 int i;
572 nick *np;
573 unsigned long *lp;
574 modechanges changes;
575
576 if(!lua_isstring(ps, 1))
577 LUA_RETURN(ps, LUA_FAIL);
578
579 cp = findchannel((char *)lua_tostring(ps, 1));
580 if(!cp || !cp->users)
581 LUA_RETURN(ps, LUA_FAIL);
582
583 localsetmodeinit(&changes, cp, lua_nick);
584
585 localdosetmode_key(&changes, NULL, MCB_DEL);
586 localdosetmode_simple(&changes, 0, CHANMODE_INVITEONLY | CHANMODE_LIMIT);
587
588 while(cp->bans)
589 localdosetmode_ban(&changes, bantostring(cp->bans), MCB_DEL);
590
591 for(i=0,lp=cp->users->content;i<cp->users->hashsize;i++,lp++)
592 if((*lp != nouser) && (*lp & CUMODE_OP)) {
593 np = getnickbynumeric(*lp);
594 if(np && !IsService(np))
595 localdosetmode_nick(&changes, np, MC_DEOP);
596 }
597
598 localsetmodeflush(&changes, 1);
599
600 LUA_RETURN(ps, LUA_OK);
601 }
602
603 static int lua_ban(lua_State *ps) {
604 channel *cp;
605 const char *mask;
606 modechanges changes;
607 int dir = MCB_ADD;
608
609 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
610 LUA_RETURN(ps, LUA_FAIL);
611
612 if(lua_isboolean(ps, 3) && lua_toboolean(ps, 3))
613 dir = MCB_DEL;
614
615 cp = findchannel((char *)lua_tostring(ps, 1));
616 if(!cp)
617 LUA_RETURN(ps, LUA_FAIL);
618
619 mask = lua_tostring(ps, 2);
620 if(!mask || !mask[0] || !lua_lineok(mask))
621 LUA_RETURN(ps, LUA_FAIL);
622
623 localsetmodeinit(&changes, cp, lua_nick);
624 localdosetmode_ban(&changes, mask, dir);
625 localsetmodeflush(&changes, 1);
626
627 LUA_RETURN(ps, LUA_OK);
628 }
629
630 static int lua_topic(lua_State *ps) {
631 channel *cp;
632 char *topic;
633
634 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
635 LUA_RETURN(ps, LUA_FAIL);
636
637 cp = findchannel((char *)lua_tostring(ps, 1));
638 if(!cp)
639 LUA_RETURN(ps, LUA_FAIL);
640
641 topic = (char *)lua_tostring(ps, 2);
642 if(!topic || !lua_lineok(topic))
643 LUA_RETURN(ps, LUA_FAIL);
644
645 localsettopic(lua_nick, cp, topic);
646
647 LUA_RETURN(ps, LUA_OK);
648 }
649
650 static int lua_getuserchanmodes(lua_State *l) {
651 nick *np;
652 channel *cp;
653 unsigned long *lp;
654
655 if(!lua_islong(l, 1) || !lua_isstring(l, 2))
656 return 0;
657
658 np = getnickbynumeric(lua_tolong(l, 1));
659 if(!np)
660 return 0;
661
662 cp = findchannel((char *)lua_tostring(l, 2));
663 if(!cp || !cp->users)
664 return 0;
665
666 lp = getnumerichandlefromchanhash(cp->users, np->numeric);
667 if(!lp)
668 return 0;
669
670 LUA_PUSHNICKCHANMODES(l, lp);
671 return 1;
672 }
673
674 static int lua_getusermodes(lua_State *l) {
675 nick *np;
676
677 if(!lua_islong(l, 1))
678 return 0;
679
680 np = getnickbynumeric(lua_tolong(l, 1));
681 if(!np)
682 return 0;
683
684 lua_pushstring(l, printflags(np->umodes, umodeflags));
685 return 1;
686 }
687
688 static int lua_fastgetnickbynumeric(lua_State *l) {
689 static struct lua_pusher *ourpusher[MAX_PUSHER];
690 nick *np;
691
692 if(!lua_islong(l, 1))
693 return 0;
694
695 np = getnickbynumeric(lua_tolong(l, 1));
696 if(!np)
697 return 0;
698
699 lua_setupnickpusher(l, 2, ourpusher, MAX_PUSHER);
700 return lua_usepusher(l, ourpusher, np);
701 }
702
703 static int lua_fastgetnickbynick(lua_State *l) {
704 static struct lua_pusher *ourpusher[MAX_PUSHER];
705 nick *np;
706
707 if(!lua_isstring(l, 1))
708 return 0;
709
710 np = getnickbynick((char *)lua_tostring(l, 1));
711 if(!np)
712 return 0;
713
714 lua_setupnickpusher(l, 2, ourpusher, MAX_PUSHER);
715 return lua_usepusher(l, ourpusher, np);
716 }
717
718 int channelnicklistindex, channelnicklistcount = -1;
719 channel *channelnicklist;
720
721 struct lua_pusher *channelnickpusher[MAX_PUSHER];
722
723 static int lua_getnextchannick(lua_State *l) {
724 nick *np;
725
726 do {
727 channelnicklistindex++;
728
729 if(channelnicklistindex >= channelnicklistcount)
730 return 0;
731 } while((channelnicklist->users->content[channelnicklistindex] == nouser) || !(np = getnickbynumeric(channelnicklist->users->content[channelnicklistindex])));
732
733 return lua_usepusher(l, channelnickpusher, np);
734 }
735
736 static int lua_getfirstchannick(lua_State *l) {
737 if(!lua_isstring(l, 1))
738 return 0;
739
740 channelnicklist = findchannel((char *)lua_tostring(l, 1));
741 if(!channelnicklist|| !channelnicklist->users)
742 return 0;
743
744 channelnicklistindex = -1;
745 channelnicklistcount = channelnicklist->users->hashsize;
746
747 lua_setupnickpusher(l, 2, channelnickpusher, MAX_PUSHER);
748
749 return lua_getnextchannick(l);
750 }
751
752 static int lua_nickonchan(lua_State *l) {
753 int success = 0;
754 if(lua_islong(l, 1) && lua_isstring(l, 2)) {
755 channel *cp = findchannel((char *)lua_tostring(l, 2));
756 if(cp && cp->users) {
757 unsigned long *lp = getnumerichandlefromchanhash(cp->users, lua_tolong(l, 1));
758 if(lp)
759 success = 1;
760 }
761 }
762
763 lua_pushboolean(l, success);
764 return 1;
765 }
766
767 static int lua_simplechanmode(lua_State *ps) {
768 channel *cp;
769 char *modes;
770 flag_t add = 0, del = ~add;
771 flag_t permitted = CHANMODE_NOEXTMSG | CHANMODE_TOPICLIMIT | CHANMODE_SECRET | CHANMODE_PRIVATE | CHANMODE_INVITEONLY | CHANMODE_MODERATE | CHANMODE_NOCOLOUR | CHANMODE_NOCTCP | CHANMODE_REGONLY | CHANMODE_DELJOINS | CHANMODE_NOQUITMSG | CHANMODE_NONOTICE | CHANMODE_MODNOAUTH | CHANMODE_SINGLETARG;
772 modechanges changes;
773
774 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
775 LUA_RETURN(ps, LUA_FAIL);
776
777 cp = findchannel((char *)lua_tostring(ps, 1));
778 if(!cp)
779 LUA_RETURN(ps, LUA_FAIL);
780
781 modes = (char *)lua_tostring(ps, 2);
782 if(!modes)
783 LUA_RETURN(ps, LUA_FAIL);
784
785 if(setflags(&add, permitted, modes, cmodeflags, REJECT_DISALLOWED|REJECT_UNKNOWN) != REJECT_NONE)
786 LUA_RETURN(ps, LUA_FAIL);
787
788 if(setflags(&del, permitted, modes, cmodeflags, REJECT_DISALLOWED|REJECT_UNKNOWN) != REJECT_NONE)
789 LUA_RETURN(ps, LUA_FAIL);
790
791 localsetmodeinit(&changes, cp, lua_nick);
792 localdosetmode_simple(&changes, add, ~del);
793 localsetmodeflush(&changes, 1);
794
795 LUA_RETURN(ps, LUA_OK);
796 }
797
798 static int lua_sethost(lua_State *ps) {
799 char *ident, *host;
800 nick *np;
801
802 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3))
803 LUA_RETURN(ps, LUA_FAIL);
804
805 np = getnickbynumeric(lua_tolong(ps, 1));
806 if(!np)
807 LUA_RETURN(ps, LUA_FAIL);
808
809 ident = (char *)lua_tostring(ps, 2);
810 host = (char *)lua_tostring(ps, 3);
811 if(!lua_lineok(ident) || !lua_lineok(host))
812 LUA_RETURN(ps, LUA_FAIL);
813
814 sethostuser(np, ident, host);
815
816 LUA_RETURN(ps, LUA_OK);
817 }
818
819 static int lua_getvisiblehostmask(lua_State *l) {
820 nick *np;
821 char buf[HOSTLEN+USERLEN+NICKLEN+REALLEN+10];
822
823 if(!lua_islong(l, 1))
824 return 0;
825
826 np = getnickbynumeric(lua_tolong(l, 1));
827 if(!np)
828 return 0;
829
830 lua_pushstring(l, visiblehostmask(np, buf));
831 return 1;
832 }
833
834 void lua_registercommands(lua_State *l) {
835 lua_register(l, "irc_smsg", lua_smsg);
836 lua_register(l, "irc_skill", lua_skill);
837
838 lua_register(l, "chanmsg", lua_chanmsg);
839 lua_register(l, "versioninfo", lua_versioninfo);
840 lua_register(l, "basepath", lua_basepath);
841 lua_register(l, "botnick", lua_botnick);
842
843 lua_register(l, "irc_report", lua_chanmsg);
844 lua_register(l, "irc_ctcp", lua_ctcp);
845 lua_register(l, "irc_kill", lua_kill);
846 lua_register(l, "irc_kick", lua_kick);
847 lua_register(l, "irc_invite", lua_invite);
848 lua_register(l, "irc_gline", lua_gline);
849 lua_register(l, "irc_counthost", lua_counthost);
850 lua_register(l, "irc_getuserbyauth", lua_getuserbyauth);
851 lua_register(l, "irc_notice", lua_noticecmd);
852 lua_register(l, "irc_privmsg", lua_privmsgcmd);
853 lua_register(l, "irc_opchan", lua_opchan);
854 lua_register(l, "irc_voicechan", lua_voicechan);
855 lua_register(l, "irc_chanfix", lua_chanfix);
856 lua_register(l, "irc_clearmode", lua_clearmode);
857 lua_register(l, "irc_ban", lua_ban);
858 lua_register(l, "irc_deopchan", lua_deopchan);
859 lua_register(l, "irc_topic", lua_topic);
860
861 lua_register(l, "irc_getfirstnick", lua_getfirstnick);
862 lua_register(l, "irc_getnextnick", lua_getnextnick);
863
864 lua_register(l, "irc_getnickchans", lua_getnickchans);
865 lua_register(l, "irc_getnickchanindex", lua_getnickchanindex);
866 lua_register(l, "irc_getnickchancount", lua_getnickchancount);
867
868 lua_register(l, "irc_getuserchanmodes", lua_getuserchanmodes);
869
870 lua_register(l, "irc_getfirstchannick", lua_getfirstchannick);
871 lua_register(l, "irc_getnextchannick", lua_getnextchannick);
872
873 lua_register(l, "irc_gethostusers", lua_gethostusers);
874 lua_register(l, "irc_getnickcountry", lua_getnickcountry);
875
876 lua_register(l, "irc_getfirstchan", lua_getfirstchan);
877 lua_register(l, "irc_getnextchan", lua_getnextchan);
878 lua_register(l, "irc_getusermodes", lua_getusermodes);
879 lua_register(l, "irc_nickonchan", lua_nickonchan);
880
881 lua_register(l, "irc_fastgetnickbynumeric", lua_fastgetnickbynumeric);
882 lua_register(l, "irc_fastgetnickbynick", lua_fastgetnickbynick);
883 lua_register(l, "irc_fastgetchaninfo", lua_fastgetchaninfo);
884
885 lua_register(l, "irc_getvisiblehostmask", lua_getvisiblehostmask);
886
887 lua_register(l, "irc_simplechanmode", lua_simplechanmode);
888 lua_register(l, "irc_sethost", lua_sethost);
889
890 lua_register(l, "irc_numerictobase64", lua_numerictobase64);
891 }
892
893 /* --- */
894
895 static int lua_smsg(lua_State *ps) {
896 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
897 LUA_RETURN(ps, LUA_FAIL);
898
899 LUA_RETURN(ps, lua_cmsg((char *)lua_tostring(ps, 2), "%s", lua_tostring(ps, 1)));
900 }
901
902 static int lua_skill(lua_State *ps) {
903 const char *n, *msg;
904 nick *np;
905
906 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
907 LUA_RETURN(ps, LUA_FAIL);
908
909 n = lua_tostring(ps, 1);
910 msg = lua_tostring(ps, 2);
911
912 np = getnickbynick(n);
913 if(!np)
914 LUA_RETURN(ps, LUA_FAIL);
915
916 if(IsOper(np) || IsService(np) || IsXOper(np))
917 LUA_RETURN(ps, LUA_FAIL);
918
919 if(!lua_lineok(msg))
920 LUA_RETURN(ps, LUA_FAIL);
921
922 killuser(lua_nick, np, "%s", msg);
923
924 LUA_RETURN(ps, LUA_OK);
925 }
926
927 #define PUSHER_STRING 1
928 #define PUSHER_REALNAME 2
929 #define PUSHER_IP 3
930 #define PUSHER_LONG 4
931 #define PUSHER_HOSTNAME 5
932 #define PUSHER_SSTRING 6
933 #define PUSHER_TOTALUSERS 7
934 #define PUSHER_TOPIC 8
935 #define PUSHER_UMODES 9
936 #define PUSHER_COUNTRY 10
937 #define PUSHER_REALUSERS 11
938 #define PUSHER_CHANMODES 12
939 #define PUSHER_TIMESTAMP 13
940 #define PUSHER_STRING_INDIRECT 14
941 #define PUSHER_ACC_ID 15
942 #define PUSHER_SERVER_NAME 16
943 #define PUSHER_SERVER_NUMERIC 17
944
945 void lua_initnickpusher(void) {
946 int i = 0;
947
948 #define PUSH_NICKPUSHER(F2, O2) nickpusher[i].argtype = F2; nickpusher[i].structname = #O2; nickpusher[i].offset = offsetof(nick, O2); i++;
949 #define PUSH_NICKPUSHER_CUSTOM(F2, custom) nickpusher[i].argtype = F2; nickpusher[i].structname = custom; nickpusher[i].offset = 0; i++;
950
951 PUSH_NICKPUSHER(PUSHER_STRING, nick);
952 PUSH_NICKPUSHER(PUSHER_STRING, ident);
953 PUSH_NICKPUSHER(PUSHER_HOSTNAME, host);
954 PUSH_NICKPUSHER(PUSHER_REALNAME, realname);
955 PUSH_NICKPUSHER(PUSHER_STRING_INDIRECT, authname);
956 PUSH_NICKPUSHER(PUSHER_IP, ipnode);
957 PUSH_NICKPUSHER(PUSHER_LONG, numeric);
958 PUSH_NICKPUSHER(PUSHER_LONG, timestamp);
959 PUSH_NICKPUSHER(PUSHER_LONG, accountts);
960 PUSH_NICKPUSHER(PUSHER_UMODES, umodes);
961 PUSH_NICKPUSHER_CUSTOM(PUSHER_COUNTRY, "country");
962 PUSH_NICKPUSHER_CUSTOM(PUSHER_ACC_ID, "accountid");
963 PUSH_NICKPUSHER_CUSTOM(PUSHER_SERVER_NAME, "servername");
964 PUSH_NICKPUSHER_CUSTOM(PUSHER_SERVER_NUMERIC, "servernumeric");
965
966 nickpushercount = i;
967 nickpusher[i].argtype = 0;
968 }
969
970 void lua_setuppusher(struct lua_pusher *pusherlist, lua_State *l, int index, struct lua_pusher **lp, int max, int pcount) {
971 int current = 0;
972
973 if(max > 0)
974 lp[0] = NULL;
975
976 if(!lua_istable(l, index) || (max < 2))
977 return;
978
979 lua_pushnil(l);
980
981 max--;
982
983 while(lua_next(l, index)) {
984 if(lua_isint(l, -1)) {
985 int index = lua_toint(l, -1);
986 if((index >= 0) && (index < pcount))
987 lp[current++] = &pusherlist[index];
988 }
989
990 lua_pop(l, 1);
991
992 if(current == max)
993 break;
994 }
995
996 lp[current] = NULL;
997 }
998
999 int lua_usepusher(lua_State *l, struct lua_pusher **lp, void *np) {
1000 int i = 0;
1001
1002 while(*lp) {
1003 void *offset = (void *)np + (*lp)->offset;
1004
1005 switch((*lp)->argtype) {
1006 case PUSHER_STRING:
1007 lua_pushstring(l, (char *)offset);
1008 break;
1009 case PUSHER_STRING_INDIRECT:
1010 lua_pushstring(l, *(char **)offset);
1011 break;
1012 case PUSHER_HOSTNAME:
1013 lua_pushstring(l, (*(host **)offset)->name->content);
1014 break;
1015 case PUSHER_REALNAME:
1016 lua_pushstring(l, (*(realname **)offset)->name->content);
1017 break;
1018 case PUSHER_SSTRING:
1019 lua_pushstring(l, (*((sstring **)offset))->content);
1020 break;
1021 case PUSHER_LONG:
1022 lua_pushlong(l, *((long *)offset));
1023 break;
1024 case PUSHER_TIMESTAMP:
1025 lua_pushlong(l, (*((channel **)offset))->timestamp);
1026 break;
1027 case PUSHER_IP:
1028 lua_pushstring(l, IPtostr((*((patricia_node_t **)offset))->prefix->sin));
1029 break;
1030 case PUSHER_TOTALUSERS:
1031 lua_pushint(l, (*((channel **)offset))->users->totalusers);
1032 break;
1033 case PUSHER_CHANMODES:
1034 lua_pushstring(l, printallmodes(*((channel **)offset)));
1035 break;
1036 case PUSHER_ACC_ID:
1037 {
1038 nick *tnp = (nick *)np;
1039 if(IsAccount(tnp) && tnp->auth) {
1040 lua_pushlong(l, tnp->auth->userid);
1041 } else {
1042 lua_pushnil(l);
1043 }
1044 break;
1045 }
1046 case PUSHER_REALUSERS:
1047 {
1048 channel *cp = *((channel **)offset);
1049 nick *np2;
1050 int i, currentusers = countuniquehosts(cp);
1051 for(i=0;i<cp->users->hashsize;i++) {
1052 if(cp->users->content[i]==nouser)
1053 continue;
1054
1055 if((np2=getnickbynumeric(cp->users->content[i]))==NULL) {
1056 Error("lua", ERR_ERROR, "Found unknown numeric %lu on channel %s", cp->users->content[i], cp->index->name->content);
1057 continue;
1058 }
1059
1060 if (IsXOper(np2) || IsService(np2))
1061 currentusers--;
1062 }
1063 lua_pushint(l, currentusers);
1064 }
1065 break;
1066 case PUSHER_UMODES:
1067 lua_pushstring(l, printflags(*((flag_t *)offset), umodeflags));
1068 break;
1069 case PUSHER_TOPIC:
1070 if((*((channel **)offset))->topic) {
1071 lua_pushstring(l, (*((channel **)offset))->topic->content);
1072 } else {
1073 lua_pushnil(l);
1074 }
1075 break;
1076 case PUSHER_COUNTRY:
1077 if(geoipext < 0) {
1078 lua_pushint(l, -1);
1079 } else {
1080 lua_pushint(l, (long)((nick *)offset)->exts[geoipext]);
1081 }
1082 break;
1083 case PUSHER_SERVER_NAME:
1084 lua_pushstring(l, serverlist[homeserver(((nick *)offset)->numeric)].name->content);
1085 break;
1086 case PUSHER_SERVER_NUMERIC:
1087 lua_pushint(l, homeserver(((nick *)offset)->numeric));
1088 break;
1089 }
1090
1091 i++;
1092 lp++;
1093 }
1094
1095 return i;
1096 }
1097
1098 void lua_initchanpusher(void) {
1099 int i = 0;
1100
1101 #define PUSH_CHANPUSHER(F2, O2, N2) chanpusher[i].argtype = F2; chanpusher[i].structname = N2; chanpusher[i].offset = offsetof(chanindex, O2); i++;
1102
1103 PUSH_CHANPUSHER(PUSHER_SSTRING, name, "name");
1104 PUSH_CHANPUSHER(PUSHER_TOTALUSERS, channel, "totalusers");
1105 PUSH_CHANPUSHER(PUSHER_TOPIC, channel, "topic");
1106 PUSH_CHANPUSHER(PUSHER_REALUSERS, channel, "realusers");
1107 PUSH_CHANPUSHER(PUSHER_TIMESTAMP, channel, "timestamp");
1108 PUSH_CHANPUSHER(PUSHER_CHANMODES, channel, "modes");
1109
1110 chanpushercount = i;
1111 chanpusher[i].argtype = 0;
1112 }
1113