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