osu: Move core library to async

This commit is contained in:
Natsu Kagami 2020-09-05 21:31:03 -04:00
parent 9e38f88e97
commit b7d398c05a
No known key found for this signature in database
GPG key ID: F17543D4B9424B94
4 changed files with 40 additions and 25 deletions

2
Cargo.lock generated
View file

@ -1960,7 +1960,7 @@ dependencies = [
"reqwest 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
"serenity 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)", "serenity 0.9.0-rc.0 (registry+https://github.com/rust-lang/crates.io-index)",
"youmubot-db 0.1.0", "youmubot-db 0.1.0",
"youmubot-prelude 0.1.0", "youmubot-prelude 0.1.0",
] ]

View file

@ -7,7 +7,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
serenity = "0.8" serenity = "0.9.0-rc.0"
chrono = "0.4.10" chrono = "0.4.10"
reqwest = "0.10.1" reqwest = "0.10.1"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }

View file

@ -8,15 +8,14 @@ mod test;
use models::*; use models::*;
use request::builders::*; use request::builders::*;
use request::*; use request::*;
use reqwest::blocking::{Client as HTTPClient, RequestBuilder, Response}; use reqwest::{Client as HTTPClient, RequestBuilder, Response};
use serenity::framework::standard::CommandError as Error; use std::convert::TryInto;
use std::{convert::TryInto, sync::Arc}; use youmubot_prelude::*;
/// Client is the client that will perform calls to the osu! api server. /// Client is the client that will perform calls to the osu! api server.
/// It's cheap to clone, so do it. #[derive(Debug)]
#[derive(Clone, Debug)]
pub struct Client { pub struct Client {
key: Arc<String>, key: String,
client: HTTPClient, client: HTTPClient,
} }
@ -34,48 +33,60 @@ impl Client {
/// Create a new client from the given API key. /// Create a new client from the given API key.
pub fn new(http_client: HTTPClient, key: String) -> Client { pub fn new(http_client: HTTPClient, key: String) -> Client {
Client { Client {
key: Arc::new(key), key,
client: http_client, client: http_client,
} }
} }
fn build_request(&self, r: RequestBuilder) -> Result<Response, Error> { async fn build_request(&self, r: RequestBuilder) -> Result<Response> {
let v = r.query(&[("k", &*self.key)]).build()?; let v = r.query(&[("k", &*self.key)]).build()?;
// dbg!(v.url()); // dbg!(v.url());
Ok(self.client.execute(v)?) Ok(self.client.execute(v).await?)
} }
pub fn beatmaps( pub async fn beatmaps(
&self, &self,
kind: BeatmapRequestKind, kind: BeatmapRequestKind,
f: impl FnOnce(&mut BeatmapRequestBuilder) -> &mut BeatmapRequestBuilder, f: impl FnOnce(&mut BeatmapRequestBuilder) -> &mut BeatmapRequestBuilder,
) -> Result<Vec<Beatmap>, Error> { ) -> Result<Vec<Beatmap>> {
let mut r = BeatmapRequestBuilder::new(kind); let mut r = BeatmapRequestBuilder::new(kind);
f(&mut r); f(&mut r);
let res: Vec<raw::Beatmap> = self.build_request(r.build(&self.client))?.json()?; let res: Vec<raw::Beatmap> = self
.build_request(r.build(&self.client))
.await?
.json()
.await?;
Ok(vec_try_into(res)?) Ok(vec_try_into(res)?)
} }
pub fn user( pub async fn user(
&self, &self,
user: UserID, user: UserID,
f: impl FnOnce(&mut UserRequestBuilder) -> &mut UserRequestBuilder, f: impl FnOnce(&mut UserRequestBuilder) -> &mut UserRequestBuilder,
) -> Result<Option<User>, Error> { ) -> Result<Option<User>, Error> {
let mut r = UserRequestBuilder::new(user); let mut r = UserRequestBuilder::new(user);
f(&mut r); f(&mut r);
let res: Vec<raw::User> = self.build_request(r.build(&self.client))?.json()?; let res: Vec<raw::User> = self
.build_request(r.build(&self.client))
.await?
.json()
.await?;
let res = vec_try_into(res)?; let res = vec_try_into(res)?;
Ok(res.into_iter().next()) Ok(res.into_iter().next())
} }
pub fn scores( pub async fn scores(
&self, &self,
beatmap_id: u64, beatmap_id: u64,
f: impl FnOnce(&mut ScoreRequestBuilder) -> &mut ScoreRequestBuilder, f: impl FnOnce(&mut ScoreRequestBuilder) -> &mut ScoreRequestBuilder,
) -> Result<Vec<Score>, Error> { ) -> Result<Vec<Score>, Error> {
let mut r = ScoreRequestBuilder::new(beatmap_id); let mut r = ScoreRequestBuilder::new(beatmap_id);
f(&mut r); f(&mut r);
let res: Vec<raw::Score> = self.build_request(r.build(&self.client))?.json()?; let res: Vec<raw::Score> = self
.build_request(r.build(&self.client))
.await?
.json()
.await?;
let mut res: Vec<Score> = vec_try_into(res)?; let mut res: Vec<Score> = vec_try_into(res)?;
// with a scores request you need to fill the beatmap ids yourself // with a scores request you need to fill the beatmap ids yourself
@ -85,23 +96,23 @@ impl Client {
Ok(res) Ok(res)
} }
pub fn user_best( pub async fn user_best(
&self, &self,
user: UserID, user: UserID,
f: impl FnOnce(&mut UserScoreRequestBuilder) -> &mut UserScoreRequestBuilder, f: impl FnOnce(&mut UserScoreRequestBuilder) -> &mut UserScoreRequestBuilder,
) -> Result<Vec<Score>, Error> { ) -> Result<Vec<Score>, Error> {
self.user_scores(UserScoreType::Best, user, f) self.user_scores(UserScoreType::Best, user, f).await
} }
pub fn user_recent( pub async fn user_recent(
&self, &self,
user: UserID, user: UserID,
f: impl FnOnce(&mut UserScoreRequestBuilder) -> &mut UserScoreRequestBuilder, f: impl FnOnce(&mut UserScoreRequestBuilder) -> &mut UserScoreRequestBuilder,
) -> Result<Vec<Score>, Error> { ) -> Result<Vec<Score>, Error> {
self.user_scores(UserScoreType::Recent, user, f) self.user_scores(UserScoreType::Recent, user, f).await
} }
fn user_scores( async fn user_scores(
&self, &self,
u: UserScoreType, u: UserScoreType,
user: UserID, user: UserID,
@ -109,7 +120,11 @@ impl Client {
) -> Result<Vec<Score>, Error> { ) -> Result<Vec<Score>, Error> {
let mut r = UserScoreRequestBuilder::new(u, user); let mut r = UserScoreRequestBuilder::new(u, user);
f(&mut r); f(&mut r);
let res: Vec<raw::Score> = self.build_request(r.build(&self.client))?.json()?; let res: Vec<raw::Score> = self
.build_request(r.build(&self.client))
.await?
.json()
.await?;
let res = vec_try_into(res)?; let res = vec_try_into(res)?;
Ok(res) Ok(res)
} }

View file

@ -1,6 +1,6 @@
use crate::models::{Mode, Mods}; use crate::models::{Mode, Mods};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use reqwest::blocking::{Client, RequestBuilder}; use reqwest::{Client, RequestBuilder};
trait ToQuery { trait ToQuery {
fn to_query(&self) -> Vec<(&'static str, String)>; fn to_query(&self) -> Vec<(&'static str, String)>;