osu_v2/src/client.rs

102 lines
2.8 KiB
Rust

use super::user::*;
use super::Error;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct Client {
client_id: String,
client_secret: String,
client_token: String,
base_url: String,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct AccessToken {
token_type: String,
expires_in: u64,
access_token: String,
}
impl<'a> Client {
pub async fn new<CI: Into<String>, CS: Into<String>>(
client_id: CI,
client_secret: CS,
) -> Result<self::Client, Error> {
let mut client = Client {
client_id: client_id.into(),
client_secret: client_secret.into(),
base_url: "https://osu.ppy.sh/api/v2".to_string(),
client_token: "".to_string(),
};
client.refresh_token().await.unwrap();
Ok(client)
}
async fn get<T>(&mut self, url: String, params: T) -> Result<reqwest::Response, Error>
where
T: Into<Option<&'a[(&'a str, &'a str)]>>
{
let cli = reqwest::Client::new();
let parms = params.into();
let resp = match cli.get(&format!("{}{}", &self.base_url, &url).to_string())
.bearer_auth(&self.client_token).query(&parms).send().await {
Ok(v) => {
if v.status().is_client_error() {
self.refresh_token().await.unwrap();
cli.get(&format!("{}{}", &self.base_url, &url).to_string())
.bearer_auth(&self.client_token).query(&parms).send().await.unwrap()
} else {
v
}
},
Err(why) => {return Err(Error::NotAuthenticated(why.to_string()))},
};
Ok(resp)
}
async fn refresh_token(&mut self) -> Result<(), Error> {
let client = reqwest::Client::new();
let mut data = HashMap::new();
data.insert("client_id", self.client_id.clone());
data.insert("client_secret", self.client_secret.clone());
data.insert("grant_type", "client_credentials".to_string());
data.insert("scope", "public".to_string());
let token = match client
.post("https://osu.ppy.sh/oauth/token")
.json(&data)
.send()
.await
{
Ok(a) => a,
Err(why) => return Err(Error::NotAuthenticated(why.to_string())),
}
.json::<AccessToken>()
.await.unwrap();
self.client_token = token.access_token;
Ok(())
}
}
#[async_trait]
impl UserMethods for Client {
async fn get_user<'a>(&'a mut self, id: u64, m: String) -> Result<Box<User>, Error> {
let resp = self
.get(format!("/users/{}/{}", id, m), None)
.await
.unwrap();
let user = resp.json::<User>().await.unwrap();
Ok(Box::new(user))
//Ok(())
}
async fn search_user<'a>(&'a mut self, name: String) -> Result<Box<SearchResult>, Error> {
let paras = [("mode", "user"), ("query", &name)];
let resp = self
.get("/search".to_string(), &paras[..])
.await
.unwrap();
let users = resp.json::<SearchResult>().await.unwrap();
Ok(Box::new(users))
}
}
//fn get()