poe-ninja 0.1.1

API wrapper for https://poe.ninja/
Documentation
//! An opinionated API wrapper around <https://poe.ninja>, specifically focused on the economy dataset.
//!
//! # Example
//! ```
//! use poe_ninja::*;
//!
//! #[tokio::main]
//! async fn main() {
//!		let client = Client::new("Scourge").unwrap();
//!		let currencies = client.get_currencies().await.unwrap();
//!     let mirror_shard = currencies.into_iter().find(|c| c.name == "Mirror Shard").unwrap();
//!     println!("Mirror Shard value is {} chaos", mirror_shard.chaos_equivalent);
//! }
//! ```

#![allow(clippy::tabs_in_doc_comments)]
use serde::Deserialize;
use reqwest::Error;

mod model;
pub use model::*;

/// The entrypoint for the library; construct a `Client`, then issue queries through it.
///
/// Constructed with [Client::new], which accepts a league as input, e.g. `Client::new("Scourge")`
///
/// Methods are all named for the left-side navigation items on <https://poe.ninja/challenge/currency>
#[derive(Clone)]
pub struct Client {
	http: reqwest::Client,
	base_url: String,
	league: String
}

impl Client {
	pub fn new(league: impl AsRef<str>) -> Result<Self, Error> {
		Ok(Self{
			http: reqwest::Client::builder()
				.gzip(true)
				.build()?,
			base_url: "https://poe.ninja/api".to_string(),
			league: league.as_ref().to_string()
		})
	}

	async fn get<T: for<'de> Deserialize<'de>>(&self, path: &str) -> Result<T, Error> {
		let url = format!("{}/{}", self.base_url, path);
		Ok(self.http.get(&url).send().await?.error_for_status()?.json().await?)
	}

	async fn get_currency_overview(&self, ctype: &str) -> Result<CurrencyResponse, Error> {
		let path = format!("data/CurrencyOverview?league={}&type={}&language=en", self.league, ctype);
		self.get(&path).await
	}

	async fn get_item_overview(&self, itype: &str) -> Result<ItemResponse, Error> {
		let path = format!("data/ItemOverview?league={}&type={}&language=en", self.league, itype);
		self.get(&path).await
	}

	// General {{{
	pub async fn get_currencies(&self) -> Result<Vec<Currency>, Error> {
		Ok(self.get_currency_overview("Currency").await?.lines)
	}

	pub async fn get_fragments(&self) -> Result<Vec<Currency>, Error> {
		Ok(self.get_currency_overview("Fragment").await?.lines)
	}

	pub async fn get_divination_cards(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("DivinationCard").await?.lines)
	}

	pub async fn get_artifacts(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("Artifact").await?.lines)
	}

	pub async fn get_prophecies(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("Prophecy").await?.lines)
	}

	pub async fn get_oils(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("Oil").await?.lines)
	}

	pub async fn get_incubators(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("Incubator").await?.lines)
	}
	// }}}

	// Equipment & Gems {{{
	pub async fn get_unique_weapons(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("UniqueWeapon").await?.lines)
	}

	pub async fn get_unique_armors(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("UniqueArmour").await?.lines)
	}

	pub async fn get_unique_accessories(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("UniqueAccessory").await?.lines)
	}

	pub async fn get_unique_flasks(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("UniqueFlask").await?.lines)
	}

	pub async fn get_unique_jewels(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("UniqueJewel").await?.lines)
	}

	pub async fn get_skill_gems(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("SkillGem").await?.lines)
	}

	pub async fn get_cluster_jewels(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("ClusterJewel").await?.lines)
	}
	// }}}

	// Atlas {{{
	pub async fn get_maps(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("Map").await?.lines)
	}

	pub async fn get_blighted_maps(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("BlightedMap").await?.lines)
	}

	pub async fn get_unique_maps(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("UniqueMap").await?.lines)
	}

	pub async fn get_delirium_orbs(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("DeliriumOrb").await?.lines)
	}

	pub async fn get_invitations(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("Invitation").await?.lines)
	}

	pub async fn get_scarabs(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("Scarab").await?.lines)
	}

	pub async fn get_watchstones(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("Watchstone").await?.lines)
	}
	// }}}

	// Crafting {{{
	pub async fn get_base_types(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("BaseType").await?.lines)
	}

	pub async fn get_fossils(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("Fossil").await?.lines)
	}

	pub async fn get_resonators(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("Resonator").await?.lines)
	}

	pub async fn get_helmet_enchants(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("HelmetEnchant").await?.lines)
	}

	pub async fn get_beasts(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("Beast").await?.lines)
	}

	pub async fn get_essences(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("Essence").await?.lines)
	}

	pub async fn get_vials(&self) -> Result<Vec<Item>, Error> {
		Ok(self.get_item_overview("Vial").await?.lines)
	}
	// }}}
}

#[cfg(test)]
mod test;