summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSadie Powell <sadie@witchery.services>2025-02-24 05:46:43 +0000
committerSadie Powell <sadie@witchery.services>2025-02-25 19:59:23 +0000
commite500258ce4b01bc02539db99c12fa7d9428cb0a6 (patch)
tree5a9fd3900ad3104741b61a907c3f8f2a99323f35
parent801a748e256cb7c4952969103f2f2eaf5ee36552 (diff)
Add the rpc_data module.
- Add rewritten and namespaced versions of the channel, oper, user events. - Add the following new events: * anope.listChannels * anope.listOpers * anope.listServers * anope.listUsers * anope.server
-rw-r--r--data/modules.example.conf16
-rw-r--r--docs/RPC/RPC7
-rw-r--r--docs/RPC/jsonrpc.php4
-rw-r--r--docs/RPC/rpc_data.md309
-rw-r--r--modules/rpc/rpc_data.cpp446
-rw-r--r--modules/rpc/rpc_main.cpp139
6 files changed, 773 insertions, 148 deletions
diff --git a/data/modules.example.conf b/data/modules.example.conf
index ebf2f3527..e360e9310 100644
--- a/data/modules.example.conf
+++ b/data/modules.example.conf
@@ -818,6 +818,22 @@ module { name = "sasl" }
}
/*
+ * rpc_data
+ *
+ * Adds support for the following RPC methods:
+ *
+ * anope.listChannels anope.channel
+ * anope.listOpers anope.oper
+ * anope.listServers anope.server
+ * anope.listUsers anope.user
+ *
+ * Requires either the jsonrpc or xmlrpc module.
+ *
+ * See docs/RPC/rpc_data.md for API documentation.
+ */
+#module { name = "rpc_data" }
+
+/*
* rpc_main
*
* Adds the main RPC core functions.
diff --git a/docs/RPC/RPC b/docs/RPC/RPC
index a93d61af8..94c7ba7f7 100644
--- a/docs/RPC/RPC
+++ b/docs/RPC/RPC
@@ -13,13 +13,6 @@ command - Takes three parameters, a service name (BotServ, ChanServ, NickServ),
stats - Takes no parameters, returns miscellaneous stats that can be found in the /operserv stats command.
-channel - Takes one parameter, a channel name, and returns real time information regarding that channel, such as users, modes
- (ban lists and such), topic etc.
-
-user - Takes one parameter, a user name, and returns real time information regarding that user.
-
-opers - Takes no parameters, returns opertypes, their privileges and commands.
-
notice - Takes three parameters, source user, target user, and message. Sends a message to the user.
RPC was designed to be used with db_sql, and will not return any information that can be pulled from the SQL
diff --git a/docs/RPC/jsonrpc.php b/docs/RPC/jsonrpc.php
index a4413b35c..a0a6e9270 100644
--- a/docs/RPC/jsonrpc.php
+++ b/docs/RPC/jsonrpc.php
@@ -117,7 +117,7 @@ class AnopeRPC
*/
public function channel($channel)
{
- return $this->run("channel", [$channel]);
+ return $this->run("anope.channel", [$channel]);
}
/**
@@ -143,7 +143,7 @@ class AnopeRPC
*/
public function user($user)
{
- return $this->run("user", [$user]);
+ return $this->run("anope.user", [$user]);
}
}
diff --git a/docs/RPC/rpc_data.md b/docs/RPC/rpc_data.md
new file mode 100644
index 000000000..9ba1ae8ac
--- /dev/null
+++ b/docs/RPC/rpc_data.md
@@ -0,0 +1,309 @@
+# Anope `rpc_data` RPC interface
+
+## `anope.listChannels`
+
+Lists all channels that exist on the network.
+
+### Parameters
+
+*None*
+
+### Errors
+
+*Only standard RPC errors*
+
+### Result
+
+Returns an array of channel names.
+
+#### Example
+
+```json
+["#chan1", "#chan2", "#chan3"]
+```
+
+## `anope.channel`
+
+Retrieves information about the specified channel.
+
+### Parameters
+
+Index | Description
+----- | -----------
+0 | The name of the channel.
+
+### Errors
+
+Code | Description
+------ | -----------
+-32099 | The specified channel does not exist.
+
+### Result
+
+Returns a map containing information about the channel.
+
+Key | Type | Description
+--- | ---- | -----------
+created | uint | The UNIX time at which the channel was originally created.
+listmodes | map | List modes which are set on the channel keyed by the mode character.
+modes | array[string] | Flag and parameter modes which are set on the channel.
+name | string | The name of the channel.
+registered | boolean | Whether the channel is registered.
+topic | map or null | The channel topic or null if no topic is set.
+topic.setat | uint | The time at which the topic was set.
+topic.setby | string | The nick or nuh of the user who set the topic.
+topic.value | string | The text of the topic.
+users | array[string] | The users that are current in the channel prefixed by their status mode prefixes.
+
+#### Example
+
+```json
+{
+ "created": 1740402691,
+ "listmodes": {
+ "b": ["foo!bar@baz", "account:bax"],
+ },
+ "modes": ["+knrt", "secret"],
+ "name": "#chan1",
+ "registered": true,
+ "topic": {
+ "setat": 1740404706,
+ "setby": "nick1",
+ "value": "Example channel topic"
+ },
+ "users": ["@nick1", "nick2"]
+}
+```
+
+## `anope.listOpers`
+
+Lists all services operators that exist on the network.
+
+### Parameters
+
+*None*
+
+### Errors
+
+*Only standard RPC errors*
+
+### Result
+
+Returns an array of services operator names.
+
+#### Example
+
+```json
+["nick1", "nick2", "nick3"]
+```
+
+## `anope.oper`
+
+Retrieves information about the specified services operator.
+
+### Parameters
+
+Index | Description
+----- | -----------
+0 | The name of the services operator.
+
+### Errors
+
+Code | Description
+------ | -----------
+-32099 | The specified services operator does not exist.
+
+### Result
+
+Returns a map containing information about the services operator.
+
+Key | Type | Description
+--- | ---- | -----------
+fingerprints | array[string] or null | The client certificate fingerprints that a user must be using to log in as this services operator or null if there are no client certificate restrictions.
+hosts | array[string] or null | The user@ip and user@ip masks that a user must be connecting from to log in as this services operator or null if there are no host restrictions.
+name | string | The name of the services operator.
+operonly | boolean | Whether a user has to be a server operator to log in as this services operator.
+opertype | map | The oper type associated with the services operator opertype.
+opertype.commands | array[string] | The commands that the services operator type can use.
+opertype.name | string | The name of the services operator type.
+opertype.privileges | array[string] | The privileges that the services operator type has.
+password | boolean | Whether a user has to specify a password to log in as the services operator.
+vhost | string or null | The vhost of the services operator or null if there is no vhost.
+
+#### Example
+
+```json
+{
+ "fingerprints": null,
+ "hosts": ["*@*.example.com"],
+ "name": "stest",
+ "operonly": true,
+ "opertype": {
+ "commands": ["hostserv/*", "operserv/session"],
+ "name": "Helper",
+ "privileges": ["chanserv/no-register-limit"]
+ },
+ "password": false,
+ "vhost": null
+}
+```
+
+## `anope.listServers`
+
+Lists all servers that exist on the network.
+
+### Parameters
+
+*None*
+
+### Errors
+
+*Only standard RPC errors*
+
+### Result
+
+Returns an array of server names.
+
+#### Example
+
+```json
+["irc1.example.com", "irc2.example.com", "services.example.com"]
+```
+
+## `anope.server`
+
+Retrieves information about the specified server.
+
+### Parameters
+
+Index | Description
+----- | -----------
+0 | The name of the server.
+
+### Errors
+
+Code | Description
+------ | -----------
+-32099 | The specified server does not exist.
+
+### Result
+
+Returns a map containing information about the server.
+
+Key | Type | Description
+--- | ---- | -----------
+description | string | The description of the server.
+downlinks | array[string] | The servers which are behind this server
+juped | boolean | Whether the server has been juped.
+name | string | The name of the server.
+sid | string or null | The unique immutable identifier of the server or null if the IRCd does not use SIDs.
+synced | boolean | Whether the server has finished syncing.
+ulined | boolean | Whether the server is U-lined.
+uplink | string or null | The server in front of this server or null if it is the services server.
+
+#### Example
+
+```json
+{
+ "description": "Anope IRC Services",
+ "downlinks": ["irc.example.com"],
+ "juped": false,
+ "name": "services.example.com",
+ "sid": "00B",
+ "synced": true,
+ "ulined": true,
+ "uplink": null
+}
+```
+
+## `anope.listUsers`
+
+Lists all users that exist on the network.
+
+### Parameters
+
+*None*
+
+### Errors
+
+*Only standard RPC errors*
+
+### Result
+
+Returns an array of user nicknames.
+
+
+#### Example
+
+```json
+["nick1", "nick2", "nick3"]
+```
+
+## `anope.user`
+
+Retrieves information about the specified user.
+
+### Parameters
+
+Index | Description
+----- | -----------
+0 | The nickname of the user.
+
+### Errors
+
+Code | Description
+------ | -----------
+-32099 | The specified user does not exist.
+
+### Result
+
+Returns a map containing information about the user.
+
+Key | Type | Description
+--- | ---- | -----------
+account | map or null | The user's account or null if they are not logged in to an account.
+account.display | string | The display nickname of the account.
+account.opertype | string or null | The account's oper type or null if the account is not a services operator.
+account.uniqueid | uint | The unique immutable identifier of the account.
+address | string | The IP address the user is connecting from.
+channels | array[string] | The channels that the user is in prefixed by their status mode prefixes.
+chost | string or null | The cloaked hostname of the user or null if they have no cloak.
+fingerprint | string or null | The fingerprint of the user's client certificate or null if they are not using one.
+host | string | The real hostname of the user.
+ident | string | The username (ident) of the user.
+modes | array[string] | Flag and parameter modes which are set on the user.
+nick | string | The nickname of the user.
+nickchanged | uint | The time at which the user last changed their nickname.
+real | string | The real name of the user.
+server | string | The server that the user is connected to.
+signon | uint | The time at which the user connected to the network.
+uid | string or null | The unique immutable identifier of the user or null if the IRCd does not use UIDs.
+vhost | string or null | The virtual host of the user or null if they have no vhost.
+vident | string or null | The virtual ident (username) of the user or null if they have no vident.
+
+#### Example
+
+```json
+{
+ "account": {
+ "display": "nick1",
+ "opertype": "Services Root",
+ "uniqueid": "17183514657819486040"
+ },
+ "address": "127.0.0.1",
+ "channels": ["@#chan1", "#chan2"],
+ "chost": "localhost",
+ "fingerprint": null,
+ "host": "localhost",
+ "id": "9TSAAAAAA",
+ "ident": "user1",
+ "modes": ["+r"],
+ "nick": "nick1",
+ "nickchanged": 1740408318,
+ "real": "An IRC User",
+ "server": "irc.example.com",
+ "signon": 1740408296,
+ "vhost": "staff.example.com",
+ "vident": null,
+}
+```
diff --git a/modules/rpc/rpc_data.cpp b/modules/rpc/rpc_data.cpp
new file mode 100644
index 000000000..670b4c57e
--- /dev/null
+++ b/modules/rpc/rpc_data.cpp
@@ -0,0 +1,446 @@
+/*
+ *
+ * (C) 2010-2025 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ */
+
+#include "module.h"
+#include "modules/rpc.h"
+
+enum
+{
+ // Used by anope.channel, anope.oper, anope.server, and anope.user
+ ERR_NO_SUCH_TARGET = RPC::ERR_CUSTOM_START,
+};
+
+class AnopeListChannelsRPCEvent final
+ : public RPC::Event
+{
+public:
+ AnopeListChannelsRPCEvent()
+ : RPC::Event("anope.listChannels")
+ {
+ }
+
+ bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override
+ {
+ auto &root = request.Root<RPC::Array>();
+ for (auto &[_, c] : ChannelList)
+ root.Reply(c->name);
+ return true;
+ }
+};
+
+class AnopeChannelRPCEvent final
+ : public RPC::Event
+{
+public:
+ AnopeChannelRPCEvent()
+ : RPC::Event("anope.channel")
+ {
+ }
+
+ bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override
+ {
+ if (request.data.empty())
+ {
+ request.Error(RPC::ERR_INVALID_PARAMS, "Not enough parameters");
+ return true;
+ }
+
+ 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);
+
+ std::map<char, RPC::Array&> modemap;
+ auto &listmodes = root.ReplyMap("listmodes");
+ for (auto *cm : ModeManager::GetChannelModes())
+ {
+ if (cm->type != MODE_LIST)
+ continue;
+
+ for (auto &entry : c->GetModeList(cm->name))
+ {
+ auto *wcm = cm->Wrap(entry);
+
+ auto it = modemap.find(wcm->mchar);
+ if (it == modemap.end())
+ it = modemap.emplace(wcm->mchar, listmodes.ReplyArray(wcm->mchar)).first;
+
+ it->second.Reply(entry);
+ }
+ }
+
+ std::vector<Anope::string> modelist = { "+" };
+ for (const auto &[mname, mvalue] : c->GetModes())
+ {
+ auto *cm = ModeManager::FindChannelModeByName(mname);
+ if (!cm || cm->type == MODE_LIST)
+ continue;
+
+ modelist.front().push_back(cm->mchar);
+ if (!mvalue.empty())
+ modelist.push_back(mvalue);
+ }
+ auto &modes = root.ReplyArray("modes");
+ for (const auto &modeparam : modelist)
+ modes.Reply(modeparam);
+
+ if (c->topic.empty())
+ root.Reply("topic", nullptr);
+ else
+ {
+ auto &topic = root.ReplyMap("topic");
+ topic.Reply("setat", c->topic_ts)
+ .Reply("setby", c->topic_setter)
+ .Reply("value", c->topic);
+ }
+
+ auto &users = root.ReplyArray("users");
+ for (const auto &[_, uc] : c->users)
+ users.Reply(uc->status.BuildModePrefixList() + uc->user->nick);
+
+ return true;
+ }
+};
+
+class AnopeListOpersRPCEvent final
+ : public RPC::Event
+{
+public:
+ AnopeListOpersRPCEvent()
+ : RPC::Event("anope.listOpers")
+ {
+ }
+
+ 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);
+ return true;
+ }
+};
+
+class AnopeOperRPCEvent final
+ : public RPC::Event
+{
+public:
+ AnopeOperRPCEvent()
+ : RPC::Event("anope.oper")
+ {
+ }
+
+ bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override
+ {
+ if (request.data.empty())
+ {
+ request.Error(RPC::ERR_INVALID_PARAMS, "Not enough parameters");
+ return true;
+ }
+
+ 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)
+ .Reply("password", !o->password.empty());
+
+ if (o->certfp.empty())
+ root.Reply("fingerprints", nullptr);
+ else
+ {
+ auto &fingerprints = root.ReplyArray("fingerprints");
+ for (const auto &fingerprint : o->certfp)
+ fingerprints.Reply(fingerprint);
+ }
+
+ if (o->hosts.empty())
+ root.Reply("hosts", nullptr);
+ else
+ {
+ auto &hosts = root.ReplyArray("hosts");
+ for (const auto &host : o->hosts)
+ hosts.Reply(host);
+ }
+
+ auto &opertype = root.ReplyMap("opertype");
+ opertype.Reply("name", o->ot->GetName());
+ {
+ auto &commands = opertype.ReplyArray("commands");
+ for (const auto &command : o->ot->GetCommands())
+ commands.Reply(command);
+
+ auto &privileges = opertype.ReplyArray("privileges");
+ for (const auto &privilege : o->ot->GetPrivs())
+ privileges.Reply(privilege);
+ }
+
+ if (o->vhost.empty())
+ root.Reply("vhost", nullptr);
+ else
+ root.Reply("vhost", o->vhost);
+
+ return true;
+ }
+};
+
+class AnopeListServersRPCEvent final
+ : public RPC::Event
+{
+public:
+ AnopeListServersRPCEvent()
+ : RPC::Event("anope.listServers")
+ {
+ }
+
+ 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());
+ return true;
+ }
+};
+
+class AnopeServerRPCEvent final
+ : public RPC::Event
+{
+public:
+ AnopeServerRPCEvent()
+ : RPC::Event("anope.server")
+ {
+ }
+
+ bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override
+ {
+ if (request.data.empty())
+ {
+ request.Error(RPC::ERR_INVALID_PARAMS, "Not enough parameters");
+ return true;
+ }
+
+ 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())
+ .Reply("synced", s->IsSynced())
+ .Reply("ulined", s->IsULined());
+
+ auto &downlinks = root.ReplyArray("downlinks");
+ for (const auto *s : s->GetLinks())
+ downlinks.Reply(s->GetName());
+
+ if (IRCD->RequiresID)
+ root.Reply("sid", s->GetSID());
+ else
+ root.Reply("sid", nullptr);
+
+ if (s->GetUplink())
+ root.Reply("uplink", s->GetUplink()->GetName());
+ else
+ root.Reply("uplink", nullptr);
+
+ return true;
+ }
+};
+
+class AnopeListUsersRPCEvent final
+ : public RPC::Event
+{
+public:
+ AnopeListUsersRPCEvent()
+ : RPC::Event("anope.listUsers")
+ {
+ }
+
+ 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);
+ return true;
+ }
+};
+
+class AnopeUserRPCEvent final
+ : public RPC::Event
+{
+public:
+ AnopeUserRPCEvent()
+ : RPC::Event("anope.user")
+ {
+ }
+
+ bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override
+ {
+ if (request.data.empty())
+ {
+ request.Error(RPC::ERR_INVALID_PARAMS, "Not enough parameters");
+ return true;
+ }
+
+ 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())
+ .Reply("nick", u->nick)
+ .Reply("nickchanged", u->timestamp)
+ .Reply("real", u->realname)
+ .Reply("server", u->server->GetName())
+ .Reply("signon", u->signon);
+
+ if (u->IsIdentified())
+ {
+ auto &account = root.ReplyMap("account");
+ account.Reply("display", u->Account()->display)
+ .Reply("uniqueid", u->Account()->GetId());
+
+ if (u->Account()->o)
+ account.Reply("opertype", u->Account()->o->ot->GetName());
+ else
+ account.Reply("opertype", nullptr);
+ }
+ else
+ {
+ root.Reply("account", nullptr);
+ }
+
+ auto &channels = root.ReplyArray("channels");
+ for (const auto &[_, cc] : u->chans)
+ channels.Reply(cc->status.BuildModePrefixList() + cc->chan->name);
+
+ if (u->chost.empty())
+ root.Reply("chost", nullptr);
+ else
+ root.Reply("chost", u->chost);
+
+ if (u->fingerprint.empty())
+ root.Reply("fingerprint", nullptr);
+ else
+ root.Reply("fingerprint", u->fingerprint);
+
+ std::vector<Anope::string> modelist = { "+" };
+ for (const auto &[mname, mvalue] : u->GetModeList())
+ {
+ auto *um = ModeManager::FindUserModeByName(mname);
+ if (!um || um->type == MODE_LIST)
+ continue;
+
+ modelist.front().push_back(um->mchar);
+ if (!mvalue.empty())
+ modelist.push_back(mvalue);
+ }
+ auto &modes = root.ReplyArray("modes");
+ for (const auto &modeparam : modelist)
+ modes.Reply(modeparam);
+
+ if (IRCD->RequiresID)
+ root.Reply("uid", u->GetUID());
+ else
+ root.Reply("uid", nullptr);
+
+ if (u->vhost.empty() || u->vhost.equals_cs(u->host))
+ root.Reply("vhost", nullptr);
+ else
+ root.Reply("vhost", u->vhost);
+
+ if (u->GetVIdent().equals_cs(u->GetIdent()))
+ root.Reply("vident", nullptr);
+ else
+ root.Reply("vident", u->GetIdent());
+
+ return true;
+ }
+};
+
+class ModuleRPCData final
+ : public Module
+{
+private:
+ ServiceReference<RPC::ServiceInterface> rpc;
+
+ AnopeListChannelsRPCEvent anopelistchannelsrpcevent;
+ AnopeChannelRPCEvent anopechannelrpcevent;
+
+ AnopeListOpersRPCEvent anopelistopersrpcevent;
+ AnopeOperRPCEvent anopeoperrpcevent;
+
+ AnopeListServersRPCEvent anopelistserversrpcevent;
+ AnopeServerRPCEvent anopeserverrpcevent;
+
+ AnopeListUsersRPCEvent anopelistusersrpcevent;
+ AnopeUserRPCEvent anopeuserrpcevent;
+
+public:
+ ModuleRPCData(const Anope::string &modname, const Anope::string &creator)
+ : Module(modname, creator, EXTRA | VENDOR)
+ , rpc("RPCServiceInterface", "rpc")
+ {
+ if (!rpc)
+ throw ModuleException("Unable to find RPC interface, is jsonrpc/xmlrpc loaded?");
+
+ rpc->Register(&anopelistchannelsrpcevent);
+ rpc->Register(&anopechannelrpcevent);
+
+ rpc->Register(&anopelistopersrpcevent);
+ rpc->Register(&anopeoperrpcevent);
+
+ rpc->Register(&anopelistserversrpcevent);
+ rpc->Register(&anopeserverrpcevent);
+
+ rpc->Register(&anopelistusersrpcevent);
+ rpc->Register(&anopeuserrpcevent);
+
+ }
+
+ ~ModuleRPCData() override
+ {
+ if (!rpc)
+ return;
+
+ rpc->Unregister(&anopelistchannelsrpcevent);
+ rpc->Unregister(&anopechannelrpcevent);
+
+ rpc->Unregister(&anopelistopersrpcevent);
+ rpc->Unregister(&anopeoperrpcevent);
+
+ rpc->Unregister(&anopelistserversrpcevent);
+ rpc->Unregister(&anopeserverrpcevent);
+
+ rpc->Unregister(&anopelistusersrpcevent);
+ rpc->Unregister(&anopeuserrpcevent);
+ }
+};
+
+MODULE_INIT(ModuleRPCData)
diff --git a/modules/rpc/rpc_main.cpp b/modules/rpc/rpc_main.cpp
index 2f22e82c7..0f35de142 100644
--- a/modules/rpc/rpc_main.cpp
+++ b/modules/rpc/rpc_main.cpp
@@ -167,136 +167,6 @@ public:
}
};
-class ChannelRPCEvent final
- : public RPC::Event
-{
-public:
- ChannelRPCEvent()
- : RPC::Event("channel")
- {
- }
-
- bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override
- {
- if (request.data.empty())
- {
- request.Error(RPC::ERR_INVALID_PARAMS, "Invalid parameters");
- return true;
- }
-
- Channel *c = Channel::Find(request.data[0]);
-
- auto &root = request.Root();
- root.Reply("name", c ? c->name : request.data[0]);
-
- if (c)
- {
- root.Reply("bancount", c->HasMode("BAN"));
- auto &bans = root.ReplyArray("bans");
- for (auto &ban : c->GetModeList("BAN"))
- bans.Reply(ban);
-
- root.Reply("exceptcount", c->HasMode("EXCEPT"));
- auto &excepts = root.ReplyArray("excepts");
- for (auto &except : c->GetModeList("EXCEPT"))
- excepts.Reply(except);
-
- root.Reply("invitecount", c->HasMode("INVITEOVERRIDE"));
- auto &invites = root.ReplyArray("invites");
- for (auto &invite : c->GetModeList("INVITEOVERRIDE"))
- invites.Reply(invite);
-
- auto &users = root.ReplyArray("users");
- for (const auto &[_, uc] : c->users)
- users.Reply(uc->status.BuildModePrefixList() + uc->user->nick);
-
- if (!c->topic.empty())
- root.Reply("topic", c->topic);
-
- if (!c->topic_setter.empty())
- root.Reply("topicsetter", c->topic_setter);
-
- root.Reply("topictime", c->topic_time);
- root.Reply("topicts", c->topic_ts);
- }
- return true;
- }
-};
-
-class UserRPCEvent final
- : public RPC::Event
-{
-public:
- UserRPCEvent()
- : RPC::Event("user")
- {
- }
-
- bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override
- {
- if (request.data.empty())
- {
- request.Error(RPC::ERR_INVALID_PARAMS, "Invalid parameters");
- return true;
- }
-
- User *u = User::Find(request.data[0]);
-
- auto &root = request.Root();
- root.Reply("nick", u ? u->nick : request.data[0]);
-
- if (u)
- {
- root.Reply("ident", u->GetIdent());
- root.Reply("vident", u->GetVIdent());
- root.Reply("host", u->host);
- if (!u->vhost.empty())
- root.Reply("vhost", u->vhost);
- if (!u->chost.empty())
- root.Reply("chost", u->chost);
- root.Reply("ip", u->ip.addr());
- root.Reply("timestamp", u->timestamp);
- root.Reply("signon", u->signon);
- if (u->IsIdentified())
- {
- root.Reply("account", u->Account()->display);
- if (u->Account()->o)
- root.Reply("opertype", u->Account()->o->ot->GetName());
- }
-
- auto &channels = root.ReplyArray("channels");
- for (const auto &[_, cc] : u->chans)
- channels.Reply(cc->status.BuildModePrefixList() + cc->chan->name);
- }
- return true;
- }
-};
-
-class OpersRPCEvent final
- : public RPC::Event
-{
-public:
- OpersRPCEvent()
- : RPC::Event("opers")
- {
- }
-
- bool Run(RPC::ServiceInterface *iface, HTTPClient *client, RPC::Request &request) override
- {
- auto &root = request.Root();
- for (auto *ot : Config->MyOperTypes)
- {
- Anope::string perms;
- for (const auto &priv : ot->GetPrivs())
- perms += " " + priv;
- for (const auto &command : ot->GetCommands())
- perms += " " + command;
- root.Reply(ot->GetName(), perms);
- }
- return true;
- }
-};
-
class NoticeRPCEvent final
: public RPC::Event
{
@@ -334,9 +204,6 @@ private:
CommandRPCEvent commandrpcevent;
CheckAuthenticationRPCEvent checkauthenticationrpcevent;
StatsRPCEvent statsrpcevent;
- ChannelRPCEvent channelrpcevent;
- UserRPCEvent userrpcevent;
- OpersRPCEvent opersrpcevent;
NoticeRPCEvent noticerpcevent;
public:
@@ -352,9 +219,6 @@ public:
rpc->Register(&commandrpcevent);
rpc->Register(&checkauthenticationrpcevent);
rpc->Register(&statsrpcevent);
- rpc->Register(&channelrpcevent);
- rpc->Register(&userrpcevent);
- rpc->Register(&opersrpcevent);
rpc->Register(&noticerpcevent);
}
@@ -366,9 +230,6 @@ public:
rpc->Unregister(&commandrpcevent);
rpc->Unregister(&checkauthenticationrpcevent);
rpc->Unregister(&statsrpcevent);
- rpc->Unregister(&channelrpcevent);
- rpc->Unregister(&userrpcevent);
- rpc->Unregister(&opersrpcevent);
rpc->Unregister(&noticerpcevent);
}
};