aboutsummaryrefslogtreecommitdiff
path: root/modules/messageflood.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/messageflood.cpp')
-rw-r--r--modules/messageflood.cpp78
1 files changed, 58 insertions, 20 deletions
diff --git a/modules/messageflood.cpp b/modules/messageflood.cpp
index a7cac8d43..32f0bed78 100644
--- a/modules/messageflood.cpp
+++ b/modules/messageflood.cpp
@@ -38,11 +38,22 @@ enum class MsgFloodAction
KICK_BAN,
};
+struct MsgFloodData final
+{
+ time_t reset;
+ double messages = 0;
+
+ MsgFloodData(unsigned long period)
+ : reset(ServerInstance->Time() + period)
+ {
+ }
+};
+
class MsgFloodSettings final
{
private:
- insp::flat_map<User*, double> counters;
- time_t reset;
+ using CounterMap = insp::flat_map<User*, MsgFloodData>;
+ CounterMap counters;
public:
MsgFloodAction action;
@@ -51,8 +62,7 @@ public:
MsgFloodSettings(MsgFloodAction a, unsigned int m, unsigned long p)
- : reset(ServerInstance->Time() + p)
- , action(a)
+ : action(a)
, messages(m)
, period(p)
{
@@ -60,20 +70,40 @@ public:
bool Add(User* who, double weight)
{
- if (ServerInstance->Time() > reset)
- {
- counters.clear();
- reset = ServerInstance->Time() + period;
- }
+ auto it = Find(who);
+ if (it == counters.end())
+ it = counters.emplace(who, MsgFloodData(period)).first;
- counters[who] += weight;
- return (counters[who] >= this->messages);
+ it->second.messages += weight;
+ return (it->second.messages >= this->messages);
}
void Clear(User* who)
{
counters.erase(who);
}
+
+
+ CounterMap::iterator Find(User* who)
+ {
+ auto found = false;
+ CounterMap::iterator ret;
+ for (auto it = counters.begin(); it != counters.end(); )
+ {
+ if (it->second.reset <= ServerInstance->Time())
+ it = counters.erase(it);
+ else
+ {
+ if (it->first == who)
+ {
+ found = true;
+ ret = it;
+ }
+ it++;
+ }
+ }
+ return found ? ret : counters.end();
+ }
};
class MsgFlood final
@@ -189,6 +219,7 @@ private:
double notice;
double privmsg;
double tagmsg;
+ bool resetonhit;
std::string message;
void CreateBan(Channel* channel, User* user, bool mute)
@@ -227,8 +258,9 @@ public:
const auto& tag = ServerInstance->Config->ConfValue("messageflood");
notice = tag->getNum<double>("notice", 1.0);
privmsg = tag->getNum<double>("privmsg", 1.0);
- tagmsg = tag->getNum<double>("tagmsg", 0.2);
- message = tag->getString("message", "Message flood detected (trigger is %messages% messages in %duration%)", 1);
+ tagmsg = tag->getNum<double>("tagmsg", 0.1);
+ message = tag->getString("message", "Message flood detected (trigger is %messages% messages in %duration.long%)", 1);
+ resetonhit = tag->getBool("resetonhit");
}
void GetLinkData(LinkData& data) override
@@ -254,20 +286,20 @@ public:
{
if (f->Add(user, weight))
{
- /* You're outttta here! */
- f->Clear(user);
-
const std::string msg = Template::Replace(message, {
- { "channel", dest->name },
- { "duration", Duration::ToString(f->period) },
- { "messages", ConvToStr(f->messages) },
- { "seconds", ConvToStr(f->period) },
+ { "channel", dest->name },
+ { "duration", Duration::ToString(f->period) },
+ { "duration.long", Duration::ToLongString(f->period) },
+ { "messages", ConvToStr(f->messages) },
+ { "seconds", ConvToStr(f->period) },
});
switch (f->action)
{
case MsgFloodAction::BAN:
InformUser(dest, user, msg);
CreateBan(dest, user, false);
+ if (resetonhit)
+ f->Clear(user);
break;
case MsgFloodAction::BLOCK:
@@ -276,16 +308,22 @@ public:
case MsgFloodAction::KICK:
dest->KickUser(ServerInstance->FakeClient, user, msg);
+ if (resetonhit)
+ f->Clear(user);
break;
case MsgFloodAction::KICK_BAN:
CreateBan(dest, user, false);
dest->KickUser(ServerInstance->FakeClient, user, msg);
+ if (resetonhit)
+ f->Clear(user);
break;
case MsgFloodAction::MUTE:
InformUser(dest, user, msg);
CreateBan(dest, user, true);
+ if (resetonhit)
+ f->Clear(user);
break;
}