diff --git a/src/platform/curseforge.rs b/src/platform/curseforge.rs index 692f14d..6fdf453 100644 --- a/src/platform/curseforge.rs +++ b/src/platform/curseforge.rs @@ -231,8 +231,10 @@ impl CurseForgePlatform { &self, slug: &str, ) -> Result { - let url = - format!("{CURSEFORGE_API_BASE}/mods/search?gameId=432&slug={slug}"); + let url = format!( + "{CURSEFORGE_API_BASE}/mods/search?gameId=432&pageSize=1&sortField=6&\ + sortOrder=desc&slug={slug}" + ); let response = self .client @@ -247,11 +249,20 @@ impl CurseForgePlatform { let result: CurseForgeSearchResponse = response.json().await?; - result + log::debug!( + "CurseForge search for '{slug}' returned {} results (slugs: {:?})", + result.data.len(), + result.data.iter().map(|p| &p.slug).collect::>() + ); + + let project = result .data - .into_iter() + .iter() .find(|p| p.slug == slug) - .ok_or_else(|| PakkerError::ProjectNotFound(slug.to_string())) + .cloned() + .or_else(|| result.data.first().cloned()); + + project.ok_or_else(|| PakkerError::ProjectNotFound(slug.to_string())) } } diff --git a/src/platform/multiplatform.rs b/src/platform/multiplatform.rs index 54dac2d..5ebaae0 100644 --- a/src/platform/multiplatform.rs +++ b/src/platform/multiplatform.rs @@ -38,7 +38,9 @@ impl MultiplatformPlatform { Err(e) => { let is_not_found = matches!( e, - PakkerError::ProjectNotFound(_) | PakkerError::InvalidResponse(_) + PakkerError::ProjectNotFound(_) + | PakkerError::InvalidResponse(_) + | PakkerError::ConfigError(_) ); if is_not_found { Ok(None) } else { Err(e) } }, @@ -60,23 +62,50 @@ impl PlatformClient for MultiplatformPlatform { let (cf_result, mr_result) = tokio::join!(cf_future, mr_future); - // Handle results - extract Options, propagate first error if both fail - let (cf_project, mr_project) = match (cf_result, mr_result) { - (Ok(Some(cf)), Ok(Some(mr))) => (Some(cf), Some(mr)), - (Ok(None), Ok(None)) => (None, None), - (Ok(None), Ok(Some(mr))) => (None, Some(mr)), - (Ok(Some(cf)), Ok(None)) => (Some(cf), None), - (Err(_e), Ok(None)) | (Ok(None), Err(_e)) => (None, None), - (Err(e), Ok(Some(_))) | (Ok(Some(_)), Err(e)) => { - return Err(e); + // Use whichever platform succeeds. Only propagate errors when BOTH fail. + let mut cf_project = None; + let mut mr_project = None; + let mut first_error = None; + + match cf_result { + Ok(Some(p)) => { + log::debug!("Multiplatform: found '{identifier}' on CurseForge"); + cf_project = Some(p); }, - (Err(e), Err(_)) => return Err(e), - }; + Ok(None) => { + log::debug!("Multiplatform: '{identifier}' not found on CurseForge"); + }, + Err(e) => { + log::debug!("Multiplatform: CurseForge error for '{identifier}': {e}"); + first_error = Some(e); + }, + } + + match mr_result { + Ok(Some(p)) => { + log::debug!("Multiplatform: found '{identifier}' on Modrinth"); + mr_project = Some(p); + }, + Ok(None) => { + log::debug!("Multiplatform: '{identifier}' not found on Modrinth"); + }, + Err(e) => { + log::debug!("Multiplatform: Modrinth error for '{identifier}': {e}"); + if first_error.is_none() { + first_error = Some(e); + } + }, + } + + if cf_project.is_none() && mr_project.is_none() { + if let Some(e) = first_error { + return Err(e); + } + return Err(PakkerError::ProjectNotFound(identifier.to_string())); + } // Cross-reference: if project exists on only one platform, fetch from the // other using the slug - let mut cf_project = cf_project; - let mut mr_project = mr_project; // Cross-reference using each platform's own slug on the other platform. // Modrinth projects store their slug under "modrinth"; CurseForge under @@ -103,9 +132,7 @@ impl PlatformClient for MultiplatformPlatform { (Some(cf), Some(mr)) => cf.merged(mr)?, (Some(cf), None) => cf, (None, Some(mr)) => mr, - (None, None) => { - return Err(PakkerError::ProjectNotFound(identifier.to_string())); - }, + (None, None) => unreachable!("handled above"), }; Ok(combined)