sync: batch file identification via hash lookup
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I85d3f1265cad1996340ac98ac9ee1f7e6a6a6964
This commit is contained in:
parent
0048a1cd73
commit
838ba82790
5 changed files with 261 additions and 1 deletions
|
|
@ -403,6 +403,78 @@ impl PlatformClient for CurseForgePlatform {
|
|||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
async fn request_projects_from_hashes(
|
||||
&self,
|
||||
hashes: &[String],
|
||||
_algorithm: &str,
|
||||
) -> Result<Vec<Project>> {
|
||||
if hashes.is_empty() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
|
||||
let fingerprints: Vec<u32> = hashes
|
||||
.iter()
|
||||
.filter_map(|h| h.parse::<u32>().ok())
|
||||
.collect();
|
||||
|
||||
if fingerprints.is_empty() {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct FingerprintRequest {
|
||||
fingerprints: Vec<u32>,
|
||||
}
|
||||
|
||||
let url = format!("{CURSEFORGE_API_BASE}/fingerprints/432");
|
||||
let response = self
|
||||
.client
|
||||
.post(&url)
|
||||
.headers(self.get_headers()?)
|
||||
.json(&FingerprintRequest {
|
||||
fingerprints: fingerprints.clone(),
|
||||
})
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
return Err(PakkerError::PlatformApiError(format!(
|
||||
"CurseForge batch API error: {}",
|
||||
response.status()
|
||||
)));
|
||||
}
|
||||
|
||||
let response_data: serde_json::Value = response.json().await?;
|
||||
|
||||
let matches = response_data["data"]["exactMatches"]
|
||||
.as_array()
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
|
||||
let mut projects = Vec::new();
|
||||
let mut seen_ids = std::collections::HashSet::new();
|
||||
|
||||
for m in matches {
|
||||
if let Some(file) = m["file"].as_object() {
|
||||
if let Some(mod_id) = file["modId"].as_u64() {
|
||||
let mod_id_str = mod_id.to_string();
|
||||
if seen_ids.contains(&mod_id_str) {
|
||||
continue;
|
||||
}
|
||||
seen_ids.insert(mod_id_str.clone());
|
||||
|
||||
if let Ok(project) =
|
||||
self.request_project_with_files(&mod_id_str, &[], &[]).await
|
||||
{
|
||||
projects.push(project);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(projects)
|
||||
}
|
||||
}
|
||||
|
||||
// CurseForge API models
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue