summaryrefslogtreecommitdiff
path: root/modules/commands
diff options
context:
space:
mode:
Diffstat (limited to 'modules/commands')
-rw-r--r--modules/commands/bs_assign.cpp65
-rw-r--r--modules/commands/bs_badwords.cpp187
-rw-r--r--modules/commands/bs_info.cpp127
-rw-r--r--modules/commands/bs_kick.cpp623
-rw-r--r--modules/commands/bs_set.cpp317
-rw-r--r--modules/commands/cs_akick.cpp2
-rw-r--r--modules/commands/cs_clone.cpp19
-rw-r--r--modules/commands/cs_drop.cpp13
-rw-r--r--modules/commands/cs_enforce.cpp4
-rw-r--r--modules/commands/cs_entrymsg.cpp48
-rw-r--r--modules/commands/cs_info.cpp45
-rw-r--r--modules/commands/cs_list.cpp83
-rw-r--r--modules/commands/cs_log.cpp126
-rw-r--r--modules/commands/cs_mode.cpp368
-rw-r--r--modules/commands/cs_seen.cpp2
-rw-r--r--modules/commands/cs_set.cpp263
-rw-r--r--modules/commands/cs_set_misc.cpp57
-rw-r--r--modules/commands/cs_suspend.cpp131
-rw-r--r--modules/commands/cs_topic.cpp129
-rw-r--r--modules/commands/greet.cpp210
-rw-r--r--modules/commands/hs_request.cpp60
-rw-r--r--modules/commands/ms_info.cpp9
-rw-r--r--modules/commands/ms_set.cpp36
-rw-r--r--modules/commands/ns_ajoin.cpp53
-rw-r--r--modules/commands/ns_alist.cpp6
-rw-r--r--modules/commands/ns_cert.cpp224
-rw-r--r--modules/commands/ns_group.cpp10
-rw-r--r--modules/commands/ns_info.cpp170
-rw-r--r--modules/commands/ns_list.cpp112
-rw-r--r--modules/commands/ns_recover.cpp49
-rw-r--r--modules/commands/ns_register.cpp63
-rw-r--r--modules/commands/ns_resetpass.cpp28
-rw-r--r--modules/commands/ns_set.cpp427
-rw-r--r--modules/commands/ns_set_misc.cpp57
-rw-r--r--modules/commands/ns_suspend.cpp125
-rw-r--r--modules/commands/os_defcon.cpp20
-rw-r--r--modules/commands/os_login.cpp21
-rw-r--r--modules/commands/os_noop.cpp20
38 files changed, 2633 insertions, 1676 deletions
diff --git a/modules/commands/bs_assign.cpp b/modules/commands/bs_assign.cpp
index 7b241f09e..ba925ad80 100644
--- a/modules/commands/bs_assign.cpp
+++ b/modules/commands/bs_assign.cpp
@@ -145,14 +145,69 @@ class CommandBSUnassign : public Command
}
};
+class CommandBSSetNoBot : public Command
+{
+ public:
+ CommandBSSetNoBot(Module *creator, const Anope::string &sname = "botserv/set/nobot") : Command(creator, sname, 2, 2)
+ {
+ this->SetDesc(_("Prevent a bot from being assigned to a channel"));
+ this->SetSyntax(_("\037channel\037 {\037ON|OFF\037}"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ {
+ ChannelInfo *ci = ChannelInfo::Find(params[0]);
+ const Anope::string &value = params[1];
+
+ if (ci == NULL)
+ {
+ source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
+ return;
+ }
+
+ if (value.equals_ci("ON"))
+ {
+ Log(LOG_ADMIN, source, this, ci) << "to enable nobot";
+
+ ci->Extend<bool>("BS_NOBOT");
+ if (ci->bi)
+ ci->bi->UnAssign(source.GetUser(), ci);
+ source.Reply(_("No-bot mode is now \002on\002 on channel %s."), ci->name.c_str());
+ }
+ else if (value.equals_ci("OFF"))
+ {
+ Log(LOG_ADMIN, source, this, ci) << "to disable nobot";
+
+ ci->Shrink<bool>("BS_NOBOT");
+ source.Reply(_("No-bot mode is now \002off\002 on channel %s."), ci->name.c_str());
+ }
+ else
+ this->OnSyntaxError(source, source.command);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ {
+ this->SendSyntax(source);
+ source.Reply(_(" \n"
+ "This option makes a channel be unassignable. If a bot\n"
+ "is already assigned to the channel, it is unassigned\n"
+ "automatically when you enable the option."));
+ return true;
+ }
+};
+
class BSAssign : public Module
{
+ ExtensibleItem<bool> nobot;
+
CommandBSAssign commandbsassign;
CommandBSUnassign commandbsunassign;
+ CommandBSSetNoBot commandbssetnobot;
public:
BSAssign(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandbsassign(this), commandbsunassign(this)
+ nobot(this, "BS_NOBOT"),
+ commandbsassign(this), commandbsunassign(this), commandbssetnobot(this)
{
}
@@ -163,7 +218,7 @@ class BSAssign : public Module
return;
AccessGroup access = c->ci->AccessFor(source);
- if (c->ci->HasExt("BS_NOBOT") || (!access.HasPriv("ASSIGN") && !source->HasPriv("botserv/administration")))
+ if (nobot.HasExt(c->ci) || (!access.HasPriv("ASSIGN") && !source->HasPriv("botserv/administration")))
{
targ->SendMessage(bi, ACCESS_DENIED);
return;
@@ -184,6 +239,12 @@ class BSAssign : public Module
bi->Assign(source, c->ci);
targ->SendMessage(bi, _("Bot \002%s\002 has been assigned to %s."), bi->nick.c_str(), c->name.c_str());
}
+
+ void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) anope_override
+ {
+ if (nobot.HasExt(ci))
+ info.AddOption(_("No bot"));
+ }
};
MODULE_INIT(BSAssign)
diff --git a/modules/commands/bs_badwords.cpp b/modules/commands/bs_badwords.cpp
index 22fa74714..ff9707778 100644
--- a/modules/commands/bs_badwords.cpp
+++ b/modules/commands/bs_badwords.cpp
@@ -10,11 +10,132 @@
*/
#include "module.h"
+#include "modules/bs_badwords.h"
+
+struct BadWordImpl : BadWord, Serializable
+{
+ BadWordImpl() : Serializable("BadWord") { }
+ ~BadWordImpl();
+
+ void Serialize(Serialize::Data &data) const anope_override
+ {
+ data["ci"] << this->chan;
+ data["word"] << this->word;
+ data.SetType("type", Serialize::Data::DT_INT); data["type"] << this->type;
+ }
+
+ static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
+};
+
+struct BadWordsImpl : BadWords
+{
+ Serialize::Reference<ChannelInfo> ci;
+ typedef std::vector<BadWordImpl *> list;
+ Serialize::Checker<list> badwords;
+
+ BadWordsImpl(Extensible *obj) : ci(anope_dynamic_static_cast<ChannelInfo *>(obj)), badwords("BadWord") { }
+
+ BadWord* AddBadWord(const Anope::string &word, BadWordType type) anope_override
+ {
+ BadWordImpl *bw = new BadWordImpl();
+ bw->chan = ci->name;
+ bw->word = word;
+ bw->type = type;
+
+ this->badwords->push_back(bw);
+
+ FOREACH_MOD(OnBadWordAdd, (ci, bw));
+
+ return bw;
+ }
+
+ BadWord* GetBadWord(unsigned index) const anope_override
+ {
+ if (this->badwords->empty() || index >= this->badwords->size())
+ return NULL;
+
+ BadWordImpl *bw = (*this->badwords)[index];
+ bw->QueueUpdate();
+ return bw;
+ }
+
+ unsigned GetBadWordCount() const anope_override
+ {
+ return this->badwords->size();
+ }
+
+ void EraseBadWord(unsigned index) anope_override
+ {
+ if (this->badwords->empty() || index >= this->badwords->size())
+ return;
+
+ FOREACH_MOD(OnBadWordDel, (ci, (*this->badwords)[index]));
+
+ delete this->badwords->at(index);
+ }
+
+ void ClearBadWords() anope_override
+ {
+ while (!this->badwords->empty())
+ delete this->badwords->back();
+ }
+
+ void Check() anope_override
+ {
+ if (this->badwords->empty())
+ ci->Shrink<BadWords>("badwords");
+ }
+};
+
+BadWordImpl::~BadWordImpl()
+{
+ ChannelInfo *ci = ChannelInfo::Find(chan);
+ if (ci)
+ {
+ BadWordsImpl *badwords = ci->GetExt<BadWordsImpl>("badwords");
+ if (badwords)
+ {
+ BadWordsImpl::list::iterator it = std::find(badwords->badwords->begin(), badwords->badwords->end(), this);
+ if (it != badwords->badwords->end())
+ badwords->badwords->erase(it);
+ }
+ }
+}
+
+Serializable* BadWordImpl::Unserialize(Serializable *obj, Serialize::Data &data)
+{
+ Anope::string sci, sword;
+
+ data["ci"] >> sci;
+ data["word"] >> sword;
+
+ ChannelInfo *ci = ChannelInfo::Find(sci);
+ if (!ci)
+ return NULL;
+
+ unsigned int n;
+ data["type"] >> n;
+
+ BadWordImpl *bw;
+ if (obj)
+ bw = anope_dynamic_static_cast<BadWordImpl *>(obj);
+ else
+ bw = new BadWordImpl();
+ bw->chan = sci;
+ bw->word = sword;
+ bw->type = static_cast<BadWordType>(n);
+
+ BadWordsImpl *bws = ci->Require<BadWordsImpl>("badwords");
+ bws->badwords->push_back(bw);
+
+ return bw;
+}
class BadwordsDelCallback : public NumberList
{
CommandSource &source;
ChannelInfo *ci;
+ BadWords *bw;
Command *c;
unsigned deleted;
bool override;
@@ -23,6 +144,7 @@ class BadwordsDelCallback : public NumberList
{
if (!source.AccessFor(ci).HasPriv("BADWORDS") && source.HasPriv("botserv/administration"))
this->override = true;
+ bw = ci->Require<BadWords>("badwords");
}
~BadwordsDelCallback()
@@ -37,12 +159,12 @@ class BadwordsDelCallback : public NumberList
void HandleNumber(unsigned Number) anope_override
{
- if (!Number || Number > ci->GetBadWordCount())
+ if (!bw || !Number || Number > bw->GetBadWordCount())
return;
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "DEL " << ci->GetBadWord(Number - 1)->word;
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "DEL " << bw->GetBadWord(Number - 1)->word;
++deleted;
- ci->EraseBadWord(Number - 1);
+ bw->EraseBadWord(Number - 1);
}
};
@@ -54,10 +176,11 @@ class CommandBSBadwords : public Command
bool override = !source.AccessFor(ci).HasPriv("BADWORDS");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "LIST";
ListFormatter list;
+ BadWords *bw = ci->GetExt<BadWords>("badwords");
list.AddColumn("Number").AddColumn("Word").AddColumn("Type");
- if (!ci->GetBadWordCount())
+ if (!bw || !bw->GetBadWordCount())
{
source.Reply(_("%s bad words list is empty."), ci->name.c_str());
return;
@@ -68,40 +191,41 @@ class CommandBSBadwords : public Command
{
ListFormatter &list;
ChannelInfo *ci;
+ BadWords *bw;
public:
- BadwordsListCallback(ListFormatter &_list, ChannelInfo *_ci, const Anope::string &numlist) : NumberList(numlist, false), list(_list), ci(_ci)
+ BadwordsListCallback(ListFormatter &_list, ChannelInfo *_ci, BadWords *_bw, const Anope::string &numlist) : NumberList(numlist, false), list(_list), ci(_ci), bw(_bw)
{
}
void HandleNumber(unsigned Number) anope_override
{
- if (!Number || Number > ci->GetBadWordCount())
+ if (!Number || Number > bw->GetBadWordCount())
return;
- const BadWord *bw = ci->GetBadWord(Number - 1);
+ const BadWord *b = bw->GetBadWord(Number - 1);
ListFormatter::ListEntry entry;
entry["Number"] = stringify(Number);
- entry["Word"] = bw->word;
- entry["Type"] = bw->type == BW_SINGLE ? "(SINGLE)" : (bw->type == BW_START ? "(START)" : (bw->type == BW_END ? "(END)" : ""));
+ entry["Word"] = b->word;
+ entry["Type"] = b->type == BW_SINGLE ? "(SINGLE)" : (b->type == BW_START ? "(START)" : (b->type == BW_END ? "(END)" : ""));
this->list.AddEntry(entry);
}
}
- nl_list(list, ci, word);
+ nl_list(list, ci, bw, word);
nl_list.Process();
}
else
{
- for (unsigned i = 0, end = ci->GetBadWordCount(); i < end; ++i)
+ for (unsigned i = 0, end = bw->GetBadWordCount(); i < end; ++i)
{
- const BadWord *bw = ci->GetBadWord(i);
+ const BadWord *b = bw->GetBadWord(i);
- if (!word.empty() && !Anope::Match(bw->word, word))
+ if (!word.empty() && !Anope::Match(b->word, word))
continue;
ListFormatter::ListEntry entry;
entry["Number"] = stringify(i + 1);
- entry["Word"] = bw->word;
- entry["Type"] = bw->type == BW_SINGLE ? "(SINGLE)" : (bw->type == BW_START ? "(START)" : (bw->type == BW_END ? "(END)" : ""));
+ entry["Word"] = b->word;
+ entry["Type"] = b->type == BW_SINGLE ? "(SINGLE)" : (b->type == BW_START ? "(START)" : (b->type == BW_END ? "(END)" : ""));
list.AddEntry(entry);
}
}
@@ -127,6 +251,7 @@ class CommandBSBadwords : public Command
size_t pos = word.rfind(' ');
BadWordType bwtype = BW_ANY;
Anope::string realword = word;
+ BadWords *badwords = ci->Require<BadWords>("badwords");
if (pos != Anope::string::npos)
{
@@ -144,7 +269,7 @@ class CommandBSBadwords : public Command
}
unsigned badwordsmax = Config->GetModule(this->module)->Get<unsigned>("badwordsmax");
- if (ci->GetBadWordCount() >= badwordsmax)
+ if (badwords->GetBadWordCount() >= badwordsmax)
{
source.Reply(_("Sorry, you can only have %d bad words entries on a channel."), badwordsmax);
return;
@@ -152,9 +277,9 @@ class CommandBSBadwords : public Command
bool casesensitive = Config->GetModule("botserv")->Get<bool>("casesensitive");
- for (unsigned i = 0, end = ci->GetBadWordCount(); i < end; ++i)
+ for (unsigned i = 0, end = badwords->GetBadWordCount(); i < end; ++i)
{
- const BadWord *bw = ci->GetBadWord(i);
+ const BadWord *bw = badwords->GetBadWord(i);
if ((casesensitive && realword.equals_cs(bw->word)) || (!casesensitive && realword.equals_ci(bw->word)))
{
@@ -165,13 +290,21 @@ class CommandBSBadwords : public Command
bool override = !source.AccessFor(ci).HasPriv("BADWORDS");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "ADD " << realword;
- ci->AddBadWord(realword, bwtype);
+ badwords->AddBadWord(realword, bwtype);
source.Reply(_("\002%s\002 added to %s bad words list."), realword.c_str(), ci->name.c_str());
}
void DoDelete(CommandSource &source, ChannelInfo *ci, const Anope::string &word)
{
+ BadWords *badwords = ci->GetExt<BadWords>("badwords");
+
+ if (!badwords || !badwords->GetBadWordCount())
+ {
+ source.Reply(_("%s bad words list is empty."), ci->name.c_str());
+ return;
+ }
+
/* Special case: is it a number/list? Only do search if it isn't. */
if (!word.empty() && isdigit(word[0]) && word.find_first_not_of("1234567890,-") == Anope::string::npos)
{
@@ -183,9 +316,9 @@ class CommandBSBadwords : public Command
unsigned i, end;
const BadWord *badword;
- for (i = 0, end = ci->GetBadWordCount(); i < end; ++i)
+ for (i = 0, end = badwords->GetBadWordCount(); i < end; ++i)
{
- badword = ci->GetBadWord(i);
+ badword = badwords->GetBadWord(i);
if (word.equals_ci(badword->word))
break;
@@ -202,10 +335,10 @@ class CommandBSBadwords : public Command
source.Reply(_("\002%s\002 deleted from %s bad words list."), badword->word.c_str(), ci->name.c_str());
- ci->EraseBadWord(i);
+ badwords->EraseBadWord(i);
}
- return;
+ badwords->Check();
}
void DoClear(CommandSource &source, ChannelInfo *ci)
@@ -213,7 +346,9 @@ class CommandBSBadwords : public Command
bool override = !source.AccessFor(ci).HasPriv("BADWORDS");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "CLEAR";
- ci->ClearBadWords();
+ BadWords *badwords = ci->GetExt<BadWords>("badwords");
+ if (badwords)
+ badwords->ClearBadWords();
source.Reply(_("Bad words list is now empty."));
}
@@ -309,10 +444,12 @@ class CommandBSBadwords : public Command
class BSBadwords : public Module
{
CommandBSBadwords commandbsbadwords;
+ ExtensibleItem<BadWordsImpl> badwords;
+ Serialize::Type badword_type;
public:
BSBadwords(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandbsbadwords(this)
+ commandbsbadwords(this), badwords(this, "badwords"), badword_type("BadWord", BadWordImpl::Unserialize)
{
}
};
diff --git a/modules/commands/bs_info.cpp b/modules/commands/bs_info.cpp
index 8bbfd0b18..a3eb9ce2d 100644
--- a/modules/commands/bs_info.cpp
+++ b/modules/commands/bs_info.cpp
@@ -36,16 +36,6 @@ class CommandBSInfo : public Command
buffers.push_back(buf);
}
- void CheckOptStr(Anope::string &buf, const Anope::string &flag, const char *option, Extensible *flags, const NickCore *nc)
- {
- if (flags->HasExt(flag))
- {
- if (!buf.empty())
- buf += ", ";
- buf += Language::Translate(nc, option);
- }
- }
-
public:
CommandBSInfo(Module *creator) : Command(creator, "botserv/info", 1, 1)
{
@@ -57,8 +47,8 @@ class CommandBSInfo : public Command
{
const Anope::string &query = params[0];
- const BotInfo *bi = BotInfo::Find(query, true);
- ChannelInfo *ci;
+ BotInfo *bi = BotInfo::Find(query, true);
+ ChannelInfo *ci = ChannelInfo::Find(query);
InfoFormatter info(source.nc);
if (bi)
@@ -70,6 +60,8 @@ class CommandBSInfo : public Command
info[_("Options")] = bi->oper_only ? _("Private") : _("None");
info[_("Used on")] = stringify(bi->GetChannelCount()) + " channel(s)";
+ FOREACH_MOD(OnBotInfo, (source, bi, ci, info));
+
std::vector<Anope::string> replies;
info.Process(replies);
@@ -85,7 +77,7 @@ class CommandBSInfo : public Command
}
}
- else if ((ci = ChannelInfo::Find(query)))
+ else if (ci)
{
if (!source.AccessFor(ci).HasPriv("INFO") && !source.HasPriv("botserv/administration"))
{
@@ -99,114 +91,7 @@ class CommandBSInfo : public Command
Anope::string enabled = Language::Translate(source.nc, _("Enabled"));
Anope::string disabled = Language::Translate(source.nc, _("Disabled"));
- if (ci->HasExt("BS_KICK_BADWORDS"))
- {
- if (ci->ttb[TTB_BADWORDS])
- info[_("Bad words kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), ci->ttb[TTB_BADWORDS]);
- else
- info[_("Bad words kicker")] = enabled;
- }
- else
- info[_("Bad words kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_BOLDS"))
- {
- if (ci->ttb[TTB_BOLDS])
- info[_("Bolds kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), ci->ttb[TTB_BOLDS]);
- else
- info[_("Bolds kicker")] = enabled;
- }
- else
- info[_("Bolds kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_CAPS"))
- {
- if (ci->ttb[TTB_CAPS])
- info[_("Caps kicker")] = Anope::printf(_("%s (%d kick(s) to ban; minimum %d/%d%%"), enabled.c_str(), ci->ttb[TTB_CAPS], ci->capsmin, ci->capspercent);
- else
- info[_("Caps kicker")] = Anope::printf(_("%s (minimum %d/%d%%)"), enabled.c_str(), ci->capsmin, ci->capspercent);
- }
- else
- info[_("Caps kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_COLORS"))
- {
- if (ci->ttb[TTB_COLORS])
- info[_("Colors kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), ci->ttb[TTB_COLORS]);
- else
- info[_("Colors kicker")] = enabled;
- }
- else
- info[_("Colors kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_FLOOD"))
- {
- if (ci->ttb[TTB_FLOOD])
- info[_("Flood kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d lines in %ds"), enabled.c_str(), ci->ttb[TTB_FLOOD], ci->floodlines, ci->floodsecs);
- else
- info[_("Flood kicker")] = Anope::printf(_("%s (%d lines in %ds)"), enabled.c_str(), ci->floodlines, ci->floodsecs);
- }
- else
- info[_("Flood kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_REPEAT"))
- {
- if (ci->ttb[TTB_REPEAT])
- info[_("Repeat kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d times)"), enabled.c_str(), ci->ttb[TTB_REPEAT], ci->repeattimes);
- else
- info[_("Repeat kicker")] = Anope::printf(_("%s (%d times)"), enabled.c_str(), ci->repeattimes);
- }
- else
- info[_("Repeat kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_REVERSES"))
- {
- if (ci->ttb[TTB_REVERSES])
- info[_("Reverses kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), ci->ttb[TTB_REVERSES]);
- else
- info[_("Reverses kicker")] = enabled;
- }
- else
- info[_("Reverses kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_UNDERLINES"))
- {
- if (ci->ttb[TTB_UNDERLINES])
- info[_("Underlines kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), ci->ttb[TTB_UNDERLINES]);
- else
- info[_("Underlines kicker")] = enabled;
- }
- else
- info[_("Underlines kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_ITALICS"))
- {
- if (ci->ttb[TTB_ITALICS])
- info[_("Italics kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), ci->ttb[TTB_ITALICS]);
- else
- info[_("Italics kicker")] = enabled;
- }
- else
- info[_("Italics kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_AMSGS"))
- {
- if (ci->ttb[TTB_AMSGS])
- info[_("AMSG kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), ci->ttb[TTB_AMSGS]);
- else
- info[_("AMSG kicker")] = enabled;
- }
- else
- info[_("AMSG kicker")] = disabled;
-
- Anope::string flags;
- CheckOptStr(flags, "BS_DONTKICKOPS", _("Ops protection"), ci, source.nc);
- CheckOptStr(flags, "BS_DONTKICKVOICES", _("Voices protection"), ci, source.nc);
- CheckOptStr(flags, "BS_FANTASY", _("Fantasy"), ci, source.nc);
- CheckOptStr(flags, "BS_GREET", _("Greet"), ci, source.nc);
- CheckOptStr(flags, "BS_NOBOT", _("No bot"), ci, source.nc);
-
- info[_("Options")] = flags.empty() ? _("None") : flags;
+ FOREACH_MOD(OnBotInfo, (source, bi, ci, info));
std::vector<Anope::string> replies;
info.Process(replies);
diff --git a/modules/commands/bs_kick.cpp b/modules/commands/bs_kick.cpp
index 50d4a0e5f..b22dd9ccb 100644
--- a/modules/commands/bs_kick.cpp
+++ b/modules/commands/bs_kick.cpp
@@ -12,9 +12,107 @@
*/
#include "module.h"
+#include "modules/bs_kick.h"
+#include "modules/bs_badwords.h"
static Module *me;
+struct KickerDataImpl : KickerData
+{
+ KickerDataImpl(Extensible *obj)
+ {
+ amsgs = badwords = bolds = caps = colors = flood = italics = repeat = reverses = underlines = false;
+ for (int16_t i = 0; i < TTB_SIZE; ++i)
+ ttb[i] = 0;
+ capsmin = capspercent = 0;
+ floodlines = floodsecs = 0;
+ repeattimes = 0;
+
+ dontkickops = dontkickvoices = false;
+ }
+
+ void Check(ChannelInfo *ci) anope_override
+ {
+ if (amsgs || badwords || bolds || caps || colors || flood || italics || repeat || reverses || underlines)
+ return;
+
+ ci->Shrink<KickerData>("kickerdata");
+ }
+
+ struct ExtensibleItem : ::ExtensibleItem<KickerDataImpl>
+ {
+ ExtensibleItem(Module *m, const Anope::string &name) : ::ExtensibleItem<KickerDataImpl>(m, name) { }
+
+ void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override
+ {
+ if (s->GetSerializableType()->GetName() != "ChannelInfo")
+ return;
+
+ const ChannelInfo *ci = anope_dynamic_static_cast<const ChannelInfo *>(e);
+ KickerData *kd = this->Get(ci);
+ if (kd == NULL)
+ return;
+
+ data["kickerdata:amsgs"] << kd->amsgs;
+ data["kickerdata:badwords"] << kd->badwords;
+ data["kickerdata:bolds"] << kd->bolds;
+ data["kickerdata:caps"] << kd->caps;
+ data["kickerdata:colors"] << kd->colors;
+ data["kickerdata:flood"] << kd->flood;
+ data["kickerdata:italics"] << kd->italics;
+ data["kickerdata:repeat"] << kd->repeat;
+ data["kickerdata:reverses"] << kd->reverses;
+ data["kickerdata:underlines"] << kd->underlines;
+
+ data.SetType("capsmin", Serialize::Data::DT_INT); data["capsmin"] << kd->capsmin;
+ data.SetType("capspercent", Serialize::Data::DT_INT); data["capspercent"] << kd->capspercent;
+ data.SetType("floodlines", Serialize::Data::DT_INT); data["floodlines"] << kd->floodlines;
+ data.SetType("floodsecs", Serialize::Data::DT_INT); data["floodsecs"] << kd->floodsecs;
+ data.SetType("repeattimes", Serialize::Data::DT_INT); data["repeattimes"] << kd->repeattimes;
+ for (int16_t i = 0; i < TTB_SIZE; ++i)
+ data["ttb"] << kd->ttb[i] << " ";
+ }
+
+ void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override
+ {
+ if (s->GetSerializableType()->GetName() != "ChannelInfo")
+ return;
+
+ ChannelInfo *ci = anope_dynamic_static_cast<ChannelInfo *>(e);
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+
+ data["kickerdata:amsgs"] >> kd->amsgs;
+ data["kickerdata:badwords"] >> kd->badwords;
+ data["kickerdata:bolds"] >> kd->bolds;
+ data["kickerdata:caps"] >> kd->caps;
+ data["kickerdata:colors"] >> kd->colors;
+ data["kickerdata:flood"] >> kd->flood;
+ data["kickerdata:italics"] >> kd->italics;
+ data["kickerdata:repeat"] >> kd->repeat;
+ data["kickerdata:reverses"] >> kd->reverses;
+ data["kickerdata:underlines"] >> kd->underlines;
+
+ data["capsmin"] >> kd->capsmin;
+ data["capspercent"] >> kd->capspercent;
+ data["floodlines"] >> kd->floodlines;
+ data["floodsecs"] >> kd->floodsecs;
+ data["repeattimes"] >> kd->repeattimes;
+
+ Anope::string ttb, tok;
+ data["ttb"] >> ttb;
+ spacesepstream sep(ttb);
+ for (int i = 0; sep.GetToken(tok) && i < TTB_SIZE; ++i)
+ try
+ {
+ ttb[i] = convertTo<int16_t>(tok);
+ }
+ catch (const ConvertException &) { }
+
+ kd->Check(ci);
+ }
+ };
+};
+
class CommandBSKick : public Command
{
public:
@@ -99,7 +197,7 @@ class CommandBSKickBase : public Command
return false;
}
- void Process(CommandSource &source, ChannelInfo *ci, const Anope::string &param, const Anope::string &ttb, size_t ttb_idx, const Anope::string &optname, const Anope::string &mdname)
+ void Process(CommandSource &source, ChannelInfo *ci, const Anope::string &param, const Anope::string &ttb, size_t ttb_idx, const Anope::string &optname, KickerData *kd, bool &val)
{
if (param.equals_ci("ON"))
{
@@ -119,15 +217,15 @@ class CommandBSKickBase : public Command
return;
}
- ci->ttb[ttb_idx] = i;
+ kd->ttb[ttb_idx] = i;
}
else
- ci->ttb[ttb_idx] = 0;
+ kd->ttb[ttb_idx] = 0;
- ci->ExtendMetadata(mdname);
- if (ci->ttb[ttb_idx])
+ val = true;
+ if (kd->ttb[ttb_idx])
source.Reply(_("Bot will now kick for \002%s\002, and will place a ban\n"
- "after %d kicks for the same user."), optname.c_str(), ci->ttb[ttb_idx]);
+ "after %d kicks for the same user."), optname.c_str(), kd->ttb[ttb_idx]);
else
source.Reply(_("Bot will now kick for \002%s\002."), optname.c_str());
@@ -139,7 +237,7 @@ class CommandBSKickBase : public Command
bool override = !source.AccessFor(ci).HasPriv("SET");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable the " << optname << "kicker";
- ci->Shrink(mdname);
+ val = false;
source.Reply(_("Bot won't kick for \002%s\002 anymore."), optname.c_str());
}
else
@@ -160,7 +258,11 @@ class CommandBSKickAMSG : public CommandBSKickBase
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
- Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_AMSGS, "AMSG", "BS_KICK_AMSGS");
+ {
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+ Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_AMSGS, "AMSG", kd, kd->amsgs);
+ kd->Check(ci);
+ }
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -188,7 +290,12 @@ class CommandBSKickBadwords : public CommandBSKickBase
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
- Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_BADWORDS, "badwords", "BS_KICK_BADWORDS");
+ {
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+ Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_BADWORDS, "badwords", kd, kd->badwords);
+ kd->Check(ci);
+ }
+
}
bool OnHelp(CommandSource