diff options
author | Sadie Powell <sadie@witchery.services> | 2025-02-24 05:46:43 +0000 |
---|---|---|
committer | Sadie Powell <sadie@witchery.services> | 2025-02-25 19:59:23 +0000 |
commit | e500258ce4b01bc02539db99c12fa7d9428cb0a6 (patch) | |
tree | 5a9fd3900ad3104741b61a907c3f8f2a99323f35 | |
parent | 801a748e256cb7c4952969103f2f2eaf5ee36552 (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.conf | 16 | ||||
-rw-r--r-- | docs/RPC/RPC | 7 | ||||
-rw-r--r-- | docs/RPC/jsonrpc.php | 4 | ||||
-rw-r--r-- | docs/RPC/rpc_data.md | 309 | ||||
-rw-r--r-- | modules/rpc/rpc_data.cpp | 446 | ||||
-rw-r--r-- | modules/rpc/rpc_main.cpp | 139 |
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(¬icerpcevent); } @@ -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(¬icerpcevent); } }; |