]>
jfr.im git - irc/quakenet/newserv.git/blob - lua/luabot.c
1 /* Copyright (C) Chris Porter 2005 */
2 /* ALL RIGHTS RESERVED. */
3 /* Don't put this into the SVN repo. */
5 #include "../localuser/localuser.h"
6 #include "../localuser/localuserchannel.h"
7 #include "../core/schedule.h"
8 #include "../lib/irc_string.h"
9 #include "../core/config.h"
16 nick
*lua_nick
= NULL
;
17 void *myureconnect
= NULL
, *myublip
= NULL
, *myutick
= NULL
;
19 void lua_bothandler(nick
*target
, int type
, void **args
);
21 void lua_onnewnick(int hooknum
, void *arg
);
22 void lua_blip(void *arg
);
23 void lua_tick(void *arg
);
24 void lua_onkick(int hooknum
, void *arg
);
25 void lua_ontopic(int hooknum
, void *arg
);
26 void lua_onauth(int hooknum
, void *arg
);
27 void lua_ondisconnect(int hooknum
, void *arg
);
28 void lua_onmode(int hooknum
, void *arg
);
29 void lua_onop(int hooknum
, void *arg
);
30 void lua_onvoice(int hooknum
, void *arg
);
31 void lua_onprequit(int hooknum
, void *arg
);
32 void lua_onquit(int hooknum
, void *arg
);
33 void lua_onrename(int hooknum
, void *arg
);
34 void lua_onconnect(int hooknum
, void *arg
);
35 void lua_onjoin(int hooknum
, void *arg
);
36 void lua_onpart(int hooknum
, void *arg
);
40 void lua_registerevents(void) {
41 registerhook(HOOK_CHANNEL_MODECHANGE
, &lua_onmode
);
42 registerhook(HOOK_NICK_NEWNICK
, &lua_onnewnick
);
43 registerhook(HOOK_IRC_DISCON
, &lua_ondisconnect
);
44 registerhook(HOOK_IRC_PRE_DISCON
, &lua_ondisconnect
);
45 registerhook(HOOK_NICK_ACCOUNT
, &lua_onauth
);
46 registerhook(HOOK_CHANNEL_TOPIC
, &lua_ontopic
);
47 registerhook(HOOK_CHANNEL_KICK
, &lua_onkick
);
48 registerhook(HOOK_CHANNEL_OPPED
, &lua_onop
);
49 registerhook(HOOK_CHANNEL_DEOPPED
, &lua_onop
);
50 registerhook(HOOK_CHANNEL_VOICED
, &lua_onvoice
);
51 registerhook(HOOK_CHANNEL_DEVOICED
, &lua_onvoice
);
52 registerhook(HOOK_NICK_PRE_LOSTNICK
, &lua_onprequit
);
53 registerhook(HOOK_NICK_LOSTNICK
, &lua_onquit
);
54 registerhook(HOOK_NICK_RENAME
, &lua_onrename
);
55 registerhook(HOOK_IRC_CONNECTED
, &lua_onconnect
);
56 registerhook(HOOK_SERVER_END_OF_BURST
, &lua_onconnect
);
57 registerhook(HOOK_CHANNEL_JOIN
, &lua_onjoin
);
58 registerhook(HOOK_CHANNEL_PART
, &lua_onpart
);
59 registerhook(HOOK_CHANNEL_CREATE
, &lua_onjoin
);
62 void lua_deregisterevents(void) {
63 deregisterhook(HOOK_CHANNEL_PART
, &lua_onpart
);
64 deregisterhook(HOOK_CHANNEL_CREATE
, &lua_onjoin
);
65 deregisterhook(HOOK_CHANNEL_JOIN
, &lua_onjoin
);
66 deregisterhook(HOOK_SERVER_END_OF_BURST
, &lua_onconnect
);
67 deregisterhook(HOOK_IRC_CONNECTED
, &lua_onconnect
);
68 deregisterhook(HOOK_NICK_RENAME
, &lua_onrename
);
69 deregisterhook(HOOK_NICK_LOSTNICK
, &lua_onquit
);
70 deregisterhook(HOOK_NICK_PRE_LOSTNICK
, &lua_onprequit
);
71 deregisterhook(HOOK_CHANNEL_DEOPPED
, &lua_onop
);
72 deregisterhook(HOOK_CHANNEL_OPPED
, &lua_onop
);
73 deregisterhook(HOOK_CHANNEL_DEVOICED
, &lua_onvoice
);
74 deregisterhook(HOOK_CHANNEL_VOICED
, &lua_onvoice
);
75 deregisterhook(HOOK_CHANNEL_KICK
, &lua_onkick
);
76 deregisterhook(HOOK_CHANNEL_TOPIC
, &lua_ontopic
);
77 deregisterhook(HOOK_NICK_ACCOUNT
, &lua_onauth
);
78 deregisterhook(HOOK_IRC_PRE_DISCON
, &lua_ondisconnect
);
79 deregisterhook(HOOK_IRC_DISCON
, &lua_ondisconnect
);
80 deregisterhook(HOOK_NICK_NEWNICK
, &lua_onnewnick
);
81 deregisterhook(HOOK_CHANNEL_MODECHANGE
, &lua_onmode
);
84 void lua_startbot(void *arg
) {
90 luabotnick
= getcopyconfigitem("lua", "botnick", "U", NICKLEN
);
92 lua_nick
= registerlocaluser(luabotnick
->content
, "lua", "quakenet.department.of.corrections", LUA_FULLVERSION
, "U", UMODE_ACCOUNT
| UMODE_DEAF
| UMODE_OPER
| UMODE_SERVICE
, &lua_bothandler
);
94 myureconnect
= scheduleoneshot(time(NULL
) + 1, &lua_startbot
, NULL
);
98 cp
= findchannel(LUA_OPERCHAN
);
99 if(cp
&& localjoinchannel(lua_nick
, cp
)) {
100 localgetops(lua_nick
, cp
);
102 localcreatechannel(lua_nick
, LUA_OPERCHAN
);
105 cp
= findchannel(LUA_PUKECHAN
);
106 if(cp
&& localjoinchannel(lua_nick
, cp
)) {
107 localgetops(lua_nick
, cp
);
109 localcreatechannel(lua_nick
, LUA_PUKECHAN
);
112 myublip
= schedulerecurring(time(NULL
) + 1, 0, 60, &lua_blip
, NULL
);
113 myutick
= schedulerecurring(time(NULL
) + 1, 0, 1, &lua_tick
, NULL
);
115 lua_registerevents();
118 void lua_destroybot(void) {
120 deleteschedule(myutick
, &lua_tick
, NULL
);
123 deleteschedule(myublip
, &lua_blip
, NULL
);
125 lua_deregisterevents();
128 deleteschedule(myureconnect
, &lua_startbot
, NULL
);
131 deregisterlocaluser(lua_nick
, NULL
);
134 freesstring(luabotnick
);
139 int _lua_vpcall(lua_State
*l
, void *function
, int mode
, const char *sig
, ...) {
141 int narg
= 0, nres
, top
= lua_gettop(l
);
143 lua_getglobal(l
, "scripterror");
144 if(mode
== LUA_CHARMODE
) {
145 lua_getglobal(l
, (const char *)function
);
147 lua_rawgeti(l
, LUA_REGISTRYINDEX
, (long)function
);
150 if(!lua_isfunction(l
, -1)) {
160 lua_pushint(l
, va_arg(va
, int));
163 lua_pushlong(l
, va_arg(va
, long));
166 lua_pushstring(l
, va_arg(va
, char *));
169 lua_pushstring(l
, ((sstring
*)(va_arg(va
, sstring
*)))->content
);
171 case 'L': /* BE VERY CAREFUL USING THIS, MAKE SURE YOU CAST THE VALUE TO LONG */
173 char *p
= va_arg(va
, char *);
174 long len
= va_arg(va
, long);
175 lua_pushlstring(l
, p
, len
);
180 nick
*np
= va_arg(va
, nick
*);
181 lua_pushnumeric(l
, np
->numeric
);
186 channel
*cp
= va_arg(va
, channel
*);
194 lua_rawgeti(l
, LUA_REGISTRYINDEX
, va_arg(va
, long));
197 lua_pushboolean(l
, va_arg(va
, int));
203 Error("lua", ERR_ERROR
, "Unable to parse vpcall signature (%c)", *(sig
- 1));
212 if(lua_debugpcall(l
, (mode
==LUA_CHARMODE
)?function
:"some_handler", narg
, nres
, top
+ 1)) {
213 Error("lua", ERR_ERROR
, "Error pcalling %s: %s.", (mode
==LUA_CHARMODE
)?(char *)function
:"some_handler", lua_tostring(l
, -1));
219 Error("lua", ERR_ERROR
, "Unable to parse vpcall return structure (%c)", *(sig
- 1));
230 void lua_bothandler(nick
*target
, int type
, void **args
) {
237 np
= (nick
*)args
[0];
243 lua_avpcall("irc_onmsg", "ls", np
->numeric
, p
);
247 np
= (nick
*)args
[0];
254 if((le
> 1) && (p
[0] == '\001')) {
255 if(p
[le
- 1] == '\001')
258 lua_avpcall("irc_onctcp", "ls", np
->numeric
, p
+ 1);
260 lua_avpcall("irc_onnotice", "ls", np
->numeric
, p
);
268 deleteschedule(myublip
, &lua_blip
, NULL
);
273 deleteschedule(myutick
, &lua_tick
, NULL
);
277 myureconnect
= scheduleoneshot(time(NULL
) + 1, &lua_startbot
, NULL
);
283 void lua_blip(void *arg
) {
284 lua_avpcall("onblip", "");
287 void lua_tick(void *arg
) {
288 lua_avpcall("ontick", "");
291 void lua_onnewnick(int hooknum
, void *arg
) {
292 nick
*np
= (nick
*)arg
;
297 lua_avpcall("irc_onnewnick", "l", np
->numeric
);
300 void lua_onkick(int hooknum
, void *arg
) {
301 void **arglist
= (void **)arg
;
302 chanindex
*ci
= ((channel
*)arglist
[0])->index
;
303 nick
*kicked
= arglist
[1];
304 nick
*kicker
= arglist
[2];
305 char *message
= (char *)arglist
[3];
308 lua_avpcall("irc_onkick", "Slls", ci
->name
, kicked
->numeric
, kicker
->numeric
, message
);
310 lua_avpcall("irc_onkick", "Sl0s", ci
->name
, kicked
->numeric
, message
);
313 void lua_ontopic(int hooknum
, void *arg
) {
314 void **arglist
= (void **)arg
;
315 channel
*cp
=(channel
*)arglist
[0];
316 nick
*np
= (nick
*)arglist
[1];
318 if(!cp
|| !cp
->topic
)
322 lua_avpcall("irc_ontopic", "SlS", cp
->index
->name
, np
->numeric
, cp
->topic
);
324 lua_avpcall("irc_ontopic", "S0S", cp
->index
->name
, cp
->topic
);
327 void lua_onop(int hooknum
, void *arg
) {
328 void **arglist
= (void **)arg
;
329 chanindex
*ci
= ((channel
*)arglist
[0])->index
;
330 nick
*np
= arglist
[1];
331 nick
*target
= arglist
[2];
337 lua_avpcall(hooknum
== HOOK_CHANNEL_OPPED
?"irc_onop":"irc_ondeop", "Sll", ci
->name
, np
->numeric
, target
->numeric
);
339 lua_avpcall(hooknum
== HOOK_CHANNEL_OPPED
?"irc_onop":"irc_ondeop", "S0l", ci
->name
, target
->numeric
);
343 void lua_onvoice(int hooknum
, void *arg
) {
344 void **arglist
= (void **)arg
;
345 chanindex
*ci
= ((channel
*)arglist
[0])->index
;
346 nick
*np
= arglist
[1];
347 nick
*target
= arglist
[2];
353 lua_avpcall(hooknum
== HOOK_CHANNEL_VOICED
?"irc_onvoice":"irc_ondevoice", "Sll", ci
->name
, np
->numeric
, target
->numeric
);
355 lua_avpcall(hooknum
== HOOK_CHANNEL_VOICED
?"irc_onvoice":"irc_ondevoice", "S0l", ci
->name
, target
->numeric
);
359 void lua_onjoin(int hooknum
, void *arg
) {
360 void **arglist
= (void **)arg
;
361 chanindex
*ci
= ((channel
*)arglist
[0])->index
;
362 nick
*np
= arglist
[1];
367 lua_avpcall("irc_onjoin", "Sl", ci
->name
, np
->numeric
);
370 void lua_onpart(int hooknum
, void *arg
) {
371 void **arglist
= (void **)arg
;
372 chanindex
*ci
= ((channel
*)arglist
[0])->index
;
373 nick
*np
= arglist
[1];
374 char *reason
= arglist
[2];
379 lua_avpcall("irc_onpart", "Sls", ci
->name
, np
->numeric
, reason
);
382 void lua_onrename(int hooknum
, void *arg
) {
383 void **harg
= (void **)arg
;
385 char *oldnick
= harg
[1];
390 lua_avpcall("irc_onrename", "ls", np
->numeric
, oldnick
);
393 void lua_onquit(int hooknum
, void *arg
) {
394 nick
*np
= (nick
*)arg
;
399 lua_avpcall("irc_onquit", "l", np
->numeric
);
402 void lua_onprequit(int hooknum
, void *arg
) {
403 nick
*np
= (nick
*)arg
;
408 lua_avpcall("irc_onprequit", "l", np
->numeric
);
411 void lua_onauth(int hooknum
, void *arg
) {
412 nick
*np
= (nick
*)arg
;
417 lua_avpcall("irc_onauth", "l", np
->numeric
);
420 void lua_ondisconnect(int hooknum
, void *arg
) {
421 lua_avpcall(hooknum
== HOOK_IRC_DISCON
?"irc_ondisconnect":"irc_onpredisconnect", "");
424 void lua_onconnect(int hooknum
, void *arg
) {
425 lua_avpcall(hooknum
== HOOK_IRC_CONNECTED
?"irc_onconnect":"irc_onendofburst", "");
428 void lua_onload(lua_State
*l
) {
429 lua_vpcall(l
, "onload", "");
432 void lua_onunload(lua_State
*l
) {
433 lua_vpcall(l
, "onunload", "");
436 int lua_channelmessage(channel
*cp
, char *message
, ...) {
440 va_start(va
, message
);
441 vsnprintf(buf
, sizeof(buf
), message
, va
);
444 sendmessagetochannel(lua_nick
, cp
, "%s", buf
);
449 int lua_message(nick
*np
, char *message
, ...) {
453 va_start(va
, message
);
454 vsnprintf(buf
, sizeof(buf
), message
, va
);
457 sendmessagetouser(lua_nick
, np
, "%s", buf
);
462 int lua_notice(nick
*np
, char *message
, ...) {
466 va_start(va
, message
);
467 vsnprintf(buf
, sizeof(buf
), message
, va
);
470 sendnoticetouser(lua_nick
, np
, "%s", buf
);
475 char *printallmodes(channel
*cp
) {
476 static char buf
[1024];
480 snprintf(buf2
, sizeof(buf2
), "%d", cp
->limit
);
482 snprintf(buf
, sizeof(buf
), "%s %s%s%s", printflags(cp
->flags
, cmodeflags
), IsLimit(cp
)?buf2
:"", IsLimit(cp
)?" ":"", IsKey(cp
)?cp
->key
->content
:"");
487 static char *printlimitedmodes(channel
*cp
, flag_t before
) {
488 static char buf
[1024];
490 snprintf(buf
, sizeof(buf
), "%s", printflags(cp
->flags
, cmodeflags
));
495 void lua_onmode(int hooknum
, void *arg
) {
496 void **arglist
= (void **)arg
;
497 channel
*cp
= (channel
*)arglist
[0];
498 chanindex
*ci
= cp
->index
;
499 nick
*np
= arglist
[1];
500 flag_t beforeflags
= (flag_t
)(long)arglist
[3];
503 lua_avpcall("irc_onmode", "Slss", ci
->name
, np
->numeric
, printallmodes(cp
), printlimitedmodes(cp
, beforeflags
));
505 lua_avpcall("irc_onmode", "S0ss", ci
->name
, printallmodes(cp
), printlimitedmodes(cp
, beforeflags
));