diff options
Diffstat (limited to 'modules/commands/cs_register.cpp')
-rw-r--r-- | modules/commands/cs_register.cpp | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/modules/commands/cs_register.cpp b/modules/commands/cs_register.cpp new file mode 100644 index 000000000..117212519 --- /dev/null +++ b/modules/commands/cs_register.cpp @@ -0,0 +1,193 @@ +/* ChanServ core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" + +class CommandCSRegister : public Command +{ + public: + CommandCSRegister(Module *creator) : Command(creator, "chanserv/register", 1, 2) + { + this->SetDesc(_("Register a channel")); + this->SetSyntax(_("\037channel\037 [\037description\037]")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + const Anope::string &chan = params[0]; + const Anope::string &chdesc = params.size() > 1 ? params[1] : ""; + + User *u = source.u; + Channel *c = findchan(params[0]); + ChannelInfo *ci = cs_findchan(params[0]); + + if (readonly) + source.Reply(_("Sorry, channel registration is temporarily disabled.")); + else if (u->Account()->HasFlag(NI_UNCONFIRMED)) + source.Reply(_("You must confirm your account before you can register a channel.")); + else if (chan[0] == '&') + source.Reply(_("Local channels cannot be registered.")); + else if (chan[0] != '#') + source.Reply(CHAN_SYMBOL_REQUIRED); + else if (!ircdproto->IsChannelValid(chan)) + source.Reply(CHAN_X_INVALID, chan.c_str()); + else if (ci) + source.Reply(_("Channel \002%s\002 is already registered!"), chan.c_str()); + else if (c && !c->HasUserStatus(u, CMODE_OP)) + source.Reply(_("You must be a channel operator to register the channel.")); + else if (Config->CSMaxReg && u->Account()->channelcount >= Config->CSMaxReg && !u->HasPriv("chanserv/no-register-limit")) + source.Reply(u->Account()->channelcount > Config->CSMaxReg ? CHAN_EXCEEDED_CHANNEL_LIMIT : _(CHAN_REACHED_CHANNEL_LIMIT), Config->CSMaxReg); + else + { + ci = new ChannelInfo(chan); + ci->SetFounder(u->Account()); + if (!chdesc.empty()) + ci->desc = chdesc; + + if (c && !c->topic.empty()) + { + ci->last_topic = c->topic; + ci->last_topic_setter = c->topic_setter; + ci->last_topic_time = c->topic_time; + } + else + ci->last_topic_setter = source.owner->nick; + + ci->bi = NULL; + Log(LOG_COMMAND, u, this, ci); + source.Reply(_("Channel \002%s\002 registered under your nickname: %s"), chan.c_str(), u->nick.c_str()); + + /* Implement new mode lock */ + if (c) + { + check_modes(c); + + ChannelMode *cm; + if (u->FindChannel(c) != NULL) + { + /* On most ircds you do not receive the admin/owner mode till its registered */ + if ((cm = ModeManager::FindChannelModeByName(CMODE_OWNER))) + c->SetMode(NULL, cm, u->nick); + else if ((cm = ModeManager::FindChannelModeByName(CMODE_PROTECT))) + c->RemoveMode(NULL, cm, u->nick); + } + + /* Mark the channel as persistant */ + if (c->HasMode(CMODE_PERM)) + ci->SetFlag(CI_PERSIST); + /* Persist may be in def cflags, set it here */ + else if (ci->HasFlag(CI_PERSIST) && (cm = ModeManager::FindChannelModeByName(CMODE_PERM))) + c->SetMode(NULL, CMODE_PERM); + } + + FOREACH_MOD(I_OnChanRegistered, OnChanRegistered(ci)); + } + return; + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Registers a channel in the %s database. In order\n" + "to use this command, you must first be a channel operator\n" + "on the channel you're trying to register.\n" + "The description, which is optional, is a\n" + "general description of the channel's purpose.\n" + " \n" + "When you register a channel, you are recorded as the\n" + "\"founder\" of the channel. The channel founder is allowed\n" + "to change all of the channel settings for the channel;\n" + "%s will also automatically give the founder\n" + "channel-operator privileges when s/he enters the channel.\n" + "See the \002ACCESS\002 command (\002%s%s HELP ACCESS\002) for\n" + "information on giving a subset of these privileges to\n" + "other channel users.\n" + " \n" + "NOTICE: In order to register a channel, you must have\n" + "first registered your nickname. If you haven't,\n" + "\002%s%s HELP\002 for information on how to do so."), + source.owner->nick.c_str(), source.owner->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + return true; + } +}; + +class ExpireCallback : public CallBack +{ + public: + ExpireCallback(Module *owner) : CallBack(owner, Config->ExpireTimeout, Anope::CurTime, true) { } + + void Tick(time_t) + { + if (!Config->CSExpire || noexpire || readonly) + return; + + for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ) + { + ChannelInfo *ci = it->second; + ++it; + + bool expire = false; + if (ci->HasFlag(CI_SUSPENDED)) + { + if (Config->CSSuspendExpire && Anope::CurTime - ci->last_used >= Config->CSSuspendExpire) + expire = true; + } + else if (!ci->c && Config->CSExpire && Anope::CurTime - ci->last_used >= Config->CSExpire) + expire = true; + + if (ci->HasFlag(CI_NO_EXPIRE)) + expire = false; + + if (expire) + { + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreChanExpire, OnPreChanExpire(ci)); + if (MOD_RESULT == EVENT_STOP) + continue; + + Anope::string extra; + if (ci->HasFlag(CI_SUSPENDED)) + extra = "suspended "; + + Log(LOG_NORMAL, "chanserv/expire") << "Expiring " << extra << "channel " << ci->name << " (founder: " << (ci->GetFounder() ? ci->GetFounder()->display : "(none)") << ")"; + FOREACH_MOD(I_OnChanExpire, OnChanExpire(ci)); + delete ci; + } + } + } +}; + +class CSRegister : public Module +{ + CommandCSRegister commandcsregister; + ExpireCallback ecb; + + public: + CSRegister(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcsregister(this), ecb(this) + { + this->SetAuthor("Anope"); + + ModuleManager::RegisterService(&commandcsregister); + ModuleManager::Attach(I_OnDelChan, this); + } + + void OnDelChan(ChannelInfo *ci) + { + if (ci->c && ci->c->HasMode(CMODE_REGISTERED)) + ci->c->RemoveMode(NULL, CMODE_REGISTERED, "", false); + } +}; + +MODULE_INIT(CSRegister) |