summaryrefslogtreecommitdiff
path: root/modules/global/global.cpp
diff options
context:
space:
mode:
authorSadie Powell <sadie@witchery.services>2024-03-14 21:18:08 +0000
committerSadie Powell <sadie@witchery.services>2024-03-14 21:35:17 +0000
commitbeaf09de7bcb0042dfd8f388064126e511a5b28d (patch)
treeba14e1ff1ff96b5623c459b2de35d766d086e427 /modules/global/global.cpp
parentc8d8978cd0bfb10613da331c5b13bbcf8486f85f (diff)
Rework sending global notices.
Admins can now queue multiple messages and send them when they are ready. This is fully compatible with the previous global behaviour. Admins can now also send messages to individual servers. This is useful for informing users of maintenance due to downtime.
Diffstat (limited to 'modules/global/global.cpp')
-rw-r--r--modules/global/global.cpp152
1 files changed, 113 insertions, 39 deletions
diff --git a/modules/global/global.cpp b/modules/global/global.cpp
index a5288d754..35177dcfd 100644
--- a/modules/global/global.cpp
+++ b/modules/global/global.cpp
@@ -15,88 +15,162 @@ class GlobalCore final
: public Module
, public GlobalService
{
- Reference<BotInfo> Global;
+private:
+ Reference<BotInfo> global;
+ PrimitiveExtensibleItem<std::vector<Anope::string>> queue;
- void ServerGlobal(BotInfo *sender, Server *s, const Anope::string &message)
+ void ServerGlobal(BotInfo *sender, Server *server, bool children, const Anope::string &message)
{
- if (s != Me && !s->IsJuped())
- s->Notice(sender, message);
- for (auto *link : s->GetLinks())
- this->ServerGlobal(sender, link, message);
+ if (server != Me && !server->IsJuped())
+ server->Notice(sender, message);
+
+ if (children)
+ {
+ for (auto *link : server->GetLinks())
+ this->ServerGlobal(sender, link, true, message);
+ }
}
public:
- GlobalCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
- GlobalService(this)
+ GlobalCore(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, PSEUDOCLIENT | VENDOR)
+ , GlobalService(this)
+ , queue(this, "global-queue")
{
}
- Reference<BotInfo> GetDefaultSender() override
+ void ClearQueue(NickCore *nc) override
{
- return Global;
+ queue.Unset(nc);
}
- void SendGlobal(BotInfo *sender, const Anope::string &source, const Anope::string &message) override
+ Reference<BotInfo> GetDefaultSender() const override
{
- if (Me->GetLinks().empty())
- return;
- if (!sender)
- sender = Global;
- if (!sender)
- return;
-
- Anope::string rmessage;
+ return global;
+ }
- if (!source.empty() && !Config->GetModule("global")->Get<bool>("anonymousglobal"))
- rmessage = "[" + source + "] " + message;
- else
- rmessage = message;
+ const std::vector<Anope::string> *GetQueue(NickCore* nc) const override
+ {
+ return queue.Get(nc);
+ }
- this->ServerGlobal(sender, Servers::GetUplink(), rmessage);
+ size_t Queue(NickCore *nc, const Anope::string &message) override
+ {
+ auto *q = queue.Require(nc);
+ q->push_back(message);
+ return q->size();
}
void OnReload(Configuration::Conf *conf) override
{
- const Anope::string &glnick = conf->GetModule(this)->Get<const Anope::string>("client");
-
+ const auto 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);
+ auto *bi = BotInfo::Find(glnick, true);
if (!bi)
throw ConfigException(Module::name + ": no bot named " + glnick);
- Global = bi;
+ global = bi;
}
void OnRestart() override
{
- const Anope::string &gl = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown");
- if (!gl.empty())
- this->SendGlobal(Global, "", gl);
+ const auto msg = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown");
+ if (!msg.empty())
+ this->SendSingle(msg, nullptr, nullptr, nullptr);
}
void OnShutdown() override
{
- const Anope::string &gl = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown");
- if (!gl.empty())
- this->SendGlobal(Global, "", gl);
+ const auto msg = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown");
+ if (!msg.empty())
+ this->SendSingle(msg, nullptr, nullptr, nullptr);
}
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);
+ const auto msg = Config->GetModule(this)->Get<const Anope::string>("globaloncycleup");
+ if (!msg.empty() && !Me->IsSynced())
+ s->Notice(global, msg);
}
EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) override
{
- if (!params.empty() || source.c || source.service != *Global)
+ if (!params.empty() || source.c || source.service != *global)
return EVENT_CONTINUE;
- source.Reply(_("%s commands:"), Global->nick.c_str());
+
+ source.Reply(_("%s commands:"), global->nick.c_str());
return EVENT_CONTINUE;
}
+
+ bool SendQueue(CommandSource &source, BotInfo *sender, Server *server) override
+ {
+ // We MUST have an account.
+ if (!source.nc)
+ return false;
+
+ // We MUST have a message queue.
+ auto *q = queue.Get(source.nc);
+ if (!q || q->empty())
+ return false;
+
+ auto success = true;
+ for (const auto &message : *q)
+ {
+ if (!SendSingle(message, &source, sender, server))
+ {
+ success = false;
+ break;
+ }
+ }
+
+ queue.Unset(source.nc);
+ return success;
+ }
+
+ bool SendSingle(const Anope::string &message, CommandSource *source, BotInfo* sender, Server* server) override
+ {
+ // We MUST have a sender.
+ if (sender)
+ sender = global;
+ if (!sender)
+ return false;
+
+ if (!server)
+ server = Servers::GetUplink();
+
+ Anope::string line;
+ if (source && !Config->GetModule(this)->Get<bool>("anonymousglobal"))
+ {
+ // A source is available and they're not anonymous.
+ line = Anope::printf("[%s] %s", source->GetNick().c_str(), message.c_str());
+ }
+ else
+ {
+ // A source isn't available or they're anonymous.
+ line = message.empty() ? " " : message;
+ }
+
+ if (server)
+ this->ServerGlobal(sender, Servers::GetUplink(), true, line);
+ else
+ this->ServerGlobal(sender, server, false, line);
+ return true;
+ }
+
+ bool Unqueue(NickCore *nc, size_t idx)
+ {
+ auto *q = queue.Get(nc);
+ if (!q || idx > q->size())
+ return false;
+
+ q->erase(q->begin() + idx);
+ if (q->empty())
+ queue.Unset(nc);
+
+ return true;
+ }
};
MODULE_INIT(GlobalCore)