From 7d1a09abf10ac9a036f3a09b6c870afbd5cd26cb Mon Sep 17 00:00:00 2001 From: LordMZTE Date: Wed, 8 Sep 2021 15:10:24 +0200 Subject: [PATCH] optimize createmodlist --- mpt/src/commands/createmodlist.rs | 137 ++++++++++++++++++------------ 1 file changed, 82 insertions(+), 55 deletions(-) diff --git a/mpt/src/commands/createmodlist.rs b/mpt/src/commands/createmodlist.rs index 19b4253..e1a7709 100644 --- a/mpt/src/commands/createmodlist.rs +++ b/mpt/src/commands/createmodlist.rs @@ -38,25 +38,81 @@ pub async fn run( let len = version.relations.len(); let mut futures = stream::iter(version.relations.into_iter()) - .map(|rel| get_meta(Arc::clone(&http), rel, &repos)) + .map(|rel| get_meta(rel, &repos)) .buffer_unordered(config.downloads.max_threads); let mut metas = vec![]; let pb = ProgressBar::new(len as u64) .with_style(util::progress_style()) .with_prefix("Resolving metadata"); - while let Some(meta) = futures.next().await { + + let mut cf_rels = vec![]; + while let Some(mi) = futures.next().await { pb.inc(1); - let meta = meta?; - pb.println(format!( - "{} {}", - "Got meta for".green(), - AsRef::::as_ref(&meta.name).cyan().bold() - )); - metas.push(meta); + let mi = mi?; + match mi { + MetaInfo::Meta(meta) => { + pb.println(format!( + "{} {}", + "Got meta for".green(), + AsRef::::as_ref(&meta.name).cyan().bold() + )); + metas.push(meta); + }, + + MetaInfo::CfId(id) => { + pb.println(format!( + "{} {}", + "Found curseforge artifact with id".green(), + id.to_string().cyan().bold() + )); + + cf_rels.push(id); + }, + } } pb.finish(); + println!("{}", "Querying CF metas.".info()); + + let res = http + .post("https://addons-ecs.forgesvc.net/api/v2/addon") + .body( + serde_json::to_string(&cf_rels) + .context("Failed to serialize curseforge relation IDs")?, + ) + .header("Content-Type", "application/json") + .send() + .await + .context("Failed sending CF relation request")? + .bytes() + .await + .context("Failed getting CF relation response body")?; + + let cf_metas = serde_json::from_slice::>(&res) + .context("Failed deserializing CF relation response")?; + + let cf_metas = cf_metas.into_iter().map(|m| Meta { + name: m.name, + contributors: m + .authors + .into_iter() + .map(|a| Contributor { + name: a.name, + roles: vec!["author".into()], + }) + .collect(), + description: Some(m.summary), + icon_url: m + .attachments + .into_iter() + .find(|a| a.is_default) + .map(|a| a.url.to_string()), + website_url: Some(m.website_url), + }); + + metas.extend(cf_metas); + metas.sort_by_key(|m| m.name.to_ascii_lowercase()); println!("{}", "Rendering modlist.".info()); @@ -78,30 +134,26 @@ pub async fn run( Ok(()) } -async fn get_meta( - http: Arc, - rel: Relation, - repos: &HashMap, -) -> anyhow::Result { +async fn get_meta(rel: Relation, repos: &HashMap) -> anyhow::Result { if let Some(meta) = rel.meta { - return Ok(meta); + return Ok(MetaInfo::Meta(meta)); } if rel.file.is_none() { - return Ok(Meta { + return Ok(MetaInfo::Meta(Meta { name: rel.id.clone(), contributors: vec![], description: rel.versions.map(|v| format!("version {}", v)), icon_url: None, website_url: None, - }); + })); } let file = rel.file.unwrap(); match file { File::Link { link, id, .. } => { - Ok(Meta { + Ok(MetaInfo::Meta(Meta { name: if let Some(id) = id { id } else { @@ -113,7 +165,7 @@ async fn get_meta( description: Some(format!("{:?}", &link)), icon_url: None, website_url: None, - }) + })) }, File::Maven { repository, @@ -125,50 +177,20 @@ async fn get_meta( .context("File references unknown repository!")?; match repo.repo_type { - RepositoryType::Maven => Ok(Meta { + RepositoryType::Maven => Ok(MetaInfo::Meta(Meta { name: artifact, contributors: vec![], description: None, icon_url: None, website_url: None, - }), + })), RepositoryType::Curseforge => { let (p_id, _) = util::parse_curseforge_artifact(&artifact)?; - let resp = http - .get(format!( - "https://addons-ecs.forgesvc.net/api/v2/addon/{}", - p_id - )) - .send() - .await? - .bytes() - .await?; + let p_id = p_id + .parse::() + .context("Failed to parse curseforge ID")?; - let resp = serde_json::from_slice::(&resp) - .context("Failed to deserialize addon info!")?; - - let icon_url = resp.attachments.into_iter().find_map(|a| { - if a.is_default { - Some(a.url.into()) - } else { - None - } - }); - - Ok(Meta { - name: resp.name, - contributors: resp - .authors - .into_iter() - .map(|a| Contributor { - name: a.name, - roles: vec![], - }) - .collect(), - description: Some(resp.summary), - icon_url, - website_url: Some(resp.website_url), - }) + Ok(MetaInfo::CfId(p_id)) }, } }, @@ -180,3 +202,8 @@ struct ModListContent { metas: Vec, pack_meta: Meta, } + +enum MetaInfo { + Meta(Meta), + CfId(u32), +}