diff options
| author | Adam <Adam@anope.org> | 2013-05-26 17:13:11 -0400 |
|---|---|---|
| committer | Adam <Adam@anope.org> | 2013-05-26 17:13:11 -0400 |
| commit | 22658d63bdb1e52a66f4514af45fa55ca5891345 (patch) | |
| tree | 673304ab19f7e077b489354248247867518331f8 /modules/pseudoclients/chanserv.cpp | |
| parent | f2dee1e1d642b07947f59f91dfba9af34ef84685 (diff) | |
Get rid of the remaining references in the core to specific services. Move more stuff out of the core to the proper modules.
Diffstat (limited to 'modules/pseudoclients/chanserv.cpp')
| -rw-r--r-- | modules/pseudoclients/chanserv.cpp | 241 |
1 files changed, 156 insertions, 85 deletions
diff --git a/modules/pseudoclients/chanserv.cpp b/modules/pseudoclients/chanserv.cpp index 7b0234d2e..5a1fed00b 100644 --- a/modules/pseudoclients/chanserv.cpp +++ b/modules/pseudoclients/chanserv.cpp @@ -9,65 +9,23 @@ * Based on the original code of Services by Andy Church. */ -/*************************************************************************/ - #include "module.h" -class ExpireCallback : public Timer +class ChanServCore : public Module, public ChanServService { - public: - ExpireCallback(Module *o) : Timer(o, Config->GetBlock("options")->Get<time_t>("expiretimeout"), Anope::CurTime, true) { } + Reference<BotInfo> ChanServ; + std::vector<Anope::string> defaults; - void Tick(time_t) anope_override + public: + ChanServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR), + ChanServService(this) { - time_t chanserv_expire = Config->GetModule("chanserv")->Get<time_t>("expire", "14d"); - - if (!chanserv_expire || Anope::NoExpire || Anope::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 (Anope::CurTime - ci->last_used >= chanserv_expire) - { - if (ci->c) - { - time_t last_used = ci->last_used; - for (Channel::ChanUserList::const_iterator cit = ci->c->users.begin(), cit_end = ci->c->users.end(); cit != cit_end && last_used == ci->last_used; ++cit) - ci->AccessFor(cit->second->user); - expire = last_used == ci->last_used; - } - else - expire = true; - } - - if (ci->HasExt("NO_EXPIRE")) - expire = false; - - FOREACH_MOD(I_OnPreChanExpire, OnPreChanExpire(ci, expire)); - - if (expire) - { - Anope::string extra; - if (ci->HasExt("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; - } - } + Implementation i[] = { I_OnReload, I_OnBotDelete, I_OnBotPrivmsg, I_OnDelCore, + I_OnPreHelp, I_OnPostHelp, I_OnCheckModes, I_OnCreateChan, I_OnCanSet, + I_OnChannelSync, I_OnBotKick, I_OnExpireTick, I_OnCheckDelete, I_OnPreUplinkSync, + I_OnChanRegistered, I_OnTopicUpdated }; + ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); } -}; - -class MyChanServService : public ChanServService -{ - public: - MyChanServService(Module *m) : ChanServService(m) { } void Hold(Channel *c) anope_override { @@ -76,13 +34,14 @@ class MyChanServService : public ChanServService */ class ChanServTimer : public Timer { + Reference<BotInfo> &ChanServ; Reference<Channel> c; public: /** Constructor * @param chan The channel */ - ChanServTimer(Module *m, Channel *chan) : Timer(m, Config->GetModule(m)->Get<time_t>("inhabit", "15s")), c(chan) + ChanServTimer(Reference<BotInfo> &cs, Module *m, Channel *chan) : Timer(m, Config->GetModule(m)->Get<time_t>("inhabit", "15s")), ChanServ(cs), c(chan) { if (!ChanServ || !c) return; @@ -122,29 +81,7 @@ class MyChanServService : public ChanServService if (c->HasExt("INHABIT")) return; - new ChanServTimer(this->owner, c); - } -}; - -class ChanServCore : public Module -{ - MyChanServService chanserv; - ExpireCallback expires; - std::vector<Anope::string> defaults; - - public: - ChanServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR), - chanserv(this), expires(this) - { - Implementation i[] = { I_OnReload, I_OnBotDelete, I_OnBotPrivmsg, I_OnDelCore, - I_OnPreHelp, I_OnPostHelp, I_OnCheckModes, I_OnCreateChan, I_OnCanSet, - I_OnChannelSync, I_OnBotKick }; - ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); - } - - ~ChanServCore() - { - ChanServ = NULL; + new ChanServTimer(ChanServ, this->owner, c); } void OnReload(Configuration::Conf *conf) anope_override @@ -152,11 +89,11 @@ class ChanServCore : public Module const Anope::string &channick = conf->GetModule(this)->Get<const Anope::string>("client"); if (channick.empty()) - throw ConfigException(this->name + ": <client> must be defined"); + throw ConfigException(Module::name + ": <client> must be defined"); BotInfo *bi = BotInfo::Find(channick, true); if (!bi) - throw ConfigException(this->name + ": no bot named " + channick); + throw ConfigException(Module::name + ": no bot named " + channick); ChanServ = bi; @@ -265,7 +202,7 @@ class ChanServCore : public Module EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.c || source.service != ChanServ) + if (!params.empty() || source.c || source.service != *ChanServ) return EVENT_CONTINUE; source.Reply(_("\002%s\002 allows you to register and control various\n" "aspects of channels. %s can often prevent\n" @@ -280,7 +217,7 @@ class ChanServCore : public Module void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.c || source.service != ChanServ) + if (!params.empty() || source.c || source.service != *ChanServ) return; time_t expire = Config->GetModule(this)->Get<time_t>("expire", "14d"); if (expire >= 86400) @@ -354,14 +291,20 @@ class ChanServCore : public Module bool perm = c->HasMode("PERM") || (c->ci && c->ci->HasExt("PERSIST")); if (!perm && !c->HasExt("BOTCHANNEL") && (c->users.empty() || (c->users.size() == 1 && c->users.begin()->second->user->server == Me))) { - chanserv.Hold(c); + this->Hold(c); } if (c->ci) { c->CheckModes(); if (Me && Me->IsSynced()) - c->ci->RestoreTopic(); + { + /* Update channel topic */ + if ((c->ci->HasExt("KEEPTOPIC") || c->ci->HasExt("TOPICLOCK")) && c->ci->last_topic != c->topic) + { + c->ChangeTopic(!c->ci->last_topic_setter.empty() ? c->ci->last_topic_setter : c->ci->WhoSends()->nick, c->ci->last_topic, c->ci->last_topic_time ? c->ci->last_topic_time : Anope::CurTime); + } + } } } @@ -372,14 +315,142 @@ class ChanServCore : public Module * ChanServ always enforces channels like this to keep people from deleting bots etc * that are holding channels. */ - if (c->ci && c->users.size() == (c->ci->bi && c->FindUser(c->ci->bi) ? 2 : 1) && !c->HasExt("INHABIT") && !c->HasExt("SYNCING")) + if (c->ci && c->users.size() == (c->ci->bi && c->FindUser(c->ci->bi) ? 2 : 1) && !c->HasExt("INHABIT") && !c->syncing) { /* Join ChanServ and set a timer for this channel to part ChanServ later */ - chanserv.Hold(c); + this->Hold(c); } return EVENT_CONTINUE; } + + void OnLog(Log *l) anope_override + { + if (l->type == LOG_CHANNEL) + l->bi = ChanServ; + } + + void OnExpireTick() anope_override + { + time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "14d"); + + if (!chanserv_expire || Anope::NoExpire || Anope::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 (Anope::CurTime - ci->last_used >= chanserv_expire) + { + if (ci->c) + { + time_t last_used = ci->last_used; + for (Channel::ChanUserList::const_iterator cit = ci->c->users.begin(), cit_end = ci->c->users.end(); cit != cit_end && last_used == ci->last_used; ++cit) + ci->AccessFor(cit->second->user); + expire = last_used == ci->last_used; + } + else + expire = true; + } + + if (ci->HasExt("NO_EXPIRE")) + expire = false; + + FOREACH_MOD(I_OnPreChanExpire, OnPreChanExpire(ci, expire)); + + if (expire) + { + Anope::string extra; + if (ci->HasExt("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; + } + } + } + + EventReturn OnCheckDelete(Channel *c) anope_override + { + /* Do not delete this channel if ChanServ/a BotServ bot is inhabiting it */ + if (c->HasExt("INHABIT")) + return EVENT_STOP; + + /* Channel is persistent, it shouldn't be deleted and the service bot should stay */ + if (c->ci && c->ci->HasExt("PERSIST")) + return EVENT_STOP; + + return EVENT_CONTINUE; + } + + void OnPreUplinkSync(Server *serv) anope_override + { + /* Find all persistent channels and create them, as we are about to finish burst to our uplink */ + for (registered_channel_map::iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it) + { + ChannelInfo *ci = it->second; + if (ci->HasExt("PERSIST")) + { + bool created; + ci->c = Channel::FindOrCreate(ci->name, created, ci->time_registered); + + if (ModeManager::FindChannelModeByName("PERM") != NULL) + { + if (created) + IRCD->SendChannel(ci->c); + ci->c->SetMode(NULL, "PERM"); + } + else + { + if (!ci->bi) + ci->WhoSends()->Assign(NULL, ci); + if (ci->c->FindUser(ci->bi) == NULL) + { + ChannelStatus status(Config->GetModule("botserv")->Get<const Anope::string>("botmodes")); + ci->bi->Join(ci->c, &status); + } + } + } + } + + } + + void OnChanRegistered(ChannelInfo *ci) anope_override + { + /* Mark the channel as persistent */ + if (ci->c->HasMode("PERM")) + ci->ExtendMetadata("PERSIST"); + /* Persist may be in def cflags, set it here */ + else if (ci->HasExt("PERSIST")) + ci->c->SetMode(NULL, "PERM"); + } + + void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override + { + if (!c->ci) + return; + + /* We only compare the topics here, not the time or setter. This is because some (old) IRCds do not + * allow us to set the topic as someone else, meaning we have to bump the TS and change the setter to us. + * This desyncs what is really set with what we have stored, and we end up resetting the topic often when + * it is not required + */ + if (c->ci->HasExt("TOPICLOCK") && c->ci->last_topic != c->topic) + { + c->ChangeTopic(c->ci->last_topic_setter, c->ci->last_topic, c->ci->last_topic_time); + } + else + { + c->ci->last_topic = c->topic; + c->ci->last_topic_setter = c->topic_setter; + c->ci->last_topic_time = c->topic_ts; + } + } }; MODULE_INIT(ChanServCore) |
