From f000b8636c230b606bcaedcaf77cb26992ad1f36 Mon Sep 17 00:00:00 2001 From: mokurin000 <1348292515a@gmail.com> Date: Sat, 2 Aug 2025 00:02:57 +0800 Subject: [PATCH] feat: implement full user music fetch --- sdgb-api/src/title/methods/mod.rs | 1 + .../src/title/model/get_user_music_api/mod.rs | 41 ++++++++++++++++++ sdgb-api/src/title/model/mod.rs | 13 +++++- sdgb-cli/src/commands.rs | 4 ++ sdgb-cli/src/main.rs | 42 +++++++++++++++++-- 5 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 sdgb-api/src/title/model/get_user_music_api/mod.rs diff --git a/sdgb-api/src/title/methods/mod.rs b/sdgb-api/src/title/methods/mod.rs index d71e952..e6a973a 100644 --- a/sdgb-api/src/title/methods/mod.rs +++ b/sdgb-api/src/title/methods/mod.rs @@ -76,6 +76,7 @@ api_implement!([ "GetUserDataApi", "GetUserPreviewApi", "GetUserRatingApi", + "GetUserMusicApi", ]); #[cfg(test)] diff --git a/sdgb-api/src/title/model/get_user_music_api/mod.rs b/sdgb-api/src/title/model/get_user_music_api/mod.rs new file mode 100644 index 0000000..e9b7f2d --- /dev/null +++ b/sdgb-api/src/title/model/get_user_music_api/mod.rs @@ -0,0 +1,41 @@ +use serde::Deserialize; +use serde::Serialize; + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct GetUserMusicApi { + pub user_id: u32, + pub next_index: u32, + pub max_count: u32, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct GetUserMusicApiResp { + pub user_id: u32, + pub length: u32, + pub next_index: u32, + pub user_music_list: Vec, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UserMusic { + pub user_music_detail_list: Vec, + pub length: u32, +} + +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct UserMusicDetail { + pub music_id: u32, + pub level: u32, + pub play_count: i64, + pub achievement: i64, + pub combo_status: i64, + pub sync_status: i64, + pub deluxscore_max: i64, + pub score_rank: i64, + pub ext_num1: i64, + pub ext_num2: i64, +} diff --git a/sdgb-api/src/title/model/mod.rs b/sdgb-api/src/title/model/mod.rs index f235650..1e43862 100644 --- a/sdgb-api/src/title/model/mod.rs +++ b/sdgb-api/src/title/model/mod.rs @@ -11,7 +11,7 @@ mod user_login_api; pub use user_login_api::{LoginError, UserLoginApi, UserLoginApiResp}; mod get_user_data_api; -pub use get_user_data_api::{GetUserDataApi, GetUserDataApiResp}; +pub use get_user_data_api::{GetUserDataApi, GetUserDataApiResp, UserData}; mod get_user_rating_api; pub use get_user_rating_api::dxrating::{ @@ -22,4 +22,13 @@ pub use get_user_rating_api::dxrating::{ DxRatingNet, DxSheetId, }; -pub use get_user_rating_api::{GetUserRatingApi, GetUserRatingApiResp}; +pub use get_user_rating_api::{ + GetUserRatingApi, + GetUserRatingApiResp, // api + MusicRating, + Udemae, + UserRating, +}; + +mod get_user_music_api; +pub use get_user_music_api::{GetUserMusicApi, GetUserMusicApiResp, UserMusic}; diff --git a/sdgb-cli/src/commands.rs b/sdgb-cli/src/commands.rs index edf9d4b..f7884b6 100644 --- a/sdgb-cli/src/commands.rs +++ b/sdgb-cli/src/commands.rs @@ -51,6 +51,10 @@ pub enum Commands { #[arg(short, long, default_value_t = RatingFormat::default())] format: RatingFormat, }, + MusicDetail { + #[arg(short, long)] + user_id: u32, + }, // below requires login Userdata { diff --git a/sdgb-cli/src/main.rs b/sdgb-cli/src/main.rs index 7fc4faf..c9b0857 100644 --- a/sdgb-cli/src/main.rs +++ b/sdgb-cli/src/main.rs @@ -16,8 +16,9 @@ use sdgb_api::{ methods::APIMethod, model::{ DataVersion, DxCalculatedEntries, DxRatingNet, GetUserDataApi, GetUserDataApiResp, - GetUserPreviewApi, GetUserPreviewApiResp, GetUserRatingApi, GetUserRatingApiResp, Ping, - PingResp, UserLogoutApi, UserLogoutApiResp, + GetUserMusicApi, GetUserMusicApiResp, GetUserPreviewApi, GetUserPreviewApiResp, + GetUserRatingApi, GetUserRatingApiResp, Ping, PingResp, UserLogoutApi, + UserLogoutApiResp, }, }, }; @@ -77,6 +78,40 @@ async fn main() -> Result<(), Box> { // TODO: refactor via enum_dispatch match command { + commands::Commands::MusicDetail { user_id } => { + let mut music_detail = Vec::new(); + let mut index = None; + + loop { + let GetUserMusicApiResp { + next_index, + mut user_music_list, + .. + } = Sdgb1_50::request::<_, GetUserMusicApiResp>( + &client, + APIMethod::GetUserMusicApi, + user_id, + GetUserMusicApi { + user_id, + next_index: index.unwrap_or_default(), + max_count: 50, + }, + ) + .await?; + + for list in &mut user_music_list { + music_detail.append(&mut list.user_music_detail_list); + } + + if next_index == 0 || user_music_list.is_empty() { + break; + } + index = Some(next_index); + } + + // TODO: `Display` support for MusicDetail + json_display(music_detail)?; + } commands::Commands::Rating { user_id, format } => { let rating: GetUserRatingApiResp = Sdgb1_50::request( &client, @@ -269,8 +304,6 @@ async fn main() -> Result<(), Box> { #[cfg(file_lock_ready)] file.try_lock()?; - let writer = BufWriter::new(file); - let txn = read_txn()?; let table = open_table_read(&txn)?; @@ -285,6 +318,7 @@ async fn main() -> Result<(), Box> { .map(|(value, _)| value) .collect::>(); + let writer = BufWriter::new(file); serde_json::to_writer(writer, &user_ids)?; info!("dumped {} user id", user_ids.len()); }