]> jfr.im git - irc/quakenet/newserv.git/blob - lua/lualocal.c
HELPMOD2: make anti-idle kick message more informative
[irc/quakenet/newserv.git] / lua / lualocal.c
1 #include <stdlib.h>
2
3 #include "../localuser/localuser.h"
4 #include "../lib/strlfunc.h"
5 #include "../core/schedule.h"
6 #include "../channel/channel.h"
7 #include "../localuser/localuserchannel.h"
8
9 #include "lua.h"
10 #include "luabot.h"
11 #include "lualocal.h"
12
13 void lua_localnickhandler(nick *target, int type, void **args);
14 void lua_reconnectlocal(void *arg);
15
16 static int lua_registerlocaluserid(lua_State *ps) {
17 lua_list *l;
18 lua_localnick *ln;
19 char *nickname, *ident, *hostname, *realname, *account;
20 flag_t modes = 0;
21 long userid;
22
23 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3) || !lua_isstring(ps, 4) || !lua_isstring(ps, 5) || !lua_isstring(ps, 7) || !lua_isfunction(ps, 8))
24 return 0;
25
26 nickname = (char *)lua_tostring(ps, 1);
27 ident = (char *)lua_tostring(ps, 2);
28 hostname = (char *)lua_tostring(ps, 3);
29 realname = (char *)lua_tostring(ps, 4);
30 account = (char *)lua_tostring(ps, 5);
31 if(lua_islong(ps, 6)) {
32 userid = lua_tolong(ps, 6);
33 } else {
34 userid = 0;
35 }
36
37 setflags(&modes, UMODE_ALL, (char *)lua_tostring(ps, 7), umodeflags, REJECT_NONE);
38
39 if(!lua_lineok(nickname) || !lua_lineok(ident) || !lua_lineok(hostname) || !lua_lineok(realname) || !lua_lineok(account))
40 return 0;
41
42 l = lua_listfromstate(ps);
43 if(!l)
44 return 0;
45
46 ln = (lua_localnick *)luamalloc(sizeof(lua_localnick));
47 if(!ln)
48 return 0;
49
50 ln->reconnect = NULL;
51
52 ln->nick = registerlocaluserflags(nickname, ident, hostname, realname, account, userid, 0, modes, &lua_localnickhandler);
53 if(!ln->nick) {
54 luafree(ln);
55 return 0;
56 }
57
58 ln->handler = luaL_ref(ps, LUA_REGISTRYINDEX);
59
60 ln->next = l->nicks;
61 l->nicks = ln;
62
63 lua_pushlong(ps, ln->nick->numeric);
64 return 1;
65 }
66
67 void lua_freelocalnick(lua_State *ps, lua_localnick *l, char *quitm) {
68 if(l->nick)
69 deregisterlocaluser(l->nick, quitm);
70
71 if(l->reconnect)
72 deleteschedule(l->reconnect, &lua_reconnectlocal, l);
73
74 luaL_unref(ps, LUA_REGISTRYINDEX, l->handler);
75
76 luafree(l);
77 }
78
79 int lua_getlocalnickbynick(nick *np, lua_list **rl, lua_localnick **rln) {
80 lua_list *l;
81 lua_localnick *ln;
82
83 for(l=lua_head;l;l=l->next)
84 for(ln=l->nicks;ln;ln=ln->next)
85 if(ln->nick == np) {
86 *rl = l;
87 *rln = ln;
88 return 1;
89 }
90
91 return 0;
92 }
93
94 static int lua_deregisterlocaluser(lua_State *ps) {
95 lua_list *l;
96 lua_localnick *l2, *lp = NULL;
97 long numeric;
98 char *quitm;
99
100 if(!lua_islong(ps, 1))
101 LUA_RETURN(ps, LUA_FAIL);
102
103 numeric = lua_tolong(ps, 1);
104
105 quitm = lua_isstring(ps, 2)?(char *)lua_tostring(ps, 2):"localuser unregistered.";
106
107 l = lua_listfromstate(ps);
108
109 for(l2=l->nicks;l2;lp=l2,l2=l2->next) {
110 if(l2->nick && l2->nick->numeric == numeric) {
111 if(lp) {
112 lp->next = l2->next;
113 } else {
114 l->nicks = l2->next;
115 }
116
117 lua_freelocalnick(ps, l2, quitm);
118 LUA_RETURN(ps, LUA_OK);
119 }
120 }
121
122 LUA_RETURN(ps, LUA_FAIL);
123 }
124
125 void lua_deregisternicks(lua_list *l) {
126 struct lua_localnick *ln, *pn;
127
128 ln = l->nicks;
129 l->nicks = NULL;
130 for(;ln;ln=pn) {
131 pn = ln->next;
132
133 lua_freelocalnick(l->l, ln, "Script unloaded.");
134 }
135
136 l->nicks = NULL;
137 }
138
139 /* todo */
140 void lua_localnickhandler(nick *target, int type, void **args) {
141 nick *np;
142 char *p;
143 lua_localnick *ln;
144 lua_list *l;
145 channel *c;
146
147 if(!lua_getlocalnickbynick(target, &l, &ln))
148 return;
149
150 switch(type) {
151 case LU_PRIVMSG:
152 np = (nick *)args[0];
153 p = (char *)args[1];
154
155 if(!np || !p)
156 return;
157
158 lua_vlpcall(l, ln, "irc_onmsg", "Ns", np, p);
159
160 break;
161
162 case LU_CHANMSG:
163 np = (nick *)args[0];
164 c = (channel *)args[1];
165 p = (char *)args[2];
166
167 if(!np || !p || !c || !c->index || !c->index->name || !c->index->name->content)
168 return;
169
170 lua_vlpcall(l, ln, "irc_onchanmsg", "Nss", np, c->index->name->content, p);
171 break;
172
173 case LU_KILLED:
174 p = (char *)args[2];
175 lua_vlpcall(l, ln, "irc_onkilled", "s", p);
176
177 strlcpy(ln->nickname, target->nick, sizeof(ln->nickname));
178 strlcpy(ln->ident, target->ident, sizeof(ln->ident));
179 strlcpy(ln->hostname, target->host->name->content, sizeof(ln->hostname));
180 strlcpy(ln->realname, target->realname->name->content, sizeof(ln->realname));
181 strlcpy(ln->account, target->authname, sizeof(ln->account));
182
183 ln->umodes = target->umodes;
184 ln->nick = NULL;
185
186 ln->reconnect = scheduleoneshot(time(NULL) + 1, &lua_reconnectlocal, ln);
187
188 break;
189 case LU_INVITE:
190 /* we were invited, check if someone invited us to PUBLICCHAN */
191 np = (nick *)args[0];
192 c = (channel *)args[1];
193
194 if(!c || !np || !c->index || !c->index->name || !c->index->name->content)
195 return;
196
197 lua_vlpcall(l, ln, "irc_oninvite", "Ns", np, c->index->name->content);
198 break;
199 }
200 }
201
202 void lua_reconnectlocal(void *arg) {
203 lua_list *l;
204 lua_localnick *ln = (lua_localnick *)arg;
205
206 ln->nick = registerlocaluser(ln->nickname, ln->ident, ln->hostname, ln->realname, ln->account, ln->umodes, &lua_localnickhandler);
207 if(!ln->nick) {
208 ln->reconnect = scheduleoneshot(time(NULL) + 1, &lua_reconnectlocal, ln);
209 return;
210 }
211
212 ln->reconnect = NULL;
213
214 if(lua_getlocalnickbynick(ln->nick, &l, &ln)) /* hacky! */
215 lua_vlpcall(l, ln, "irc_onkillreconnect", "");
216 }
217
218 static int lua_localjoin(lua_State *ps) {
219 nick *source;
220 channel *target;
221 char *chan;
222
223 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2))
224 LUA_RETURN(ps, LUA_FAIL);
225
226 source = getnickbynumeric(lua_tolong(ps, 1));
227 if(!source)
228 LUA_RETURN(ps, LUA_FAIL);
229
230 chan = (char *)lua_tostring(ps, 2);
231 if(chan[0] != '#')
232 LUA_RETURN(ps, LUA_FAIL);
233
234 if(!lua_lineok(chan))
235 LUA_RETURN(ps, LUA_FAIL);
236
237 target = findchannel(chan);
238 if(target) {
239 localjoinchannel(source, target);
240 } else {
241 localcreatechannel(source, chan);
242 }
243
244 LUA_RETURN(ps, LUA_OK);
245 }
246
247 static int lua_localpart(lua_State *ps) {
248 nick *source;
249 channel *target;
250 char *chan, *reason;
251
252 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2))
253 LUA_RETURN(ps, LUA_FAIL);
254
255 source = getnickbynumeric(lua_tolong(ps, 1));
256 if(!source)
257 LUA_RETURN(ps, LUA_FAIL);
258
259 chan = (char *)lua_tostring(ps, 2);
260
261 if(!lua_lineok(chan))
262 LUA_RETURN(ps, LUA_FAIL);
263
264 if(lua_isstring(ps, 3)) {
265 reason = (char *)lua_tostring(ps, 3);
266 if(!lua_lineok(reason))
267 LUA_RETURN(ps, LUA_FAIL);
268 } else {
269 reason = NULL;
270 }
271
272 target = findchannel(chan);
273 if(target) {
274 localpartchannel(source, target, reason);
275 } else {
276 LUA_RETURN(ps, LUA_FAIL);
277 }
278
279 LUA_RETURN(ps, LUA_OK);
280 }
281
282 static int lua_localchanmsg(lua_State *ps) {
283 char *msg;
284 nick *source;
285 channel *target;
286
287 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3))
288 LUA_RETURN(ps, LUA_FAIL);
289
290 source = getnickbynumeric(lua_tolong(ps, 1));
291 if(!source)
292 LUA_RETURN(ps, LUA_FAIL);
293
294 target = findchannel((char *)lua_tostring(ps, 2));
295 if(!target)
296 LUA_RETURN(ps, LUA_FAIL);
297
298 msg = (char *)lua_tostring(ps, 3);
299
300 if(!lua_lineok(msg))
301 LUA_RETURN(ps, LUA_FAIL);
302
303 sendmessagetochannel(source, target, "%s", msg);
304
305 LUA_RETURN(ps, LUA_OK);
306 }
307
308 static int lua_localnotice(lua_State *ps) {
309 char *msg;
310 nick *source;
311 nick *target;
312
313 if(!lua_islong(ps, 1) || !lua_islong(ps, 2) || !lua_isstring(ps, 3))
314 LUA_RETURN(ps, LUA_FAIL);
315
316 source = getnickbynumeric(lua_tolong(ps, 1));
317 if(!source)
318 LUA_RETURN(ps, LUA_FAIL);
319
320 target = getnickbynumeric(lua_tolong(ps, 2));
321 if(!target)
322 LUA_RETURN(ps, LUA_FAIL);
323
324 msg = (char *)lua_tostring(ps, 3);
325
326 if(!lua_lineok(msg))
327 LUA_RETURN(ps, LUA_FAIL);
328
329 sendnoticetouser(source, target, "%s", msg);
330
331 LUA_RETURN(ps, LUA_OK);
332 }
333
334 static int lua_localprivmsg(lua_State *ps) {
335 char *msg;
336 nick *source;
337 nick *target;
338
339 if(!lua_islong(ps, 1) || !lua_islong(ps, 2) || !lua_isstring(ps, 3))
340 LUA_RETURN(ps, LUA_FAIL);
341
342 source = getnickbynumeric(lua_tolong(ps, 1));
343 if(!source)
344 LUA_RETURN(ps, LUA_FAIL);
345
346 target = getnickbynumeric(lua_tolong(ps, 2));
347 if(!target)
348 LUA_RETURN(ps, LUA_FAIL);
349
350 msg = (char *)lua_tostring(ps, 3);
351
352 if(!lua_lineok(msg))
353 LUA_RETURN(ps, LUA_FAIL);
354
355 sendmessagetouser(source, target, "%s", msg);
356
357 LUA_RETURN(ps, LUA_OK);
358 }
359
360 static int lua_localovmode(lua_State *l) {
361 nick *source;
362 channel *chan;
363 int state = 0, add = 0, realmode = 0, ignoring = 0;
364 modechanges changes;
365
366 if(!lua_islong(l, 1) || !lua_isstring(l, 2) || !lua_istable(l, 3))
367 LUA_RETURN(l, LUA_FAIL);
368
369 source = getnickbynumeric(lua_tolong(l, 1));
370 if(!source)
371 LUA_RETURN(l, LUA_FAIL);
372
373 chan = findchannel((char *)lua_tostring(l, 2));
374 if(!chan)
375 LUA_RETURN(l, LUA_FAIL);
376
377 localsetmodeinit(&changes, chan, source);
378
379 lua_pushnil(l);
380
381 while(lua_next(l, 3)) {
382 if(state == 0) {
383 ignoring = 0;
384
385 if(!lua_isboolean(l, -1)) {
386 ignoring = 1;
387 } else {
388 add = (int)lua_toboolean(l, -1);
389 }
390 } else if((state == 1) && !ignoring) {
391 if(!lua_isstring(l, -1)) {
392 ignoring = 1;
393 } else {
394 char *mode = (char *)lua_tostring(l, -1);
395 if((*mode == 'o') && add) {
396 realmode = MC_OP;
397 } else if (*mode == 'o') {
398 realmode = MC_DEOP;
399 } else if((*mode == 'v') && add) {
400 realmode = MC_VOICE;
401 } else if (*mode == 'v') {
402 realmode = MC_DEVOICE;
403 } else {
404 ignoring = 1;
405 }
406 }
407 } else if((state == 2) && !ignoring) {
408 if(lua_islong(l, -1)) {
409 nick *target = getnickbynumeric(lua_tolong(l, -1));
410 if(target)
411 localdosetmode_nick(&changes, target, realmode);
412 }
413 }
414
415 lua_pop(l, 1);
416
417 state = (state + 1) % 3;
418 }
419
420 localsetmodeflush(&changes, 1);
421
422 LUA_RETURN(l, LUA_OK);
423 }
424
425 static int lua_localumodes(lua_State *ps) {
426 nick *np;
427 char *modes;
428 flag_t newmodes = 0;
429
430 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2))
431 LUA_RETURN(ps, LUA_FAIL);
432
433 np = getnickbynumeric(lua_tolong(ps, 1));
434 if(!np)
435 LUA_RETURN(ps, LUA_FAIL);
436
437 modes = (char *)lua_tostring(ps, 2);
438
439 setflags(&newmodes, UMODE_ALL, modes, umodeflags, REJECT_NONE);
440
441 localusersetumodes(np, newmodes);
442 LUA_RETURN(ps, LUA_OK);
443 }
444
445 static int lua_localtopic(lua_State *ps) {
446 nick *np;
447 channel *cp;
448 char *topic;
449
450 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3))
451 LUA_RETURN(ps, LUA_FAIL);
452
453 np = getnickbynumeric(lua_tolong(ps, 1));
454 if(!np)
455 LUA_RETURN(ps, LUA_FAIL);
456
457 cp = findchannel((char *)lua_tostring(ps, 2));
458 if(!cp)
459 LUA_RETURN(ps, LUA_FAIL);
460
461 topic = (char *)lua_tostring(ps, 3);
462 if(!topic || !lua_lineok(topic))
463 LUA_RETURN(ps, LUA_FAIL);
464
465 localsettopic(np, cp, topic);
466
467 LUA_RETURN(ps, LUA_OK);
468 }
469
470 static int lua_localban(lua_State *ps) {
471 channel *cp;
472 const char *mask;
473 modechanges changes;
474 nick *source;
475
476 int dir = MCB_ADD;
477
478 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3))
479 LUA_RETURN(ps, LUA_FAIL);
480
481 if(lua_isboolean(ps, 4) && lua_toboolean(ps, 4))
482 dir = MCB_DEL;
483
484 source = getnickbynumeric(lua_tolong(ps, 1));
485
486 cp = findchannel((char *)lua_tostring(ps, 2));
487 if(!cp)
488 LUA_RETURN(ps, LUA_FAIL);
489
490 mask = lua_tostring(ps, 3);
491 if(!mask || !mask[0] || !lua_lineok(mask))
492 LUA_RETURN(ps, LUA_FAIL);
493
494 localsetmodeinit(&changes, cp, source);
495 localdosetmode_ban(&changes, mask, dir);
496 localsetmodeflush(&changes, 1);
497
498 LUA_RETURN(ps, LUA_OK);
499 }
500
501 static int lua_localkick(lua_State *ps) {
502 const char *n, *msg, *chan;
503 nick *source, *np;
504 channel *cp;
505 int dochecks = 1;
506
507 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3) || !lua_isstring(ps, 4))
508 LUA_RETURN(ps, LUA_FAIL);
509
510 source = getnickbynumeric(lua_tolong(ps, 1));
511 chan = lua_tostring(ps, 2);
512 n = lua_tostring(ps, 3);
513 msg = lua_tostring(ps, 4);
514 if(!source)
515 LUA_RETURN(ps, LUA_FAIL);
516
517 if(lua_isboolean(ps, 4) && !lua_toboolean(ps, 4))
518 dochecks = 0;
519
520 np = getnickbynick(n);
521 if(!np)
522 LUA_RETURN(ps, LUA_FAIL);
523
524 if(dochecks && (IsOper(np) || IsXOper(np) || IsService(np)))
525 LUA_RETURN(ps, LUA_FAIL);
526
527 cp = findchannel((char *)chan);
528 if(!cp)
529 LUA_RETURN(ps, LUA_FAIL);
530
531 if(!lua_lineok(msg))
532 LUA_RETURN(ps, LUA_FAIL);
533
534 localkickuser(source, cp, np, msg);
535
536 LUA_RETURN(ps, LUA_OK);
537 }
538
539 static int lua_localrename(lua_State *ps) {
540 nick *np;
541 char *changeto;
542
543 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) )
544 LUA_RETURN(ps, LUA_FAIL);
545
546 np = getnickbynumeric(lua_tolong(ps, 1));
547 changeto = (char *)lua_tostring(ps, 2);
548
549 if(!lua_lineok(changeto))
550 LUA_RETURN(ps, LUA_FAIL);
551
552 renamelocaluser(np, changeto);
553
554 LUA_RETURN(ps, LUA_OK);
555 }
556
557 void lua_registerlocalcommands(lua_State *l) {
558 lua_register(l, "irc_localregisteruserid", lua_registerlocaluserid);
559 lua_register(l, "irc_localderegisteruser", lua_deregisterlocaluser);
560 lua_register(l, "irc_localjoin", lua_localjoin);
561 lua_register(l, "irc_localpart", lua_localpart);
562 lua_register(l, "irc_localchanmsg", lua_localchanmsg);
563 lua_register(l, "irc_localnotice", lua_localnotice);
564 lua_register(l, "irc_localprivmsg", lua_localprivmsg);
565
566 lua_register(l, "irc_localovmode", lua_localovmode);
567 lua_register(l, "irc_localtopic", lua_localtopic);
568
569 lua_register(l, "irc_localban", lua_localban);
570 lua_register(l, "irc_localkick", lua_localkick);
571 lua_register(l, "irc_localumodes", lua_localumodes);
572
573 lua_register(l, "irc_localrename", lua_localrename);
574 }
575