]> jfr.im git - irc/quakenet/newserv.git/blob - lua/lualocal.c
Newserv now required userid in the AC/N messages to auth, services with no userid...
[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->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 for(ln=l->nicks;ln;ln=pn) {
123 pn = ln->next;
124
125 lua_freelocalnick(l->l, ln, "Script unloaded.");
126 }
127
128 l->nicks = NULL;
129 }
130
131 /* todo */
132 void lua_localnickhandler(nick *target, int type, void **args) {
133 nick *np;
134 char *p;
135 lua_localnick *ln;
136 lua_list *l;
137 channel *c;
138
139 if(!lua_getlocalnickbynick(target, &l, &ln))
140 return;
141
142 switch(type) {
143 case LU_PRIVMSG:
144 np = (nick *)args[0];
145 p = (char *)args[1];
146
147 if(!np || !p)
148 return;
149
150 lua_vlpcall(l, ln, "irc_onmsg", "Ns", np, p);
151
152 break;
153
154 case LU_CHANMSG:
155 np = (nick *)args[0];
156 c = (channel *)args[1];
157 p = (char *)args[2];
158
159 if(!np || !p || !c || !c->index || !c->index->name || !c->index->name->content)
160 return;
161
162 lua_vlpcall(l, ln, "irc_onchanmsg", "Nss", np, c->index->name->content, p);
163 break;
164
165 case LU_KILLED:
166 p = (char *)args[2];
167 lua_vlpcall(l, ln, "irc_onkilled", "s", p);
168
169 strlcpy(ln->nickname, target->nick, sizeof(ln->nickname));
170 strlcpy(ln->ident, target->ident, sizeof(ln->ident));
171 strlcpy(ln->hostname, target->host->name->content, sizeof(ln->hostname));
172 strlcpy(ln->realname, target->realname->name->content, sizeof(ln->realname));
173 strlcpy(ln->account, target->authname, sizeof(ln->account));
174
175 ln->umodes = target->umodes;
176 ln->nick = NULL;
177
178 ln->reconnect = scheduleoneshot(time(NULL) + 1, &lua_reconnectlocal, ln);
179
180 break;
181 case LU_INVITE:
182 /* we were invited, check if someone invited us to PUBLICCHAN */
183 np = (nick *)args[0];
184 c = (channel *)args[1];
185
186 if(!c || !np || !c->index || !c->index->name || !c->index->name->content)
187 return;
188
189 lua_vlpcall(l, ln, "irc_oninvite", "Ns", np, c->index->name->content);
190 break;
191 }
192 }
193
194 void lua_reconnectlocal(void *arg) {
195 lua_list *l;
196 lua_localnick *ln = (lua_localnick *)arg;
197
198 ln->nick = registerlocaluser(ln->nickname, ln->ident, ln->hostname, ln->realname, ln->account, ln->umodes, &lua_localnickhandler);
199 if(!ln->nick) {
200 ln->reconnect = scheduleoneshot(time(NULL) + 1, &lua_reconnectlocal, ln);
201 return;
202 }
203
204 ln->reconnect = NULL;
205
206 if(lua_getlocalnickbynick(ln->nick, &l, &ln)) /* hacky! */
207 lua_vlpcall(l, ln, "irc_onkillreconnect", "");
208 }
209
210 static int lua_localjoin(lua_State *ps) {
211 nick *source;
212 channel *target;
213 char *chan;
214
215 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2))
216 LUA_RETURN(ps, LUA_FAIL);
217
218 source = getnickbynumeric(lua_tolong(ps, 1));
219 if(!source)
220 LUA_RETURN(ps, LUA_FAIL);
221
222 chan = (char *)lua_tostring(ps, 2);
223 if(chan[0] != '#')
224 LUA_RETURN(ps, LUA_FAIL);
225
226 if(!lua_lineok(chan))
227 LUA_RETURN(ps, LUA_FAIL);
228
229 target = findchannel(chan);
230 if(target) {
231 localjoinchannel(source, target);
232 } else {
233 localcreatechannel(source, chan);
234 }
235
236 LUA_RETURN(ps, LUA_OK);
237 }
238
239 static int lua_localpart(lua_State *ps) {
240 nick *source;
241 channel *target;
242 char *chan, *reason;
243
244 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2))
245 LUA_RETURN(ps, LUA_FAIL);
246
247 source = getnickbynumeric(lua_tolong(ps, 1));
248 if(!source)
249 LUA_RETURN(ps, LUA_FAIL);
250
251 chan = (char *)lua_tostring(ps, 2);
252
253 if(!lua_lineok(chan))
254 LUA_RETURN(ps, LUA_FAIL);
255
256 if(lua_isstring(ps, 3)) {
257 reason = (char *)lua_tostring(ps, 3);
258 if(!lua_lineok(reason))
259 LUA_RETURN(ps, LUA_FAIL);
260 } else {
261 reason = NULL;
262 }
263
264 target = findchannel(chan);
265 if(target) {
266 localpartchannel(source, target, reason);
267 } else {
268 LUA_RETURN(ps, LUA_FAIL);
269 }
270
271 LUA_RETURN(ps, LUA_OK);
272 }
273
274 static int lua_localchanmsg(lua_State *ps) {
275 char *msg;
276 nick *source;
277 channel *target;
278
279 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3))
280 LUA_RETURN(ps, LUA_FAIL);
281
282 source = getnickbynumeric(lua_tolong(ps, 1));
283 if(!source)
284 LUA_RETURN(ps, LUA_FAIL);
285
286 target = findchannel((char *)lua_tostring(ps, 2));
287 if(!target)
288 LUA_RETURN(ps, LUA_FAIL);
289
290 msg = (char *)lua_tostring(ps, 3);
291
292 if(!lua_lineok(msg))
293 LUA_RETURN(ps, LUA_FAIL);
294
295 sendmessagetochannel(source, target, "%s", msg);
296
297 LUA_RETURN(ps, LUA_OK);
298 }
299
300 static int lua_localnotice(lua_State *ps) {
301 char *msg;
302 nick *source;
303 nick *target;
304
305 if(!lua_islong(ps, 1) || !lua_islong(ps, 2) || !lua_isstring(ps, 3))
306 LUA_RETURN(ps, LUA_FAIL);
307
308 source = getnickbynumeric(lua_tolong(ps, 1));
309 if(!source)
310 LUA_RETURN(ps, LUA_FAIL);
311
312 target = getnickbynumeric(lua_tolong(ps, 2));
313 if(!target)
314 LUA_RETURN(ps, LUA_FAIL);
315
316 msg = (char *)lua_tostring(ps, 3);
317
318 if(!lua_lineok(msg))
319 LUA_RETURN(ps, LUA_FAIL);
320
321 sendnoticetouser(source, target, "%s", msg);
322
323 LUA_RETURN(ps, LUA_OK);
324 }
325
326 static int lua_localprivmsg(lua_State *ps) {
327 char *msg;
328 nick *source;
329 nick *target;
330
331 if(!lua_islong(ps, 1) || !lua_islong(ps, 2) || !lua_isstring(ps, 3))
332 LUA_RETURN(ps, LUA_FAIL);
333
334 source = getnickbynumeric(lua_tolong(ps, 1));
335 if(!source)
336 LUA_RETURN(ps, LUA_FAIL);
337
338 target = getnickbynumeric(lua_tolong(ps, 2));
339 if(!target)
340 LUA_RETURN(ps, LUA_FAIL);
341
342 msg = (char *)lua_tostring(ps, 3);
343
344 if(!lua_lineok(msg))
345 LUA_RETURN(ps, LUA_FAIL);
346
347 sendmessagetouser(source, target, "%s", msg);
348
349 LUA_RETURN(ps, LUA_OK);
350 }
351
352 static int lua_localovmode(lua_State *l) {
353 nick *source;
354 channel *chan;
355 int state = 0, add = 0, realmode = 0, ignoring = 0;
356 modechanges changes;
357
358 if(!lua_islong(l, 1) || !lua_isstring(l, 2) || !lua_istable(l, 3))
359 LUA_RETURN(l, LUA_FAIL);
360
361 source = getnickbynumeric(lua_tolong(l, 1));
362 if(!source)
363 LUA_RETURN(l, LUA_FAIL);
364
365 chan = findchannel((char *)lua_tostring(l, 2));
366 if(!chan)
367 LUA_RETURN(l, LUA_FAIL);
368
369 localsetmodeinit(&changes, chan, source);
370
371 lua_pushnil(l);
372
373 while(lua_next(l, 3)) {
374 if(state == 0) {
375 ignoring = 0;
376
377 if(!lua_isboolean(l, -1)) {
378 ignoring = 1;
379 } else {
380 add = (int)lua_toboolean(l, -1);
381 }
382 } else if((state == 1) && !ignoring) {
383 if(!lua_isstring(l, -1)) {
384 ignoring = 1;
385 } else {
386 char *mode = (char *)lua_tostring(l, -1);
387 if((*mode == 'o') && add) {
388 realmode = MC_OP;
389 } else if (*mode == 'o') {
390 realmode = MC_DEOP;
391 } else if((*mode == 'v') && add) {
392 realmode = MC_VOICE;
393 } else if (*mode == 'v') {
394 realmode = MC_DEVOICE;
395 } else {
396 ignoring = 1;
397 }
398 }
399 } else if((state == 2) && !ignoring) {
400 if(lua_islong(l, -1)) {
401 nick *target = getnickbynumeric(lua_tolong(l, -1));
402 if(target)
403 localdosetmode_nick(&changes, target, realmode);
404 }
405 }
406
407 lua_pop(l, 1);
408
409 state = (state + 1) % 3;
410 }
411
412 localsetmodeflush(&changes, 1);
413
414 LUA_RETURN(l, LUA_OK);
415 }
416
417 static int lua_localumodes(lua_State *ps) {
418 nick *np;
419 char *modes;
420 flag_t newmodes = 0;
421
422 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2))
423 LUA_RETURN(ps, LUA_FAIL);
424
425 np = getnickbynumeric(lua_tolong(ps, 1));
426 if(!np)
427 LUA_RETURN(ps, LUA_FAIL);
428
429 modes = (char *)lua_tostring(ps, 2);
430
431 setflags(&newmodes, UMODE_ALL, modes, umodeflags, REJECT_NONE);
432
433 localusersetumodes(np, newmodes);
434 LUA_RETURN(ps, LUA_OK);
435 }
436
437 static int lua_localtopic(lua_State *ps) {
438 nick *np;
439 channel *cp;
440 char *topic;
441
442 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3))
443 LUA_RETURN(ps, LUA_FAIL);
444
445 np = getnickbynumeric(lua_tolong(ps, 1));
446 if(!np)
447 LUA_RETURN(ps, LUA_FAIL);
448
449 cp = findchannel((char *)lua_tostring(ps, 2));
450 if(!cp)
451 LUA_RETURN(ps, LUA_FAIL);
452
453 topic = (char *)lua_tostring(ps, 3);
454 if(!topic || !lua_lineok(topic))
455 LUA_RETURN(ps, LUA_FAIL);
456
457 localsettopic(np, cp, topic);
458
459 LUA_RETURN(ps, LUA_OK);
460 }
461
462 static int lua_localban(lua_State *ps) {
463 channel *cp;
464 const char *mask;
465 modechanges changes;
466 nick *source;
467
468 int dir = MCB_ADD;
469
470 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3))
471 LUA_RETURN(ps, LUA_FAIL);
472
473 if(lua_isboolean(ps, 4) && lua_toboolean(ps, 4))
474 dir = MCB_DEL;
475
476 source = getnickbynumeric(lua_tolong(ps, 1));
477
478 cp = findchannel((char *)lua_tostring(ps, 2));
479 if(!cp)
480 LUA_RETURN(ps, LUA_FAIL);
481
482 mask = lua_tostring(ps, 3);
483 if(!mask || !mask[0] || !lua_lineok(mask))
484 LUA_RETURN(ps, LUA_FAIL);
485
486 localsetmodeinit(&changes, cp, source);
487 localdosetmode_ban(&changes, mask, dir);
488 localsetmodeflush(&changes, 1);
489
490 LUA_RETURN(ps, LUA_OK);
491 }
492
493 static int lua_localkick(lua_State *ps) {
494 const char *n, *msg, *chan;
495 nick *source, *np;
496 channel *cp;
497 int dochecks = 1;
498
499 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3) || !lua_isstring(ps, 4))
500 LUA_RETURN(ps, LUA_FAIL);
501
502 source = getnickbynumeric(lua_tolong(ps, 1));
503 chan = lua_tostring(ps, 2);
504 n = lua_tostring(ps, 3);
505 msg = lua_tostring(ps, 4);
506 if(!source)
507 LUA_RETURN(ps, LUA_FAIL);
508
509 if(lua_isboolean(ps, 4) && !lua_toboolean(ps, 4))
510 dochecks = 0;
511
512 np = getnickbynick(n);
513 if(!np)
514 LUA_RETURN(ps, LUA_FAIL);
515
516 if(dochecks && (IsOper(np) || IsXOper(np) || IsService(np)))
517 LUA_RETURN(ps, LUA_FAIL);
518
519 cp = findchannel((char *)chan);
520 if(!cp)
521 LUA_RETURN(ps, LUA_FAIL);
522
523 if(!lua_lineok(msg))
524 LUA_RETURN(ps, LUA_FAIL);
525
526 localkickuser(source, cp, np, msg);
527
528 LUA_RETURN(ps, LUA_OK);
529 }
530
531 void lua_registerlocalcommands(lua_State *l) {
532 lua_register(l, "irc_localregisteruser", lua_registerlocaluser);
533 lua_register(l, "irc_localderegisteruser", lua_deregisterlocaluser);
534 lua_register(l, "irc_localjoin", lua_localjoin);
535 lua_register(l, "irc_localpart", lua_localpart);
536 lua_register(l, "irc_localchanmsg", lua_localchanmsg);
537 lua_register(l, "irc_localnotice", lua_localnotice);
538 lua_register(l, "irc_localprivmsg", lua_localprivmsg);
539
540 lua_register(l, "irc_localovmode", lua_localovmode);
541 lua_register(l, "irc_localtopic", lua_localtopic);
542
543 lua_register(l, "irc_localban", lua_localban);
544 lua_register(l, "irc_localkick", lua_localkick);
545 lua_register(l, "irc_localumodes", lua_localumodes);
546 }
547