Add support for the raw mod provider

This commit is contained in:
Warren Hood 2024-09-01 12:50:23 +02:00
parent c216873393
commit 6aa9cff368
4 changed files with 59 additions and 14 deletions

8
Cargo.lock generated
View file

@ -1930,12 +1930,6 @@ dependencies = [
"smallvec",
]
[[package]]
name = "lhash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "744a4c881f502e98c2241d2e5f50040ac73b30194d64452bb6260393b53f0dc9"
[[package]]
name = "libc"
version = "0.2.158"
@ -2073,10 +2067,10 @@ dependencies = [
"clap",
"git2",
"home",
"lhash",
"reqwest",
"semver",
"serde",
"sha1",
"sha2",
"tempfile",
"tokio",

View file

@ -9,10 +9,10 @@ anyhow = "1.0.86"
clap = { version = "4.5.15", features = ["derive"] }
git2 = "0.19.0"
home = "0.5.9"
lhash = { version = "1.1.0", features = ["sha1", "sha512"] }
reqwest = { version = "0.12.5", features = ["json"] }
semver = { version = "1.0.23", features = ["serde"] }
serde = { version = "1.0.207", features = ["derive"] }
sha1 = "0.10.6"
sha2 = "0.10.8"
tempfile = "3.12.0"
tokio = { version = "1.39.2", features = ["full"] }

View file

@ -34,7 +34,9 @@ pub struct ModMeta {
pub providers: Option<Vec<ModProvider>>,
pub mc_version: Option<String>,
pub loader: Option<ModLoader>,
download_url: Option<String>,
pub download_url: Option<String>,
pub server_side: Option<bool>,
pub client_side: Option<bool>
}
impl PartialEq for ModMeta {
@ -106,6 +108,8 @@ impl Default for ModMeta {
download_url: Default::default(),
mc_version: None,
loader: None,
server_side: None,
client_side: None,
}
}
}

View file

@ -1,5 +1,7 @@
use anyhow::Result;
use reqwest::{header::CONTENT_DISPOSITION, Url};
use serde::{Deserialize, Serialize};
use sha1::Sha1;
use sha2::{Digest, Sha512};
use std::{
collections::{BTreeMap, HashSet},
@ -10,7 +12,7 @@ use std::{
use crate::{
mod_meta::{ModMeta, ModProvider},
modpack::ModpackMeta,
providers::{modrinth::Modrinth, DownloadSide, PinnedMod},
providers::{modrinth::Modrinth, DownloadSide, FileSource, PinnedMod},
};
const MODPACK_LOCK_FILENAME: &str = "modpack.lock";
@ -244,7 +246,54 @@ impl PinnedPackMeta {
);
}
}
crate::mod_meta::ModProvider::Raw => unimplemented!(),
crate::mod_meta::ModProvider::Raw => {
let url = mod_metadata
.download_url
.clone()
.ok_or(anyhow::format_err!(
"A download url is required to pin {}",
mod_metadata.name
))?;
let file_response = reqwest::get(&url).await?;
// TODO: Get filename from content disposition
let _content_disposition = file_response.headers().get(CONTENT_DISPOSITION);
let url_parsed = Url::parse(&url)?;
let filename = url_parsed
.path_segments()
.ok_or(anyhow::format_err!(
"Cannot get path segments from url {}",
url
))?
.last()
.ok_or(anyhow::format_err!("Cannot get filename from url {}", url))?;
let file_contents = file_response.bytes().await?;
let mut sha1_hasher = Sha1::new();
let mut sha512_hasher = Sha512::new();
sha1_hasher.update(&file_contents);
sha512_hasher.update(&file_contents);
let sha1_hash = format!("{:X}", sha1_hasher.finalize()).to_ascii_lowercase();
let sha512_hash =
format!("{:X}", sha512_hasher.finalize()).to_ascii_lowercase();
let pinned_mod = PinnedMod {
source: vec![FileSource::Download {
url: url.into(),
sha1: sha1_hash,
sha512: sha512_hash,
filename: filename.into(),
}],
version: "Unknown".into(),
deps: None,
server_side: mod_metadata.server_side.unwrap_or(true),
client_side: mod_metadata.client_side.unwrap_or(true),
};
self.mods
.insert(mod_metadata.name.clone(), pinned_mod.clone());
println!("Pinned {}@{}", mod_metadata.name, pinned_mod.version);
return Ok(vec![]);
}
};
}
@ -378,9 +427,7 @@ impl PinnedPackMeta {
Ok(toml::from_str(&modpack_lock_contents)?)
}
pub async fn load_from_current_directory(
ignore_transitive_versions: bool,
) -> Result<Self> {
pub async fn load_from_current_directory(ignore_transitive_versions: bool) -> Result<Self> {
Self::load_from_directory(&std::env::current_dir()?, ignore_transitive_versions).await
}