summaryrefslogtreecommitdiff
path: root/modules/pseudoclients
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2013-05-05 01:55:04 -0400
committerAdam <Adam@anope.org>2013-05-05 01:55:04 -0400
commit1d0bb9b26b7ad58ab0bf979ac046f4511b3bf12b (patch)
tree4486f0784bdf050fd7eb225c0cb9df352ce1f45a /modules/pseudoclients
parent781defb7076ddfddf723ca08cd0a518b6657b64f (diff)
Rework the config file reader to be much more flexible and move many configuration directives to the actual modules they are used in.
Diffstat (limited to 'modules/pseudoclients')
-rw-r--r--modules/pseudoclients/botserv.cpp144
-rw-r--r--modules/pseudoclients/chanserv.cpp205
-rw-r--r--modules/pseudoclients/chanserv.h18
-rw-r--r--modules/pseudoclients/global.cpp48
-rw-r--r--modules/pseudoclients/global.h4
-rw-r--r--modules/pseudoclients/hostserv.cpp24
-rw-r--r--modules/pseudoclients/memoserv.cpp64
-rw-r--r--modules/pseudoclients/memoserv.h4
-rw-r--r--modules/pseudoclients/nickserv.cpp136
-rw-r--r--modules/pseudoclients/nickserv.h4
-rw-r--r--modules/pseudoclients/operserv.cpp29
11 files changed, 529 insertions, 151 deletions
diff --git a/modules/pseudoclients/botserv.cpp b/modules/pseudoclients/botserv.cpp
index 29c1b1143..c33a8eeb5 100644
--- a/modules/pseudoclients/botserv.cpp
+++ b/modules/pseudoclients/botserv.cpp
@@ -18,13 +18,8 @@ class BotServCore : public Module
public:
BotServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR)
{
-
- BotServ = BotInfo::Find(Config->BotServ);
- if (!BotServ)
- throw ModuleException("No bot named " + Config->BotServ);
-
- Implementation i[] = { I_OnBotDelete, I_OnPrivmsg, I_OnJoinChannel, I_OnLeaveChannel,
- I_OnPreHelp, I_OnPostHelp, I_OnChannelModeSet };
+ Implementation i[] = { I_OnReload, I_OnSetCorrectModes, I_OnBotAssign, I_OnBotDelete, I_OnPrivmsg, I_OnJoinChannel, I_OnLeaveChannel,
+ I_OnPreHelp, I_OnPostHelp, I_OnChannelModeSet, I_OnCreateChan, I_OnUserKicked };
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
}
@@ -33,6 +28,40 @@ class BotServCore : public Module
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");
+
+ BotInfo *bi = BotInfo::Find(bsnick, true);
+ if (!bi)
+ throw ConfigException(this->name + ": no bot named " + bsnick);
+
+ BotServ = bi;
+ }
+
+ void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool give_modes) anope_override
+ {
+ /* Do not allow removing bot modes on our service bots */
+ if (chan->ci && chan->ci->bi == user)
+ {
+ const Anope::string &botmodes = Config->GetModule(this)->Get<const Anope::string &>("botmodes");
+ for (unsigned i = 0; i < botmodes.length(); ++i)
+ chan->SetMode(chan->ci->bi, ModeManager::FindChannelModeByChar(botmodes[i]), chan->ci->bi->GetUID());
+ }
+ }
+
+ void OnBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) anope_override
+ {
+ if (Me->IsSynced() && ci->c && ci->c->users.size() >= Config->GetModule(this)->Get<unsigned>("minusers"))
+ {
+ ChannelStatus status(Config->GetModule(this)->Get<const Anope::string &>("botmodes"));
+ bi->Join(ci->c, &status);
+ }
+ }
+
void OnBotDelete(BotInfo *bi) anope_override
{
if (bi == BotServ)
@@ -70,9 +99,7 @@ class BotServCore : public Module
if (!realbuf.find(c->ci->bi->nick))
params.erase(params.begin());
- else if (Config->BSFantasyCharacter.empty())
- ;
- else if (!realbuf.find_first_of(Config->BSFantasyCharacter))
+ else if (!realbuf.find_first_of(Config->GetModule(this)->Get<const Anope::string &>("fantasycharacter", "!")))
params[0].erase(params[0].begin());
else
return;
@@ -158,6 +185,42 @@ class BotServCore : public Module
void OnJoinChannel(User *user, Channel *c) anope_override
{
+ if (!Config || !IRCD)
+ return;
+
+ BotInfo *bi = user->server == Me ? dynamic_cast<BotInfo *>(user) : NULL;
+ if (bi && Config->GetModule(this)->Get<bool>("smartjoin"))
+ {
+ std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> bans = c->GetModeList("BAN");
+
+ /* We check for bans */
+ for (; bans.first != bans.second; ++bans.first)
+ {
+ Entry ban("BAN", bans.first->second);
+ if (ban.Matches(user))
+ c->RemoveMode(NULL, "BAN", ban.GetMask());
+ }
+
+ Anope::string Limit;
+ unsigned limit = 0;
+ try
+ {
+ if (c->GetParam("LIMIT", Limit))
+ limit = convertTo<unsigned>(Limit);
+ }
+ catch (const ConvertException &) { }
+
+ /* Should we be invited? */
+ if (c->HasMode("INVITE") || (limit && c->users.size() >= limit))
+ {
+ ChannelMode *cm = ModeManager::FindChannelModeByName("OP");
+ char symbol = cm ? anope_dynamic_static_cast<ChannelModeStatus *>(cm)->symbol : 0;
+ IRCD->SendNotice(bi, (symbol ? Anope::string(symbol) : "") + c->name, "%s invited %s into the channel.", user->nick.c_str(), user->nick.c_str());
+ }
+
+ ModeManager::ProcessModes();
+ }
+
if (user->server != Me && c->ci && c->ci->bi)
{
/**
@@ -166,8 +229,11 @@ class BotServCore : public Module
* make it into the channel, leaving the channel botless even for
* legit users - Rob
**/
- if (c->users.size() >= Config->BSMinUsers && !c->FindUser(c->ci->bi))
- c->ci->bi->Join(c, &ModeManager::DefaultBotModes);
+ if (c->users.size() >= Config->GetModule(this)->Get<unsigned>("minusers") && !c->FindUser(c->ci->bi))
+ {
+ ChannelStatus status(Config->GetModule(this)->Get<const Anope::string &>("botmodes"));
+ c->ci->bi->Join(c, &status);
+ }
/* Only display the greet if the main uplink we're connected
* to has synced, or we'll get greet-floods when the net
* recovers from a netsplit. -GD
@@ -197,7 +263,7 @@ class BotServCore : public Module
return;
/* This is called prior to removing the user from the channnel, so c->users.size() - 1 should be safe */
- if (c->ci && c->ci->bi && u != *c->ci->bi && c->users.size() - 1 <= Config->BSMinUsers && c->FindUser(c->ci->bi))
+ if (c->ci && c->ci->bi && u != *c->ci->bi && c->users.size() - 1 <= Config->GetModule(this)->Get<unsigned>("minusers") && c->FindUser(c->ci->bi))
c->ci->bi->Part(c->ci->c);
}
@@ -209,17 +275,18 @@ class BotServCore : public Module
if (source.c)
{
source.Reply(_("\002%s\002 allows you to execute \"fantasy\" commands in the channel.\n"
- "Fantasy commands are tied to existing commands, usually on \002%s\002,\n"
- "and provide a more convenient way to execute commands. Commands that\n"
+ "Fantasy commands are commands that can be executed from messaging a\n"
+ "channel, and provide a more convenient way to execute commands. Commands that\n"
"require a channel as a parameter will automatically have that parameter\n"
- "given.\n"), source.service->nick.c_str(), Config->ChanServ.c_str());
- if (!Config->BSFantasyCharacter.empty())
+ "given.\n"), source.service->nick.c_str());
+ const Anope::string &fantasycharacters = Config->GetModule(this)->Get<const Anope::string &>("fantasycharacter", "!");
+ if (!fantasycharacters.empty())
source.Reply(_(" \n"
- "Fantasy commands may be prefixed with one of the following characters: %s\n"), Config->BSFantasyCharacter.c_str());
+ "Fantasy commands may be prefixed with one of the following characters: %s\n"), fantasycharacters.c_str());
source.Reply(_(" \n"
"Available commands are:"));
}
- else if (source.service->nick == Config->BotServ)
+ else if (*source.service == BotServ)
{
source.Reply(_("\002%s\002 allows you to have a bot on your own channel.\n"
"It has been created for users that can't host or\n"
@@ -228,8 +295,8 @@ class BotServCore : public Module
"below; to use them, type \002%s%s \037command\037\002. For\n"
"more information on a specific command, type\n"
"\002%s%s %s \037command\037\002.\n "),
- Config->BotServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->BotServ.c_str(),
- Config->UseStrictPrivMsgString.c_str(), Config->BotServ.c_str(), source.command.c_str());
+ BotServ->nick.c_str(), Config->StrictPrivmsg.c_str(), BotServ->nick.c_str(),
+ Config->StrictPrivmsg.c_str(), BotServ->nick.c_str(), source.command.c_str());
}
return EVENT_CONTINUE;
@@ -237,21 +304,22 @@ class BotServCore : public Module
void OnPostHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
{
- if (!params.empty() || source.c || source.service->nick != Config->BotServ)
+ if (!params.empty() || source.c || source.service != BotServ)
return;
source.Reply(_(" \n"
"Bot will join a channel whenever there is at least\n"
- "\002%d\002 user(s) on it."), Config->BSMinUsers);
- if (!Config->BSFantasyCharacter.empty())
- source.Reply(_("Additionally, all %s commands can be used if fantasy\n"
- "is enabled by prefixing the command name with one of\n"
- "the following characters: %s"), Config->ChanServ.c_str(), Config->BSFantasyCharacter.c_str());
+ "\002%d\002 user(s) on it."), Config->GetModule(this)->Get<unsigned>("minusers"));
+ const Anope::string &fantasycharacters = Config->GetModule(this)->Get<const Anope::string &>("fantasycharacter", "!");
+ if (!fantasycharacters.empty())
+ source.Reply(_("Additionally, if fantasy is enabled fantasy commands\n"
+ "can be executed by prefixing the command name with\n"
+ "one of the following characters: %s"), fantasycharacters.c_str());
}
EventReturn OnChannelModeSet(Channel *c, MessageSource &, const Anope::string &mname, const Anope::string &param) anope_override
{
- if (Config->BSSmartJoin && mname == "BAN" && c->ci && c->ci->bi && c->FindUser(c->ci->bi))
+ if (Config->GetModule(this)->Get<bool>("smartjoin") && mname == "BAN" && c->ci && c->ci->bi && c->FindUser(c->ci->bi))
{
BotInfo *bi = c->ci->bi;
@@ -262,6 +330,26 @@ class BotServCore : public Module
return EVENT_CONTINUE;
}
+
+ void OnCreateChan(ChannelInfo *ci) anope_override
+ {
+ /* Set default bot flags */
+ spacesepstream sep(Config->GetModule(this)->Get<const Anope::string &>("defaults", "greet fantasy"));
+ for (Anope::string token; sep.GetToken(token);)
+ this->ExtendMetadata("BS_" + token);
+ }
+
+ void OnPreUserKicked(MessageSource &source, ChanUserContainer *cu, const Anope::string &kickmsg) anope_override
+ {
+ }
+
+ void OnUserKicked(MessageSource &source, User *target, const Anope::string &channel, ChannelStatus &status, const Anope::string &kickmsg) anope_override
+ {
+ BotInfo *bi = BotInfo::Find(target->nick);
+ if (bi)
+ /* Bots get rejoined */
+ bi->Join(channel, &status);
+ }
};
MODULE_INIT(BotServCore)
diff --git a/modules/pseudoclients/chanserv.cpp b/modules/pseudoclients/chanserv.cpp
index 2c5cffcea..e34cd56e8 100644
--- a/modules/pseudoclients/chanserv.cpp
+++ b/modules/pseudoclients/chanserv.cpp
@@ -16,11 +16,13 @@
class ExpireCallback : public Timer
{
public:
- ExpireCallback(Module *o) : Timer(o, Config->ExpireTimeout, Anope::CurTime, true) { }
+ ExpireCallback(Module *o) : Timer(o, Config->GetBlock("options")->Get<time_t>("expiretimeout"), Anope::CurTime, true) { }
void Tick(time_t) anope_override
{
- if (!Config->CSExpire || Anope::NoExpire || Anope::ReadOnly)
+ 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; )
@@ -30,7 +32,7 @@ class ExpireCallback : public Timer
bool expire = false;
- if (Anope::CurTime - ci->last_used >= Config->CSExpire)
+ if (Anope::CurTime - ci->last_used >= chanserv_expire)
{
if (ci->c)
{
@@ -62,19 +64,81 @@ class ExpireCallback : public Timer
}
};
+class MyChanServService : public ChanServService
+{
+ public:
+ MyChanServService(Module *m) : ChanServService(m) { }
+
+ void Hold(Channel *c) anope_override
+ {
+ /** A timer used to keep the BotServ bot/ChanServ in the channel
+ * after kicking the last user in a channel
+ */
+ class ChanServTimer : public Timer
+ {
+ Reference<Channel> c;
+
+ public:
+ /** Constructor
+ * @param chan The channel
+ */
+ ChanServTimer(Module *m, Channel *chan) : Timer(m, Config->GetModule(this->GetOwner())->Get<time_t>("inhabit", "15s")), c(chan)
+ {
+ if (!ChanServ || !c)
+ return;
+ c->Extend("INHABIT");
+ if (!c->ci || !c->ci->bi)
+ ChanServ->Join(c);
+ else if (!c->FindUser(c->ci->bi))
+ c->ci->bi->Join(c);
+
+ /* Set +ntsi to prevent rejoin */
+ c->SetMode(NULL, "NOEXTERNAL");
+ c->SetMode(NULL, "TOPIC");
+ c->SetMode(NULL, "SECRET");
+ c->SetMode(NULL, "INVITE");
+ }
+
+ /** Called when the delay is up
+ * @param The current time
+ */
+ void Tick(time_t) anope_override
+ {
+ if (!c)
+ return;
+
+ c->Shrink("INHABIT");
+
+ if (!c->ci || !c->ci->bi)
+ {
+ if (ChanServ)
+ ChanServ->Part(c);
+ }
+ else
+ c->ci->bi->Part(c);
+ }
+ };
+
+ 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), expires(this)
+ ChanServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
+ chanserv(this), expires(this)
{
-
- ChanServ = BotInfo::Find(Config->ChanServ);
- if (!ChanServ)
- throw ModuleException("No bot named " + Config->ChanServ);
-
- Implementation i[] = { I_OnBotDelete, I_OnBotPrivmsg, I_OnDelCore, I_OnPreHelp, I_OnPostHelp, I_OnCheckModes };
+ 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));
}
@@ -83,6 +147,31 @@ class ChanServCore : public Module
ChanServ = NULL;
}
+ void OnReload(Configuration::Conf *conf) anope_override
+ {
+ const Anope::string &channick = conf->GetModule(this)->Get<const Anope::string &>("client");
+
+ if (channick.empty())
+ throw ConfigException(this->name + ": <client> must be defined");
+
+ BotInfo *bi = BotInfo::Find(channick, true);
+ if (!bi)
+ throw ConfigException(this->name + ": no bot named " + channick);
+
+ ChanServ = bi;
+
+ spacesepstream(conf->GetModule(this)->Get<const Anope::string &>("defaults", "greet fantasy")).GetTokens(defaults);
+ if (defaults.empty())
+ {
+ defaults.push_back("KEEPTOPIC");
+ defaults.push_back("SECURE");
+ defaults.push_back("SECUREFOUNDER");
+ defaults.push_back("SIGNKICK");
+ }
+ else if (defaults[0].equals_ci("none"))
+ defaults.erase(defaults.begin());
+ }
+
void OnBotDelete(BotInfo *bi) anope_override
{
if (bi == ChanServ)
@@ -91,7 +180,7 @@ class ChanServCore : public Module
EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message) anope_override
{
- if (Config->CSOpersOnly && bi == ChanServ && !u->HasMode("OPER"))
+ if (bi == ChanServ && Config->GetModule(this)->Get<bool>("operonly") && !u->HasMode("OPER"))
{
u->SendMessage(bi, ACCESS_DENIED);
return EVENT_STOP;
@@ -104,6 +193,7 @@ class ChanServCore : public Module
{
std::deque<ChannelInfo *> chans;
nc->GetChannelReferences(chans);
+ int max_reg = Config->GetModule(this)->Get<int>("maxregistered");
for (unsigned i = 0; i < chans.size(); ++i)
{
@@ -112,7 +202,7 @@ class ChanServCore : public Module
if (ci->GetFounder() == nc)
{
NickCore *newowner = NULL;
- if (ci->GetSuccessor() && ci->GetSuccessor() != nc && (ci->GetSuccessor()->IsServicesOper() || !Config->CSMaxReg || ci->GetSuccessor()->channelcount < Config->CSMaxReg))
+ if (ci->GetSuccessor() && ci->GetSuccessor() != nc && (ci->GetSuccessor()->IsServicesOper() || !max_reg || ci->GetSuccessor()->channelcount < max_reg))
newowner = ci->GetSuccessor();
else
{
@@ -122,7 +212,7 @@ class ChanServCore : public Module
const ChanAccess *ca = ci->GetAccess(j);
const NickCore *anc = NickCore::Find(ca->mask);
- if (!anc || (!anc->IsServicesOper() && Config->CSMaxReg && anc->channelcount >= Config->CSMaxReg) || (anc == nc))
+ if (!anc || (!anc->IsServicesOper() && max_reg && anc->channelcount >= max_reg) || (anc == nc))
continue;
if (!highest || *ca > *highest)
highest = ca;
@@ -175,7 +265,7 @@ class ChanServCore : public Module
EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
{
- if (!params.empty() || source.c || source.service->nick != Config->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"
@@ -184,19 +274,20 @@ class ChanServCore : public Module
"commands are listed below; to use them, type\n"
"\002%s%s \037command\037\002. For more information on a\n"
"specific command, type \002%s%s HELP \037command\037\002.\n "),
- Config->ChanServ.c_str(), Config->ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->ChanServ.c_str(), Config->ChanServ.c_str(), source.command.c_str());
+ ChanServ->nick.c_str(), ChanServ->nick.c_str(), Config->StrictPrivmsg.c_str(), ChanServ->nick.c_str(), Config->StrictPrivmsg.c_str(), ChanServ->nick.c_str(), ChanServ->nick.c_str(), source.command.c_str());
return EVENT_CONTINUE;
}
void OnPostHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
{
- if (!params.empty() || source.c || source.service->nick != Config->ChanServ)
+ if (!params.empty() || source.c || source.service != ChanServ)
return;
- if (Config->CSExpire >= 86400)
+ time_t expire = Config->GetModule(this)->Get<time_t>("expire", "14d");
+ if (expire >= 86400)
source.Reply(_(" \n"
"Note that any channel which is not used for %d days\n"
"(i.e. which no user on the channel's access list enters\n"
- "for that period of time) will be automatically dropped."), Config->CSExpire / 86400);
+ "for that period of time) will be automatically dropped."), expire / 86400);
if (source.IsServicesOper())
source.Reply(_(" \n"
"Services Operators can also, depending on their access drop\n"
@@ -206,12 +297,84 @@ class ChanServCore : public Module
EventReturn OnCheckModes(Channel *c) anope_override
{
- if (!Config->CSRequire.empty())
+ const Anope::string &require = Config->GetModule(this)->Get<const Anope::string &>("require", "r");
+ if (!require.empty())
{
if (c->ci)
- c->SetModes(NULL, false, "+%s", Config->CSRequire.c_str());
+ c->SetModes(NULL, false, "+%s", require.c_str());
else
- c->SetModes(NULL, false, "-%s", Config->CSRequire.c_str());
+ c->SetModes(NULL, false, "-%s", require.c_str());
+ }
+
+ return EVENT_CONTINUE;
+ }
+
+ void OnCreateChan(ChannelInfo *ci) anope_override
+ {
+ ci->bantype = Config->GetModule(this)->Get<int>("defbantype", "2");
+
+ /* Set default chan flags */
+ for (unsigned i = 0; i < defaults.size(); ++i)
+ this->ExtendMetadata(defaults[i]);
+
+ {
+ Anope::string modes;
+ spacesepstream sep(Config->GetModule(this)->Get<const Anope::string &>("mlock", "+nrt"));
+ if (sep.GetToken(modes))
+ {
+ bool add = true;
+ for (unsigned i = 0; i < modes.length(); ++i)
+ {
+ if (modes[i] == '+')
+ add = true;
+ else if (modes[i] == '-')
+ add = false;
+ else
+ {
+ ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]);
+ Anope::string param;
+ if (cm && (cm->type == MODE_REGULAR || sep.GetToken(param)))
+ ci->SetMLock(cm, add, param);
+ }
+ }
+ }
+ }
+ }
+
+ EventReturn OnCanSet(User *u, const ChannelMode *cm) anope_override
+ {
+ if (Config->GetModule(this)->Get<const Anope::string &>("nomlock").find(cm->mchar) != Anope::string::npos
+ || Config->GetModule(this)->Get<const Anope::string &>("require", "r").find(cm->mchar) || Anope::string::npos)
+ return EVENT_STOP;
+ return EVENT_CONTINUE;
+ }
+
+ void OnChannelSync(Channel *c) anope_override
+ {
+ if (!c->HasMode("PERM") && (c->users.empty() || (c->users.size() == 1 && c->ci && c->ci->bi && *c->ci->bi == c->users.begin()->second->user)))
+ {
+ chanserv.Hold(c);
+ }
+ if (c->ci)
+ {
+ c->CheckModes();
+
+ if (Me && Me->IsSynced())
+ c->ci->RestoreTopic();
+ }
+ }
+
+ EventReturn OnBotKick(BotInfo *bi, Channel *c, User *u, const Anope::string &reason)
+ {
+ /* If the channel isn't syncing and doesn't have any users, join ChanServ
+ * Note that the user AND POSSIBLY the botserv bot exist here
+ * 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"))
+ {
+ /* Join ChanServ and set a timer for this channel to part ChanServ later */
+ chanserv.Hold(c);
}
return EVENT_CONTINUE;
diff --git a/modules/pseudoclients/chanserv.h b/modules/pseudoclients/chanserv.h
new file mode 100644
index 000000000..e1c3849fd
--- /dev/null
+++ b/modules/pseudoclients/chanserv.h
@@ -0,0 +1,18 @@
+#ifndef CHANSERV_H
+#define CHANSERV_H
+
+class ChanServService : public Service
+{
+ public:
+ ChanServService(Module *m) : Service(m, "ChanServService", "ChanServ")
+ {
+ }
+
+ /* Have ChanServ hold the channel, that is, join and set +nsti and wait
+ * for a few minutes so no one can join or rejoin.
+ */
+ virtual void Hold(Channel *c) = 0;
+};
+
+#endif // CHANSERV_H
+
diff --git a/modules/pseudoclients/global.cpp b/modules/pseudoclients/global.cpp
index 02b199afa..837200e5d 100644
--- a/modules/pseudoclients/global.cpp
+++ b/modules/pseudoclients/global.cpp
@@ -34,29 +34,24 @@ class MyGlobalService : public GlobalService
Anope::string rmessage;
- if (!source.empty() && !Config->AnonymousGlobal)
+ if (!source.empty() && !Config->GetModule("global")->Get<bool>("anonymousglobal"))
rmessage = "[" + source + "] " + message;
else
rmessage = message;
- this->ServerGlobal(sender, Me->GetLinks().front(), rmessage);
+ this->ServerGlobal(sender, Servers::GetUplink(), rmessage);
}
};
class GlobalCore : public Module
{
- MyGlobalService myglobalservice;
+ MyGlobalService global;
public:
GlobalCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
- myglobalservice(this)
+ global(this)
{
-
- Global = BotInfo::Find(Config->Global);
- if (!Global)
- throw ModuleException("No bot named " + Config->Global);
-
- Implementation i[] = { I_OnBotDelete, I_OnRestart, I_OnShutdown, I_OnNewServer, I_OnPreHelp };
+ Implementation i[] = { I_OnReload, I_OnBotDelete, I_OnRestart, I_OnShutdown, I_OnNewServer, I_OnPreHelp };
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
}
@@ -65,6 +60,20 @@ class GlobalCore : public Module
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");
+
+ BotInfo *bi = BotInfo::Find(glnick, true);
+ if (!bi)
+ throw ConfigException(this->name + ": no bot named " + glnick);
+
+ Global = bi;
+ }
+
void OnBotDelete(BotInfo *bi) anope_override
{
if (bi == Global)
@@ -73,27 +82,30 @@ class GlobalCore : public Module
void OnRestart() anope_override
{
- if (Config->GlobalOnCycle)
- this->myglobalservice.SendGlobal(Global, "", Config->GlobalOnCycleMessage);
+ const Anope::string &gl = Config->GetModule(this)->Get<const Anope::string &>("globaloncycledown");
+ if (!gl.empty())
+ this->global.SendGlobal(Global, "", gl);
}
void OnShutdown() anope_override
{
- if (Config->GlobalOnCycle)
- this->myglobalservice.SendGlobal(Global, "", Config->GlobalOnCycleMessage);
+ const Anope::string &gl = Config->GetModule(this)->Get<const Anope::string &>("globaloncycledown");
+ if (!gl.empty())
+ this->global.SendGlobal(Global, "", gl);
}
void OnNewServer(Server *s) anope_override
{
- if (Config->GlobalOnCycle && !Config->GlobalOnCycleUP.empty())
- s->Notice(Global, Config->GlobalOnCycleUP);
+ const Anope::string &gl = Config->GetModule(this)->Get<const Anope::string &>("globaloncycleup");
+ if (!gl.empty() && !Me->IsSynced())
+ s->Notice(Global, gl);
}
EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
{
- if (!params.empty() || source.c || source.service->nick != Config->Global)
+ if (!params.empty() || source.c || source.service != Global)
return EVENT_CONTINUE;
- source.Reply(_("%s commands:"), Config->Global.c_str());
+ source.Reply(_("%s commands:"), Global->nick.c_str());
return EVENT_CONTINUE;
}
};
diff --git a/modules/pseudoclients/global.h b/modules/pseudoclients/global.h
index fccd96558..52afc4a23 100644
--- a/modules/pseudoclients/global.h
+++ b/modules/pseudoclients/global.h
@@ -4,7 +4,9 @@
class GlobalService : public Service
{
public:
- GlobalService(Module *m) : Service(m, "GlobalService", "Global") { }
+ GlobalService(Module *m) : Service(m, "GlobalService", "Global")
+ {
+ }
/** Send out a global message to all users
* @param sender Our client which should send the global
diff --git a/modules/pseudoclients/hostserv.cpp b/modules/pseudoclients/hostserv.cpp
index d8cd74d69..acca6f7ff 100644
--- a/modules/pseudoclients/hostserv.cpp
+++ b/modules/pseudoclients/hostserv.cpp
@@ -22,11 +22,7 @@ class HostServCore : public Module
if (!IRCD || !IRCD->CanSetVHost)
throw ModuleException("Your IRCd does not support vhosts");
- HostServ = BotInfo::Find(Config->HostServ);
- if (!HostServ)
- throw ModuleException("No bot named " + Config->HostServ);
-
- Implementation i[] = { I_OnBotDelete, I_OnNickIdentify, I_OnNickUpdate, I_OnPreHelp };
+ Implementation i[] = { I_OnReload, I_OnBotDelete, I_OnNickIdentify, I_OnNickUpdate, I_OnPreHelp };
ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation));
}
@@ -35,6 +31,20 @@ class HostServCore : public Module
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");
+
+ BotInfo *bi = BotInfo::Find(hsnick, true);
+ if (!bi)
+ throw ConfigException(this->name + ": no bot named " + hsnick);
+
+ HostServ = bi;
+ }
+
void OnBotDelete(BotInfo *bi) anope_override
{
if (bi == HostServ)
@@ -76,9 +86,9 @@ class HostServCore : public Module
EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) anope_override
{
- if (!params.empty() || source.c || source.service->nick != Config->HostServ)
+ if (!params.empty() || source.c || source.service != HostServ)
return EVENT_CONTINUE;
- source.Reply(_("%s commands:"), Config->HostServ.c_str());
+ source.Reply(_("%s commands:"), HostServ->nick.c_str());
return EVENT_CONTINUE;
}
};
diff --git a/modules/pseudoclients/memoserv.cpp b/modules/pseudoclients/memoserv.cpp
index 5eca5cd4e..46ad82194 100644
--- a/modules/pseudoclients/memoserv.cpp
+++ b/modules/pseudoclients/memoserv.cpp
@@ -16,20 +16,20 @@
static bool SendMemoMail(NickCore *nc, MemoInfo *mi, Memo *m)
{
- Anope::string subject = Language::Translate(nc, Config->MailMemoSubject.c_str());
- Anope::string message = Language::Translate(nc, Config->MailMemoMessage.c_str());
+ Anope::string subject = Language::Translate(nc, Config->GetBlock("mail")->Get<const char *>("memo_subject")),
+ message = Language::Translate(Config->GetBlock("mail")->Get<const char *>("memo_message"));
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->NetworkName);
+ 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->NetworkName);
+ message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string &>("networkname"));
return Mail::Send(nc, subject, message);
}
@@ -50,7 +50,8 @@ class MyMemoServService : public MemoServService
User *sender = User::Find(source);
if (sender != NULL && !sender->HasPriv("memoserv/no-limit") && !force)
{
- if (Config->MSSendDelay > 0 && sender->lastmemosend + Config->MSSendDelay > Anope::CurTime)
+ time_t send_delay = Config->GetModule("memoserv")->Get<time_t>("senddelay");
+ if (send_delay > 0 && sender->lastmemosend + send_delay > Anope::CurTime)
return MEMO_TOO_FAST;
else if (!mi->memomax)
return MEMO_TARGET_FULL;
@@ -86,7 +87,7 @@ class MyMemoServService : public MemoServService
if (ci->AccessFor(cu->user).HasPriv("MEMO"))
{
if (cu->user->Account() && cu->user->Account()->HasExt("MEMO_RECEIVE"))
- cu->user->SendMessage(MemoServ, MEMO_NEW_X_MEMO_ARRIVED, ci->name.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->MemoServ.c_str(), ci->name.c_str(), mi->memos->size());
+ cu->user->SendMessage(MemoServ, MEMO_NEW_X_MEMO_ARRIVED, ci->name.c_str(), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str(), ci->name.c_str(), mi->memos->size());
}
}
}
@@ -102,7 +103,7 @@ class MyMemoServService : public MemoServService
const NickAlias *na = nc->aliases->at(i);
User *user = User::Find(na->nick);
if (user && user->IsIdentified())
- user->SendMessage(MemoServ, MEMO_NEW_MEMO_ARRIVED, source.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->MemoServ.c_str(), mi->memos->size());
+ user->SendMessage(MemoServ, MEMO_NEW_MEMO_ARRIVED, source.c_str(), Config->StrictPrivmsg.c_str(), MemoServ->nick.c_str(), mi->memos->size());
}
}
@@ -138,17 +139,12 @@ class MyMemoServService : public MemoServService
class MemoServCore : public Module
{
- MyMemoServService mymemoserv;
+ MyMemoServService memoserv;
public:
MemoServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
- mymemoserv(this)
+ memoserv(this)
{
-
- MemoServ = BotInfo::Find(Config->MemoServ);
- if (!MemoServ)
- throw ModuleException("No bot named " + Config->MemoServ);
-
- Implementation i[] = { I_OnBotDelete, I_OnNickIdentify, I_OnJoinChannel, I_OnUserAway, I_OnNickUpdate, I_OnPreHelp, I_OnPostHelp };
+ 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));
}
@@ -157,6 +153,30 @@ class MemoServCore : public Module
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");
+
+ BotInfo *bi = BotInfo::Find(msnick, true);
+ if (!bi)
+ throw ConfigException(this->name + ": no bot named " + msnick);
+
+ MemoServ = bi;
+ }
+
+ void OnNickCoreCreate(NickCore *nc) anope_override
+ {
+ nc->memos.memomax = Config->GetModule(this)->Get<int>("maxmemos");
+ }
+
+ void OnCreateChan(ChannelInfo *ci) anope_override
+ {
+ ci->memos.memomax = Config->GetModule(this)->Get<int>("maxmemos");
+ }
+
void OnBotDelete(BotInfo *bi) anope_override
{
if (bi == MemoServ)
@@ -165,7 +185,7 @@ class MemoServCore : public Module
void OnNickIdentify(User *u) anope_override
{
- this->mymemoserv.Check(u);
+ this->memoserv.Check(u);
}
void OnJoinChannel(User *u, Channel *c) anope_override
@@ -182,37 +202,37 @@ class MemoServCore : public Module
void OnUserAway(User *u, const Anope::string &message) anope_override
{
if (message.empty())
- this->mymemoserv.Check(u);
+ this-&