X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/6269435f5bbbc8c76e6a9894cc1ee5eebaf2fedf..8c684fca9c7dbb4a2601628c744be9236ee68641:/lua/luabot.c diff --git a/lua/luabot.c b/lua/luabot.c index ae2da0a4..8f5501fd 100644 --- a/lua/luabot.c +++ b/lua/luabot.c @@ -6,13 +6,12 @@ #include "../localuser/localuserchannel.h" #include "../core/schedule.h" #include "../lib/irc_string.h" +#include "../core/config.h" #include "lua.h" #include "luabot.h" -#ifdef LUA_JITLIBNAME -#include -#endif +#include nick *lua_nick = NULL; void *myureconnect = NULL, *myublip = NULL, *myutick = NULL; @@ -32,8 +31,12 @@ void lua_onquit(int hooknum, void *arg); void lua_onrename(int hooknum, void *arg); void lua_onconnect(int hooknum, void *arg); void lua_onjoin(int hooknum, void *arg); +void lua_onpart(int hooknum, void *arg); + +sstring *luabotnick; void lua_registerevents(void) { + registerhook(HOOK_CHANNEL_MODECHANGE, &lua_onmode); registerhook(HOOK_NICK_NEWNICK, &lua_onnewnick); registerhook(HOOK_IRC_DISCON, &lua_ondisconnect); registerhook(HOOK_IRC_PRE_DISCON, &lua_ondisconnect); @@ -47,10 +50,12 @@ void lua_registerevents(void) { registerhook(HOOK_IRC_CONNECTED, &lua_onconnect); registerhook(HOOK_SERVER_END_OF_BURST, &lua_onconnect); registerhook(HOOK_CHANNEL_JOIN, &lua_onjoin); + registerhook(HOOK_CHANNEL_PART, &lua_onpart); registerhook(HOOK_CHANNEL_CREATE, &lua_onjoin); } void lua_deregisterevents(void) { + deregisterhook(HOOK_CHANNEL_PART, &lua_onpart); deregisterhook(HOOK_CHANNEL_CREATE, &lua_onjoin); deregisterhook(HOOK_CHANNEL_JOIN, &lua_onjoin); deregisterhook(HOOK_SERVER_END_OF_BURST, &lua_onconnect); @@ -65,6 +70,7 @@ void lua_deregisterevents(void) { deregisterhook(HOOK_IRC_PRE_DISCON, &lua_ondisconnect); deregisterhook(HOOK_IRC_DISCON, &lua_ondisconnect); deregisterhook(HOOK_NICK_NEWNICK, &lua_onnewnick); + deregisterhook(HOOK_CHANNEL_MODECHANGE, &lua_onmode); } void lua_startbot(void *arg) { @@ -72,24 +78,28 @@ void lua_startbot(void *arg) { myureconnect = NULL; - lua_nick = registerlocaluser("U", "lua", "quakenet.department.of.corrections", -"Lua engine v" LUA_BOTVERSION " (" LUA_VERSION ")" -#ifdef LUAJIT_VERSION -" + " LUAJIT_VERSION -#endif -, "U", UMODE_ACCOUNT | UMODE_DEAF | UMODE_OPER | UMODE_SERVICE, &lua_bothandler); + if(!luabotnick) + luabotnick = getcopyconfigitem("lua", "botnick", "U", NICKLEN); + + lua_nick = registerlocaluser(luabotnick->content, "lua", "quakenet.department.of.corrections", LUA_FULLVERSION, "U", UMODE_ACCOUNT | UMODE_DEAF | UMODE_OPER | UMODE_SERVICE, &lua_bothandler); if(!lua_nick) { myureconnect = scheduleoneshot(time(NULL) + 1, &lua_startbot, NULL); return; } cp = findchannel(LUA_OPERCHAN); - if(cp && localjoinchannel(lua_nick, cp)) + if(cp && localjoinchannel(lua_nick, cp)) { localgetops(lua_nick, cp); + } else { + localcreatechannel(lua_nick, LUA_OPERCHAN); + } cp = findchannel(LUA_PUKECHAN); - if(cp && localjoinchannel(lua_nick, cp)) + if(cp && localjoinchannel(lua_nick, cp)) { localgetops(lua_nick, cp); + } else { + localcreatechannel(lua_nick, LUA_PUKECHAN); + } myublip = schedulerecurring(time(NULL) + 1, 0, 60, &lua_blip, NULL); myutick = schedulerecurring(time(NULL) + 1, 0, 1, &lua_tick, NULL); @@ -111,13 +121,108 @@ void lua_destroybot(void) { if(lua_nick) deregisterlocaluser(lua_nick, NULL); + + if(luabotnick) { + freesstring(luabotnick); + luabotnick = NULL; + } +} + +int _lua_vpcall(lua_State *l, void *function, int mode, const char *sig, ...) { + va_list va; + int narg = 0, nres, top = lua_gettop(l); + + lua_getglobal(l, "scripterror"); + if(mode == LUA_CHARMODE) { + lua_getglobal(l, (const char *)function); + } else { + lua_rawgeti(l, LUA_REGISTRYINDEX, (long)function); + } + + if(!lua_isfunction(l, -1)) { + lua_settop(l, top); + return 1; + } + + va_start(va, sig); + + while(*sig) { + switch(*sig++) { + case 'i': + lua_pushint(l, va_arg(va, int)); + break; + case 'l': + lua_pushlong(l, va_arg(va, long)); + break; + case 's': + lua_pushstring(l, va_arg(va, char *)); + break; + case 'S': + lua_pushstring(l, ((sstring *)(va_arg(va, sstring *)))->content); + break; + case 'L': /* BE VERY CAREFUL USING THIS, MAKE SURE YOU CAST THE VALUE TO LONG */ + { + char *p = va_arg(va, char *); + long len = va_arg(va, long); + lua_pushlstring(l, p, len); + } + break; + case 'N': + { + nick *np = va_arg(va, nick *); + lua_pushnumeric(l, np->numeric); + break; + } + case 'C': + { + channel *cp = va_arg(va, channel *); + LUA_PUSHCHAN(l, cp); + break; + } + case '0': + lua_pushnil(l); + break; + case 'R': + lua_rawgeti(l, LUA_REGISTRYINDEX, va_arg(va, long)); + break; + case 'b': + lua_pushboolean(l, va_arg(va, int)); + break; + case '>': + goto endwhile; + + default: + Error("lua", ERR_ERROR, "Unable to parse vpcall signature (%c)", *(sig - 1)); + } + narg++; + } + +endwhile: + + nres = strlen(sig); + + if(lua_debugpcall(l, (mode==LUA_CHARMODE)?function:"some_handler", narg, nres, top + 1)) { + Error("lua", ERR_ERROR, "Error pcalling %s: %s.", (mode==LUA_CHARMODE)?(char *)function:"some_handler", lua_tostring(l, -1)); + } else { + nres = -nres; + while(*sig) { + switch(*sig++) { + default: + Error("lua", ERR_ERROR, "Unable to parse vpcall return structure (%c)", *(sig - 1)); + } + nres++; + } + } + + lua_settop(l, top); + va_end(va); + return 0; } void lua_bothandler(nick *target, int type, void **args) { nick *np; char *p; - lua_State *l; - int le, top; + int le; switch(type) { case LU_PRIVMSG: @@ -127,23 +232,7 @@ void lua_bothandler(nick *target, int type, void **args) { if(!np || !p) return; - LUA_STARTLOOP(l); - - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - lua_getglobal(l, "irc_onmsg"); - - if(lua_isfunction(l, -1)) { - LUA_PUSHNICK(l, np); - lua_pushstring(l, p); - - lua_pcall(l, 2, 0, top + 1); - } - - lua_settop(l, top); - - LUA_ENDLOOP(); + lua_avpcall("irc_onmsg", "ls", np->numeric, p); break; case LU_PRIVNOTICE: @@ -158,23 +247,7 @@ void lua_bothandler(nick *target, int type, void **args) { if(p[le - 1] == '\001') p[le - 1] = '\000'; - LUA_STARTLOOP(l); - - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - lua_getglobal(l, "irc_onctcp"); - - if(lua_isfunction(l, -1)) { - LUA_PUSHNICK(l, np); - lua_pushstring(l, p + 1); - - lua_pcall(l, 2, 0, top + 1); - } - - lua_settop(l, top); - - LUA_ENDLOOP(); + lua_avpcall("irc_onctcp", "ls", np->numeric, p + 1); } @@ -199,61 +272,20 @@ void lua_bothandler(nick *target, int type, void **args) { } void lua_blip(void *arg) { - lua_State *l; - int top; - - LUA_STARTLOOP(l); - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - lua_getglobal(l, "onblip"); - - if(lua_isfunction(l, -1)) - lua_pcall(l, 0, 0, top + 1); - - lua_settop(l, top); - LUA_ENDLOOP(); + lua_avpcall("onblip", ""); } void lua_tick(void *arg) { - lua_State *l; - int top; - - LUA_STARTLOOP(l); - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - lua_getglobal(l, "ontick"); - - if(lua_isfunction(l, -1)) - lua_pcall(l, 0, 0, top + 1); - - lua_settop(l, top); - LUA_ENDLOOP(); + lua_avpcall("ontick", ""); } void lua_onnewnick(int hooknum, void *arg) { nick *np = (nick *)arg; - int top; - lua_State *l; if(!np) return; - LUA_STARTLOOP(l); - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - lua_getglobal(l, "irc_onnewnick"); - - if(lua_isfunction(l, -1)) { - LUA_PUSHNICK(l, np); - - lua_pcall(l, 1, 0, top + 1); - } - - lua_settop(l, top); - LUA_ENDLOOP(); + lua_avpcall("irc_onnewnick", "l", np->numeric); } void lua_onkick(int hooknum, void *arg) { @@ -262,58 +294,31 @@ void lua_onkick(int hooknum, void *arg) { nick *kicked = arglist[1]; nick *kicker = arglist[2]; char *message = (char *)arglist[3]; - lua_State *l; - int top; + int mode = 1; if(!kicker || IsOper(kicker) || IsService(kicker) || IsXOper(kicker)) /* bloody Cruicky */ - return; - - LUA_STARTLOOP(l); - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - lua_getglobal(l, "irc_onkick"); - - if(lua_isfunction(l, -1)) { - lua_pushstring(l, ci->name->content); - LUA_PUSHNICK(l, kicked); - LUA_PUSHNICK(l, kicker); - lua_pushstring(l, message); - - lua_pcall(l, 4, 0, top + 1); - } - - lua_settop(l, top); - LUA_ENDLOOP(); + mode = 0; + + if(mode) { + lua_avpcall("irc_onkick", "Slls", ci->name, kicked->numeric, kicker->numeric, message); + } else if(kicker) { + lua_avpcall("irc_onkickall", "Slls", ci->name, kicked->numeric, kicker->numeric, message); + } else { + lua_avpcall("irc_onkickall", "Sl0s", ci->name, kicked->numeric, message); + } } void lua_ontopic(int hooknum, void *arg) { void **arglist = (void **)arg; channel *cp=(channel*)arglist[0]; nick *np = (nick *)arglist[1]; - lua_State *l; - int top; if(!np || IsOper(np) || IsService(np) || IsXOper(np)) return; if(!cp || !cp->topic) return; - LUA_STARTLOOP(l); - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - lua_getglobal(l, "irc_ontopic"); - - if(lua_isfunction(l, -1)) { - lua_pushstring(l, cp->index->name->content); - LUA_PUSHNICK(l, np); - lua_pushstring(l, cp->topic->content); - - lua_pcall(l, 3, 0, top + 1); - } - lua_settop(l, top); - LUA_ENDLOOP(); + lua_avpcall("irc_ontopic", "SlS", cp->index->name, np->numeric, cp->topic); } void lua_onop(int hooknum, void *arg) { @@ -321,200 +326,80 @@ void lua_onop(int hooknum, void *arg) { chanindex *ci = ((channel *)arglist[0])->index; nick *np = arglist[1]; nick *target = arglist[2]; - lua_State *l; - int top; if(!target) return; - LUA_STARTLOOP(l); - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - if(hooknum == HOOK_CHANNEL_OPPED) { - lua_getglobal(l, "irc_onop"); - } else { - lua_getglobal(l, "irc_ondeop"); - } - - if(lua_isfunction(l, -1)) { - lua_pushstring(l, ci->name->content); - - if(np) { - LUA_PUSHNICK(l, np); - } else { - lua_pushnil(l); - } - LUA_PUSHNICK(l, target); - - lua_pcall(l, 3, 0, top + 1); - } - - lua_settop(l, top); - LUA_ENDLOOP(); + if(np) { + lua_avpcall(hooknum == HOOK_CHANNEL_OPPED?"irc_onop":"irc_ondeop", "Sll", ci->name, np->numeric, target->numeric); + } else { + lua_avpcall(hooknum == HOOK_CHANNEL_OPPED?"irc_onop":"irc_ondeop", "S0l", ci->name, target->numeric); + } } void lua_onjoin(int hooknum, void *arg) { void **arglist = (void **)arg; chanindex *ci = ((channel *)arglist[0])->index; nick *np = arglist[1]; - lua_State *l; - int top; if(!ci || !np) return; - LUA_STARTLOOP(l); - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - lua_getglobal(l, "irc_onjoin"); - - if(lua_isfunction(l, -1)) { - lua_pushstring(l, ci->name->content); + lua_avpcall("irc_onjoin", "Sl", ci->name, np->numeric); +} - LUA_PUSHNICK(l, np); +void lua_onpart(int hooknum, void *arg) { + void **arglist = (void **)arg; + chanindex *ci = ((channel *)arglist[0])->index; + nick *np = arglist[1]; - lua_pcall(l, 2, 0, top + 1); - } + if(!ci || !np) + return; - lua_settop(l, top); - LUA_ENDLOOP(); + lua_avpcall("irc_onpart", "Sl", ci->name, np->numeric); } void lua_onrename(int hooknum, void *arg) { nick *np = (void *)arg; - lua_State *l; - int top; if(!np) return; - LUA_STARTLOOP(l); - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - lua_getglobal(l, "irc_onrename"); - - if(lua_isfunction(l, -1)) { - LUA_PUSHNICK(l, np); - - lua_pcall(l, 1, 0, top + 1); - } - - lua_settop(l, top); - LUA_ENDLOOP(); + lua_avpcall("irc_onrename", "l", np->numeric); } void lua_onquit(int hooknum, void *arg) { nick *np = (nick *)arg; - lua_State *l; - int top; if(!np) return; - LUA_STARTLOOP(l); - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - lua_getglobal(l, "irc_onquit"); - - if(lua_isfunction(l, -1)) { - LUA_PUSHNICK(l, np); - - lua_pcall(l, 1, 0, top + 1); - } - - lua_settop(l, top); - LUA_ENDLOOP(); + lua_avpcall("irc_onquit", "l", np->numeric); } void lua_onauth(int hooknum, void *arg) { nick *np = (nick *)arg; - lua_State *l; - int top; if(!np) return; - LUA_STARTLOOP(l); - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - lua_getglobal(l, "irc_onauth"); - - if(lua_isfunction(l, -1)) { - LUA_PUSHNICK(l, np); - - lua_pcall(l, 1, 0, top + 1); - } - lua_settop(l, top); - LUA_ENDLOOP(); + lua_avpcall("irc_onauth", "l", np->numeric); } void lua_ondisconnect(int hooknum, void *arg) { - lua_State *l; - int top; - - LUA_STARTLOOP(l); - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - if(hooknum == HOOK_IRC_DISCON) { - lua_getglobal(l, "irc_ondisconnect"); - } else { - lua_getglobal(l, "irc_onpredisconnect"); - } - if(lua_isfunction(l, -1)) - lua_pcall(l, 0, 0, top + 1); - lua_settop(l, top); - LUA_ENDLOOP(); + lua_avpcall(hooknum == HOOK_IRC_DISCON?"irc_ondisconnect":"irc_onpredisconnect", ""); } void lua_onconnect(int hooknum, void *arg) { - lua_State *l; - int top; - - LUA_STARTLOOP(l); - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - if(hooknum == HOOK_IRC_CONNECTED) { - lua_getglobal(l, "irc_onconnect"); - } else { - lua_getglobal(l, "irc_onendofburst"); - } - if(lua_isfunction(l, -1)) - lua_pcall(l, 0, 0, top + 1); - lua_settop(l, top); - LUA_ENDLOOP(); + lua_avpcall(hooknum == HOOK_IRC_CONNECTED?"irc_onconnect":"irc_onendofburst", ""); } void lua_onload(lua_State *l) { - int top; - - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - lua_getglobal(l, "onload"); - - if(lua_isfunction(l, -1)) - lua_pcall(l, 0, 0, top + 1); - lua_settop(l, top); + lua_vpcall(l, "onload", ""); } void lua_onunload(lua_State *l) { - int top; - - top = lua_gettop(l); - - lua_getglobal(l, "scripterror"); - lua_getglobal(l, "onunload"); - - if(lua_isfunction(l, -1)) - lua_pcall(l, 0, 0, top + 1); - lua_settop(l, top); + lua_vpcall(l, "onunload", ""); } int lua_channelmessage(channel *cp, char *message, ...) { @@ -556,4 +441,29 @@ int lua_notice(nick *np, char *message, ...) { return 0; } +char *printallmodes(channel *cp) { + static char buf[1024]; + char buf2[12]; + + if(IsLimit(cp)) + snprintf(buf2, sizeof(buf2), "%d", cp->limit); + + snprintf(buf, sizeof(buf), "%s %s%s%s", printflags(cp->flags, cmodeflags), IsLimit(cp)?buf2:"", IsLimit(cp)?" ":"", IsKey(cp)?cp->key->content:""); + + return buf; +} + +void lua_onmode(int hooknum, void *arg) { + void **arglist = (void **)arg; + channel *cp = (channel *)arglist[0]; + chanindex *ci = cp->index; + nick *np = arglist[1]; + + if(np) { + lua_avpcall("irc_onmode", "Sls", ci->name, np->numeric, printallmodes(cp)); + } else { + lua_avpcall("irc_onmode", "S0s", ci->name, printallmodes(cp)); + } +} +