mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-18 16:28:55 +00:00
Implement score request
This commit is contained in:
parent
3e951554d7
commit
f1742664c4
5 changed files with 117 additions and 12 deletions
|
@ -24,6 +24,16 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
fn build_request(
|
||||
&self,
|
||||
c: &HTTPClient,
|
||||
r: reqwest::RequestBuilder,
|
||||
) -> Result<reqwest::Response, Error> {
|
||||
let v = r.query(&[("k", &self.key)]).build()?;
|
||||
// println!("{}", v.url());
|
||||
Ok(c.execute(v)?)
|
||||
}
|
||||
|
||||
pub fn beatmaps(
|
||||
&self,
|
||||
client: &HTTPClient,
|
||||
|
@ -32,7 +42,7 @@ impl Client {
|
|||
) -> Result<Vec<Beatmap>, Error> {
|
||||
let mut r = BeatmapRequestBuilder::new(kind);
|
||||
f(&mut r);
|
||||
let res = r.build(client).query(&[("k", &self.key)]).send()?.json()?;
|
||||
let res = self.build_request(client, r.build(client))?.json()?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
|
@ -44,7 +54,7 @@ impl Client {
|
|||
) -> Result<Option<User>, Error> {
|
||||
let mut r = UserRequestBuilder::new(user);
|
||||
f(&mut r);
|
||||
let res: Vec<_> = r.build(client).query(&[("k", &self.key)]).send()?.json()?;
|
||||
let res: Vec<_> = self.build_request(client, r.build(client))?.json()?;
|
||||
Ok(res.into_iter().next())
|
||||
}
|
||||
|
||||
|
@ -56,7 +66,43 @@ impl Client {
|
|||
) -> Result<Vec<Score>, Error> {
|
||||
let mut r = ScoreRequestBuilder::new(beatmap_id);
|
||||
f(&mut r);
|
||||
let res = r.build(client).query(&[("k", &self.key)]).send()?.json()?;
|
||||
let mut res: Vec<Score> = self.build_request(client, r.build(client))?.json()?;
|
||||
|
||||
// with a scores request you need to fill the beatmap ids yourself
|
||||
res.iter_mut().for_each(|v| {
|
||||
v.beatmap_id = beatmap_id;
|
||||
});
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn user_best(
|
||||
&self,
|
||||
client: &HTTPClient,
|
||||
user: UserID,
|
||||
f: impl FnOnce(&mut UserScoreRequestBuilder) -> &mut UserScoreRequestBuilder,
|
||||
) -> Result<Vec<Score>, Error> {
|
||||
self.user_scores(UserScoreType::Best, client, user, f)
|
||||
}
|
||||
|
||||
pub fn user_recent(
|
||||
&self,
|
||||
client: &HTTPClient,
|
||||
user: UserID,
|
||||
f: impl FnOnce(&mut UserScoreRequestBuilder) -> &mut UserScoreRequestBuilder,
|
||||
) -> Result<Vec<Score>, Error> {
|
||||
self.user_scores(UserScoreType::Recent, client, user, f)
|
||||
}
|
||||
|
||||
fn user_scores(
|
||||
&self,
|
||||
u: UserScoreType,
|
||||
client: &HTTPClient,
|
||||
user: UserID,
|
||||
f: impl FnOnce(&mut UserScoreRequestBuilder) -> &mut UserScoreRequestBuilder,
|
||||
) -> Result<Vec<Score>, Error> {
|
||||
let mut r = UserScoreRequestBuilder::new(u, user);
|
||||
f(&mut r);
|
||||
let res = self.build_request(client, r.build(client))?.json()?;
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,15 +13,18 @@ impl<'de> Deserialize<'de> for Score {
|
|||
{
|
||||
let raw: raw::Score = raw::Score::deserialize(deserializer)?;
|
||||
Ok(Score {
|
||||
id: parse_from_str(&raw.score_id)?,
|
||||
username: raw.username,
|
||||
id: raw.score_id.map(parse_from_str).transpose()?,
|
||||
user_id: parse_from_str(&raw.user_id)?,
|
||||
date: parse_date(&raw.date)?,
|
||||
beatmap_id: raw.beatmap_id.map(parse_from_str).transpose()?.unwrap_or(0),
|
||||
replay_available: parse_bool(&raw.replay_available)?,
|
||||
score: parse_from_str(&raw.score)?,
|
||||
pp: parse_from_str(&raw.pp)?,
|
||||
rank: parse_from_str(&raw.rank)?,
|
||||
mods: parse_from_str(&raw.enabled_mods)?,
|
||||
mods: {
|
||||
let v: u64 = parse_from_str(&raw.enabled_mods)?;
|
||||
Mods::from_bits(v).unwrap_or(Mods::NOMOD)
|
||||
},
|
||||
count_300: parse_from_str(&raw.count300)?,
|
||||
count_100: parse_from_str(&raw.count100)?,
|
||||
count_50: parse_from_str(&raw.count50)?,
|
||||
|
|
|
@ -149,6 +149,18 @@ pub struct Beatmap {
|
|||
pub pass_count: u64,
|
||||
}
|
||||
|
||||
const NEW_MODE_NAMES: [&'static str; 4] = ["osu", "taiko", "fruits", "mania"];
|
||||
|
||||
impl Beatmap {
|
||||
/// Gets a link pointing to the beatmap, in the new format.
|
||||
pub fn link(&self) -> String {
|
||||
format!(
|
||||
"https://osu.ppy.sh/beatmapsets/{}#{}/{}",
|
||||
self.beatmapset_id, NEW_MODE_NAMES[self.mode as usize], self.beatmap_id
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UserEvent {
|
||||
pub display_html: String,
|
||||
|
@ -203,8 +215,8 @@ impl std::str::FromStr for Rank {
|
|||
type Err = String;
|
||||
fn from_str(a: &str) -> Result<Self, Self::Err> {
|
||||
Ok(match &a.to_uppercase()[..] {
|
||||
"SS" => Rank::SS,
|
||||
"SSH" => Rank::SSH,
|
||||
"SS" | "X" => Rank::SS,
|
||||
"SSH" | "XH" => Rank::SSH,
|
||||
"S" => Rank::S,
|
||||
"SH" => Rank::SH,
|
||||
"A" => Rank::A,
|
||||
|
@ -225,11 +237,11 @@ impl fmt::Display for Rank {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Score {
|
||||
pub id: u64,
|
||||
pub username: String,
|
||||
pub id: Option<u64>, // No id if you fail
|
||||
pub user_id: u64,
|
||||
pub date: DateTime<Utc>,
|
||||
pub replay_available: bool,
|
||||
pub beatmap_id: u64,
|
||||
|
||||
pub score: u64,
|
||||
pub pp: f64,
|
||||
|
|
|
@ -78,9 +78,9 @@ pub(crate) struct UserEvent {
|
|||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub(crate) struct Score {
|
||||
pub score_id: String,
|
||||
pub score_id: Option<String>,
|
||||
pub beatmap_id: Option<String>,
|
||||
pub score: String,
|
||||
pub username: String,
|
||||
pub count300: String,
|
||||
pub count100: String,
|
||||
pub count50: String,
|
||||
|
|
|
@ -207,6 +207,50 @@ pub mod builders {
|
|||
.query(&self.limit.map(|v| ("limit", v.to_string())).to_query())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum UserScoreType {
|
||||
Recent,
|
||||
Best,
|
||||
}
|
||||
|
||||
pub struct UserScoreRequestBuilder {
|
||||
score_type: UserScoreType,
|
||||
user: UserID,
|
||||
mode: Option<Mode>,
|
||||
limit: Option<u8>,
|
||||
}
|
||||
|
||||
impl UserScoreRequestBuilder {
|
||||
pub(crate) fn new(score_type: UserScoreType, user: UserID) -> Self {
|
||||
UserScoreRequestBuilder {
|
||||
score_type,
|
||||
user,
|
||||
mode: None,
|
||||
limit: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mode(&mut self, m: Mode) -> &mut Self {
|
||||
self.mode = Some(m);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn limit(&mut self, limit: u8) -> &mut Self {
|
||||
self.limit = Some(limit).filter(|&v| v <= 100).or(self.limit);
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn build(&self, client: &Client) -> RequestBuilder {
|
||||
client
|
||||
.get(match self.score_type {
|
||||
UserScoreType::Best => "https://osu.ppy.sh/api/get_user_best",
|
||||
UserScoreType::Recent => "https://osu.ppy.sh/api/get_user_recent"
|
||||
})
|
||||
.query(&self.user.to_query())
|
||||
.query(&self.mode.to_query())
|
||||
.query(&self.limit.map(|v| ("limit", v.to_string())).to_query())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UserBestRequest {
|
||||
|
|
Loading…
Add table
Reference in a new issue