#include "module.h" #define AUTHOR "DrStein" #define MYNAME "cs_nounregistered" #define VERSION "1.3.1" /* -------------------------------------------- * MODULE AUTHOR AND RELEASE DATE * -------------------------------------------- * Name: cs_nounregistered * Author: DrStein * Original cs_forbidunreg: SGR * Date: 10/03/2004 * * -------------------------------------------- * MODULE DESCRIPTION * -------------------------------------------- * When set ON, this module will forbid users * joining any channels that are not registered * Opers and above are not affected. * When an user joins a non-registered channel * ChanServ will join that channel and stay * there for TIME_TO_INHABIT amount of time. * ChanServ will send a Global message to warn * Global IRC Operators up. * * -------------------------------------------- * COMMANDS LIST * -------------------------------------------- * /msg ChanServ NOUNREG [ON|OFF] * * -------------------------------------------- * MODULE SUPPORT * -------------------------------------------- * IRCd: ONLY Unreal 3.2.2 or later. * Anope version: ONLY 1.7.6 or later. * * Note: CAPAB support! * * -------------------------------------------- * CHANGELOG * -------------------------------------------- * v1.3.1 - Fixed several issues around. * v1.3.0 - Updated to the last IRCd protocol * supporting changes. * Now, the module only support * UnrealIRCd. Release Notes for more. * v1.2.0 - Added complete CAPAB compatibility. * Now, ChanServ will send a Global on * users joins. * v1.1.0 - Added support for Anope 1.6 * v1.0.0 - Initial release. * * -------------------------------------------- * GRATEFULNESS * -------------------------------------------- * SGR, Trystan * * -------------------------------------------- * RELEASE NOTES * -------------------------------------------- * There are a few changes in the Unreal * protocol support. We (Anope) are now using * SJOIN for Unreal and SJB64 time stamps. * I have no time for now to update for other * IRCd, so.. this module will work on Unreal * only. * * -------------------------------------------- * START OF CONFIGURATION BLOCK - please read * the comments. * -------------------------------------------- */ /* Please, 5 lines only. */ #define nounregisteredMsg1 "You can not create new channels on this NetWork." #define nounregisteredMsg2 "Please, join an official channel." #define nounregisteredMsg3 "Join #help, for help or doubts." //#define nounregisteredMsg4 " More info?" //#define nounregisteredMsg5 "Add it here." #define nounregKICKREASON "You can not create new channels." /* Set this to a reasonable time, between 3 and 30 seconds */ #define TIME_TO_INHABIT "5s" /* Send a Global when an user joins a non-registered channel */ #define SEND_GLOBAL_ON_JOIN /* --------------------------------------------- * Please don't edit anything below here. * --------------------------------------------- */ /* Main rutine */ int do_nounreg(char *source, int ac, char **av); /* Handle the user commands */ int do_setnounreg(User *u); /* Short help */ void nounreg_help(User *u); /* Full help */ int nounreg_help_full(User *u); /* Makes ChanServ to leave a channel, CallBack purposes */ int do_leavechan(int argc, char **argv); /* Hanlde the MODE event. */ int nounreg_modesilence(char *source, int ac, char **av); char *LASTBANCHAN; int nounreg_on = 1; /** * AnopeInit is called when the module is loaded * @param argc Argument count * @param argv Argument list * @return MOD_STOP if we want to unload, MOD_CONT if we want to carry on **/ int AnopeInit(int argc, char **argv) { Command *c; Message *msg = NULL; int status = 0; alog("[%s.so] Loading...", MYNAME); c = createCommand("NOUNREG", do_setnounreg, is_services_admin, -1,-1,-1,-1,-1); status += moduleAddCommand(CHANSERV, c, MOD_HEAD); msg = createMessage("SJOIN", do_nounreg); status += moduleAddMessage(msg, MOD_TAIL); msg = createMessage("MODE", nounreg_modesilence); status += moduleAddMessage(msg, MOD_HEAD); if (status == 0) { alog("[%s.so] Loaded successfully", MYNAME); alog("[%s.so] For more info see /msg %s HELP NOUNREG", MYNAME, s_ChanServ); } else { alog("[%s.so] FAILED to load - result %d", MYNAME, status); } moduleAddHelp(c, nounreg_help_full); moduleSetChanHelp(nounreg_help); moduleAddAuthor(AUTHOR); moduleAddVersion(VERSION); return MOD_CONT; } /** * AnopeFini is called when the module is unloaded **/ void AnopeFini(void) { alog("Unloading module %s.so", MYNAME); } void nounreg_help(User *u) { if (is_services_admin(u)) notice(s_ChanServ,u->nick, " NOUNREG Forbid non oper'ed users making channels."); } int nounreg_help_full(User *u) { if (is_services_admin(u)) { notice(s_ChanServ, u->nick, "Syntax: NOUNREG [ON|OFF]"); notice(s_ChanServ, u->nick, " "); notice(s_ChanServ, u->nick, "Use this command without any parameters to setting to see the"); notice(s_ChanServ, u->nick, " current setting. When set to ON, %s will forbid a user", s_ChanServ); notice(s_ChanServ, u->nick, " joining any channels that are not registered."); notice(s_ChanServ, u->nick, "Opers and above are not affected."); } return MOD_CONT; } /** * Provide the user inteface to set [ON|OFF] the module * @param u The user who executed this command * @return MOD_CONT if we want to process other commands * in this command stack, MOD_STOP if we dont **/ int do_setnounreg(User *u) { char *args = NULL; char *seton = NULL; if (moduleGetLastBuffer()) { args = sstrdup(moduleGetLastBuffer()); seton = myStrGetToken(args,' ',0); free(args); } if (!seton) { if (nounreg_on) { notice(s_ChanServ, u->nick, "The current NOUNREG setting is ON"); } else { notice(s_ChanServ, u->nick, "The current NOUNREG setting is OFF"); } return MOD_CONT; } if (stricmp(seton,"ON") == 0 ) { notice(s_ChanServ, u->nick, "The current NOUNREG setting is ON"); anope_cmd_global(s_ChanServ, "%s set NOUNREG ON.", u->nick); nounreg_on = 1; return MOD_CONT; } if (stricmp(seton,"OFF") == 0 ) { notice(s_ChanServ,u->nick, "The current NOUNREG setting is OFF"); anope_cmd_global(s_ChanServ, "%s set NOUNREG OFF.", u->nick); nounreg_on = 0; return MOD_CONT; } else { notice(s_ChanServ, u->nick, "SYNTAX: NOUNREG [ON|OFF]"); return MOD_CONT; } return MOD_CONT; } /** * Module's main rutine. Detect when an user joined a * channel. If the user is not an IRC Operator, will * be kicked and banned out from the channel. **/ int do_nounreg(char *source, int ac, char **av) { ChannelInfo *ci; Channel *c; User *u = NULL; if (!nounreg_on) { return MOD_CONT; } if ((!source) || (ac != 3)) { return MOD_CONT; } if (!stristr(av[1],"#")) { return MOD_CONT; } if ((ci = cs_findchan(av[1]))) { return MOD_CONT; } c = findchan(av[1]); if (!c) { return MOD_CONT; } if (c->usercount > 1) { return MOD_CONT; } else { char fcounter[CHANMAX+7], *am[3]; struct c_userlist *cu, *next; int i = 0; int count = c->exceptcount; char **excepts = scalloc(sizeof(char *) * count, 1); char *s, *end, cubuf[ircd->max_symbols + 2], *end2, *cumodes[ircd->max_symbols + 1], *argv[1], *an[3]; cubuf[0] = '+'; cumodes[0] = cubuf; s = av[2]; end = strchr(s, ' '); if (end) *end = 0; end2 = cubuf + 1; while (csmodes[(int) *s] != 0) *end2++ = csmodes[(int) *s++]; *end2 = 0; u = finduser(s); if (!u) { alog("[%s.so] user: SJOIN for nonexistent user %s on %s", MYNAME, s, av[1]); return MOD_CONT; } if (is_oper(u)) { return MOD_CONT; } LASTBANCHAN = av[1]; #if defined(SEND_GLOBAL_ON_JOIN) anope_cmd_global(s_ChanServ, "[%s.so] %s has just joined a non-registered channel (%s).", MYNAME, u->nick, av[1]); #endif anope_cmd_join(s_ChanServ, av[1], time(NULL)); anope_cmd_mode(whosends(ci), av[1], "+o %s %lu", s_ChanServ, time(NULL)); anope_cmd_mode(whosends(ci), av[1], "+b *!*@* %lu", time(NULL)); for (i = 0; i < count; i++) { excepts[i] = sstrdup(c->excepts[i]); } for (i = 0; i < count; i++) { an[0] = sstrdup(av[1]); an[1] = sstrdup("-e"); an[2] = excepts[i]; anope_cmd_mode(whosends(ci), an[0], "%s :%s", an[1], an[2]); do_cmode(s_ChanServ, 3, an); free(an[2]); free(an[1]); free(an[0]); } free(excepts); for (cu = c->users; cu; cu = next) { next = cu->next; if (is_oper(cu->user)) { continue; } am[0] = c->name; am[1] = cu->user->nick; #ifdef nounregKICKREASON am[2] = nounregKICKREASON; #else am[2] = "Only registered channels may be joined."; #endif anope_cmd_kick(whosends(ci), am[0], am[1], "%s", am[2]); do_kick(s_ChanServ, 3, am); #ifdef nounregisteredMsg1 notice(s_ChanServ, cu->user->nick, nounregisteredMsg1); #endif #ifdef nounregisteredMsg2 notice(s_ChanServ, cu->user->nick , nounregisteredMsg2); #endif #ifdef nounregisteredMsg3 notice(s_ChanServ, cu->user->nick, nounregisteredMsg3); #endif #ifdef nounregisteredMsg4 notice(s_ChanServ, cu->user->nick, nounregisteredMsg4); #endif #ifdef nounregisteredMsg5 notice(s_ChanServ, cu->user->nick, nounregisteredMsg5); #endif } argv[0] = sstrdup(av[1]); snprintf(fcounter,CHANMAX+7,"%s-forbid",av[1]); if (moduleAddCallback(fcounter, time(NULL)+dotime(TIME_TO_INHABIT), do_leavechan,1,argv) != MOD_ERR_OK) { anope_cmd_part(s_ChanServ, av[1], NULL); } if (argv[0] != NULL) { free(argv[0]); } return MOD_CONT; } return MOD_CONT; } /** * Too simple :) **/ int do_leavechan(int argc, char **argv) { char *chan = argv[0]; anope_cmd_part(s_ChanServ, chan, NULL); return MOD_CONT; } /** * Handle the MODEs changes. If the channel is * "our" channel, ChanServ will reset * LASTBANCHAN. **/ int nounreg_modesilence(char *source, int ac, char **av) { if (*av[0] == '#' || *av[0] == '&') { if (ac < 2) { return MOD_CONT; } if (av[0] == LASTBANCHAN) { LASTBANCHAN = "none"; return MOD_STOP; } } else { return MOD_CONT; } return MOD_CONT; } /* EOF */