1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
use super::super::{
archive::{Archive, read_json},
types::{ModpackFile, ModpackInfo, ParsedModpack},
};
pub(crate) fn parse(archive: &mut Archive) -> Result<ParsedModpack, String> {
let json = read_json(archive, "modrinth.index.json")?;
let (mod_loader, mod_loader_version) = parse_loader(&json["dependencies"]);
let files = json["files"]
.as_array()
.map(|items| {
items
.iter()
.filter_map(|file| {
if file["env"]["client"].as_str() == Some("unsupported") {
return None;
}
let path = file["path"].as_str()?;
if path.contains("..") {
return None;
}
Some(ModpackFile {
path: path.to_string(),
url: file["downloads"].as_array()?.first()?.as_str()?.to_string(),
size: file["fileSize"].as_u64(),
sha1: file["hashes"]["sha1"].as_str().map(String::from),
})
})
.collect()
})
.unwrap_or_default();
Ok(ParsedModpack {
info: ModpackInfo {
name: json["name"].as_str().unwrap_or("Modrinth Modpack").into(),
minecraft_version: json["dependencies"]["minecraft"].as_str().map(Into::into),
mod_loader,
mod_loader_version,
modpack_type: "modrinth".into(),
instance_id: None,
},
files,
override_prefixes: vec!["client-overrides/".into(), "overrides/".into()],
})
}
fn parse_loader(deps: &serde_json::Value) -> (Option<String>, Option<String>) {
const LOADERS: [(&str, &str); 5] = [
("fabric-loader", "fabric"),
("forge", "forge"),
("quilt-loader", "quilt"),
("neoforge", "neoforge"),
("neo-forge", "neoforge"),
];
LOADERS
.iter()
.find_map(|(key, name)| {
let version = deps[*key].as_str()?;
Some((Some((*name).to_string()), Some(version.to_string())))
})
.unwrap_or((None, None))
}
|