diff options
| author | 2025-09-30 21:45:55 +0100 | |
|---|---|---|
| committer | 2025-09-30 21:46:44 +0100 | |
| commit | 72f9fa781f236112ca72fd3484315de8cf85e50d (patch) | |
| tree | 3f2b8a3432e7d3343b32d9afdb14160faa70627e /modules/messageflood.cpp | |
| parent | Fix some misc issues with the services module. (diff) | |
| parent | Tweak a message to make it clear that its not always an error. (diff) | |
Merge branch 'insp4' into master.
Diffstat (limited to 'modules/messageflood.cpp')
| -rw-r--r-- | modules/messageflood.cpp | 78 |
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; } |
