summaryrefslogtreecommitdiff
path: root/modules/pseudoclients
diff options
context:
space:
mode:
authorSadie Powell <sadie@witchery.services>2024-01-24 12:34:03 +0000
committerSadie Powell <sadie@witchery.services>2024-01-24 12:34:34 +0000
commit484160eb4ed560eeda97c94a42dd8e31431ab251 (patch)
tree03600af16b55fa2f268904d7a42a8b87f86c09f4 /modules/pseudoclients
parent7ac1fe58478d58e2480b6919c4abf3a82929169c (diff)
Shuffle modules around a bit.
Diffstat (limited to 'modules/pseudoclients')
-rw-r--r--modules/pseudoclients/botserv.cpp213
-rw-r--r--modules/pseudoclients/chanserv.cpp481
-rw-r--r--modules/pseudoclients/global.cpp102
-rw-r--r--modules/pseudoclients/hostserv.cpp131
-rw-r--r--modules/pseudoclients/memoserv.cpp237
-rw-r--r--modules/pseudoclients/nickserv.cpp569
-rw-r--r--modules/pseudoclients/operserv.cpp300
7 files changed, 0 insertions, 2033 deletions
diff --git a/modules/pseudoclients/botserv.cpp b/modules/pseudoclients/botserv.cpp
deleted file mode 100644
index d2b8df4bb..000000000
--- a/modules/pseudoclients/botserv.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/* BotServ core functions
- *
- * (C) 2003-2024 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- */
-
-#include "module.h"
-
-class BotServCore final
- : public Module
-{
- Reference<BotInfo> BotServ;
- ExtensibleRef<bool> persist, inhabit;
-
-public:
- BotServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
- persist("PERSIST"), inhabit("inhabit")
- {
- }
-
- void OnReload(Configuration::Conf *conf) override
- {
- const Anope::string &bsnick = conf->GetModule(this)->Get<const Anope::string>("client");
- BotServ = BotInfo::Find(bsnick, true);
- }
-
- void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) 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 (auto botmode : botmodes)
- chan->SetMode(chan->ci->bi, ModeManager::FindChannelModeByChar(botmode), chan->ci->bi->GetUID());
- }
- }
-
- void OnBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) override
- {
- if (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 OnJoinChannel(User *user, Channel *c) override
- {
- if (!Config || !IRCD)
- return;
-
- BotInfo *bi = user->server == Me ? dynamic_cast<BotInfo *>(user) : NULL;
- if (bi && Config->GetModule(this)->Get<bool>("smartjoin"))
- {
- /* We check for bans */
- for (const auto &entry : c->GetModeList("BAN"))
- {
- Entry ban("BAN", entry);
- 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)
- {
- /**
- * We let the bot join even if it was an ignored user, as if we don't,
- * and the ignored user doesn't just leave, the bot will never
- * make it into the channel, leaving the channel botless even for
- * legit users - Rob
- **/
- /* This is before the user has joined the channel, so check usercount + 1 */
- if (c->users.size() + 1 >= 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);
- }
- }
- }
-
- void OnLeaveChannel(User *u, Channel *c) override
- {
- /* Channel is persistent, it shouldn't be deleted and the service bot should stay */
- if (c->ci && persist && persist->HasExt(c->ci))
- return;
-
- /* Channel is syncing from a netburst, don't destroy it as more users are probably wanting to join immediately
- * We also don't part the bot here either, if necessary we will part it after the sync
- */
- if (c->syncing)
- return;
-
- /* Additionally, do not delete this channel if ChanServ/a BotServ bot is inhabiting it */
- if (inhabit && inhabit->HasExt(c))
- return;
-
- /* This is called prior to removing the user from the channel, so c->users.size() - 1 should be safe */
- 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);
- }
-
- EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) override
- {
- if (!params.empty())
- return EVENT_CONTINUE;
-
- if (source.c)
- {
- source.Reply(_("\002%s\002 allows you to execute \"fantasy\" commands in the channel.\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());
- const Anope::string &fantasycharacters = Config->GetModule("fantasy")->Get<const Anope::string>("fantasycharacter", "!");
- if (!fantasycharacters.empty())
- source.Reply(_(" \n"
- "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 == 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"
- "configure a bot, or for use on networks that don't\n"
- "allow user bots. Available commands are listed\n"
- "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"),
- 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;
- }
-
- void OnPostHelp(CommandSource &source, const std::vector<Anope::string> &params) override
- {
- 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->GetModule(this)->Get<unsigned>("minusers"));
- const Anope::string &fantasycharacters = Config->GetModule("fantasy")->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 &source, ChannelMode *mode, const Anope::string &param) override
- {
- if (source.GetUser() && !source.GetBot() && Config->GetModule(this)->Get<bool>("smartjoin") && mode->name == "BAN" && c->ci && c->ci->bi && c->FindUser(c->ci->bi))
- {
- BotInfo *bi = c->ci->bi;
-
- Entry ban("BAN", param);
- if (ban.Matches(bi))
- c->RemoveMode(bi, "BAN", param);
- }
-
- return EVENT_CONTINUE;
- }
-
- void OnCreateChan(ChannelInfo *ci) override
- {
- /* Set default bot flags */
- spacesepstream sep(Config->GetModule(this)->Get<const Anope::string>("defaults", "greet fantasy"));
- for (Anope::string token; sep.GetToken(token);)
- ci->Extend<bool>("BS_" + token.upper());
- }
-
- void OnUserKicked(const MessageSource &source, User *target, const Anope::string &channel, ChannelStatus &status, const Anope::string &kickmsg) override
- {
- BotInfo *bi = BotInfo::Find(target->GetUID());
- if (bi)
- /* Bots get rejoined */
- bi->Join(channel, &status);
- }
-
- void OnCreateBot(BotInfo *bi) override
- {
- if (bi->botmodes.empty())
- bi->botmodes = Config->GetModule(this)->Get<const Anope::string>("botumodes");
- }
-};
-
-MODULE_INIT(BotServCore)
diff --git a/modules/pseudoclients/chanserv.cpp b/modules/pseudoclients/chanserv.cpp
deleted file mode 100644
index c47f2d77f..000000000
--- a/modules/pseudoclients/chanserv.cpp
+++ /dev/null
@@ -1,481 +0,0 @@
-/* ChanServ core functions
- *
- * (C) 2003-2024 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- */
-
-#include "module.h"
-#include "modules/cs_mode.h"
-
-inline static Anope::string BotModes()
-{
- return Config->GetModule("botserv")->Get<Anope::string>("botmodes",
- Config->GetModule("chanserv")->Get<Anope::string>("botmodes", "o")
- );
-}
-
-class ChanServCore final
- : public Module
- , public ChanServService
-{
- Reference<BotInfo> ChanServ;
- std::vector<Anope::string> defaults;
- ExtensibleItem<bool> inhabit;
- ExtensibleRef<bool> persist;
- bool always_lower = false;
-
-public:
- ChanServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
- ChanServService(this), inhabit(this, "inhabit"), persist("PERSIST")
- {
- }
-
- void Hold(Channel *c) override
- {
- /** A timer used to keep the BotServ bot/ChanServ in the channel
- * after kicking the last user in a channel
- */
- class ChanServTimer final
- : public Timer
- {
- Reference<BotInfo> &ChanServ;
- ExtensibleItem<bool> &inhabit;
- Reference<Channel> c;
-
- public:
- /** Constructor
- * @param chan The channel
- */
- ChanServTimer(Reference<BotInfo> &cs, ExtensibleItem<bool> &i, Module *m, Channel *chan) : Timer(m, Config->GetModule(m)->Get<time_t>("inhabit", "15s")), ChanServ(cs), inhabit(i), c(chan)
- {
- if (!ChanServ || !c)
- return;
- inhabit.Set(c, true);
- 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) override
- {
- if (!c)
- return;
-
- /* In the event we don't part */
- c->RemoveMode(NULL, "SECRET");
- c->RemoveMode(NULL, "INVITE");
-
- inhabit.Unset(c); /* now we're done changing modes, unset inhabit */
-
- if (!c->ci || !c->ci->bi)
- {
- if (ChanServ)
- ChanServ->Part(c);
- }
- /* If someone has rejoined this channel in the meantime, don't part the bot */
- else if (c->users.size() <= 1)
- c->ci->bi->Part(c);
- }
- };
-
- if (inhabit.HasExt(c))
- return;
-
- new ChanServTimer(ChanServ, inhabit, this->owner, c);
- }
-
- void OnReload(Configuration::Conf *conf) override
- {
- const Anope::string &channick = conf->GetModule(this)->Get<const Anope::string>("client");
-
- if (channick.empty())
- throw ConfigException(Module::name + ": <client> must be defined");
-
- BotInfo *bi = BotInfo::Find(channick, true);
- if (!bi)
- throw ConfigException(Module::name + ": no bot named " + channick);
-
- ChanServ = bi;
-
- spacesepstream(conf->GetModule(this)->Get<const Anope::string>("defaults", "keeptopic peace cs_secure securefounder signkick")).GetTokens(defaults);
- if (defaults.empty())
- {
- defaults.emplace_back("KEEPTOPIC");
- defaults.emplace_back("PEACE");
- defaults.emplace_back("CS_SECURE");
- defaults.emplace_back("SECUREFOUNDER");
- defaults.emplace_back("SIGNKICK");
- }
- else if (defaults[0].equals_ci("none"))
- defaults.clear();
-
- always_lower = conf->GetModule(this)->Get<bool>("always_lower_ts");
- }
-
- void OnBotDelete(BotInfo *bi) override
- {
- if (bi == ChanServ)
- ChanServ = NULL;
- }
-
- EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message) override
- {
- if (bi == ChanServ && Config->GetModule(this)->Get<bool>("opersonly") && !u->HasMode("OPER"))
- {
- u->SendMessage(bi, ACCESS_DENIED);
- return EVENT_STOP;
- }
-
- return EVENT_CONTINUE;
- }
-
- void OnDelCore(NickCore *nc) override
- {
- std::deque<ChannelInfo *> chans;
- nc->GetChannelReferences(chans);
- int max_reg = Config->GetModule(this)->Get<int>("maxregistered");
-
- for (auto *ci : chans)
- {
- if (ci->GetFounder() == nc)
- {
- NickCore *newowner = NULL;
- if (ci->GetSuccessor() && ci->GetSuccessor() != nc && (ci->GetSuccessor()->IsServicesOper() || !max_reg || ci->GetSuccessor()->channelcount < max_reg))
- newowner = ci->GetSuccessor();
- else
- {
- const ChanAccess *highest = NULL;
- for (unsigned j = 0; j < ci->GetAccessCount(); ++j)
- {
- const ChanAccess *ca = ci->GetAccess(j);
- NickCore *anc = ca->GetAccount();
-
- if (!anc || (!anc->IsServicesOper() && max_reg && anc->channelcount >= max_reg) || (anc == nc))
- continue;
- if (!highest || *ca > *highest)
- highest = ca;
- }
- if (highest)
- newowner = highest->GetAccount();
- }
-
- if (newowner)
- {
- Log(LOG_NORMAL, "chanserv/drop", ChanServ) << "Transferring foundership of " << ci->name << " from deleted nick " << nc->display << " to " << newowner->display;
- ci->SetFounder(newowner);
- ci->SetSuccessor(NULL);
- }
- else
- {
- Log(LOG_NORMAL, "chanserv/drop", ChanServ) << "Deleting channel " << ci->name << " owned by deleted nick " << nc->display;
-
- delete ci;
- continue;
- }
- }
-
- if (ci->GetSuccessor() == nc)
- ci->SetSuccessor(NULL);
-
- for (unsigned j = 0; j < ci->GetAccessCount(); ++j)
- {
- const ChanAccess *ca = ci->GetAccess(j);
-
- if (ca->GetAccount() == nc)
- {
- delete ci->EraseAccess(j);
- break;
- }
- }
-
- for (unsigned j = 0; j < ci->GetAkickCount(); ++j)
- {
- const AutoKick *akick = ci->GetAkick(j);
- if (akick->nc == nc)
- {
- ci->EraseAkick(j);
- break;
- }
- }
- }
- }
-
- void OnDelChan(ChannelInfo *ci) override
- {
- /* remove access entries that are this channel */
-
- std::deque<Anope::string> chans;
- ci->GetChannelReferences(chans);
-
- for (const auto &chan : chans)
- {
- ChannelInfo *c = ChannelInfo::Find(chan);
- if (!c)
- continue;
-
- for (unsigned j = 0; j < c->GetAccessCount(); ++j)
- {
- ChanAccess *a = c->GetAccess(j);
-
- if (a->Mask().equals_ci(ci->name))
- {
- delete a;
- break;
- }
- }
- }
-
- if (ci->c)
- {
- ci->c->RemoveMode(ci->WhoSends(), "REGISTERED", "", false);
-
- const Anope::string &require = Config->GetModule(this)->Get<const Anope::string>("require");
- if (!require.empty())
- ci->c->SetModes(ci->WhoSends(), false, "-%s", require.c_str());
- }
- }
-
- EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) override
- {
- 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"
- "malicious users from \"taking over\" channels by limiting\n"
- "who is allowed channel operator privileges. Available\n"
- "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"),
- ChanServ->nick.c_str(), ChanServ->nick.c_str(), Config->StrictPrivmsg.c_str(), ChanServ->nick.c_str(), Config->StrictPrivmsg.c_str(), ChanServ->nick.c_str());
- return EVENT_CONTINUE;
- }
-
- void OnPostHelp(CommandSource &source, const std::vector<Anope::string> &params) override
- {
- if (!params.empty() || source.c || source.service != *ChanServ)
- return;
- time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "30d");
- if (chanserv_expire >= 86400)
- source.Reply(_(" \n"
- "Note that any channel which is not used for %lu days\n"
- "(i.e. which no user on the channel's access list enters\n"
- "for that period of time) will be automatically dropped."), (unsigned long)chanserv_expire / 86400);
- if (source.IsServicesOper())
- source.Reply(_(" \n"
- "Services Operators can also, depending on their access drop\n"
- "any channel, view (and modify) the access, levels and akick\n"
- "lists and settings for any channel."));
- }
-
- void OnCheckModes(Reference<Channel> &c) override
- {
- if (!c)
- return;
-
- if (c->ci)
- c->SetMode(c->ci->WhoSends(), "REGISTERED", "", false);
- else
- c->RemoveMode(c->WhoSends(), "REGISTERED", "", false);
-
- const Anope::string &require = Config->GetModule(this)->Get<const Anope::string>("require");
- if (!require.empty())
- {
- if (c->ci)
- c->SetModes(c->ci->WhoSends(), false, "+%s", require.c_str());
- else
- c->SetModes(c->WhoSends(), false, "-%s", require.c_str());
- }
- }
-
- void OnCreateChan(ChannelInfo *ci) override
- {
- /* Set default chan flags */
- for (const auto &def : defaults)
- ci->Extend<bool>(def.upper());
- }
-
- EventReturn OnCanSet(User *u, const ChannelMode *cm) override
- {
- if (Config->GetModule(this)->Get<const Anope::string>("nomlock").find(cm->mchar) != Anope::string::npos
- || Config->GetModule(this)->Get<const Anope::string>("require").find(cm->mchar) != Anope::string::npos)
- return EVENT_STOP;
- return EVENT_CONTINUE;
- }
-
- void OnChannelSync(Channel *c) override
- {
- bool perm = c->HasMode("PERM") || (c->ci && persist && persist->HasExt(c->ci));
- if (!perm && !c->botchannel && (c->users.empty() || (c->users.size() == 1 && c->users.begin()->second->user->server == Me)))
- {
- this->Hold(c);
- }
- }
-
- void OnLog(Log *l) override
- {
- if (l->type == LOG_CHANNEL)
- l->bi = ChanServ;
- }
-
- void OnExpireTick() override
- {
- time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "30d");
-
- if (!chanserv_expire || Anope::NoExpire || Anope::ReadOnly)
- return;
-
- for (registered_channel_map::const_iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; )
- {
- ChannelInfo *ci = it->second;
- ++it;
-
- bool expire = false;
-
- if (Anope::CurTime - ci->last_used >= chanserv_expire)
- {
- if (ci->c)
- {
- time_t last_used = ci->last_used;
- for (Channel::ChanUserList::const_iterator cit = ci->c->users.begin(), cit_end = ci->c->users.end(); cit != cit_end && last_used == ci->last_used; ++cit)
- ci->AccessFor(cit->second->user);
- expire = last_used == ci->last_used;
- }
- else
- expire = true;
- }
-
- FOREACH_MOD(OnPreChanExpire, (ci, expire));
-
- if (expire)
- {
- Log(LOG_NORMAL, "chanserv/expire", ChanServ) << "Expiring channel " << ci->name << " (founder: " << (ci->GetFounder() ? ci->GetFounder()->display : "(none)") << ")";
- FOREACH_MOD(OnChanExpire, (ci));
- delete ci;
- }
- }
- }
-
- EventReturn OnCheckDelete(Channel *c) override
- {
- /* Do not delete this channel if ChanServ/a BotServ bot is inhabiting it */
- if (inhabit.HasExt(c))
- return EVENT_STOP;
-
- return EVENT_CONTINUE;
- }
-
- void OnPostInit() override
- {
- if (!persist)
- return;
-
- ChannelMode *perm = ModeManager::FindChannelModeByName("PERM");
-
- /* Find all persistent channels and create them, as we are about to finish burst to our uplink */
- for (const auto &[_, ci] : *RegisteredChannelList)
- {
- if (!persist->HasExt(ci))
- continue;
-
- bool c;
- ci->c = Channel::FindOrCreate(ci->name, c, ci->time_registered);
- ci->c->syncing |= created;
-
- if (perm)
- {
- ci->c->SetMode(NULL, perm);
- }
- else
- {
- if (!ci->bi)
- ci->WhoSends()->Assign(NULL, ci);
- if (ci->c->FindUser(ci->bi) == NULL)
- {
- ChannelStatus status(BotModes());
- ci->bi->Join(ci->c, &status);
- }
- }
- }
-
- }
-
- void OnChanRegistered(ChannelInfo *ci) override
- {
- if (!persist || !ci->c)
- return;
- /* Mark the channel as persistent */
- if (ci->c->HasMode("PERM"))
- persist->Set(ci);
- /* Persist may be in def cflags, set it here */
- else if (persist->HasExt(ci))
- ci->c->SetMode(NULL, "PERM");
- }
-
- void OnJoinChannel(User *u, Channel *c) override
- {
- if (always_lower && c->ci && c->creation_time > c->ci->time_registered)
- {
- Log(LOG_DEBUG) << "Changing TS of " << c->name << " from " << c->creation_time << " to " << c->ci->time_registered;
- c->creation_time = c->ci->time_registered;
- IRCD->SendChannel(c);
- c->Reset();
- }
- }
-
- EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) override
- {
- if (!always_lower && Anope::CurTime == c->creation_time && c->ci && setter.GetUser() && !setter.GetUser()->server->IsULined())
- {
- ChanUserContainer *cu = c->FindUser(setter.GetUser());
- ChannelMode *cm = ModeManager::FindChannelModeByName("OP");
- if (cu && cm && !cu->status.HasMode(cm->mchar))
- {
- /* Our -o and their mode change crossing, bounce their mode */
- c->RemoveMode(c->ci->WhoSends(), mode, param);
- /* We don't set mlocks until after the join has finished processing, it will stack with this change,
- * so there isn't much for the user to remove except -nt etc which is likely locked anyway.
- */
- }
- }
-
- return EVENT_CONTINUE;
- }
-
- void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) override
- {
- if (!show_all)
- return;
-
- time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "30d");
- if (!ci->HasExt("CS_NO_EXPIRE") && chanserv_expire && !Anope::NoExpire && ci->last_used != Anope::CurTime)
- info[_("Expires")] = Anope::strftime(ci->last_used + chanserv_expire, source.GetAccount());
- }
-
- void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) override
- {
- if (always_lower)
- // Since we always lower the TS, the other side will remove the modes if the channel ts lowers, so we don't
- // have to worry about it
- take_modes = false;
- else if (ModeManager::FindChannelModeByName("REGISTERED"))
- // Otherwise if the registered channel mode exists, we should remove modes if the channel is not +r
- take_modes = !chan->HasMode("REGISTERED");
- }
-};
-
-MODULE_INIT(ChanServCore)
diff --git a/modules/pseudoclients/global.cpp b/modules/pseudoclients/global.cpp
deleted file mode 100644
index a5288d754..000000000
--- a/modules/pseudoclients/global.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/* Global core functions
- *
- * (C) 2003-2024 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- */
-
-#include "module.h"
-
-class GlobalCore final
- : public Module
- , public GlobalService
-{
- Reference<BotInfo> Global;
-
- void ServerGlobal(BotInfo *sender, Server *s, const Anope::string &message)
- {
- if (s != Me && !s->IsJuped())
- s->Notice(sender, message);
- for (auto *link : s->GetLinks())
- this->ServerGlobal(sender, link, message);
- }
-
-public:
- GlobalCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
- GlobalService(this)
- {
- }
-
- Reference<BotInfo> GetDefaultSender() override
- {
- return Global;
- }
-
- void SendGlobal(BotInfo *sender, const Anope::string &source, const Anope::string &message) override
- {
- if (Me->GetLinks().empty())
- return;
- if (!sender)
- sender = Global;
- if (!sender)
- return;
-
- Anope::string rmessage;
-
- if (!source.empty() && !Config->GetModule("global")->Get<bool>("anonymousglobal"))
- rmessage = "[" + source + "] " + message;
- else
- rmessage = message;
-
- this->ServerGlobal(sender, Servers::GetUplink(), rmessage);
- }
-
- void OnReload(Configuration::Conf *conf) override
- {
- const Anope::string &glnick = conf->GetModule(this)->Get<const Anope::string>("client");
-
- if (glnick.empty())
- throw ConfigException(Module::name + ": <client> must be defined");
-
- BotInfo *bi = BotInfo::Find(glnick, true);
- if (!bi)
- throw ConfigException(Module::name + ": no bot named " + glnick);
-
- Global = bi;
- }
-
- void OnRestart() override
- {
- const Anope::string &gl = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown");
- if (!gl.empty())
- this->SendGlobal(Global, "", gl);
- }
-
- void OnShutdown() override
- {
- const Anope::string &gl = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown");
- if (!gl.empty())
- this->SendGlobal(Global, "", gl);
- }
-
- void OnNewServer(Server *s) override
- {
- 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) override
- {
- if (!params.empty() || source.c || source.service != *Global)
- return EVENT_CONTINUE;
- source.Reply(_("%s commands:"), Global->nick.c_str());
- return EVENT_CONTINUE;
- }
-};
-
-MODULE_INIT(GlobalCore)
diff --git a/modules/pseudoclients/hostserv.cpp b/modules/pseudoclients/hostserv.cpp
deleted file mode 100644
index 17c820377..000000000
--- a/modules/pseudoclients/hostserv.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/* HostServ core functions
- *
- * (C) 2003-2024 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- */
-
-#include "module.h"
-
-class HostServCore final
- : public Module
-{
- Reference<BotInfo> HostServ;
-public:
- HostServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR)
- {
- if (!IRCD || !IRCD->CanSetVHost)
- throw ModuleException("Your IRCd does not support vhosts");
- }
-
- void OnReload(Configuration::Conf *conf) override
- {
- const Anope::string &hsnick = conf->GetModule(this)->Get<const Anope::string>("client");
-
- if (hsnick.empty())
- throw ConfigException(Module::name + ": <client> must be defined");
-
- BotInfo *bi = BotInfo::Find(hsnick, true);
- if (!bi)
- throw ConfigException(Module::name + ": no bot named " + hsnick);
-
- HostServ = bi;
- }
-
- void OnUserLogin(User *u) override
- {
- if (!IRCD->CanSetVHost)
- return;
-
- const NickAlias *na = NickAlias::Find(u->nick);
- if (!na || na->nc != u->Account() || !na->HasVhost())
- na = NickAlias::Find(u->Account()->display);
- if (!na || !na->HasVhost())
- return;
-
- if (u->vhost.empty() || !u->vhost.equals_cs(na->GetVhostHost()) || (!na->GetVhostIdent().empty() && !u->GetVIdent().equals_cs(na->GetVhostIdent())))
- {
- IRCD->SendVhost(u, na->GetVhostIdent(), na->GetVhostHost());
-
- u->vhost = na->GetVhostHost();
- u->UpdateHost();
-
- if (IRCD->CanSetVIdent && !na->GetVhostIdent().empty())
- u->SetVIdent(na->GetVhostIdent());
-
- if (HostServ)
- {
- if (!na->GetVhostIdent().empty())
- u->SendMessage(HostServ, _("Your vhost of \002%s\002@\002%s\002 is now activated."), na->GetVhostIdent().c_str(), na->GetVhostHost().c_str());
- else
- u->SendMessage(HostServ, _("Your vhost of \002%s\002 is now activated."), na->GetVhostHost().c_str());
- }
- }
- }
-
- void OnNickDrop(CommandSource &source, NickAlias *na) override
- {
- if (na->HasVhost())
- {
- FOREACH_MOD(OnDeleteVhost, (na));
- na->RemoveVhost();
- }
- }
-
- void OnNickUpdate(User *u) override
- {
- this->OnUserLogin(u);
- }
-
- EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) override
- {
- if (!params.empty() || source.c || source.service != *HostServ)
- return EVENT_CONTINUE;
- source.Reply(_("%s commands:"), HostServ->nick.c_str());
- return EVENT_CONTINUE;
- }
-
- void OnSetVhost(NickAlias *na) override
- {
- if (Config->GetModule(this)->Get<bool>("activate_on_set"))
- {
- User *u = User::Find(na->nick);
-
- if (u && u->Account() == na->nc)
- {
- IRCD->SendVhost(u, na->GetVhostIdent(), na->GetVhostHost());
-
- u->vhost = na->GetVhostHost();
- u->UpdateHost();
-
- if (IRCD->CanSetVIdent && !na->GetVhostIdent().empty())
- u->SetVIdent(na->GetVhostIdent());
-
- if (HostServ)
- {
- if (!na->GetVhostIdent().empty())
- u->SendMessage(HostServ, _("Your vhost of \002%s\002@\002%s\002 is now activated."), na->GetVhostIdent().c_str(), na->GetVhostHost().c_str());
- else
- u->SendMessage(HostServ, _("Your vhost of \002%s\002 is now activated."), na->GetVhostHost().c_str());
- }
- }
- }
- }
-
- void OnDeleteVhost(NickAlias *na) override
- {
- if (Config->GetModule(this)->Get<bool>("activate_on_set"))
- {
- User *u = User::Find(na->nick);
-
- if (u && u->Account() == na->nc)
- IRCD->SendVhostDel(u);
- }
- }
-};
-
-MODULE_INIT(HostServCore)
diff --git a/modules/pseudoclients/memoserv.cpp b/modules/pseudoclients/memoserv.cpp
deleted file mode 100644
index 0961017e0..000000000
--- a/modules/pseudoclients/memoserv.cpp
+++ /dev/null
@@ -1,237 +0,0 @@
-/* MemoServ core functions
- *
- * (C) 2003-2024 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- */
-
-#include "module.h"
-
-class MemoServCore final
- : public Module
- , public MemoServService
-{
- Reference<BotInfo> MemoServ;
-
- bool SendMemoMail(NickCore *nc, MemoInfo *mi, Memo *m)
- {
- Anope::string subject = Language::Translate(nc, Config->GetBlock("mail")->Get<const Anope::string>("memo_subject").c_str()),
- message = Language::Translate(Config->GetBlock("mail")->Get<const Anope::string>("memo_message").c_str());
-
- 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->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->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
-
- return Mail::Send(nc, subject, message);
- }
-
-public:
- MemoServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
- MemoServService(this)
- {
- }
-
- MemoResult Send(const Anope::string &source, const Anope::string &target, const Anope::string &message, bool force) override
- {
- bool ischan;
- MemoInfo *mi = MemoInfo::GetMemoInfo(target, ischan);
-
- if (mi == NULL)
- return MEMO_INVALID_TARGET;
-
- Anope::string sender_display = source;
-
- User *sender = User::Find(source, tr