102 lines
2.8 KiB
Rust
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(), ¶s[..])
|
|
.await
|
|
.unwrap();
|
|
let users = resp.json::<SearchResult>().await.unwrap();
|
|
Ok(Box::new(users))
|
|
}
|
|
}
|
|
|
|
//fn get()
|