diff options
author | Sadie Powell <sadie@witchery.services> | 2025-05-05 13:25:40 +0100 |
---|---|---|
committer | Sadie Powell <sadie@witchery.services> | 2025-05-05 13:25:40 +0100 |
commit | 1321f4f0711b8d0fc799f3d0ea114984083a2c11 (patch) | |
tree | 58b9e4e86342a2a61eb1792161471a18ce571d5c /docs | |
parent | 4319b6428fc51063ba9e0ee5587ec617ae85cd32 (diff) |
Add an example Ruby JSON-RPC client.
Diffstat (limited to 'docs')
-rw-r--r-- | docs/RPC/jsonrpc.rb | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/docs/RPC/jsonrpc.rb b/docs/RPC/jsonrpc.rb new file mode 100644 index 000000000..7dfd3992d --- /dev/null +++ b/docs/RPC/jsonrpc.rb @@ -0,0 +1,198 @@ +# SPDX-License-Identifier: CC0-1.0 + +require "base64" +require "json" +require "net/http" + +# Implements methods for accessing an Anope JSON-RPC server. +class AnopeRPC + + # The RPC host base URL. + attr_accessor :host + + # The bearer token for authorizing with the RPC interface. + attr_accessor :token + + # Initializes a new AnopeRPC instance with the specified RPC host. + # + # @param host [String] The RPC host base URL. + # @param token [String] The bearer token for authorizing with the RPC interface. + def initialize(host, token = nil) + @host = URI(host) + @token = token + end + + # Executes an arbitrary RPC query. + # + # @param method [String] The name of the method to execute. + # @param params [Object] The parameters pass to the method. + # @return [Object] The result of the RPC query. + private def run(method, *params) + body = { + jsonrpc: "2.0", + method: method, + params: params, + id: rand(36**16).to_s(36) + }.to_json + + headers = {} + headers["Authorization"] = "Bearer #{Base64.strict_encode64(@token)}" if @token + + response = Net::HTTP.post(@host, body, headers) + raise "HTTP returned #{response.status}" unless response.is_a?(Net::HTTPSuccess) + + json = JSON.parse(response.body, symbolize_names: true) + raise "JSON-RPC returned #{json[:error][:code]}: #{json[:error][:message]}" if json.key?(:error) + + json.dig(:result) + end + + # Retrieves a list of accounts. + # + # Requires the rpc_data module to be loaded. + # + # @param detail [Symbol] detail The level of detail to request. + # @return [Array] If the detail level is set to :name then an array of account names. + # @return [Hash] If the detail level is set to :full then a hash of information about the + # accounts. + def list_accounts(detail = :name) + self.run("anope.listAccounts", detail) + end + + # Retrieves information about the specified account. + # + # Requires the rpc_data module to be loaded. + # + # @param name [String] The name of the account. + # @return [Hash] A hash containing information about the account. + def account(name) + self.run("anope.account", name) + end + + # Retrieves a list of channels. + # + # Requires the rpc_data module to be loaded. + # + # @param detail [Symbol] detail The level of detail to request. + # @return [Array] If the detail level is set to :name then an array of channel names. + # @return [Hash] If the detail level is set to :full then a hash of information about the + # channels. + def list_channels(detail = :name) + self.run("anope.listChannels", detail) + end + + # Retrieves information about the specified channel. + # + # Requires the rpc_data module to be loaded. + # + # @param name [String] The name of the channel. + # @return [Hash] A hash containing information about the channel. + def channel(name) + self.run("anope.channel", name) + end + + # Retrieves a list of services operators. + # + # Requires the rpc_data module to be loaded. + # + # @param detail [Symbol] detail The level of detail to request. + # @return [Array] If the detail level is set to :name then an array of services operator names. + # @return [Hash] If the detail level is set to :full then a hash of information about the + # services operators. + def list_opers(detail = :name) + self.run("anope.listOpers", detail) + end + + # Retrieves information about the specified services operator. + # + # Requires the rpc_data module to be loaded. + # + # @param name [String] The name of the services operator. + # @return [Hash] A hash containing information about the services operator. + def oper(name) + self.run("anope.oper", name) + end + + # Retrieves a list of servers. + # + # Requires the rpc_data module to be loaded. + # + # @param detail [Symbol] detail The level of detail to request. + # @return [Array] If the detail level is set to :name then an array of server names. + # @return [Hash] If the detail level is set to :full then a hash of information about the + # servers. + def list_servers(detail = :name) + self.run("anope.listServers", detail) + end + + # Retrieves information about the specified server. + # + # Requires the rpc_data module to be loaded. + # + # @param name [String] The name of the server. + # @return [Hash] A hash containing information about the server. + def server(name) + self.run("anope.server", name) + end + + # Retrieves a list of users. + # + # Requires the rpc_data module to be loaded. + # + # @param detail [Symbol] detail The level of detail to request. + # @return [Array] If the detail level is set to :name then an array of user nicknames. + # @return [Hash] If the detail level is set to :full then a hash of information about the + # users. + def list_users(detail = :name) + self.run("anope.listUsers", detail) + end + + # Retrieves information about the specified user. + # + # Requires the rpc_data module to be loaded. + # + # @param name [String] The name of the user. + # @return [Hash] A hash containing information about the user. + def user(name) + self.run("anope.user", name) + end + + # Sends a message to every user on the network. + # + # Requires the rpc_message module to be loaded. + # + # @param messages [Array<String>] One or more messages to send. + def message_network(*messages) + self.run("anope.messageNetwork", *messages) + end + + # Sends a message to every user on the specified server. + # + # Requires the rpc_message module to be loaded. + # + # @param name [String] The name of the server. + # @param messages [Array<String>] One or more messages to send. + def message_server(server, *messages) + self.run("anope.messageServer", server, *messages) + end + + # Sends a message to the specified user. + # + # Requires the rpc_message module to be loaded. + # + # @param source [String] The source pseudoclient to send the message from. + # @param target [String] The target user to send the message to. + # @param messages [Array<String>] One or more messages to send. + def message_user(source, target, *messages) + self.run("anope.messageUser", source, target, *messages) + end +end + +=begin +arpc = AnopeRPC.new("http://127.0.0.1:8080/jsonrpc") +begin + pp arpc.list_servers(:full) +rescue StandardError => err + STDERR.puts err +end +=end |