Tornex.SpecQuery (Tornex v0.3.0)

View Source

The query struct containing API request data for API v2 requests.

The Tornex.SpecQuery struct works against the OpenAPI specification for the Torn API v2. Tornex.SpecQuery can be used by Tornex.API.get/1 and Tornex.Scheduler.Bucket.enqueue/1 to make API calls. The struct stores the required information to perform the API call. To use APIv2 calls with the OpenAPI specification and an autogenerated client, you will need to add the Tornium/torngen_elixir_client library to your dependencies; this library includes the paths and schemas required to make and parse APIv2 calls. Alternatively, to make APIv2 calls without the OpenAPI specification, use Tornex.Query instead and prepend the resource with v2/ (e.g. v2/user).

Preparing Query

Create an empty query using new/0. Use put_path/2 and put_parameter to set up the query.

iex> query =
...>   Tornex.SpecQuery.new(nice: 0)
...>   |> Tornex.SpecQuery.put_key("foo")
...>   |> Tornex.SpecQuery.put_path(Torngen.Client.Path.User.Id.Bounties)
...>   |> Tornex.SpecQuery.put_parameter(:id, 2383326)

Making Query

The SpecQuery can be executed using Tornex.API.get/1 and Tornex.Scheduler.Bucket.enqueue/1 to perform the API calls. Once the API call has been finished, the response can be parsed into schema structs and validated using parse/2.

iex> api_response = Tornex.API.get(query)
iex> parsed_response = Tornex.SpecQuery.parse(query, api_response)

Summary

Functions

Initialize an empty query against the OpenAPI specification.

Parse the response of an API call against the query into schema structs.

Parse a SpecQuery to determine the base path and selections.

Add an API key to the query.

Add the owner of the API key to the query.

Add an OpenAPI parameter to the query.

Add an OpenAPI path to the query.

Generate and validate a URI to perform the Tornex.SpecQuery.

Types

parameter()

@type parameter() :: {atom(), term()}

t()

@type t() :: %Tornex.SpecQuery{
  key: String.t() | nil,
  key_owner: integer(),
  nice: integer(),
  origin: GenServer.from() | nil,
  parameters: [parameter()],
  paths: [atom()]
}

Functions

new(opts \\ [])

@spec new(opts :: Keyword.t()) :: t()

Initialize an empty query against the OpenAPI specification.

By default, the niceness of the request will be set to 20 and the key owner will be set to 0. The key owner of 0 is intended to be for requests where the owner of the key is not known (e.g. for determining the owner of the API key).

Options

  • :paths - list of API paths
  • :parameters - list of query/path parameters
  • :key - API key
  • :key_owner - ID of the owner of the API key (default: 0)
  • :nice - Priority of the API call between -20 and 20 (default: 20)

parse(query, response)

@spec parse(query :: t(), response :: list() | map()) :: %{
  required(module()) => term()
}

Parse the response of an API call against the query into schema structs.

path_selections!(query)

@spec path_selections!(query :: t()) :: {String.t(), [String.t()]}

Parse a SpecQuery to determine the base path and selections.

Raises RuntimeError if the SpecQuery does not contain any paths or has conflicting base paths.

Examples

iex> query = 
...>   Tornex.SpecQuery.new()
...>   |> Tornex.SpecQuery.put_path(Torngen.Client.Path.User.Id.Personalstats)
...>   |> Tornex.SpecQuery.put_path(Torngen.Client.Path.User.Id.Bounties)
...>   |> Tornex.SpecQuery.put_parameter(:id, 2383326)
...>   |> Tornex.SpecQuery.put_parameter(:stats, ["attackswon", "attackslost"])
iex> Tornex.SpecQuery.path_selections!()
{"user/{id}/", ["personalstats", "bounties"]}

iex> query = 
...>   Tornex.SpecQuery.new()
...>   |> Tornex.SpecQuery.put_path(Torngen.Client.Path.User.Id.Personalstats)
...>   |> Tornex.SpecQuery.put_path(Torngen.Client.Path.User.Attacks)
...>   |> Tornex.SpecQuery.put_parameter(:id, 2383326)
...>   |> Tornex.SpecQuery.put_parameter(:stats, ["attackswon", "attackslost"])
iex> Tornex.SpecQuery.path_selections!()
** (RuntimeError) 2 base paths were added to the query **

iex> query = Tornex.SpecQuery.new()
iex> Tornex.SpecQuery.path_selections!()
** (RuntimeError) No paths were added to the query **

put_key(query, api_key)

@spec put_key(query :: t(), api_key :: String.t()) :: t()

Add an API key to the query.

put_key_owner(query, key_owner)

@spec put_key_owner(query :: t(), key_owner :: pos_integer()) :: t()

Add the owner of the API key to the query.

put_parameter(query, parameter_name, parameter_value)

@spec put_parameter(query :: t(), parameter_name :: atom(), parameter_value :: term()) ::
  t()

Add an OpenAPI parameter to the query.

During the execution of the query, the parameter will be inserted as either a path or query parameter depending on the OpenAPI specifications for the paths included in the query. The parameter_value must be an implementation of the String.Chars protocol. If parameter_value is a list and the parameter_name is a query parameter, the values of the list will be joined with commas and used as the parameter value.

Examples

iex> query = 
...>   Tornex.SpecQuery.new()
...>   |> Tornex.SpecQuery.put_path(Torngen.Client.Path.User.Id.Personalstats)
...>   |> Tornex.SpecQuery.put_parameter(:id, 2383326)
...>   |> |> Tornex.SpecQuery.put_parameter(:stat, ["attackswon", "attackslost"])

put_path(query, path)

@spec put_path(query :: t(), path :: term()) :: t()

Add an OpenAPI path to the query.

The OpenAPI path must be an implementation of the Torngen.Client.Path behavior (originating from the torngen library). However, multiple base resources can not be combined into one query when adding paths to the query. This includes paths for the same resource type (e.g. user) but differing resource IDs such as /user/${id}/bounties.

Examples

iex> query =
...>   Tornex.SpecQuery.new()
...>   |> Tornex.SpecQuery.put_path(Torngen.Client.Path.User.Attacks)
...>   |> Tornex.SpecQuery.put_path(Torngen.Client.Path.User.Bounties)

uri!(query)

@spec uri!(query :: t()) :: URI.t()

Generate and validate a URI to perform the Tornex.SpecQuery.

Raises RuntimeError if the SpecQuery does not contain all of the necessary path parameters or if a base path and selections cannot be determined by path_selections!/1.

Examples

iex> query = 
...>   Tornex.SpecQuery.new()
...>   |> Tornex.SpecQuery.put_path(Torngen.Client.Path.User.Id.Personalstats)
...>   |> Tornex.SpecQuery.put_path(Torngen.Client.Path.User.Id.Bounties)
...>   |> Tornex.SpecQuery.put_parameter(:id, 2383326)
...>   |> Tornex.SpecQuery.put_parameter(:stat, ["attackswon", "attackslost"])
iex> Tornex.SpecQuery.uri!(query)
%URI{
  scheme: "https",
  userinfo: nil,
  host: "api.torn.com",
  port: 443,
  path: "/v2/user/2383326",
  query: "selections=personalstats,bounties&stat=attackswon,attackslost",
}

iex> query = 
...>   Tornex.SpecQuery.new()
...>   |> Tornex.SpecQuery.put_path(Torngen.Client.Path.Faction.Id.Chain)
...>   |> Tornex.SpecQuery.put_path(Torngen.Client.Path.Faction.Id.Members)
iex> Tornex.SpecQuery.uri!(query)
** (RuntimeError) Invalid fragment "{id}" in generated URI: https://api.torn.com/v2/faction/{id}/?selections=chain,members **