brawlhalla 0.1.4

An async Brawlhalla API Wrapper using tokio
Documentation
//! # brawlhalla - An async Brawlhalla API Wrapper using tokio
//! With this crate, you can now conveniently call [the official Brawlhalla API](https://dev.brawlhalla.com) from Rust!
//! At this point in time, this crate has 100% API coverage, but no additional functionality.
//!
//! # Creating an API Connector
//! To call the API, you must first create an `APIConnection`. To do so, you should use a ConnectionBuilder.
//! A typical API call would look like this:
//! ```
//! extern crate brawlhalla;
//! use brawlhalla::ConnectionBuilder;
//! #[tokio::main]
//! async fn main() -> Result<(), brawlhalla::APIError> {
//!     let conn = ConnectionBuilder::default() // Make a builder struct
//!         .with_apikey("your personal API key") // Configure your API key
//!         .build(); // Create an APIConnection from the template
//!
//!     let legends = conn.legends().await?; // Retrieves data about all legends
//!     println!("{}", legends[0].bio_aka());
//!     Ok(())
//! }
//! ```
//!
//! At this time, the API can only be called via async/tokio.
#[macro_use]
extern crate shorthand;

mod apistructs;
use apistructs::result::APIResult;
pub use apistructs::*;

macro_rules! apicall {
    ($c:expr, $s:expr,$($args:expr),*) => {
        match Ok($c
            .get(
                format!(
                    $s,
                    $($args),+,
                )
                .as_str(),
            )
            .send()
            .await?
            .json()
            .await?) {
            Ok(v) => match v {
                APIResult::Ok(r) => Ok(r),
                APIResult::Err(e) => Err(APIError::CallingError(e)),
            },
            Err(e) => Err(APIError::ReqwestError(e)),
        }
    };
}

/// Builder struct for an APIConnection.
///
/// You would use it like this:
/// ```
/// extern crate brawlhalla;
/// use brawlhalla::ConnectionBuilder;
///
/// #[tokio::main]
/// async fn main() -> Result<(), brawlhalla::APIError> {
///     let steamid: u64 = 42069;
///     ConnectionBuilder::default()
///     .with_apikey("your_apikey")
///     .build()
///     .search_by_steam_id(steamid)
///     .await?;
///     println!("{}", steamid);
///     Ok(())
/// }
/// ```
///
pub struct ConnectionBuilder<'a> {
    apikey: &'a str,
    apiurl: &'a str,
}

impl<'a> ConnectionBuilder<'a> {
    /// Configures an API Key for your builder
    pub fn with_apikey(mut self, apikey: &'a str) -> Self {
        self.apikey = apikey;
        self
    }

    /// Configures the API URL for the builder. You will probably never need this function.
    pub fn with_apiurl(mut self, apiurl: &'a str) -> Self {
        self.apiurl = apiurl;
        self
    }

    /// Builds an APIConnection struct from your builder.
    pub fn build(self) -> APIConnection {
        APIConnection::new(self.apikey, self.apiurl)
    }

    /// This constructor is probably not what you want, use `ConnectionBuilder::default()` instead.
    /// Creates a builder struct with a custom API URL. This allows you to call any API that works like [the official Brawlhalla API](https://dev.brawlhalla.com).
    pub fn new(apikey: &'a str, apiurl: &'a str) -> Self {
        Self { apikey, apiurl }
    }
}

impl<'a> Default for ConnectionBuilder<'a> {
    /// The default constructor for the builder. This is probably the constructor you want to use.
    fn default() -> Self {
        Self {
            apikey: "",
            apiurl: "https://api.brawlhalla.com",
        }
    }
}

/// The actual API handler struct which is created from a [ConnectionBuilder](struct.ConnectionBuilder.html).
///
/// This struct handles all the API calling. You can construct it with a Builder struct, which you can get
/// either from a [ConnectionBuilder](struct.ConnectionBuilder.html) or the `.builder()` method.
pub struct APIConnection {
    client: reqwest::Client,
    apikey: String,
    apiurl: String,
}

impl APIConnection {
    fn new(apikey: &str, apiurl: &str) -> Self {
        Self {
            client: reqwest::Client::new(),
            apikey: apikey.to_owned(),
            apiurl: apiurl.to_owned(),
        }
    }

    /// Returns a builder for an APIConnection. This just calls `ConnectionBuilder::default()`.
    pub fn builder<'a>() -> ConnectionBuilder<'a> {
        ConnectionBuilder::default()
    }

    /// Searches a Brawlhalla player by their steam64 id.
    pub async fn search_by_steam_id(
        &self,
        steamid: u64,
    ) -> Result<apistructs::SearchResult, APIError> {
        apicall!(
            self.client,
            "{}/search?steamid={}&api_key={}",
            &self.apiurl,
            steamid,
            &self.apikey
        )
    }

    /// Retrieves a specific page of ranked player stats. One page contains 50 entries.
    /// Warning: Indexing starts at 1 here!
    pub async fn rankings(
        &self,
        bracket: &str,
        region: &str,
        page: u64,
    ) -> Result<Vec<apistructs::rankings::Rankings>, APIError> {
        apicall!(
            self.client,
            "{}/rankings/{}/{}/{}?api_key={}",
            &self.apiurl,
            bracket,
            region,
            page,
            &self.apikey
        )
    }

    /// Searches a player by their name and returns ranked data for every possible match.
    pub async fn rankings_search(
        &self,
        bracket: &str,
        region: &str,
        name: &str,
    ) -> Result<Vec<apistructs::Rankings>, APIError> {
        apicall!(
            self.client,
            "{}/rankings/{}/{}/1?name={}&api_key={}",
            &self.apiurl,
            bracket,
            region,
            name,
            &self.apikey
        )
    }

    /// Retrieves information about the player with the specified Brawlhalla ID.
    pub async fn player_stats(&self, brawlhalla_id: u64) -> Result<apistructs::Player, APIError> {
        apicall!(
            self.client,
            "{}/player/{}/stats?api_key={}",
            &self.apiurl,
            brawlhalla_id,
            &self.apikey
        )
    }

    /// Retrieves ranked stats about the player with the specified Brawlhalla ID.
    pub async fn ranked_stats(
        &self,
        brawlhalla_id: u64,
    ) -> Result<apistructs::RankedStats, APIError> {
        apicall!(
            self.client,
            "{}/player/{}/ranked?api_key={}",
            &self.apiurl,
            brawlhalla_id,
            &self.apikey
        )
    }

    /// Retrieves clan stats about the clan with the specified clan ID.
    pub async fn claninfo(&self, clan_id: u64) -> Result<apistructs::Clan, APIError> {
        apicall!(
            self.client,
            "{}/clan/{}?api_key={}",
            &self.apiurl,
            clan_id,
            &self.apikey
        )
    }

    /// Retrieves miscellanous data about all legends, such as legend ID, bio, name etc.
    pub async fn legends(&self) -> Result<Vec<apistructs::SmallLegend>, APIError> {
        apicall!(
            self.client,
            "{}/legend/all?api_key={}",
            &self.apiurl,
            &self.apikey
        )
    }

    /// Retrieves extensive data about a single legend specified by their legend ID.
    pub async fn legendinfo(&self, legendid: u64) -> Result<apistructs::FullLegend, APIError> {
        apicall!(
            self.client,
            "{}/legend/{}?api_key={}",
            &self.apiurl,
            legendid,
            &self.apikey
        )
    }
}