From 62ca6c96eb391abe6b33794d44e7b9f5a113eaeb Mon Sep 17 00:00:00 2001 From: Sadie Powell Date: Mon, 24 Nov 2025 12:36:22 +0000 Subject: [PATCH] Move akick from the core to cs_akick. --- include/defs.h | 2 +- include/modules.h | 8 +- include/modules/chanserv/akick.h | 108 +++++++++ include/regchannel.h | 67 ------ include/serialize.h | 1 - modules/chanserv/chanserv.cpp | 10 - modules/chanserv/cs_akick.cpp | 265 ++++++++++++++++++--- modules/chanserv/cs_clone.cpp | 14 +- modules/chanserv/cs_status.cpp | 28 ++- modules/database/db_atheme.cpp | 13 +- modules/webcpanel/pages/chanserv/akick.cpp | 20 +- src/regchannel.cpp | 149 ------------ src/serialize.cpp | 1 - 13 files changed, 397 insertions(+), 289 deletions(-) create mode 100644 include/modules/chanserv/akick.h diff --git a/include/defs.h b/include/defs.h index 52fef0163..49df9dc31 100644 --- a/include/defs.h +++ b/include/defs.h @@ -15,7 +15,7 @@ #pragma once class AccessGroup; -class AutoKick; +namespace ChanServ { class AutoKick; } class BotInfo; class CallBack; class ChanAccess; diff --git a/include/modules.h b/include/modules.h index d6f529cb2..63cecb0d6 100644 --- a/include/modules.h +++ b/include/modules.h @@ -672,14 +672,14 @@ public: * @param ci The channel * @param ak The akick */ - virtual void OnAkickAdd(CommandSource &source, ChannelInfo *ci, const AutoKick *ak) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); } + virtual void OnAKickAdd(CommandSource &source, ChannelInfo *ci, const ChanServ::AutoKick *ak) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); } /** Called before removing an akick from a channel * @param source The source of the command * @param ci The channel * @param ak The akick */ - virtual void OnAkickDel(CommandSource &source, ChannelInfo *ci, const AutoKick *ak) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); } + virtual void OnAKickDel(CommandSource &source, ChannelInfo *ci, const ChanServ::AutoKick *ak) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); } /** Called after a user join a channel when we decide whether to kick them or not * @param u The user @@ -1087,8 +1087,8 @@ enum Implementation I_OnAccessClear, I_OnAccessDel, I_OnAddXLine, - I_OnAkickAdd, - I_OnAkickDel, + I_OnAKickAdd, + I_OnAKickDel, I_OnBadWordAdd, I_OnBadWordDel, I_OnBotAssign, diff --git a/include/modules/chanserv/akick.h b/include/modules/chanserv/akick.h new file mode 100644 index 000000000..5a7b9378a --- /dev/null +++ b/include/modules/chanserv/akick.h @@ -0,0 +1,108 @@ +// Anope IRC Services +// +// Copyright (C) 2003-2025 Anope Contributors +// +// Anope is free software. You can use, modify, and/or distribute it under the +// terms of version 2 of the GNU General Public License. See docs/LICENSE.txt +// for the complete terms of this license and docs/AUTHORS.txt for a list of +// contributors. +// +// Based on the original code of Epona by Lara +// Based on the original code of Services by Andy Church +// +// SPDX-License-Identifier: GPL-2.0-only + +#pragma once + +#define AUTOKICK_TYPE "AutoKick" +#define AUTOKICK_SERVICE "ChanServ::AutoKickService" + +namespace ChanServ +{ + class AutoKick; + class AutoKickService; + + ServiceReference akick_service(AUTOKICK_SERVICE, AUTOKICK_TYPE); +} + +class ChanServ::AutoKickService + : public Service +{ +public: + AutoKickService(Module *m) + : Service(m, AUTOKICK_SERVICE, AUTOKICK_TYPE) + { + } + + /** Add an akick entry to the channel by NickCore + * @param user The user who added the akick + * @param akicknc The nickcore being akicked + * @param reason The reason for the akick + * @param t The time the akick was added, defaults to now + * @param lu The time the akick was last used, defaults to never + */ + virtual AutoKick *AddAKick(ChannelInfo *ci, const Anope::string &user, NickCore *akicknc, const Anope::string &reason, time_t t = Anope::CurTime, time_t lu = 0) = 0; + + /** Add an akick entry to the channel by reason + * @param user The user who added the akick + * @param mask The mask of the akick + * @param reason The reason for the akick + * @param t The time the akick was added, defaults to now + * @param lu The time the akick was last used, defaults to never + */ + virtual AutoKick *AddAKick(ChannelInfo *ci, const Anope::string &user, const Anope::string &mask, const Anope::string &reason, time_t t = Anope::CurTime, time_t lu = 0) = 0; + + /** Get an entry from the channel akick list + * @param index The index in the akick vector + * @return The akick structure, or NULL if not found + */ + virtual AutoKick *GetAKick(ChannelInfo *ci, unsigned index) = 0; + + /** Get the size of the akick vector for this channel + * @return The akick vector size + */ + virtual unsigned GetAKickCount(ChannelInfo *ci) = 0; + + /** Erase an entry from the channel akick list + * @param index The index of the akick + */ + virtual void EraseAKick(ChannelInfo *ci, unsigned index) = 0; + virtual void EraseAKick(ChannelInfo *ci, AutoKick *akick) = 0; + + /** Clear the whole akick list + */ + virtual void ClearAKick(ChannelInfo *ci) = 0; +}; + +class ChanServ::AutoKick final + : public Serializable +{ +public: + /* Channel this autokick is on */ + Serialize::Reference ci; + + Anope::string mask; + Serialize::Reference nc; + + Anope::string reason; + Anope::string creator; + time_t addtime; + time_t last_used; + + AutoKick() + : Serializable(AUTOKICK_TYPE) + { + } + + ~AutoKick() + { + if (!this->ci) + return; + + if (ChanServ::akick_service) + ChanServ::akick_service->EraseAKick(this->ci, this); + + if (this->nc) + this->nc->RemoveChannelReference(this->ci); + } +}; diff --git a/include/regchannel.h b/include/regchannel.h index 98c9e04c5..65019c2ce 100644 --- a/include/regchannel.h +++ b/include/regchannel.h @@ -26,34 +26,6 @@ typedef Anope::unordered_map registered_channel_map; extern CoreExport Serialize::Checker RegisteredChannelList; -/* AutoKick data. */ -class CoreExport AutoKick final - : public Serializable -{ -public: - struct Type final - : public Serialize::Type - { - Type(); - void Serialize(Serializable *obj, Serialize::Data &data) const override; - Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override; - }; - - /* Channel this autokick is on */ - Serialize::Reference ci; - - Anope::string mask; - Serialize::Reference nc; - - Anope::string reason; - Anope::string creator; - time_t addtime; - time_t last_used; - - AutoKick(); - ~AutoKick(); -}; - /* It matters that Base is here before Extensible (it is inherited by Serializable) */ class CoreExport ChannelInfo final @@ -75,7 +47,6 @@ private: Serialize::Reference founder; /* Channel founder */ Serialize::Reference successor; /* Who gets the channel if the founder nick is dropped or expires */ Serialize::Checker > access; /* List of authorized users */ - Serialize::Checker > akick; /* List of users to kickban */ Anope::map levels; public: @@ -180,44 +151,6 @@ public: */ void ClearAccess(); - /** Add an akick entry to the channel by NickCore - * @param user The user who added the akick - * @param akicknc The nickcore being akicked - * @param reason The reason for the akick - * @param t The time the akick was added, defaults to now - * @param lu The time the akick was last used, defaults to never - */ - AutoKick *AddAkick(const Anope::string &user, NickCore *akicknc, const Anope::string &reason, time_t t = Anope::CurTime, time_t lu = 0); - - /** Add an akick entry to the channel by reason - * @param user The user who added the akick - * @param mask The mask of the akick - * @param reason The reason for the akick - * @param t The time the akick was added, defaults to now - * @param lu The time the akick was last used, defaults to never - */ - AutoKick *AddAkick(const Anope::string &user, const Anope::string &mask, const Anope::string &reason, time_t t = Anope::CurTime, time_t lu = 0); - - /** Get an entry from the channel akick list - * @param index The index in the akick vector - * @return The akick structure, or NULL if not found - */ - AutoKick *GetAkick(unsigned index) const; - - /** Get the size of the akick vector for this channel - * @return The akick vector size - */ - unsigned GetAkickCount() const; - - /** Erase an entry from the channel akick list - * @param index The index of the akick - */ - void EraseAkick(unsigned index); - - /** Clear the whole akick list - */ - void ClearAkick(); - /** Get the level entries for the channel. * @return The levels for the channel. */ diff --git a/include/serialize.h b/include/serialize.h index a6fc7c294..b501a62a9 100644 --- a/include/serialize.h +++ b/include/serialize.h @@ -20,7 +20,6 @@ #include "base.h" /** Names of serialization types implemented in the core. */ -#define AUTOKICK_TYPE "AutoKick" #define BOTINFO_TYPE "BotInfo" #define CHANACCESS_TYPE "ChanAccess" #define CHANNELINFO_TYPE "ChannelInfo" diff --git a/modules/chanserv/chanserv.cpp b/modules/chanserv/chanserv.cpp index 24657fea3..bdb92456d 100644 --- a/modules/chanserv/chanserv.cpp +++ b/modules/chanserv/chanserv.cpp @@ -211,16 +211,6 @@ public: break; } } - - for (unsigned j = 0; j < ci->GetAkickCount(); ++j) - { - const AutoKick *akick = ci->GetAkick(j); - if (akick->nc == nc) - { - ci->EraseAkick(j); - break; - } - } } } diff --git a/modules/chanserv/cs_akick.cpp b/modules/chanserv/cs_akick.cpp index 788d2db19..ff84bf0ba 100644 --- a/modules/chanserv/cs_akick.cpp +++ b/modules/chanserv/cs_akick.cpp @@ -13,6 +13,180 @@ // SPDX-License-Identifier: GPL-2.0-only #include "module.h" +#include "modules/chanserv/akick.h" + +#define AKICK_EXT "akicks" + +class AKickService final + : public ChanServ::AutoKickService +{ +private: + struct AKickList final + : Serialize::Checker> + { + AKickList(Extensible *) + : Serialize::Checker>(AKICK_EXT) + { + } + }; + ExtensibleItem akickext; + +public: + AKickService(Module *m) + : ChanServ::AutoKickService(m) + , akickext(m, AKICK_EXT) + { + } + + ChanServ::AutoKick *AddAKick(ChannelInfo *ci, const Anope::string &user, NickCore *akicknc, const Anope::string &reason, time_t t = Anope::CurTime, time_t lu = 0) override + { + auto *akick = new ChanServ::AutoKick(); + akick->ci = ci; + akick->nc = akicknc; + akick->reason = reason; + akick->creator = user; + akick->addtime = t; + akick->last_used = lu; + + auto *akicks = akickext.Require(ci); + (*akicks)->push_back(akick); + + akicknc->AddChannelReference(ci); + + return akick; + } + + ChanServ::AutoKick *AddAKick(ChannelInfo *ci, const Anope::string &user, const Anope::string &mask, const Anope::string &reason, time_t t = Anope::CurTime, time_t lu = 0) override + { + auto *akick = new ChanServ::AutoKick(); + akick->ci = ci; + akick->mask = mask; + akick->nc = nullptr; + akick->reason = reason; + akick->creator = user; + akick->addtime = t; + akick->last_used = lu; + + auto *akicks = akickext.Require(ci); + (*akicks)->push_back(akick); + + return akick; + } + + ChanServ::AutoKick *GetAKick(ChannelInfo *ci, unsigned index) override + { + auto *akicks = akickext.Get(ci); + if (!akicks || index >= (*akicks)->size()) + return nullptr; + + auto *akick = (*akicks)->at(index); + akick->QueueUpdate(); + return akick; + } + + unsigned GetAKickCount(ChannelInfo *ci) override + { + auto *akicks = akickext.Get(ci); + return akicks ? (*akicks)->size() : 0; + } + + void EraseAKick(ChannelInfo *ci, unsigned index) override + { + auto *akicks = akickext.Get(ci); + if (akicks && index < (*akicks)->size()) + delete (*akicks)->at(index); + } + + void EraseAKick(ChannelInfo *ci, ChanServ::AutoKick *akick) override + { + auto *akicks = akickext.Get(ci); + if (!akicks) + return; + + auto it = std::find((*akicks)->begin(), (*akicks)->end(), akick); + if (it != (*akicks)->end()) + (*akicks)->erase(it); + } + + void ClearAKick(ChannelInfo *ci) override + { + auto *akicks = akickext.Get(ci); + if (!akicks) + return; // No akick list. + + while (!(*akicks)->empty()) + delete (*akicks)->back(); + } +}; + +struct AutoKickType final + : public Serialize::Type +{ + AutoKickType() + : Serialize::Type(AUTOKICK_TYPE) + { + } + + void Serialize(Serializable *obj, Serialize::Data &data) const override + { + const auto *ak = static_cast(obj); + data.Store("ci", ak->ci->name); + if (ak->nc) + data.Store("ncid", ak->nc->GetId()); + else + data.Store("mask", ak->mask); + data.Store("reason", ak->reason); + data.Store("creator", ak->creator); + data.Store("addtime", ak->addtime); + data.Store("last_used", ak->last_used); + } + + Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override + { + Anope::string sci, snc; + uint64_t sncid = 0; + + data["ci"] >> sci; + data["nc"] >> snc; // Deprecated 2.0 field + data["ncid"] >> sncid; + + ChannelInfo *ci = ChannelInfo::Find(sci); + if (!ci) + return NULL; + + ChanServ::AutoKick *ak; + auto *nc = sncid ? NickCore::FindId(sncid) : NickCore::Find(snc); + if (obj) + { + ak = anope_dynamic_static_cast(obj); + data["creator"] >> ak->creator; + data["reason"] >> ak->reason; + ak->nc = nc; + data["mask"] >> ak->mask; + data["addtime"] >> ak->addtime; + data["last_used"] >> ak->last_used; + } + else + { + time_t addtime, lastused; + data["addtime"] >> addtime; + data["last_used"] >> lastused; + + Anope::string screator, sreason, smask; + + data["creator"] >> screator; + data["reason"] >> sreason; + data["mask"] >> smask; + + if (nc) + ak = ChanServ::akick_service->AddAKick(ci, screator, nc, sreason, addtime, lastused); + else + ak = ChanServ::akick_service->AddAKick(ci, screator, smask, sreason, addtime, lastused); + } + + return ak; + } +}; class CommandCSAKick final : public Command @@ -48,7 +222,7 @@ class CommandCSAKick final Anope::string reason = params.size() > 3 ? params[3] : ""; const NickAlias *na = NickAlias::Find(mask); NickCore *nc = NULL; - const AutoKick *akick; + const ChanServ::AutoKick *akick; unsigned reasonmax = Config->GetModule("chanserv").Get("reasonmax", "200"); if (reason.length() > reasonmax) @@ -163,9 +337,9 @@ class CommandCSAKick final } } - for (unsigned j = 0, end = ci->GetAkickCount(); j < end; ++j) + for (unsigned j = 0, end = ChanServ::akick_service->GetAKickCount(ci); j < end; ++j) { - akick = ci->GetAkick(j); + akick = ChanServ::akick_service->GetAKick(ci, j); if (akick->nc ? akick->nc == nc : mask.equals_ci(akick->mask)) { source.Reply(_("\002%s\002 already exists on %s autokick list."), akick->nc ? akick->nc->display.c_str() : akick->mask.c_str(), ci->name.c_str()); @@ -173,20 +347,20 @@ class CommandCSAKick final } } - if (ci->GetAkickCount() >= Config->GetModule(this->owner).Get("autokickmax")) + if (ChanServ::akick_service->GetAKickCount(ci) >= Config->GetModule(this->owner).Get("autokickmax")) { source.Reply(_("Sorry, you can only have %d autokick masks on a channel."), Config->GetModule(this->owner).Get("autokickmax")); return; } if (nc) - akick = ci->AddAkick(source.GetNick(), nc, reason); + akick = ChanServ::akick_service->AddAKick(ci, source.GetNick(), nc, reason); else - akick = ci->AddAkick(source.GetNick(), mask, reason); + akick = ChanServ::akick_service->AddAKick(ci, source.GetNick(), mask, reason); Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to add " << mask << (reason == "" ? "" : ": ") << reason; - FOREACH_MOD(OnAkickAdd, (source, ci, akick)); + FOREACH_MOD(OnAKickAdd, (source, ci, akick)); source.Reply(_("\002%s\002 added to %s autokick list."), mask.c_str(), ci->name.c_str()); @@ -198,7 +372,7 @@ class CommandCSAKick final const Anope::string &mask = params[2]; unsigned i, end; - if (!ci->GetAkickCount()) + if (!ChanServ::akick_service->GetAKickCount(ci)) { source.Reply(_("%s autokick list is empty."), ci->name.c_str()); return; @@ -241,19 +415,19 @@ class CommandCSAKick final void HandleNumber(unsigned number) override { - if (!number || number > ci->GetAkickCount()) + if (!number || number > ChanServ::akick_service->GetAKickCount(ci)) return; - const AutoKick *akick = ci->GetAkick(number - 1); + const auto *akick = ChanServ::akick_service->GetAKick(ci, number - 1); - FOREACH_MOD(OnAkickDel, (source, ci, akick)); + FOREACH_MOD(OnAKickDel, (source, ci, akick)); bool override = !ag.HasPriv("AKICK"); lastdeleted = (akick->nc ? akick->nc->display : akick->mask); Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "to delete " << lastdeleted; ++deleted; - ci->EraseAkick(number - 1); + ChanServ::akick_service->EraseAKick(ci, number - 1); } } delcallback(source, ci, this, mask); @@ -264,15 +438,15 @@ class CommandCSAKick final const NickAlias *na = NickAlias::Find(mask); const NickCore *nc = na ? *na->nc : NULL; - for (i = 0, end = ci->GetAkickCount(); i < end; ++i) + for (i = 0, end = ChanServ::akick_service->GetAKickCount(ci); i < end; ++i) { - const AutoKick *akick = ci->GetAkick(i); + const auto *akick = ChanServ::akick_service->GetAKick(ci, i); if (akick->nc ? akick->nc == nc : mask.equals_ci(akick->mask)) break; } - if (i == ci->GetAkickCount()) + if (i == ChanServ::akick_service->GetAKickCount(ci)) { source.Reply(_("\002%s\002 not found on %s autokick list."), mask.c_str(), ci->name.c_str()); return; @@ -281,9 +455,9 @@ class CommandCSAKick final bool override = !source.AccessFor(ci).HasPriv("AKICK"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to delete " << mask; - FOREACH_MOD(OnAkickDel, (source, ci, ci->GetAkick(i))); + FOREACH_MOD(OnAKickDel, (source, ci, ChanServ::akick_service->GetAKick(ci, i))); - ci->EraseAkick(i); + ChanServ::akick_service->EraseAKick(ci, i); source.Reply(_("\002%s\002 deleted from %s autokick list."), mask.c_str(), ci->name.c_str()); } @@ -308,10 +482,10 @@ class CommandCSAKick final void HandleNumber(unsigned number) override { - if (!number || number > ci->GetAkickCount()) + if (!number || number > ChanServ::akick_service->GetAKickCount(ci)) return; - const AutoKick *akick = ci->GetAkick(number - 1); + const auto *akick = ChanServ::akick_service->GetAKick(ci, number - 1); Anope::string timebuf, lastused; if (akick->addtime) @@ -341,9 +515,9 @@ class CommandCSAKick final } else { - for (unsigned i = 0, end = ci->GetAkickCount(); i < end; ++i) + for (unsigned i = 0, end = ChanServ::akick_service->GetAKickCount(ci); i < end; ++i) { - const AutoKick *akick = ci->GetAkick(i); + const auto *akick = ChanServ::akick_service->GetAKick(ci, i); if (!mask.empty()) { @@ -389,7 +563,7 @@ class CommandCSAKick final void DoList(CommandSource &source, ChannelInfo *ci, const std::vector ¶ms) { - if (!ci->GetAkickCount()) + if (!ChanServ::akick_service->GetAKickCount(ci)) { source.Reply(_("%s autokick list is empty."), ci->name.c_str()); return; @@ -409,7 +583,7 @@ class CommandCSAKick final void DoView(CommandSource &source, ChannelInfo *ci, const std::vector ¶ms) { - if (!ci->GetAkickCount()) + if (!ChanServ::akick_service->GetAKickCount(ci)) { source.Reply(_("%s autokick list is empty."), ci->name.c_str()); return; @@ -445,7 +619,7 @@ class CommandCSAKick final bool override = !source.AccessFor(ci).HasPriv("AKICK"); Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to clear the akick list"; - ci->ClearAkick(); + ChanServ::akick_service->ClearAKick(ci); source.Reply(_("Channel %s akick list has been cleared."), ci->name.c_str()); } @@ -561,22 +735,57 @@ public: class CSAKick final : public Module { +private: + AKickService akick_service; + AutoKickType autokick_type; CommandCSAKick commandcsakick; public: - CSAKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandcsakick(this) + CSAKick(const Anope::string &modname, const Anope::string &creator) + : Module(modname, creator, VENDOR) + , akick_service(this) + , commandcsakick(this) { } + void OnCreateChan(ChannelInfo *ci) override + { + OnDelChan(ci); // copy ctor might have been called + } + + void OnDelChan(ChannelInfo *ci) override + { + akick_service.ClearAKick(ci); + } + + void OnDelCore(NickCore *nc) override + { + std::deque chans; + nc->GetChannelReferences(chans); + + for (auto *ci : chans) + { + for (unsigned j = 0; j < akick_service.GetAKickCount(ci); ++j) + { + const auto *akick = akick_service.GetAKick(ci, j); + if (akick->nc == nc) + { + akick_service.EraseAKick(ci, j); + break; + } + } + } + } + EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) override { if (!c->ci || c->MatchesList(u, "EXCEPT")) return EVENT_CONTINUE; - for (unsigned j = 0, end = c->ci->GetAkickCount(); j < end; ++j) + + for (unsigned j = 0, end = ChanServ::akick_service->GetAKickCount(c->ci); j < end; ++j) { - AutoKick *autokick = c->ci->GetAkick(j); + auto *autokick = ChanServ::akick_service->GetAKick(c->ci, j); bool kick = false; if (autokick->nc) diff --git a/modules/chanserv/cs_clone.cpp b/modules/chanserv/cs_clone.cpp index 4c4328b3b..407e5807a 100644 --- a/modules/chanserv/cs_clone.cpp +++ b/modules/chanserv/cs_clone.cpp @@ -14,6 +14,7 @@ #include "module.h" #include "modules/botserv/badwords.h" +#include "modules/chanserv/akick.h" class CommandCSClone final : public Command @@ -63,14 +64,17 @@ class CommandCSClone final static void CopyAkick(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci) { - target_ci->ClearAkick(); - for (unsigned i = 0; i < ci->GetAkickCount(); ++i) + if (!ChanServ::akick_service) + return; + + ChanServ::akick_service->ClearAKick(target_ci); + for (unsigned i = 0; i < ChanServ::akick_service->GetAKickCount(ci); ++i) { - const AutoKick *akick = ci->GetAkick(i); + const auto *akick = ChanServ::akick_service->GetAKick(ci, i); if (akick->nc) - target_ci->AddAkick(akick->creator, akick->nc, akick->reason, akick->addtime, akick->last_used); + ChanServ::akick_service->AddAKick(ci, akick->creator, akick->nc, akick->reason, akick->addtime, akick->last_used); else - target_ci->AddAkick(akick->creator, akick->mask, akick->reason, akick->addtime, akick->last_used); + ChanServ::akick_service->AddAKick(ci, akick->creator, akick->mask, akick->reason, akick->addtime, akick->last_used); } source.Reply(_("All akick entries from \002%s\002 have been cloned to \002%s\002."), ci->name.c_str(), target_ci->name.c_str()); diff --git a/modules/chanserv/cs_status.cpp b/modules/chanserv/cs_status.cpp index 73efa2e23..418b2d9b1 100644 --- a/modules/chanserv/cs_status.cpp +++ b/modules/chanserv/cs_status.cpp @@ -13,6 +13,7 @@ // SPDX-License-Identifier: GPL-2.0-only #include "module.h" +#include "modules/chanserv/akick.h" class CommandCSStatus final : public Command @@ -82,20 +83,23 @@ public: } } - for (unsigned j = 0, end = ci->GetAkickCount(); j < end; ++j) + if (ChanServ::akick_service) { - AutoKick *autokick = ci->GetAkick(j); + for (unsigned j = 0, end = ChanServ::akick_service->GetAKickCount(ci); j < end; ++j) + { + const auto *autokick = ChanServ::akick_service->GetAKick(ci, j); - if (autokick->nc) - { - if (na && *autokick->nc == na->nc) - source.Reply(_("\002%s\002 is on the auto kick list of \002%s\002 (%s)."), na->nc->display.c_str(), ci->name.c_str(), autokick->reason.c_str()); - } - else if (u != NULL) - { - Entry akick_mask("", autokick->mask); - if (akick_mask.Matches(u)) - source.Reply(_("\002%s\002 matches auto kick entry %s on \002%s\002 (%s)."), u->nick.c_str(), autokick->mask.c_str(), ci->name.c_str(), autokick->reason.c_str()); + if (autokick->nc) + { + if (na && *autokick->nc == na->nc) + source.Reply(_("\002%s\002 is on the auto kick list of \002%s\002 (%s)."), na->nc->display.c_str(), ci->name.c_str(), autokick->reason.c_str()); + } + else if (u != NULL) + { + Entry akick_mask("", autokick->mask); + if (akick_mask.Matches(u)) + source.Reply(_("\002%s\002 matches auto kick entry %s on \002%s\002 (%s)."), u->nick.c_str(), autokick->mask.c_str(), ci->name.c_str(), autokick->reason.c_str()); + } } } } diff --git a/modules/database/db_atheme.cpp b/modules/database/db_atheme.cpp index 8624a2ded..55de10b6b 100644 --- a/modules/database/db_atheme.cpp +++ b/modules/database/db_atheme.cpp @@ -16,6 +16,7 @@ #include "module.h" #include "modules/botserv/badwords.h" #include "modules/botserv/kick.h" +#include "modules/chanserv/akick.h" #include "modules/chanserv/entrymsg.h" #include "modules/chanserv/mode.h" #include "modules/hostserv/request.h" @@ -121,7 +122,7 @@ struct ModeLockData final struct ChannelData final { - Anope::unordered_map akicks; + Anope::unordered_map akicks; Anope::string bot; Anope::string info_adder; Anope::string info_message; @@ -609,11 +610,17 @@ private: auto *nc = NickCore::Find(mask); if (flags.find('b') != Anope::string::npos) { + if (ChanServ::akick_service) + { + Log(this) << "Unable to import channel akick for " << ci->name << " as cs_akick is not loaded"; + return true; + } + auto *data = chandata.Require(ci); if (nc) - data->akicks[mask] = ci->AddAkick(setter, nc, "", modifiedtime, modifiedtime); + data->akicks[mask] = ChanServ::akick_service->AddAKick(ci, setter, nc, "", modifiedtime, modifiedtime); else - data->akicks[mask] = ci->AddAkick(setter, mask, "", modifiedtime, modifiedtime); + data->akicks[mask] = ChanServ::akick_service->AddAKick(ci, setter, mask, "", modifiedtime, modifiedtime); return true; } diff --git a/modules/webcpanel/pages/chanserv/akick.cpp b/modules/webcpanel/pages/chanserv/akick.cpp index a36d901c5..70fcd7753 100644 --- a/modules/webcpanel/pages/chanserv/akick.cpp +++ b/modules/webcpanel/pages/chanserv/akick.cpp @@ -13,6 +13,7 @@ // SPDX-License-Identifier: GPL-2.0-only #include "../../webcpanel.h" +#include "modules/chanserv/akick.h" WebCPanel::ChanServ::Akick::Akick(const Anope::string &cat, const Anope::string &u) : WebPanelProtectedPage(cat, u) { @@ -75,16 +76,19 @@ bool WebCPanel::ChanServ::Akick::OnRequest(HTTP::Provider *server, const Anope:: replacements["ESCAPED_CHANNEL"] = HTTP::URLEncode(chname); - for (unsigned i = 0; i < ci->GetAkickCount(); ++i) + if (::ChanServ::akick_service) { - AutoKick *akick = ci->GetAkick(i); + for (unsigned i = 0; i < ::ChanServ::akick_service->GetAKickCount(ci); ++i) + { + const auto *akick = ::ChanServ::akick_service->GetAKick(ci, i); - if (akick->nc) - replacements["MASKS"] = akick->nc->display; - else - replacements["MASKS"] = akick->mask; - replacements["CREATORS"] = akick->creator; - replacements["REASONS"] = akick->reason; + if (akick->nc) + replacements["MASKS"] = akick->nc->display; + else + replacements["MASKS"] = akick->mask; + replacements["CREATORS"] = akick->creator; + replacements["REASONS"] = akick->reason; + } } Page.Serve(server, page_name, client, message, reply, replacements); diff --git a/src/regchannel.cpp b/src/regchannel.cpp index 698e200c7..ebd8f51c5 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -24,93 +24,9 @@ Serialize::Checker RegisteredChannelList(CHANNELINFO_TYPE); -AutoKick::AutoKick() - : Serializable(AUTOKICK_TYPE) -{ -} - -AutoKick::~AutoKick() -{ - if (this->ci) - { - std::vector::iterator it = std::find(this->ci->akick->begin(), this->ci->akick->end(), this); - if (it != this->ci->akick->end()) - this->ci->akick->erase(it); - - if (nc) - nc->RemoveChannelReference(this->ci); - } -} - -AutoKick::Type::Type() - : Serialize::Type(AUTOKICK_TYPE) -{ -} - -void AutoKick::Type::Serialize(Serializable *obj, Serialize::Data &data) const -{ - const auto *ak = static_cast(obj); - data.Store("ci", ak->ci->name); - if (ak->nc) - data.Store("ncid", ak->nc->GetId()); - else - data.Store("mask", ak->mask); - data.Store("reason", ak->reason); - data.Store("creator", ak->creator); - data.Store("addtime", ak->addtime); - data.Store("last_used", ak->last_used); -} - -Serializable *AutoKick::Type::Unserialize(Serializable *obj, Serialize::Data &data) const -{ - Anope::string sci, snc; - uint64_t sncid = 0; - - data["ci"] >> sci; - data["nc"] >> snc; // Deprecated 2.0 field - data["ncid"] >> sncid; - - ChannelInfo *ci = ChannelInfo::Find(sci); - if (!ci) - return NULL; - - AutoKick *ak; - auto *nc = sncid ? NickCore::FindId(sncid) : NickCore::Find(snc); - if (obj) - { - ak = anope_dynamic_static_cast(obj); - data["creator"] >> ak->creator; - data["reason"] >> ak->reason; - ak->nc = nc; - data["mask"] >> ak->mask; - data["addtime"] >> ak->addtime; - data["last_used"] >> ak->last_used; - } - else - { - time_t addtime, lastused; - data["addtime"] >> addtime; - data["last_used"] >> lastused; - - Anope::string screator, sreason, smask; - - data["creator"] >> screator; - data["reason"] >> sreason; - data["mask"] >> smask; - - if (nc) - ak = ci->AddAkick(screator, nc, sreason, addtime, lastused); - else - ak = ci->AddAkick(screator, smask, sreason, addtime, lastused); - } - - return ak; -} - ChannelInfo::ChannelInfo(const Anope::string &chname) : Serializable(CHANNELINFO_TYPE) , access(CHANACCESS_TYPE) - , akick(AUTOKICK_TYPE) , name(chname) , registered(Anope::CurTime) , last_used(Anope::CurTime) @@ -131,7 +47,6 @@ ChannelInfo::ChannelInfo(const Anope::string &chname) ChannelInfo::ChannelInfo(const ChannelInfo &ci) : Serializable(CHANNELINFO_TYPE) , access(CHANACCESS_TYPE) - , akick(AUTOKICK_TYPE) { *this = ci; @@ -139,7 +54,6 @@ ChannelInfo::ChannelInfo(const ChannelInfo &ci) ++this->founder->channelcount; this->access->clear(); - this->akick->clear(); FOREACH_MOD(OnCreateChan, (this)); } @@ -174,7 +88,6 @@ ChannelInfo::~ChannelInfo() this->SetSuccessor(NULL); this->ClearAccess(); - this->ClearAkick(); if (!this->memos.memos->empty()) { @@ -540,68 +453,6 @@ void ChannelInfo::ClearAccess() delete this->GetAccess(i - 1); } -AutoKick *ChannelInfo::AddAkick(const Anope::string &user, NickCore *akicknc, const Anope::string &reason, time_t t, time_t lu) -{ - auto *autokick = new AutoKick(); - autokick->ci = this; - autokick->nc = akicknc; - autokick->reason = reason; - autokick->creator = user; - autokick->addtime = t; - autokick->last_used = lu; - - this->akick->push_back(autokick); - - akicknc->AddChannelReference(this); - - return autokick; -} - -AutoKick *ChannelInfo::AddAkick(const Anope::string &user, const Anope::string &mask, const Anope::string &reason, time_t t, time_t lu) -{ - auto *autokick = new AutoKick(); - autokick->ci = this; - autokick->mask = mask; - autokick->nc = NULL; - autokick->reason = reason; - autokick->creator = user; - autokick->addtime = t; - autokick->last_used = lu; - - this->akick->push_back(autokick); - - return autokick; -} - -AutoKick *ChannelInfo::GetAkick(unsigned index) const -{ - if (this->akick->empty() || index >= this->akick->size()) - return NULL; - - AutoKick *ak = (*this->akick)[index]; - ak->QueueUpdate(); - return ak; -} - -unsigned ChannelInfo::GetAkickCount() const -{ - return this->akick->size(); -} - -void ChannelInfo::EraseAkick(unsigned index) -{ - if (this->akick->empty() || index >= this->akick->size()) - return; - - delete this->GetAkick(index); -} - -void ChannelInfo::ClearAkick() -{ - while (!this->akick->empty()) - delete this->akick->back(); -} - const Anope::map &ChannelInfo::GetLevelEntries() { return this->levels; diff --git a/src/serialize.cpp b/src/serialize.cpp index 5cda01b7f..94b50ad2a 100644 --- a/src/serialize.cpp +++ b/src/serialize.cpp @@ -35,7 +35,6 @@ void Serialize::RegisterTypes() static BotInfo::Type bi; static ChannelInfo::Type ci; static ChanAccess::Type access; - static AutoKick::Type akick; static Memo::Type memo; static XLine::Type xline; CreateTypes();