summaryrefslogtreecommitdiff
path: root/modules/pseudoclients/chanserv.cpp
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2013-05-26 17:13:11 -0400
committerAdam <Adam@anope.org>2013-05-26 17:13:11 -0400
commit22658d63bdb1e52a66f4514af45fa55ca5891345 (patch)
tree673304ab19f7e077b489354248247867518331f8 /modules/pseudoclients/chanserv.cpp
parentf2dee1e1d642b07947f59f91dfba9af34ef84685 (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.cpp241
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> &params) 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> &params) 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)