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