mod errors;
mod models;
use std::convert::TryInto;
use std::fmt;
use std::str::FromStr;
use reqwest::{Client, Url};
use serde::de::DeserializeOwned;
use crate::data::Mode;
pub use self::errors::{Error, Result};
pub use self::models::*;
const API_BASE: &str = "https://osu.ppy.sh/api";
pub struct API {
client: Client,
api_key: String,
}
impl API {
pub async fn new(api_key: impl AsRef<str>) -> Result<Self> {
Ok(API {
client: Client::builder().build()?,
api_key: api_key.as_ref().to_owned(),
})
}
pub async fn get<T>(&self, url: impl AsRef<str>) -> Result<T>
where
T: DeserializeOwned,
{
let full_url = Url::from_str(&format!("{}{}", API_BASE, url.as_ref()))?;
let resp = self.client.get(full_url).send().await?;
let result = resp.json().await?;
Ok(result)
}
pub async fn get_user_recent(
&self,
user: impl Into<UserLookup>,
mode: Option<Mode>,
limit: Option<u32>,
) -> Result<Vec<UserScore>> {
let user = user.into();
let mode = match mode {
Some(n) => n as u32,
None => 0,
};
let uri = format!(
"/get_user_recent?k={}&u={}&m={}&limit={}",
self.api_key,
user,
mode,
limit.unwrap_or(10),
);
self.get(uri).await
}
}
pub enum UserLookup {
Id(u32),
Name(String),
}
impl fmt::Display for UserLookup {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
UserLookup::Id(n) => write!(f, "{}", n),
UserLookup::Name(s) => write!(f, "{}", s),
}
}
}
impl From<&str> for UserLookup {
fn from(s: &str) -> Self {
UserLookup::Name(s.to_owned())
}
}
impl From<u32> for UserLookup {
fn from(n: u32) -> Self {
UserLookup::Id(n)
}
}