diff --git a/Cargo.lock b/Cargo.lock index 3ba490c..e8ed891 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1872,6 +1872,7 @@ dependencies = [ "futures", "lapin", "log", + "md5", "redis", "reqwest", "rkyv", diff --git a/Cargo.toml b/Cargo.toml index 744fed8..9185aa7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,6 +65,7 @@ improved-miss-penalty = { package = "akatsuki-pp", git = "https://github.com/osu accuracy-fun = { package = "akatsuki-pp", git = "https://github.com/osuAkatsuki/akatsuki-pp-rs", rev = "879fd8caa2cb082a5b9c0761fc2ddca3b283b226", features = [ "async_tokio", ] } +md5 = "0.7.0" [profile.release] lto = "fat" diff --git a/src/api/routes/calculate.rs b/src/api/routes/calculate.rs index 8d86880..5759512 100644 --- a/src/api/routes/calculate.rs +++ b/src/api/routes/calculate.rs @@ -11,6 +11,7 @@ pub fn router() -> Router { #[derive(serde::Serialize, serde::Deserialize)] pub struct CalculateRequest { pub beatmap_id: i32, + pub beatmap_md5: String, pub mode: i32, pub mods: i32, pub max_combo: i32, @@ -36,8 +37,12 @@ async fn calculate_relax_pp( request: &CalculateRequest, context: Arc, ) -> anyhow::Result { - let beatmap_bytes = - usecases::beatmaps::fetch_beatmap_osu_file(request.beatmap_id, context).await?; + let beatmap_bytes = usecases::beatmaps::fetch_beatmap_osu_file( + request.beatmap_id, + &request.beatmap_md5, + context, + ) + .await?; let beatmap = Beatmap::from_bytes(&beatmap_bytes).await?; let result = akatsuki_pp_rs::osu_2019::OsuPP::new(&beatmap) @@ -72,8 +77,12 @@ async fn calculate_rosu_pp( request: &CalculateRequest, context: Arc, ) -> anyhow::Result { - let beatmap_bytes = - usecases::beatmaps::fetch_beatmap_osu_file(request.beatmap_id, context).await?; + let beatmap_bytes = usecases::beatmaps::fetch_beatmap_osu_file( + request.beatmap_id, + &request.beatmap_md5, + context, + ) + .await?; let beatmap = Beatmap::from_bytes(&beatmap_bytes).await?; let result = beatmap diff --git a/src/deploy/mod.rs b/src/deploy/mod.rs index bc2e155..9b16332 100644 --- a/src/deploy/mod.rs +++ b/src/deploy/mod.rs @@ -9,6 +9,7 @@ use tokio::sync::Mutex; #[derive(serde::Serialize, serde::Deserialize)] pub struct CalculateRequest { pub beatmap_id: i32, + pub beatmap_md5: String, pub mode: i32, pub mods: i32, pub max_combo: i32, @@ -44,8 +45,12 @@ async fn calculate_special_pp( .unwrap() .clone() } else { - let beatmap_bytes = - usecases::beatmaps::fetch_beatmap_osu_file(request.beatmap_id, context.clone()).await?; + let beatmap_bytes = usecases::beatmaps::fetch_beatmap_osu_file( + request.beatmap_id, + &request.beatmap_md5, + context.clone(), + ) + .await?; let beatmap = Beatmap::from_bytes(&beatmap_bytes).await?; recalc_mutex @@ -91,8 +96,12 @@ async fn calculate_rosu_pp( .unwrap() .clone() } else { - let beatmap_bytes = - usecases::beatmaps::fetch_beatmap_osu_file(request.beatmap_id, context.clone()).await?; + let beatmap_bytes = usecases::beatmaps::fetch_beatmap_osu_file( + request.beatmap_id, + &request.beatmap_md5, + context.clone(), + ) + .await?; let beatmap = Beatmap::from_bytes(&beatmap_bytes).await?; recalc_mutex @@ -139,6 +148,7 @@ async fn recalculate_score( ) -> anyhow::Result<()> { let request = CalculateRequest { beatmap_id: score.beatmap_id, + beatmap_md5: score.beatmap_md5, mode: score.play_mode, mods: score.mods, max_combo: score.max_combo, @@ -427,12 +437,11 @@ async fn recalculate_user( .execute(ctx.database.get().await?.deref_mut()) .await?; - let (country, user_privileges): (String, i32) = sqlx::query_as( - "SELECT country, privileges FROM users WHERE id = ?", - ) - .bind(user_id) - .fetch_one(ctx.database.get().await?.deref_mut()) - .await?; + let (country, user_privileges): (String, i32) = + sqlx::query_as("SELECT country, privileges FROM users WHERE id = ?") + .bind(user_id) + .fetch_one(ctx.database.get().await?.deref_mut()) + .await?; let last_score_time: Option = sqlx::query_scalar(&format!( "SELECT max(time) FROM {} INNER JOIN beatmaps USING(beatmap_md5) diff --git a/src/processor/mod.rs b/src/processor/mod.rs index a4770d6..2647aa8 100644 --- a/src/processor/mod.rs +++ b/src/processor/mod.rs @@ -43,7 +43,8 @@ async fn calculate_conceptual_pp( context: Arc, ) -> anyhow::Result { let beatmap_bytes = - usecases::beatmaps::fetch_beatmap_osu_file(score.beatmap_id, context).await?; + usecases::beatmaps::fetch_beatmap_osu_file(score.beatmap_id, &score.beatmap_md5, context) + .await?; let beatmap = ConceptualBeatmap::from_bytes(&beatmap_bytes).await?; let result = beatmap @@ -74,7 +75,8 @@ async fn calculate_skill_rebalance_pp( context: Arc, ) -> anyhow::Result { let beatmap_bytes = - usecases::beatmaps::fetch_beatmap_osu_file(score.beatmap_id, context).await?; + usecases::beatmaps::fetch_beatmap_osu_file(score.beatmap_id, &score.beatmap_md5, context) + .await?; let beatmap = SkillRebalanceBeatmap::from_bytes(&beatmap_bytes).await?; let result = beatmap @@ -105,7 +107,8 @@ async fn calculate_cursordance_pp( context: Arc, ) -> anyhow::Result { let beatmap_bytes = - usecases::beatmaps::fetch_beatmap_osu_file(score.beatmap_id, context).await?; + usecases::beatmaps::fetch_beatmap_osu_file(score.beatmap_id, &score.beatmap_md5, context) + .await?; let beatmap = CdBeatmap::from_bytes(&beatmap_bytes).await?; let result = cursordance::osu_2019::OsuPP::new(&beatmap) @@ -128,7 +131,8 @@ async fn calculate_no_accuracy_pp( context: Arc, ) -> anyhow::Result { let beatmap_bytes = - usecases::beatmaps::fetch_beatmap_osu_file(score.beatmap_id, context).await?; + usecases::beatmaps::fetch_beatmap_osu_file(score.beatmap_id, &score.beatmap_md5, context) + .await?; let beatmap = NoAccuracyBeatmap::from_bytes(&beatmap_bytes).await?; let result = no_accuracy::osu_2019::OsuPP::new(&beatmap) @@ -151,7 +155,8 @@ async fn calculate_simplfy_relax_pp( context: Arc, ) -> anyhow::Result { let beatmap_bytes = - usecases::beatmaps::fetch_beatmap_osu_file(score.beatmap_id, context).await?; + usecases::beatmaps::fetch_beatmap_osu_file(score.beatmap_id, &score.beatmap_md5, context) + .await?; let beatmap = SimplifyRelaxBeatmap::from_bytes(&beatmap_bytes).await?; let result = simplify_relax::osu_2019::OsuPP::new(&beatmap) @@ -174,7 +179,8 @@ async fn calculate_improved_miss_penalty_pp( context: Arc, ) -> anyhow::Result { let beatmap_bytes = - usecases::beatmaps::fetch_beatmap_osu_file(score.beatmap_id, context).await?; + usecases::beatmaps::fetch_beatmap_osu_file(score.beatmap_id, &score.beatmap_md5, context) + .await?; let beatmap = ImprovedMissPenaltyBeatmap::from_bytes(&beatmap_bytes).await?; let result = improved_miss_penalty::osu_2019::OsuPP::new(&beatmap) @@ -197,7 +203,8 @@ async fn calculate_accuracy_fun_pp( context: Arc, ) -> anyhow::Result { let beatmap_bytes = - usecases::beatmaps::fetch_beatmap_osu_file(score.beatmap_id, context).await?; + usecases::beatmaps::fetch_beatmap_osu_file(score.beatmap_id, &score.beatmap_md5, context) + .await?; let beatmap = AccuracyFunBeatmap::from_bytes(&beatmap_bytes).await?; let result = accuracy_fun::osu_2019::OsuPP::new(&beatmap) diff --git a/src/usecases/beatmaps.rs b/src/usecases/beatmaps.rs index ca212ec..acea6a0 100644 --- a/src/usecases/beatmaps.rs +++ b/src/usecases/beatmaps.rs @@ -6,6 +6,7 @@ use crate::context::Context; pub async fn fetch_beatmap_osu_file( beatmap_id: i32, + beatmap_md5: &str, context: Arc, ) -> anyhow::Result> { let beatmap_path = &format!("beatmaps/{beatmap_id}.osu"); @@ -15,8 +16,17 @@ pub async fn fetch_beatmap_osu_file( Err(S3Error::Http(status_code, _)) if status_code == 404 => Ok(None), Err(e) => Err(e), }?; - if existing_file.is_some() { - return Ok(existing_file.unwrap().to_vec()); + + match existing_file { + Some(existing_file) => { + let osu_file_data = existing_file.to_vec(); + let osu_file_data_md5 = format!("{:x}", md5::compute(&osu_file_data)); + + if osu_file_data_md5 == beatmap_md5 { + return Ok(osu_file_data); + } + } + None => {} } let osu_response = reqwest::get(&format!("https://old.ppy.sh/osu/{beatmap_id}"))