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,
|
&self,
|
||||||
slug: &str,
|
slug: &str,
|
||||||
) -> Result<CurseForgeProject> {
|
) -> Result<CurseForgeProject> {
|
||||||
let url =
|
let url = format!(
|
||||||
format!("{CURSEFORGE_API_BASE}/mods/search?gameId=432&slug={slug}");
|
"{CURSEFORGE_API_BASE}/mods/search?gameId=432&pageSize=1&sortField=6&\
|
||||||
|
sortOrder=desc&slug={slug}"
|
||||||
|
);
|
||||||
|
|
||||||
let response = self
|
let response = self
|
||||||
.client
|
.client
|
||||||
|
|
@ -247,11 +249,20 @@ impl CurseForgePlatform {
|
||||||
|
|
||||||
let result: CurseForgeSearchResponse = response.json().await?;
|
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
|
.data
|
||||||
.into_iter()
|
.iter()
|
||||||
.find(|p| p.slug == slug)
|
.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) => {
|
Err(e) => {
|
||||||
let is_not_found = matches!(
|
let is_not_found = matches!(
|
||||||
e,
|
e,
|
||||||
PakkerError::ProjectNotFound(_) | PakkerError::InvalidResponse(_)
|
PakkerError::ProjectNotFound(_)
|
||||||
|
| PakkerError::InvalidResponse(_)
|
||||||
|
| PakkerError::ConfigError(_)
|
||||||
);
|
);
|
||||||
if is_not_found { Ok(None) } else { Err(e) }
|
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);
|
let (cf_result, mr_result) = tokio::join!(cf_future, mr_future);
|
||||||
|
|
||||||
// Handle results - extract Options, propagate first error if both fail
|
// Use whichever platform succeeds. Only propagate errors when BOTH fail.
|
||||||
let (cf_project, mr_project) = match (cf_result, mr_result) {
|
let mut cf_project = None;
|
||||||
(Ok(Some(cf)), Ok(Some(mr))) => (Some(cf), Some(mr)),
|
let mut mr_project = None;
|
||||||
(Ok(None), Ok(None)) => (None, None),
|
let mut first_error = None;
|
||||||
(Ok(None), Ok(Some(mr))) => (None, Some(mr)),
|
|
||||||
(Ok(Some(cf)), Ok(None)) => (Some(cf), None),
|
match cf_result {
|
||||||
(Err(_e), Ok(None)) | (Ok(None), Err(_e)) => (None, None),
|
Ok(Some(p)) => {
|
||||||
(Err(e), Ok(Some(_))) | (Ok(Some(_)), Err(e)) => {
|
log::debug!("Multiplatform: found '{identifier}' on CurseForge");
|
||||||
return Err(e);
|
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
|
// Cross-reference: if project exists on only one platform, fetch from the
|
||||||
// other using the slug
|
// 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.
|
// Cross-reference using each platform's own slug on the other platform.
|
||||||
// Modrinth projects store their slug under "modrinth"; CurseForge under
|
// 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), Some(mr)) => cf.merged(mr)?,
|
||||||
(Some(cf), None) => cf,
|
(Some(cf), None) => cf,
|
||||||
(None, Some(mr)) => mr,
|
(None, Some(mr)) => mr,
|
||||||
(None, None) => {
|
(None, None) => unreachable!("handled above"),
|
||||||
return Err(PakkerError::ProjectNotFound(identifier.to_string()));
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(combined)
|
Ok(combined)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue