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 | |
| 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')
| -rw-r--r-- | modules/pseudoclients/botserv.cpp | 27 | ||||
| -rw-r--r-- | modules/pseudoclients/chanserv.cpp | 241 | ||||
| -rw-r--r-- | modules/pseudoclients/global.cpp | 51 | ||||
| -rw-r--r-- | modules/pseudoclients/hostserv.cpp | 22 | ||||
| -rw-r--r-- | modules/pseudoclients/memoserv.cpp | 85 | ||||
| -rw-r--r-- | modules/pseudoclients/nickserv.cpp | 295 | ||||
| -rw-r--r-- | modules/pseudoclients/operserv.cpp | 29 |
7 files changed, 417 insertions, 333 deletions
diff --git a/modules/pseudoclients/botserv.cpp b/modules/pseudoclients/botserv.cpp index 5a84d1e7f..828f3b0e2 100644 --- a/modules/pseudoclients/botserv.cpp +++ b/modules/pseudoclients/botserv.cpp @@ -9,40 +9,35 @@ * Based on the original code of Services by Andy Church. */ -/*************************************************************************/ - #include "module.h" class BotServCore : public Module { + Reference<BotInfo> BotServ; + public: BotServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR) { - Implementation i[] = { I_OnReload, I_OnSetCorrectModes, I_OnBotAssign, I_OnBotDelete, I_OnPrivmsg, I_OnJoinChannel, I_OnLeaveChannel, + Implementation i[] = { I_OnReload, I_OnSetCorrectModes, I_OnBotAssign, I_OnPrivmsg, I_OnJoinChannel, I_OnLeaveChannel, I_OnPreHelp, I_OnPostHelp, I_OnChannelModeSet, I_OnCreateChan, I_OnUserKicked, I_OnCreateBot }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); } - ~BotServCore() - { - BotServ = NULL; - } - void OnReload(Configuration::Conf *conf) anope_override { const Anope::string &bsnick = conf->GetModule(this)->Get<const Anope::string>("client"); if (bsnick.empty()) - throw ConfigException(this->name + ": <client> must be defined"); + throw ConfigException(Module::name + ": <client> must be defined"); BotInfo *bi = BotInfo::Find(bsnick, true); if (!bi) - throw ConfigException(this->name + ": no bot named " + bsnick); + throw ConfigException(Module::name + ": no bot named " + bsnick); BotServ = bi; } - void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool give_modes) anope_override + void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) anope_override { /* Do not allow removing bot modes on our service bots */ if (chan->ci && chan->ci->bi == user) @@ -62,12 +57,6 @@ class BotServCore : public Module } } - void OnBotDelete(BotInfo *bi) anope_override - { - if (bi == BotServ) - BotServ = NULL; - } - void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override { if (!u || !c || !c->ci || !c->ci->bi || msg.empty()) @@ -256,7 +245,7 @@ class BotServCore : public Module /* Channel is syncing from a netburst, don't destroy it as more users are probably wanting to join immediatly * We also don't part the bot here either, if necessary we will part it after the sync */ - if (c->HasExt("SYNCING")) + if (c->syncing) return; /* Additionally, do not delete this channel if ChanServ/a BotServ bot is inhabiting it */ @@ -305,7 +294,7 @@ class BotServCore : public Module void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.c || source.service != BotServ) + if (!params.empty() || source.c || source.service != *BotServ) return; source.Reply(_(" \n" 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) diff --git a/modules/pseudoclients/global.cpp b/modules/pseudoclients/global.cpp index 67cb594c5..224cbeea1 100644 --- a/modules/pseudoclients/global.cpp +++ b/modules/pseudoclients/global.cpp @@ -9,12 +9,12 @@ * Based on the original code of Services by Andy Church. */ -/*************************************************************************/ - #include "module.h" -class MyGlobalService : public GlobalService +class GlobalCore : public Module, public GlobalService { + Reference<BotInfo> Global; + void ServerGlobal(const BotInfo *sender, Server *s, const Anope::string &message) { if (s != Me && !s->IsJuped()) @@ -24,12 +24,21 @@ class MyGlobalService : public GlobalService } public: - MyGlobalService(Module *m) : GlobalService(m) { } + GlobalCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR), + GlobalService(this) + { + Implementation i[] = { I_OnReload, I_OnRestart, I_OnShutdown, I_OnNewServer, I_OnPreHelp }; + ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); + } void SendGlobal(const BotInfo *sender, const Anope::string &source, const Anope::string &message) anope_override { if (Me->GetLinks().empty()) return; + if (!sender) + sender = Global; + if (!sender) + return; Anope::string rmessage; @@ -40,57 +49,33 @@ class MyGlobalService : public GlobalService this->ServerGlobal(sender, Servers::GetUplink(), rmessage); } -}; - -class GlobalCore : public Module -{ - MyGlobalService global; - - public: - GlobalCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR), - global(this) - { - Implementation i[] = { I_OnReload, I_OnBotDelete, I_OnRestart, I_OnShutdown, I_OnNewServer, I_OnPreHelp }; - ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); - } - - ~GlobalCore() - { - Global = NULL; - } void OnReload(Configuration::Conf *conf) anope_override { const Anope::string &glnick = conf->GetModule(this)->Get<const Anope::string>("client"); if (glnick.empty()) - throw ConfigException(this->name + ": <client> must be defined"); + throw ConfigException(Module::name + ": <client> must be defined"); BotInfo *bi = BotInfo::Find(glnick, true); if (!bi) - throw ConfigException(this->name + ": no bot named " + glnick); + throw ConfigException(Module::name + ": no bot named " + glnick); Global = bi; } - void OnBotDelete(BotInfo *bi) anope_override - { - if (bi == Global) - Global = NULL; - } - void OnRestart() anope_override { const Anope::string &gl = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown"); if (!gl.empty()) - this->global.SendGlobal(Global, "", gl); + this->SendGlobal(Global, "", gl); } void OnShutdown() anope_override { const Anope::string &gl = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown"); if (!gl.empty()) - this->global.SendGlobal(Global, "", gl); + this->SendGlobal(Global, "", gl); } void OnNewServer(Server *s) anope_override @@ -102,7 +87,7 @@ class GlobalCore : public Module EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.c || source.service != Global) + if (!params.empty() || source.c || source.service != *Global) return EVENT_CONTINUE; source.Reply(_("%s commands:"), Global->nick.c_str()); return EVENT_CONTINUE; diff --git a/modules/pseudoclients/hostserv.cpp b/modules/pseudoclients/hostserv.cpp index e3afa37d3..7c98c7344 100644 --- a/modules/pseudoclients/hostserv.cpp +++ b/modules/pseudoclients/hostserv.cpp @@ -9,12 +9,11 @@ * Based on the original code of Services by Andy Church. */ -/*************************************************************************/ - #include "module.h" class HostServCore : public Module { + Reference<BotInfo> HostServ; public: HostServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR) { @@ -22,36 +21,25 @@ class HostServCore : public Module if (!IRCD || !IRCD->CanSetVHost) throw ModuleException("Your IRCd does not support vhosts"); - Implementation i[] = { I_OnReload, I_OnBotDelete, I_OnNickIdentify, I_OnNickUpdate, I_OnPreHelp, + Implementation i[] = { I_OnReload, I_OnNickIdentify, I_OnNickUpdate, I_OnPreHelp, I_OnSetVhost, I_OnDeleteVhost }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); } - ~HostServCore() - { - HostServ = NULL; - } - void OnReload(Configuration::Conf *conf) anope_override { const Anope::string &hsnick = conf->GetModule(this)->Get<const Anope::string>("client"); if (hsnick.empty()) - throw ConfigException(this->name + ": <client> must be defined"); + throw ConfigException(Module::name + ": <client> must be defined"); BotInfo *bi = BotInfo::Find(hsnick, true); if (!bi) - throw ConfigException(this->name + ": no bot named " + hsnick); + throw ConfigException(Module::name + ": no bot named " + hsnick); HostServ = bi; } - void OnBotDelete(BotInfo *bi) anope_override - { - if (bi == HostServ) - HostServ = NULL; - } - void OnNickIdentify(User *u) anope_override { const NickAlias *na = NickAlias::Find(u->nick); @@ -87,7 +75,7 @@ class HostServCore : public Module EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.c || source.service != HostServ) + if (!params.empty() || source.c || source.service != *HostServ) return EVENT_CONTINUE; source.Reply(_("%s commands:"), HostServ->nick.c_str()); return EVENT_CONTINUE; diff --git a/modules/pseudoclients/memoserv.cpp b/modules/pseudoclients/memoserv.cpp index 1988961cd..5136e2af0 100644 --- a/modules/pseudoclients/memoserv.cpp +++ b/modules/pseudoclients/memoserv.cpp @@ -9,34 +9,39 @@ * Based on the original code of Services by Andy Church. */ -/*************************************************************************/ - #include "module.h" -static bool SendMemoMail(NickCore *nc, MemoInfo *mi, Memo *m) +class MemoServCore : public Module, public MemoServService { - Anope::string subject = Language::Translate(nc, Config->GetBlock("mail")->Get<const Anope::string>("memo_subject").c_str()), - message = Language::Translate(Config->GetBlock("mail")->Get<const Anope::string>("memo_message").c_str()); - - subject = subject.replace_all_cs("%n", nc->display); - subject = subject.replace_all_cs("%s", m->sender); - subject = subject.replace_all_cs("%d", stringify(mi->GetIndex(m) + 1)); - subject = subject.replace_all_cs("%t", m->text); - subject = subject.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname")); - - message = message.replace_all_cs("%n", nc->display); - message = message.replace_all_cs("%s", m->sender); - message = message.replace_all_cs("%d", stringify(mi->GetIndex(m) + 1)); - message = message.replace_all_cs("%t", m->text); - message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname")); + Reference<BotInfo> MemoServ; - return Mail::Send(nc, subject, message); -} + bool SendMemoMail(NickCore *nc, MemoInfo *mi, Memo *m) + { + Anope::string subject = Language::Translate(nc, Config->GetBlock("mail")->Get<const Anope::string>("memo_subject").c_str()), + message = Language::Translate(Config->GetBlock("mail")->Get<const Anope::string>("memo_message").c_str()); + + subject = subject.replace_all_cs("%n", nc->display); + subject = subject.replace_all_cs("%s", m->sender); + subject = subject.replace_all_cs("%d", stringify(mi->GetIndex(m) + 1)); + subject = subject.replace_all_cs("%t", m->text); + subject = subject.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname")); + + message = message.replace_all_cs("%n", nc->display); + message = message.replace_all_cs("%s", m->sender); + message = message.replace_all_cs("%d", stringify(mi->GetIndex(m) + 1)); + message = message.replace_all_cs("%t", m->text); + message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname")); + + return Mail::Send(nc, subject, message); + } -class MyMemoServService : public MemoServService -{ public: - MyMemoServService(Module *m) : MemoServService(m) { } + MemoServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR), + MemoServService(this) + { + Implementation i[] = { I_OnNickCoreCreate, I_OnCreateChan, I_OnReload, I_OnBotDelete, I_OnNickIdentify, I_OnJoinChannel, I_OnUserAway, I_OnNickUpdate, I_OnPreHelp, I_OnPostHelp }; + ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); + } MemoResult Send(const Anope::string &source, const Anope::string &target, const Anope::string &message, bool force) anope_override { @@ -134,34 +139,17 @@ class MyMemoServService : public MemoServService u->SendMessage(MemoServ, _("You have reached your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."), nc->memos.memomax); } } -}; - -class MemoServCore : public Module -{ - MyMemoServService memoserv; - public: - MemoServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR), - memoserv(this) - { - Implementation i[] = { I_OnNickCoreCreate, I_OnCreateChan, I_OnReload, I_OnBotDelete, I_OnNickIdentify, I_OnJoinChannel, I_OnUserAway, I_OnNickUpdate, I_OnPreHelp, I_OnPostHelp }; - ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); - } - - ~MemoServCore() - { - MemoServ = NULL; - } void OnReload(Configuration::Conf *conf) anope_override { const Anope::string &msnick = conf->GetModule(this)->Get<const Anope::string>("client"); if (msnick.empty()) - throw ConfigException(this->name + ": <client> must be defined"); + throw ConfigException(Module::name + ": <client> must be defined"); BotInfo *bi = BotInfo::Find(msnick, true); if (!bi) - throw ConfigException(this->name + ": no bot named " + msnick); + throw ConfigException(Module::name + ": no bot named " + msnick); MemoServ = bi; } @@ -184,7 +172,7 @@ class MemoServCore : public Module void OnNickIdentify(User *u) anope_override { - this->memoserv.Check(u); + this->Check(u); } void OnJoinChannel(User *u, Channel *c) anope_override @@ -201,17 +189,17 @@ class MemoServCore : public Module void OnUserAway(User *u, const Anope::string &message) anope_override { if (message.empty()) - this->memoserv.Check(u); + this->Check(u); } void OnNickUpdate(User *u) anope_override { - this->memoserv.Check(u); + this->Check(u); } EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.c || source.service != MemoServ) + if (!params.empty() || source.c || source.service != *MemoServ) return EVENT_CONTINUE; source.Reply(_("\002%s\002 is a utility allowing IRC users to send short\n" "messages to other IRC users, whether they are online at\n" @@ -224,14 +212,11 @@ class MemoServCore : public Module void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.c || source.service != MemoServ) + if (!params.empty() || source.c || source.service != *MemoServ) return; source.Reply(_(" \n" "Type \002%s%s HELP \037command\037\002 for help on any of the\n" - "above commands.\n" - "(*) By default, any user with at least level 10 access on a\n" - " channel can read that channel's memos. This can be\n" - " changed with the %s \002LEVELS\002 command."), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str(), ChanServ->nick.c_str()); + "above commands."), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str()); } }; diff --git a/modules/pseudoclients/nickserv.cpp b/modules/pseudoclients/nickserv.cpp index be60f3982..642b22f2d 100644 --- a/modules/pseudoclients/nickserv.cpp +++ b/modules/pseudoclients/nickserv.cpp @@ -9,63 +9,116 @@ * Based on the original code of Services by Andy Church. */ -/*************************************************************************/ - #include "module.h" -class NickServCollide; - -typedef std::map<Anope::string, NickServCollide *> nickservcollides_map; - -static nickservcollides_map NickServCollides; - /** Timer for colliding nicks to force people off of nicknames */ class NickServCollide : public Timer { + NickServService *service; Reference<User> u; + Reference<NickAlias> na; + + public: + NickServCollide(NickServService *nss, User *user, NickAlias *nick, time_t delay) : Timer(delay), service(nss), u(user), na(nick) + { + } + + void Tick(time_t t) anope_override + { + if (!u || !na) + return; + /* If they identified or don't exist anymore, don't kill them. */ + if (u->Account() == na->nc || u->timestamp > this->GetSetTime()) + return; + + service->Collide(u, na); + } +}; + +/** Timer for removing HELD status from nicks. + */ +class NickServHeld : public Timer +{ + Reference<NickAlias> na; + Anope::string nick; + public: + NickServHeld(NickAlias *n, long l) : Timer(l), na(n), nick(na->nick) + { + } + + void Tick(time_t) + { + if (na) + na->Shrink("HELD"); + } +}; + +/** Timer for releasing nicks to be available for use + */ +class CoreExport NickServRelease : public User, public Timer +{ + static std::map<Anope::string, NickServRelease *> NickServReleases; Anope::string nick; public: - /** Constructor - * @param nick The nick we're colliding - * @param delay How long to delay before kicking the user off the nick - */ - NickServCollide(User *user, time_t delay) : Timer(delay), u(user), nick(u->nick) + NickServRelease(NickAlias *na, time_t delay) : User(na->nick, Config->GetBlock("options")->Get<const Anope::string>("enforceruser"), + Config->GetBlock("options")->Get<const Anope::string>("enforcerhost"), "", "", Me, "Services Enforcer", Anope::CurTime, "", Servers::TS6_UID_Retrieve()), Timer(delay), nick(na->nick) { - /* Erase the current collide and use the new one */ - nickservcollides_map::iterator nit = NickServCollides.find(user->nick); - if (nit != NickServCollides.end()) + /* Erase the current release timer and use the new one */ + std::map<Anope::string, NickServRelease *>::iterator nit = NickServReleases.find(this->nick); + if (nit != NickServReleases.end()) + { + IRCD->SendQuit(nit->second, ""); delete nit->second; + } - NickServCollides.insert(std::make_pair(nick, this)); + NickServReleases.insert(std::make_pair(this->nick, this)); + + IRCD->SendClientIntroduction(this); } - virtual ~NickServCollide() + ~NickServRelease() { - NickServCollides.erase(this->nick); + NickServReleases.erase(this->nick); } - /** Called when the delay is up - * @param t The current time - */ - void Tick(time_t t) anope_override + void Tick(time_t t) { - if (!u) - return; - /* If they identified or don't exist anymore, don't kill them. */ - NickAlias *na = NickAlias::Find(u->nick); - if (!na || u->Account() == na->nc || u->timestamp > this->GetSetTime()) - return; - - u->Collide(na); + IRCD->SendQuit(this, ""); } }; +std::map<Anope::string, NickServRelease *> NickServRelease::NickServReleases; -class MyNickServService : public NickServService +class NickServCore : public Module, public NickServService { + Reference<BotInfo> NickServ; + std::vector<Anope::string> defaults; + + void OnCancel(User *u, NickAlias *na) + { + if (na->HasExt("COLLIDED")) + { + na->Extend("HELD"); + na->Shrink("COLLIDED"); + + new NickServHeld(na, Config->GetBlock("options")->Get<time_t>("releasetimeout")); + + if (IRCD->CanSVSHold) + IRCD->SendSVSHold(na->nick, Config->GetBlock("options")->Get<time_t>("releasetimeout")); + else + new NickServRelease(na, Config->GetBlock("options")->Get<time_t>("releasetimeout")); + } + } + public: - MyNickServService(Module *m) : NickServService(m) { } + NickServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR), NickServService(this) + { + Implementation i[] = { I_OnReload, I_OnDelNick, I_OnDelCore, I_OnChangeCoreDisplay, I_OnNickIdentify, I_OnNickGroup, + I_OnNickUpdate, I_OnUserConnect, I_OnPostUserLogoff, I_OnServerSync, I_OnUserNickChange, I_OnPreHelp, I_OnPostHelp, + I_OnNickCoreCreate, I_OnUserQuit, I_OnExpireTick, I_OnUserLogin }; + ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); + } void Validate(User *u) anope_override { @@ -76,7 +129,7 @@ class MyNickServService : public NickServService if (na->nc->HasExt("SUSPENDED")) { u->SendMessage(NickServ, NICK_X_SUSPENDED, u->nick.c_str()); - u->Collide(na); + this->Collide(u, na); return; } @@ -113,98 +166,79 @@ class MyNickServService : public NickServService if (na->nc->HasExt("KILL_IMMED")) { u->SendMessage(NickServ, FORCENICKCHANGE_NOW); - u->Collide(na); + this->Collide(u, na); } else if (na->nc->HasExt("KILL_QUICK")) { time_t killquick = Config->GetModule("nickserv")->Get<time_t>("killquick", "60s"); u->SendMessage(NickServ, _("If you do not change within %s, I will change your nick."), Anope::Duration(killquick, u->Account()).c_str()); - new NickServCollide(u, killquick); + new NickServCollide(this, u, na, killquick); } else { time_t kill = Config->GetModule("nickserv")->Get<time_t>("kill", "20s"); u->SendMessage(NickServ, _("If you do not change within %s, I will change your nick."), Anope::Duration(kill, u->Account()).c_str()); - new NickServCollide(u, kill); + new NickServCollide(this, u, na, kill); } } } - void Login(User *user, NickAlias *na) anope_override + void OnUserLogin(User *u) anope_override { - const NickAlias *u_na = NickAlias::Find(user->nick); - user->Login(na->nc); - if (u_na && *u_na->nc == *na->nc && !Config->GetBlock("options")->Get<bool>("nonicknameownership") && na->nc->HasExt("UNCONFIRMED") == false) - user->SetMode(NickServ, "REGISTERED"); + NickAlias *na = NickAlias::Find(u->nick); + if (na && *na->nc == u->Account() && !Config->GetBlock("options")->Get<bool>("nonicknameownership") && na->nc->HasExt("UNCONFIRMED") == false) + u->SetMode(NickServ, "REGISTERED"); } -}; -class ExpireCallback : public Timer -{ - public: - ExpireCallback(Module *o) : Timer(o, Config->GetBlock("options")->Get<time_t>("expiretimeout"), Anope::CurTime, true) { } - - void Tick(time_t) anope_override + void Collide(User *u, NickAlias *na) anope_override { - if (Anope::NoExpire || Anope::ReadOnly) - return; - - time_t unconfirmed_expire = Config->GetModule(this->GetOwner())->Get<time_t>("unconfirmedexpire", "1d"); - time_t nickserv_expire = Config->GetModule(this->GetOwner())->Get<time_t>("expire"); + if (na) + na->Extend("COLLIDED"); - for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; ) + if (IRCD->CanSVSNick) { - NickAlias *na = it->second; - ++it; + const Anope::string &guestprefix = Config->GetBlock("options")->Get<const Anope::string>("guestnickprefix"); + + Anope::string guestnick; - User *u = User::Find(na->nick); - if (u && (na->nc->HasExt("SECURE") ? u->IsIdentified(true) : u->IsRecognized())) - na->last_seen = Anope::CurTime; - - bool expire = false; - - if (na->nc->HasExt("UNCONFIRMED")) - if (unconfirmed_expire && Anope::CurTime - na->time_registered >= unconfirmed_expire) - expire = true; - if (nickserv_expire && Anope::CurTime - na->last_seen >= nickserv_expire) - expire = true; - if (na->HasExt("NO_EXPIRE")) - expire = false; + int i = 0; + do + { + guestnick = guestprefix + stringify(static_cast<uint16_t>(rand())); + } + while (User::Find(guestnick) && i++ < 10); - FOREACH_MOD(I_OnPreNickExpire, OnPreNickExpire(na, expire)); - - if (expire) + if (i == 11) + u->Kill(NickServ ? NickServ->nick : "", "Services nickname-enforcer kill"); + else { - Anope::string extra; - if (na->nc->HasExt("SUSPENDED")) - extra = "suspended "; - Log(LOG_NORMAL, "expire") << "Expiring " << extra << "nickname " << na->nick << " (group: " << na->nc->display << ") (e-mail: " << (na->nc->email.empty() ? "none" : na->nc->email) << ")"; - FOREACH_MOD(I_OnNickExpire, OnNickExpire(na)); - delete na; + if (NickServ) + u->SendMessage(NickServ, _("Your nickname is now being changed to \002%s\002"), guestnick.c_str()); + IRCD->SendForceNickChange(u, guestnick, Anope::CurTime); } } + else + u->Kill(NickServ ? NickServ->nick : "", "Services nickname-enforcer kill"); } -}; -class NickServCore : public Module -{ - MyNickServService nickserv; - ExpireCallback expires; - std::vector<Anope::string> defaults; - - public: - NickServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR), nickserv(this), expires(this) + void Release(NickAlias *na) anope_override { - Implementation i[] = { I_OnReload, I_OnBotDelete, I_OnDelNick, I_OnDelCore, I_OnChangeCoreDisplay, I_OnNickIdentify, I_OnNickGroup, - I_OnNickUpdate, I_OnUserConnect, I_OnPostUserLogoff, I_OnServerSync, I_OnUserNickChange, I_OnPreHelp, I_OnPostHelp, - I_OnNickCoreCreate, I_OnUserQuit }; - ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); - } + if (na->HasExt("HELD")) + { + if (IRCD->CanSVSHold) + IRCD->SendSVSHoldDel(na->nick); + else + { + User *u = User::Find(na->nick); + if (u && u->server == Me) + { + u->Quit(); + } + } - ~NickServCore() - { - NickServ = NULL; + na->Shrink("HELD"); + } } void OnReload(Configuration::Conf *conf) anope_override @@ -212,11 +246,11 @@ class NickServCore : public Module const Anope::string &nsnick = conf->GetModule(this)->Get<const Anope::string>("client"); if (nsnick.empty()) - throw ConfigException(this->name + ": <client> must be defined"); + throw ConfigException(Module::name + ": <client> must be defined"); BotInfo *bi = BotInfo::Find(nsnick, true); if (!bi) - throw ConfigException(this->name + ": no bot named " + nsnick); + throw ConfigException(Module::name + ": no bot named " + nsnick); NickServ = bi; @@ -229,12 +263,6 @@ class NickServCore : public Module } } - void OnBotDelete(BotInfo *bi) anope_override - { - if (bi == NickServ) - NickServ = NULL; - } - void OnDelNick(NickAlias *na) anope_override { User *u = User::Find(na->nick); @@ -284,7 +312,7 @@ class NickServCore : public Module ChanUserContainer *cc = it->second; Channel *c = cc->chan; if (c) - c->SetCorrectModes(u, true, true); + c->SetCorrectModes(u, true); } const Anope::string &modesonid = block->Get<const Anope::string>("modesonid"); @@ -325,7 +353,7 @@ class NickServCore : public Module ChanUserContainer *cc = it->second; Channel *c = cc->chan; if (c) - c->SetCorrectModes(u, true, true); + c->SetCorrectModes(u, true); } } @@ -340,14 +368,14 @@ class NickServCore : public Module if (!Config->GetBlock("options")->Get<bool>("nonicknameownership") && !unregistered_notice.empty() && !na) u->SendMessage(NickServ, unregistered_notice); else if (na) - this->nickserv.Validate(u); + this->Validate(u); } void OnPostUserLogoff(User *u) anope_override { NickAlias *na = NickAlias::Find(u->nick); if (na) - na->OnCancel(u); + OnCancel(u, na); } void OnServerSync(Server *s) anope_override @@ -356,7 +384,7 @@ class NickServCore : public Module { User *u = it->second; if (u->server == s && !u->IsIdentified()) - this->nickserv.Validate(u); + this->Validate(u); } } @@ -369,7 +397,7 @@ class NickServCore : public Module /* Remove +r, but keep an account associated with the user */ u->RemoveMode(NickServ, "REGISTERED"); - this->nickserv.Validate(u); + this->Validate(u); } else { @@ -381,7 +409,7 @@ class NickServCore : public Module } if (!u->nick.equals_ci(oldnick) && old_na) - old_na->OnCancel(u); + OnCancel(u, old_na); } void OnUserModeSet(User *u, const Anope::string &mname) anope_override @@ -392,7 +420,7 @@ class NickServCore : public Module EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.c || source.service != NickServ) + if (!params.empty() || source.c || source.service != *NickServ) return EVENT_CONTINUE; if (!Config->GetBlock("options")->Get<bool>("nonicknameownership")) source.Reply(_("\002%s\002 allows you to register a nickname and\n" @@ -412,7 +440,7 @@ class NickServCore : public Module void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.c || source.service != NickServ) + if (!params.empty() || source.c || source.service != *NickServ) return; if (source.IsServicesOper()) source.Reply(_(" \n" @@ -454,6 +482,47 @@ class NickServCore : public Module na->last_quit = msg; } } + + void OnExpireTick() anope_override + { + if (Anope::NoExpire || Anope::ReadOnly) + return; + + time_t unconfirmed_expire = Config->GetModule(this)->Get<time_t>("unconfirmedexpire", "1d"); + time_t nickserv_expire = Config->GetModule(this)->Get<time_t>("expire"); + + for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; ) + { + NickAlias *na = it->second; + ++it; + + User *u = User::Find(na->nick); + if (u && (na->nc->HasExt("SECURE") ? u->IsIdentified(true) : u->IsRecognized())) + na->last_seen = Anope::CurTime; + + bool expire = false; + + if (na->nc->HasExt("UNCONFIRMED")) + if (unconfirmed_expire && Anope::CurTime - na->time_registered >= unconfirmed_expire) + expire = true; + if (nickserv_expire && Anope::CurTime - na->last_seen >= nickserv_expire) + expire = true; + if (na->HasExt("NO_EXPIRE")) + expire = false; + + FOREACH_MOD(I_OnPreNickExpire, OnPreNickExpire(na, expire)); + + if (expire) + { + Anope::string extra; + if (na->nc->HasExt("SUSPENDED")) + extra = "suspended "; + Log(LOG_NORMAL, "expire") << "Expiring " << extra << "nickname " << na->nick << " (group: " << na->nc->display << ") (e-mail: " << (na->nc->email.empty() ? "none" : na->nc->email) << ")"; + FOREACH_MOD(I_OnNickExpire, OnNickExpire(na)); + delete na; + } + } + } }; MODULE_INIT(NickServCore) diff --git a/modules/pseudoclients/operserv.cpp b/modules/pseudoclients/operserv.cpp index c514536fa..85984327c 100644 --- a/modules/pseudoclients/operserv.cpp +++ b/modules/pseudoclients/operserv.cpp @@ -9,8 +9,6 @@ * Based on the original code of Services by Andy Church. */ -/*************************************************************************/ - #include "module.h" class SGLineManager : public XLineManager @@ -25,7 +23,7 @@ class SGLineManager : public XLineManager void OnExpire(const XLine *x) anope_override { - Log(OperServ, "expire/akill") << "AKILL on \002" << x->mask << "\002 has expired"; + Log(Config->GetClient("OperServ"), "expire/akill") << "AKILL on \002" << x->mask << "\002 has expired"; } void Send(User *u, XLine *x) anope_override @@ -80,7 +78,7 @@ class SQLineManager : public XLineManager void OnExpire(const XLine *x) anope_override { - Log(OperServ, "expire/sqline") << "SQLINE on \002" << x->mask << "\002 has expired"; + Log(Config->GetClient("OperServ"), "expire/sqline") << "SQLINE on \002" << x->mask << "\002 has expired"; } void Send(User *u, XLine *x) anope_override @@ -129,7 +127,7 @@ class SNLineManager : public XLineManager void OnExpire(const XLine *x) anope_override { - Log(OperServ, "expire/snline") << "SNLINE on \002" << x->mask << "\002 has expired"; + Log(Config->GetClient("OperServ"), "expire/snline") << "SNLINE on \002" << x->mask << "\002 has expired"; } void Send(User *u, XLine *x) anope_override @@ -152,6 +150,7 @@ class SNLineManager : public XLineManager class OperServCore : public Module { + Reference<BotInfo> OperServ; SGLineManager sglines; SQLineManager sqlines; SNLineManager snlines; @@ -160,7 +159,7 @@ class OperServCore : public Module OperServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR), sglines(this), sqlines(this), snlines(this) { - Implementation i[] = { I_OnReload, I_OnBotDelete, I_OnBotPrivmsg, I_OnServerQuit, I_OnUserModeSet, I_OnUserModeUnset, I_OnUserConnect, I_OnUserNickChange, I_OnPreHelp }; + Implementation i[] = { I_OnReload, I_OnBotPrivmsg, I_OnServerQuit, I_OnUserModeSet, I_OnUserModeUnset, I_OnUserConnect, I_OnUserNickChange, I_OnPreHelp, I_OnLog }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); /* Yes, these are in this order for a reason. Most violent->least violent. */ @@ -171,8 +170,6 @@ class OperServCore : public Module ~OperServCore() { - OperServ = NULL; - this->sglines.Clear(); this->sqlines.Clear(); this->snlines.Clear(); @@ -196,18 +193,12 @@ class OperServCore : public Module OperServ = bi; } - void OnBotDelete(BotInfo *bi) anope_override - { - if (bi == OperServ) - OperServ = NULL; - } - EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message) anope_override { if (bi == OperServ && !u->HasMode("OPER") && Config->GetModule(this)->Get<bool>("opersonly")) { u->SendMessage(bi, ACCESS_DENIED); - Log(OperServ, "bados") << "Denied access to " << bi->nick << " from " << u->GetMask() << " (non-oper)"; + Log(bi, "bados") << "Denied access to " << bi->nick << " from " << u->GetMask() << " (non-oper)"; return EVENT_STOP; } @@ -258,11 +249,17 @@ class OperServCore : public Module EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!params.empty() || source.c || source.service != OperServ) + if (!params.empty() || source.c || source.service != *OperServ) return EVENT_CONTINUE; source.Reply(_("%s commands:"), OperServ->nick.c_str()); return EVENT_CONTINUE; } + + void OnLog(Log *l) anope_override + { + if (l->type == LOG_SERVER) + l->bi = OperServ; + } }; MODULE_INIT(OperServCore) |
