diff options
author | Sadie Powell <sadie@witchery.services> | 2025-04-19 13:16:28 +0100 |
---|---|---|
committer | Sadie Powell <sadie@witchery.services> | 2025-04-19 15:16:07 +0100 |
commit | 18dfa62626468c18177ba6ff24be34f4b64f1d37 (patch) | |
tree | 464d14b4648a1624498f56bc6903bac4fb3a532c | |
parent | d81590639331f9b233d3e16512aeb01f5c024a16 (diff) |
Add expanded data to the rpc_data list events.
-rw-r--r-- | docs/RPC/jsonrpc.js | 20 | ||||
-rw-r--r-- | docs/RPC/rpc_data.md | 32 | ||||
-rw-r--r-- | modules/rpc/rpc_data.cpp | 233 |
3 files changed, 188 insertions, 97 deletions
diff --git a/docs/RPC/jsonrpc.js b/docs/RPC/jsonrpc.js index b726678a2..357cbc844 100644 --- a/docs/RPC/jsonrpc.js +++ b/docs/RPC/jsonrpc.js @@ -49,10 +49,11 @@ class AnopeRPC { * * Requires the rpc_data module to be loaded. * + * @param {string} The level of detail to request. * @returns {array} An array of channel names. */ - listChannels() { - return this.run("anope.listChannels"); + listChannels(detail = "name") { + return this.run("anope.listChannels", detail); } /** @@ -72,10 +73,11 @@ class AnopeRPC { * * Requires the rpc_data module to be loaded. * + * @param {string} The level of detail to request. * @returns {array} An array of channel names. */ - listOpers() { - return this.run("anope.listOpers"); + listOpers(detail = "name") { + return this.run("anope.listOpers", detail); } /** @@ -95,10 +97,11 @@ class AnopeRPC { * * Requires the rpc_data module to be loaded. * + * @param {string} The level of detail to request. * @returns {array} An array of servers names. */ - listServers() { - return this.run("anope.listServers"); + listServers(detail = "name") { + return this.run("anope.listServers", detail); } /** @@ -118,10 +121,11 @@ class AnopeRPC { * * Requires the rpc_data module to be loaded. * + * @param {string} The level of detail to request. * @returns {array} An array of channel names. */ - listUsers() { - return this.run("anope.listUsers"); + listUsers(detail = "name") { + return this.run("anope.listUsers", detail); } /** diff --git a/docs/RPC/rpc_data.md b/docs/RPC/rpc_data.md index 9ba1ae8ac..6aa16bd3a 100644 --- a/docs/RPC/rpc_data.md +++ b/docs/RPC/rpc_data.md @@ -6,11 +6,15 @@ Lists all channels that exist on the network. ### Parameters -*None* +Index | Description +----- | ----------- +0 | If specified then the level of detail to retrieve. Can be set to "full" to retrieve all detail or "name" to just retrieve the channel names. Defaults to "name". ### Errors -*Only standard RPC errors* +Code | Description +------ | ----------- +-32099 | The specified detail level does not exist. ### Result @@ -81,11 +85,15 @@ Lists all services operators that exist on the network. ### Parameters -*None* +Index | Description +----- | ----------- +0 | If specified then the level of detail to retrieve. Can be set to "full" to retrieve all detail or "name" to just retrieve the services operator nicknames. Defaults to "name". ### Errors -*Only standard RPC errors* +Code | Description +------ | ----------- +-32099 | The specified detail level does not exist. ### Result @@ -154,11 +162,15 @@ Lists all servers that exist on the network. ### Parameters -*None* +Index | Description +----- | ----------- +0 | If specified then the level of detail to retrieve. Can be set to "full" to retrieve all detail or "name" to just retrieve the server names. Defaults to "name". ### Errors -*Only standard RPC errors* +Code | Description +------ | ----------- +-32099 | The specified detail level does not exist. ### Result @@ -222,11 +234,15 @@ Lists all users that exist on the network. ### Parameters -*None* +Index | Description +----- | ----------- +0 | If specified then the level of detail to retrieve. Can be set to "full" to retrieve all detail or "name" to just retrieve the user nicknames. Defaults to "name". ### Errors -*Only standard RPC errors* +Code | Description +------ | ----------- +-32099 | The specified detail level does not exist. ### Result diff --git a/modules/rpc/rpc_data.cpp b/modules/rpc/rpc_data.cpp index 1f74b8179..5f7a14e63 100644 --- a/modules/rpc/rpc_data.cpp +++ b/modules/rpc/rpc_data.cpp @@ -13,6 +13,9 @@ enum { // Used by anope.channel, anope.oper, anope.server, and anope.user ERR_NO_SUCH_TARGET = RPC::ERR_CUSTOM_START, + + // Used by anope.listChannels, anope.listOpers, anope.listServers, and anope.listUsers + ERR_NO_SUCH_DETAIL = RPC::ERR_CUSTOM_START, }; class AnopeListChannelsRPCEvent final @@ -24,34 +27,8 @@ public: { } - bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override + static void GetInfo(Channel *c, RPC::Map &root) { - auto &root = request.Root<RPC::Array>(); - for (auto &[_, c] : ChannelList) - root.Reply(c->name); - return true; - } -}; - -class AnopeChannelRPCEvent final - : public RPC::Event -{ -public: - AnopeChannelRPCEvent(Module *o) - : RPC::Event(o, "anope.channel", 1) - { - } - - bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override - { - auto *c = Channel::Find(request.data[0]); - if (!c) - { - request.Error(ERR_NO_SUCH_TARGET, "No such channel"); - return true; - } - - auto &root = request.Root(); root.Reply("created", c->creation_time) .Reply("name", c->name) .Reply("registered", !!c->ci); @@ -103,48 +80,65 @@ public: auto &users = root.ReplyArray("users"); for (const auto &[_, uc] : c->users) users.Reply(uc->status.BuildModePrefixList() + uc->user->nick); + } + bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override + { + const auto detail = request.data.empty() ? "name" : request.data[0]; + if (detail.equals_ci("name")) + { + auto &root = request.Root<RPC::Array>(); + for (auto &[_, c] : ChannelList) + root.Reply(c->name); + } + else if (detail.equals_ci("full")) + { + auto &root = request.Root<RPC::Map>(); + for (auto &[_, c] : ChannelList) + GetInfo(c, root.ReplyMap(c->name)); + } + else + { + request.Error(ERR_NO_SUCH_DETAIL, "No such detail level"); + } return true; } }; -class AnopeListOpersRPCEvent final +class AnopeChannelRPCEvent final : public RPC::Event { public: - AnopeListOpersRPCEvent(Module *o) - : RPC::Event(o, "anope.listOpers") + AnopeChannelRPCEvent(Module *o) + : RPC::Event(o, "anope.channel", 1) { } bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override { - auto &root = request.Root<RPC::Array>(); - for (auto *oper : Oper::opers) - root.Reply(oper->name); + auto *c = Channel::Find(request.data[0]); + if (!c) + { + request.Error(ERR_NO_SUCH_TARGET, "No such channel"); + return true; + } + + AnopeListChannelsRPCEvent::GetInfo(c, request.Root()); return true; } }; -class AnopeOperRPCEvent final +class AnopeListOpersRPCEvent final : public RPC::Event { public: - AnopeOperRPCEvent(Module *o) - : RPC::Event(o, "anope.oper", 1) + AnopeListOpersRPCEvent(Module *o) + : RPC::Event(o, "anope.listOpers") { } - bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override + static void GetInfo(Oper *o, RPC::Map &root) { - auto *o = Oper::Find(request.data[0]); - if (!o) - { - request.Error(ERR_NO_SUCH_TARGET, "No such oper"); - return true; - } - - auto &root = request.Root(); root .Reply("name", o->name) .Reply("operonly", o->require_oper) @@ -184,48 +178,65 @@ public: root.Reply("vhost", nullptr); else root.Reply("vhost", o->vhost); + } + bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override + { + const auto detail = request.data.empty() ? "name" : request.data[0]; + if (detail.equals_ci("name")) + { + auto &root = request.Root<RPC::Array>(); + for (auto *o : Oper::opers) + root.Reply(o->name); + } + else if (detail.equals_ci("full")) + { + auto &root = request.Root<RPC::Map>(); + for (auto *o : Oper::opers) + GetInfo(o, root.ReplyMap(o->name)); + } + else + { + request.Error(ERR_NO_SUCH_DETAIL, "No such detail level"); + } return true; } }; -class AnopeListServersRPCEvent final +class AnopeOperRPCEvent final : public RPC::Event { public: - AnopeListServersRPCEvent(Module *o) - : RPC::Event(o, "anope.listServers") + AnopeOperRPCEvent(Module *o) + : RPC::Event(o, "anope.oper", 1) { } bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override { - auto &root = request.Root<RPC::Array>(); - for (auto &[_, s] : Servers::ByName) - root.Reply(s->GetName()); + auto *o = Oper::Find(request.data[0]); + if (!o) + { + request.Error(ERR_NO_SUCH_TARGET, "No such oper"); + return true; + } + + AnopeListOpersRPCEvent::GetInfo(o, request.Root()); return true; } }; -class AnopeServerRPCEvent final +class AnopeListServersRPCEvent final : public RPC::Event { public: - AnopeServerRPCEvent(Module *o) - : RPC::Event(o, "anope.server") + AnopeListServersRPCEvent(Module *o) + : RPC::Event(o, "anope.listServers") { } - bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override + static void GetInfo(Server *s, RPC::Map &root) { - auto *s = Server::Find(request.data[0]); - if (!s) - { - request.Error(ERR_NO_SUCH_TARGET, "No such server"); - return true; - } - - auto &root = request.Root(); root.Reply("description", s->GetDescription()) .Reply("juped", s->IsJuped()) .Reply("name", s->GetName()) @@ -245,48 +256,65 @@ public: root.Reply("uplink", s->GetUplink()->GetName()); else root.Reply("uplink", nullptr); + } + bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override + { + const auto detail = request.data.empty() ? "name" : request.data[0]; + if (detail.equals_ci("name")) + { + auto &root = request.Root<RPC::Array>(); + for (auto &[_, s] : Servers::ByName) + root.Reply(s->GetName()); + } + else if (detail.equals_ci("full")) + { + auto &root = request.Root<RPC::Map>(); + for (auto &[_, s] : Servers::ByName) + GetInfo(s, root.ReplyMap(s->GetName())); + } + else + { + request.Error(ERR_NO_SUCH_DETAIL, "No such detail level"); + } return true; } }; -class AnopeListUsersRPCEvent final +class AnopeServerRPCEvent final : public RPC::Event { public: - AnopeListUsersRPCEvent(Module *o) - : RPC::Event(0, "anope.listUsers") + AnopeServerRPCEvent(Module *o) + : RPC::Event(o, "anope.server") { } bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override { - auto &root = request.Root<RPC::Array>(); - for (auto &[_, u] : UserListByNick) - root.Reply(u->nick); + auto *s = Server::Find(request.data[0]); + if (!s) + { + request.Error(ERR_NO_SUCH_TARGET, "No such server"); + return true; + } + + AnopeListServersRPCEvent::GetInfo(s, request.Root()); return true; } }; -class AnopeUserRPCEvent final +class AnopeListUsersRPCEvent final : public RPC::Event { public: - AnopeUserRPCEvent(Module *o) - : RPC::Event(o, "anope.user", 1) + AnopeListUsersRPCEvent(Module *o) + : RPC::Event(0, "anope.listUsers") { } - bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override + static void GetInfo(User *u, RPC::Map &root) { - auto *u = User::Find(request.data[0]); - if (!u) - { - request.Error(ERR_NO_SUCH_TARGET, "No such user"); - return true; - } - - auto &root = request.Root(); root.Reply("address", u->ip.addr()) .Reply("host", u->host) .Reply("ident", u->GetIdent()) @@ -355,7 +383,50 @@ public: root.Reply("vident", nullptr); else root.Reply("vident", u->GetIdent()); + } + + bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override + { + const auto detail = request.data.empty() ? "name" : request.data[0]; + if (detail.equals_ci("name")) + { + auto &root = request.Root<RPC::Array>(); + for (auto &[_, u] : UserListByNick) + root.Reply(u->nick); + } + else if (detail.equals_ci("full")) + { + auto &root = request.Root<RPC::Map>(); + for (auto &[_, u] : UserListByNick) + GetInfo(u, root.ReplyMap(u->nick)); + } + else + { + request.Error(ERR_NO_SUCH_DETAIL, "No such detail level"); + } + return true; + } +}; + +class AnopeUserRPCEvent final + : public RPC::Event +{ +public: + AnopeUserRPCEvent(Module *o) + : RPC::Event(o, "anope.user", 1) + { + } + + bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override + { + auto *u = User::Find(request.data[0]); + if (!u) + { + request.Error(ERR_NO_SUCH_TARGET, "No such user"); + return true; + } + AnopeListUsersRPCEvent::GetInfo(u, request.Root()); return true; } }; |