+static int lua_ban(lua_State *ps) {
+ channel *cp;
+ const char *mask;
+ modechanges changes;
+ int dir = MCB_ADD;
+
+ if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
+ LUA_RETURN(ps, LUA_FAIL);
+
+ if(lua_isboolean(ps, 3) && lua_toboolean(ps, 3))
+ dir = MCB_DEL;
+
+ cp = findchannel((char *)lua_tostring(ps, 1));
+ if(!cp)
+ LUA_RETURN(ps, LUA_FAIL);
+
+ mask = lua_tostring(ps, 2);
+ if(!mask || !mask[0] || !lua_lineok(mask))
+ LUA_RETURN(ps, LUA_FAIL);
+
+ localsetmodeinit(&changes, cp, lua_nick);
+ localdosetmode_ban(&changes, mask, dir);
+ localsetmodeflush(&changes, 1);
+
+ LUA_RETURN(ps, LUA_OK);
+}
+
+static int lua_topic(lua_State *ps) {
+ channel *cp;
+ char *topic;
+
+ if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
+ LUA_RETURN(ps, LUA_FAIL);
+
+ cp = findchannel((char *)lua_tostring(ps, 1));
+ if(!cp)
+ LUA_RETURN(ps, LUA_FAIL);
+
+ topic = (char *)lua_tostring(ps, 2);
+ if(!topic || !lua_lineok(topic))
+ LUA_RETURN(ps, LUA_FAIL);
+
+ localsettopic(lua_nick, cp, topic);
+
+ LUA_RETURN(ps, LUA_OK);
+}
+
+static int lua_getuserchanmodes(lua_State *l) {
+ nick *np;
+ channel *cp;
+ unsigned long *lp;
+
+ if(!lua_islong(l, 1) || !lua_isstring(l, 2))
+ return 0;
+
+ np = getnickbynumeric(lua_tolong(l, 1));
+ if(!np)
+ return 0;
+
+ cp = findchannel((char *)lua_tostring(l, 2));
+ if(!cp || !cp->users)
+ return 0;
+
+ lp = getnumerichandlefromchanhash(cp->users, np->numeric);
+ if(!lp)
+ return 0;
+
+ LUA_PUSHNICKCHANMODES(l, lp);
+ return 1;
+}
+
+static int lua_getusermodes(lua_State *l) {
+ nick *np;
+
+ if(!lua_islong(l, 1))
+ return 0;
+
+ np = getnickbynumeric(lua_tolong(l, 1));
+ if(!np)
+ return 0;
+
+ lua_pushstring(l, printflags(np->umodes, umodeflags));
+ return 1;
+}
+
+static int lua_fastgetnickbynumeric(lua_State *l) {
+ static struct lua_pusher *ourpusher[MAX_PUSHER];
+ nick *np;
+
+ if(!lua_islong(l, 1))
+ return 0;
+
+ np = getnickbynumeric(lua_tolong(l, 1));
+ if(!np)
+ return 0;
+
+ lua_setupnickpusher(l, 2, ourpusher, MAX_PUSHER);
+ return lua_usepusher(l, ourpusher, np);
+}
+
+static int lua_fastgetnickbynick(lua_State *l) {
+ static struct lua_pusher *ourpusher[MAX_PUSHER];
+ nick *np;
+
+ if(!lua_isstring(l, 1))
+ return 0;
+
+ np = getnickbynick((char *)lua_tostring(l, 1));
+ if(!np)
+ return 0;
+
+ lua_setupnickpusher(l, 2, ourpusher, MAX_PUSHER);
+ return lua_usepusher(l, ourpusher, np);
+}
+
+int channelnicklistindex, channelnicklistcount = -1;
+channel *channelnicklist;
+
+struct lua_pusher *channelnickpusher[MAX_PUSHER];
+
+static int lua_getnextchannick(lua_State *l) {
+ nick *np;
+
+ do {
+ channelnicklistindex++;
+
+ if(channelnicklistindex >= channelnicklistcount)
+ return 0;
+ } while((channelnicklist->users->content[channelnicklistindex] == nouser) || !(np = getnickbynumeric(channelnicklist->users->content[channelnicklistindex])));
+
+ return lua_usepusher(l, channelnickpusher, np);
+}
+
+static int lua_getfirstchannick(lua_State *l) {
+ if(!lua_isstring(l, 1))
+ return 0;
+
+ channelnicklist = findchannel((char *)lua_tostring(l, 1));
+ if(!channelnicklist|| !channelnicklist->users)
+ return 0;
+
+ channelnicklistindex = -1;
+ channelnicklistcount = channelnicklist->users->hashsize;
+
+ lua_setupnickpusher(l, 2, channelnickpusher, MAX_PUSHER);
+
+ return lua_getnextchannick(l);
+}
+
+static int lua_nickonchan(lua_State *l) {
+ int success = 0;
+ if(lua_islong(l, 1) && lua_isstring(l, 2)) {
+ channel *cp = findchannel((char *)lua_tostring(l, 2));
+ if(cp && cp->users) {
+ unsigned long *lp = getnumerichandlefromchanhash(cp->users, lua_tolong(l, 1));
+ if(lp)
+ success = 1;
+ }
+ }
+
+ lua_pushboolean(l, success);
+ return 1;
+}
+
+static int lua_simplechanmode(lua_State *ps) {
+ channel *cp;
+ char *modes;
+ flag_t add = 0, del = ~add;
+ flag_t permitted = CHANMODE_NOEXTMSG | CHANMODE_TOPICLIMIT | CHANMODE_SECRET | CHANMODE_PRIVATE | CHANMODE_INVITEONLY | CHANMODE_MODERATE | CHANMODE_NOCOLOUR | CHANMODE_NOCTCP | CHANMODE_REGONLY | CHANMODE_DELJOINS | CHANMODE_NOQUITMSG | CHANMODE_NONOTICE | CHANMODE_MODNOAUTH | CHANMODE_SINGLETARG;
+ modechanges changes;
+
+ if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
+ LUA_RETURN(ps, LUA_FAIL);
+
+ cp = findchannel((char *)lua_tostring(ps, 1));
+ if(!cp)
+ LUA_RETURN(ps, LUA_FAIL);
+
+ modes = (char *)lua_tostring(ps, 2);
+ if(!modes)
+ LUA_RETURN(ps, LUA_FAIL);
+
+ if(setflags(&add, permitted, modes, cmodeflags, REJECT_DISALLOWED|REJECT_UNKNOWN) != REJECT_NONE)
+ LUA_RETURN(ps, LUA_FAIL);
+
+ if(setflags(&del, permitted, modes, cmodeflags, REJECT_DISALLOWED|REJECT_UNKNOWN) != REJECT_NONE)
+ LUA_RETURN(ps, LUA_FAIL);
+
+ localsetmodeinit(&changes, cp, lua_nick);
+ localdosetmode_simple(&changes, add, ~del);
+ localsetmodeflush(&changes, 1);
+
+ LUA_RETURN(ps, LUA_OK);
+}
+
+static int lua_sethost(lua_State *ps) {
+ char *ident, *host;
+ nick *np;
+
+ if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3))
+ LUA_RETURN(ps, LUA_FAIL);
+
+ np = getnickbynumeric(lua_tolong(ps, 1));
+ if(!np)
+ LUA_RETURN(ps, LUA_FAIL);
+
+ ident = (char *)lua_tostring(ps, 2);
+ host = (char *)lua_tostring(ps, 3);
+ if(!lua_lineok(ident) || !lua_lineok(host))
+ LUA_RETURN(ps, LUA_FAIL);
+
+ sethostuser(np, ident, host);
+
+ LUA_RETURN(ps, LUA_OK);
+}
+
+static int lua_getvisiblehostmask(lua_State *l) {
+ nick *np;
+ char buf[HOSTLEN+USERLEN+NICKLEN+REALLEN+10];
+
+ if(!lua_islong(l, 1))
+ return 0;
+
+ np = getnickbynumeric(lua_tolong(l, 1));
+ if(!np)
+ return 0;
+
+ lua_pushstring(l, visiblehostmask(np, buf));
+ return 1;
+}
+