optimize createmodlist

This commit is contained in:
LordMZTE 2021-09-08 15:10:24 +02:00
parent 3d84356cfb
commit 7d1a09abf1

View file

@ -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::<str>::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::<str>::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::<Vec<AddonInfoResponse>>(&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<Client>,
rel: Relation,
repos: &HashMap<String, Repository>,
) -> anyhow::Result<Meta> {
async fn get_meta(rel: Relation, repos: &HashMap<String, Repository>) -> anyhow::Result<MetaInfo> {
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::<u32>()
.context("Failed to parse curseforge ID")?;
let resp = serde_json::from_slice::<AddonInfoResponse>(&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<Meta>,
pack_meta: Meta,
}
enum MetaInfo {
Meta(Meta),
CfId(u32),
}