mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-19 16:58:55 +00:00
Add library for user requests
This commit is contained in:
parent
0da274ca6f
commit
c6ec62f33b
5 changed files with 141 additions and 1 deletions
|
@ -35,4 +35,16 @@ impl Client {
|
||||||
let res = r.build(client).query(&[("k", &self.key)]).send()?.json()?;
|
let res = r.build(client).query(&[("k", &self.key)]).send()?.json()?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn user(
|
||||||
|
&self,
|
||||||
|
client: &HTTPClient,
|
||||||
|
user: UserID,
|
||||||
|
f: impl FnOnce(&mut UserRequestBuilder) -> &mut UserRequestBuilder,
|
||||||
|
) -> 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()?;
|
||||||
|
Ok(res.into_iter().next())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,44 @@ use chrono::{
|
||||||
use serde::{de, Deserialize, Deserializer};
|
use serde::{de, Deserialize, Deserializer};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for User {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let raw: raw::User = raw::User::deserialize(deserializer)?;
|
||||||
|
Ok(User {
|
||||||
|
id: parse_from_str(&raw.user_id)?,
|
||||||
|
username: raw.username,
|
||||||
|
joined: parse_date(&raw.join_date)?,
|
||||||
|
country: raw.country,
|
||||||
|
count_300: parse_from_str(&raw.count300)?,
|
||||||
|
count_100: parse_from_str(&raw.count100)?,
|
||||||
|
count_50: parse_from_str(&raw.count50)?,
|
||||||
|
play_count: parse_from_str(&raw.playcount)?,
|
||||||
|
played_time: parse_duration(&raw.total_seconds_played)?,
|
||||||
|
ranked_score: parse_from_str(&raw.ranked_score)?,
|
||||||
|
total_score: parse_from_str(&raw.total_score)?,
|
||||||
|
count_ss: parse_from_str(&raw.count_rank_ss)?,
|
||||||
|
count_ssh: parse_from_str(&raw.count_rank_ssh)?,
|
||||||
|
count_s: parse_from_str(&raw.count_rank_s)?,
|
||||||
|
count_sh: parse_from_str(&raw.count_rank_sh)?,
|
||||||
|
count_a: parse_from_str(&raw.count_rank_a)?,
|
||||||
|
rank: parse_from_str(&raw.pp_rank)?,
|
||||||
|
level: parse_from_str(&raw.level)?,
|
||||||
|
pp: Some(parse_from_str(&raw.pp_raw)?).filter(|v| *v != 0.0),
|
||||||
|
accuracy: parse_from_str(&raw.accuracy)?,
|
||||||
|
events: {
|
||||||
|
let mut v = Vec::new();
|
||||||
|
for e in raw.events.into_iter() {
|
||||||
|
v.push(parse_user_event(e)?);
|
||||||
|
}
|
||||||
|
v
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for Beatmap {
|
impl<'de> Deserialize<'de> for Beatmap {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
|
@ -55,6 +93,16 @@ impl<'de> Deserialize<'de> for Beatmap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_user_event<E: de::Error>(s: raw::UserEvent) -> Result<UserEvent, E> {
|
||||||
|
Ok(UserEvent {
|
||||||
|
display_html: s.display_html,
|
||||||
|
beatmap_id: parse_from_str(&s.beatmap_id)?,
|
||||||
|
beatmapset_id: parse_from_str(&s.beatmapset_id)?,
|
||||||
|
date: parse_date(&s.date)?,
|
||||||
|
epic_factor: parse_from_str(&s.epicfactor)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_mode<E: de::Error>(s: impl AsRef<str>) -> Result<Mode, E> {
|
fn parse_mode<E: de::Error>(s: impl AsRef<str>) -> Result<Mode, E> {
|
||||||
let t: u8 = parse_from_str(s)?;
|
let t: u8 = parse_from_str(s)?;
|
||||||
use Mode::*;
|
use Mode::*;
|
||||||
|
|
|
@ -176,7 +176,7 @@ pub struct User {
|
||||||
// Rankings
|
// Rankings
|
||||||
pub rank: u64,
|
pub rank: u64,
|
||||||
pub level: f64,
|
pub level: f64,
|
||||||
pub pp: Option<u64>,
|
pub pp: Option<f64>,
|
||||||
pub accuracy: f64,
|
pub accuracy: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,3 +40,38 @@ pub(crate) struct Beatmap {
|
||||||
pub download_unavailable: String,
|
pub download_unavailable: String,
|
||||||
pub audio_unavailable: String,
|
pub audio_unavailable: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub(crate) struct User {
|
||||||
|
pub user_id: String,
|
||||||
|
pub username: String,
|
||||||
|
pub join_date: String,
|
||||||
|
pub count300: String,
|
||||||
|
pub count100: String,
|
||||||
|
pub count50: String,
|
||||||
|
pub playcount: String,
|
||||||
|
pub ranked_score: String,
|
||||||
|
pub total_score: String,
|
||||||
|
pub pp_rank: String,
|
||||||
|
pub level: String,
|
||||||
|
pub pp_raw: String,
|
||||||
|
pub accuracy: String,
|
||||||
|
pub count_rank_ss: String,
|
||||||
|
pub count_rank_ssh: String,
|
||||||
|
pub count_rank_s: String,
|
||||||
|
pub count_rank_sh: String,
|
||||||
|
pub count_rank_a: String,
|
||||||
|
pub country: String,
|
||||||
|
pub total_seconds_played: String,
|
||||||
|
pub pp_country_rank: String,
|
||||||
|
pub events: Vec<UserEvent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub(crate) struct UserEvent {
|
||||||
|
pub display_html: String,
|
||||||
|
pub beatmap_id: String,
|
||||||
|
pub beatmapset_id: String,
|
||||||
|
pub date: String,
|
||||||
|
pub epicfactor: String,
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,12 @@ impl<T: ToQuery> ToQuery for Option<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToQuery for Mode {
|
||||||
|
fn to_query(&self) -> Vec<(&'static str, String)> {
|
||||||
|
vec![("m", (*self as u8).to_string())]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ToQuery for (Mode, bool) {
|
impl ToQuery for (Mode, bool) {
|
||||||
fn to_query(&self) -> Vec<(&'static str, String)> {
|
fn to_query(&self) -> Vec<(&'static str, String)> {
|
||||||
vec![
|
vec![
|
||||||
|
@ -106,6 +112,45 @@ pub mod builders {
|
||||||
.query(&self.mode.to_query())
|
.query(&self.mode.to_query())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct UserRequestBuilder {
|
||||||
|
user: UserID,
|
||||||
|
mode: Option<Mode>,
|
||||||
|
event_days: Option<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UserRequestBuilder {
|
||||||
|
pub(crate) fn new(user: UserID) -> Self {
|
||||||
|
UserRequestBuilder {
|
||||||
|
user,
|
||||||
|
mode: None,
|
||||||
|
event_days: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mode(&mut self, mode: Mode) -> &mut Self {
|
||||||
|
self.mode = Some(mode);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn event_days(&mut self, event_days: u8) -> &mut Self {
|
||||||
|
self.event_days = Some(event_days).filter(|&v| v <= 31).or(self.event_days);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn build(&self, client: &Client) -> RequestBuilder {
|
||||||
|
client
|
||||||
|
.get("https://osu.ppy.sh/api/get_user")
|
||||||
|
.query(&self.user.to_query())
|
||||||
|
.query(&self.mode.to_query())
|
||||||
|
.query(
|
||||||
|
&self
|
||||||
|
.event_days
|
||||||
|
.map(|v| ("event_days", v.to_string()))
|
||||||
|
.to_query(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UserRequest {
|
pub struct UserRequest {
|
||||||
|
|
Loading…
Add table
Reference in a new issue