platform: improve multiplatform resolution and CurseForge search
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ia32a968e1b048ed396ba0f61df30bb616a6a6964
This commit is contained in:
parent
a84a654841
commit
65ac620831
2 changed files with 60 additions and 22 deletions
|
|
@ -231,8 +231,10 @@ impl CurseForgePlatform {
|
|||
&self,
|
||||
slug: &str,
|
||||
) -> Result<CurseForgeProject> {
|
||||
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::<Vec<_>>()
|
||||
);
|
||||
|
||||
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()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue