use crate::error::Result;
use crate::v2::client::gloo::check::check_res;
use crate::v2::interface::beatmaps::IBeatmaps;
use crate::v2::model::beatmap::structs::beatmap::Beatmap;
use crate::v2::model::beatmap::structs::beatmaps::Beatmaps;
use crate::v2::model::beatmap::structs::difficulty_attributes::Attributes;
use crate::v2::model::beatmap::structs::pack::BeatmapPack;
use crate::v2::model::beatmap::structs::packs::BeatmapPacks;
use crate::v2::model::mode::enums::mode::Mode;
use crate::v2::model::oauth::structs::o_token::OToken;
use crate::v2::model::score::structs::beatmap_scores::BeatmapScores;
use crate::v2::model::score::structs::beatmap_user_score::BeatmapUserScore;
use crate::v2::model::score::structs::non_legacy_scores::NonLegacyScores;
use crate::v2::model::score::structs::scores::Scores;
use gloo_net::http::Request;
use std::sync::{Arc, Mutex};
use wasm_bindgen::JsValue;
use web_sys::console;
#[derive(Clone, Default)]
pub struct GlooBeatmaps {
pub o_token: Arc<Mutex<OToken>>,
pub proxy_url: Arc<Mutex<String>>,
}
impl IBeatmaps for GlooBeatmaps {
async fn get_beatmap_packs(
&self,
pack_type: Option<String>,
cursor_string: Option<String>,
) -> Result<BeatmapPacks> {
console::log_1(&JsValue::from_str("GlooBeatmaps get_beatmap_packs"));
let access_token = {
let token = self.o_token.lock().unwrap();
token.access_token.clone()
};
let proxy_url = {
let url = self.proxy_url.lock().unwrap();
url.clone()
};
let mut query_params = Vec::new();
if let Some(pack_type) = pack_type {
query_params.push(("type", pack_type));
}
if let Some(cursor) = cursor_string {
query_params.push(("cursor", cursor));
}
let query_string = serde_urlencoded::to_string(&query_params)?;
let url = if query_string.is_empty() {
format!("{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/packs")
} else {
format!("{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/packs?{query_string}")
};
let res = Request::get(&url)
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", &format!("Bearer {access_token}"))
.send()
.await?;
let response = check_res(res)?;
let beatmap_packs: BeatmapPacks = response.json().await?;
Ok(beatmap_packs)
}
async fn get_beatmap_pack(
&self,
pack: String,
legacy_only: Option<u32>,
) -> Result<BeatmapPack> {
console::log_1(&JsValue::from_str("GlooBeatmaps get_beatmap_pack"));
let access_token = {
let token = self.o_token.lock().unwrap();
token.access_token.clone()
};
let proxy_url = {
let url = self.proxy_url.lock().unwrap();
url.clone()
};
let mut query_params = Vec::new();
if let Some(legacy) = legacy_only {
query_params.push(("legacy_only", legacy.to_string()));
}
let query_string = serde_urlencoded::to_string(&query_params)?;
let url = if query_string.is_empty() {
format!("{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/packs/{pack}")
} else {
format!("{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/packs/{pack}?{query_string}")
};
let res = Request::get(&url)
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", &format!("Bearer {access_token}"))
.send()
.await?;
let response = check_res(res)?;
let beatmap_pack: BeatmapPack = response.json().await?;
Ok(beatmap_pack)
}
async fn lookup(
&self,
checksum: Option<String>,
filename: Option<String>,
id: Option<String>,
) -> Result<Beatmap> {
console::log_1(&JsValue::from_str("GlooBeatmaps lookup"));
let access_token = {
let token = self.o_token.lock().unwrap();
token.access_token.clone()
};
let proxy_url = {
let url = self.proxy_url.lock().unwrap();
url.clone()
};
let mut query_params = Vec::new();
if let Some(checksum) = checksum {
query_params.push(("checksum", checksum));
}
if let Some(filename) = filename {
query_params.push(("filename", filename));
}
if let Some(id) = id {
query_params.push(("id", id));
}
let query_string = serde_urlencoded::to_string(&query_params)?;
let url = if query_string.is_empty() {
format!("{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/lookup")
} else {
format!("{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/lookup?{query_string}")
};
let res = Request::get(&url)
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", &format!("Bearer {access_token}"))
.send()
.await?;
let response = check_res(res)?;
let beatmap: Beatmap = response.json().await?;
Ok(beatmap)
}
async fn get_user_score(
&self,
beatmap_id: u32,
user_id: u32,
legacy_only: Option<u32>,
mode: Option<Mode>,
mods: Option<String>,
) -> Result<BeatmapUserScore> {
console::log_1(&JsValue::from_str("GlooBeatmaps get_user_score"));
let access_token = {
let token = self.o_token.lock().unwrap();
token.access_token.clone()
};
let proxy_url = {
let url = self.proxy_url.lock().unwrap();
url.clone()
};
let mut query_params = Vec::new();
if let Some(legacy) = legacy_only {
query_params.push(("legacy_only", legacy.to_string()));
}
if let Some(mode) = mode {
query_params.push(("mode", mode.to_ruleset()));
}
if let Some(mods) = mods {
query_params.push(("mods", mods));
}
let query_string = serde_urlencoded::to_string(&query_params)?;
let url = if query_string.is_empty() {
format!(
"{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/{beatmap_id}/scores/users/{user_id}"
)
} else {
format!(
"{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/{beatmap_id}/scores/users/{user_id}?{query_string}"
)
};
let res = Request::get(&url)
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", &format!("Bearer {access_token}"))
.send()
.await?;
let response = check_res(res)?;
let beatmap_user_score: BeatmapUserScore = response.json().await?;
Ok(beatmap_user_score)
}
async fn get_user_scores(
&self,
beatmap_id: u32,
user_id: u32,
legacy_only: Option<u32>,
mode: Option<Mode>,
ruleset: Option<Mode>,
) -> Result<Scores> {
console::log_1(&JsValue::from_str("GlooBeatmaps get_user_scores"));
let access_token = {
let token = self.o_token.lock().unwrap();
token.access_token.clone()
};
let proxy_url = {
let url = self.proxy_url.lock().unwrap();
url.clone()
};
let mut query_params = Vec::new();
if let Some(legacy) = legacy_only {
query_params.push(("legacy_only", legacy.to_string()));
}
if let Some(mode) = mode {
query_params.push(("mode", mode.to_ruleset()));
}
if let Some(ruleset) = ruleset {
query_params.push(("ruleset", ruleset.to_string()));
}
let query_string = serde_urlencoded::to_string(&query_params)?;
let url = if query_string.is_empty() {
format!(
"{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/{beatmap_id}/scores/users/{user_id}/all"
)
} else {
format!(
"{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/{beatmap_id}/scores/users/{user_id}/all?{query_string}"
)
};
let res = Request::get(&url)
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", &format!("Bearer {access_token}"))
.send()
.await?;
let response = check_res(res)?;
let scores: Scores = response.json().await?;
Ok(scores)
}
async fn get_scores(
&self,
beatmap_id: u32,
legacy_only: Option<u32>,
mode: Option<Mode>,
mods: Option<String>,
ranking_type: Option<String>,
) -> Result<BeatmapScores> {
console::log_1(&JsValue::from_str("GlooBeatmaps get_scores"));
let access_token = {
let token = self.o_token.lock().unwrap();
token.access_token.clone()
};
let proxy_url = {
let url = self.proxy_url.lock().unwrap();
url.clone()
};
let mut query_params = Vec::new();
if let Some(legacy) = legacy_only {
query_params.push(("legacy_only", legacy.to_string()));
}
if let Some(mode) = mode {
query_params.push(("mode", mode.to_ruleset()));
}
if let Some(mods) = mods {
query_params.push(("mods", mods));
}
if let Some(ranking_type) = ranking_type {
query_params.push(("type", ranking_type));
}
let query_string = serde_urlencoded::to_string(&query_params)?;
let url = if query_string.is_empty() {
format!("{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/{beatmap_id}/scores")
} else {
format!(
"{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/{beatmap_id}/scores?{query_string}"
)
};
let res = Request::get(&url)
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", &format!("Bearer {access_token}"))
.send()
.await?;
let response = check_res(res)?;
let beatmap_scores: BeatmapScores = response.json().await?;
Ok(beatmap_scores)
}
async fn get_solo_scores(
&self,
beatmap_id: u32,
mode: Option<Mode>,
mods: Option<String>,
ranking_type: Option<String>,
) -> Result<NonLegacyScores> {
console::log_1(&JsValue::from_str("GlooBeatmaps get_solo_scores"));
let access_token = {
let token = self.o_token.lock().unwrap();
token.access_token.clone()
};
let proxy_url = {
let url = self.proxy_url.lock().unwrap();
url.clone()
};
let mut query_params = Vec::new();
if let Some(mode) = mode {
query_params.push(("mode", mode.to_ruleset()));
}
if let Some(mods) = mods {
query_params.push(("mods", mods));
}
if let Some(ranking_type) = ranking_type {
query_params.push(("type", ranking_type));
}
let query_string = serde_urlencoded::to_string(&query_params)?;
let url = if query_string.is_empty() {
format!("{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/{beatmap_id}/solo-scores")
} else {
format!(
"{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/{beatmap_id}/solo-scores?{query_string}"
)
};
let res = Request::get(&url)
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", &format!("Bearer {access_token}"))
.send()
.await?;
let response = check_res(res)?;
let non_legacy_scores: NonLegacyScores = response.json().await?;
Ok(non_legacy_scores)
}
async fn get_beatmaps(&self, beatmap_ids: Vec<u32>) -> Result<Beatmaps> {
console::log_1(&JsValue::from_str("GlooBeatmaps get_beatmaps"));
let access_token = {
let token = self.o_token.lock().unwrap();
token.access_token.clone()
};
let proxy_url = {
let url = self.proxy_url.lock().unwrap();
url.clone()
};
let ids_string = beatmap_ids
.iter()
.map(|id| id.to_string())
.collect::<Vec<_>>()
.join(",");
let query_params = vec![("ids", ids_string)];
let query_string = serde_urlencoded::to_string(&query_params)?;
let url = format!("{proxy_url}https://osu.ppy.sh/api/v2/beatmaps?{query_string}");
let res = Request::get(&url)
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", &format!("Bearer {access_token}"))
.send()
.await?;
let response = check_res(res)?;
let beatmaps: Beatmaps = response.json().await?;
Ok(beatmaps)
}
async fn get_beatmap(&self, beatmap_id: u32) -> Result<Beatmap> {
console::log_1(&JsValue::from_str("GlooBeatmaps get_beatmap"));
let access_token = {
let token = self.o_token.lock().unwrap();
token.access_token.clone()
};
let proxy_url = {
let url = self.proxy_url.lock().unwrap();
url.clone()
};
let url = format!("{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/{beatmap_id}");
let res = Request::get(&url)
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", &format!("Bearer {access_token}"))
.send()
.await?;
let response = check_res(res)?;
let beatmap: Beatmap = response.json().await?;
Ok(beatmap)
}
async fn get_beatmap_attributes(
&self,
beatmap_id: u32,
mods: Option<Vec<String>>,
ruleset: Option<Mode>,
ruleset_id: Option<i32>,
) -> Result<Attributes> {
console::log_1(&JsValue::from_str("GlooBeatmaps get_beatmap_attributes"));
let access_token = {
let token = self.o_token.lock().unwrap();
token.access_token.clone()
};
let proxy_url = {
let url = self.proxy_url.lock().unwrap();
url.clone()
};
let mut query_params = Vec::new();
if let Some(mods) = mods {
for mod_name in mods {
query_params.push(("mods[]", mod_name));
}
}
if let Some(ruleset) = ruleset {
query_params.push(("ruleset", ruleset.to_string()));
}
if let Some(ruleset_id) = ruleset_id {
query_params.push(("ruleset_id", ruleset_id.to_string()));
}
let query_string = serde_urlencoded::to_string(&query_params)?;
let url = if query_string.is_empty() {
format!("{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/{beatmap_id}/attributes")
} else {
format!(
"{proxy_url}https://osu.ppy.sh/api/v2/beatmaps/{beatmap_id}/attributes?{query_string}"
)
};
let res = Request::post(&url)
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Authorization", &format!("Bearer {access_token}"))
.send()
.await?;
let response = check_res(res)?;
let attributes: Attributes = response.json().await?;
Ok(attributes)
}
}