From 6aa9cff368980b555799c08bd516a40d24d643ed Mon Sep 17 00:00:00 2001 From: Warren Hood Date: Sun, 1 Sep 2024 12:50:23 +0200 Subject: [PATCH] Add support for the raw mod provider --- Cargo.lock | 8 +----- mcmpmgr/Cargo.toml | 2 +- mcmpmgr/src/mod_meta.rs | 6 ++++- mcmpmgr/src/resolver.rs | 57 +++++++++++++++++++++++++++++++++++++---- 4 files changed, 59 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0548a6e..21e7222 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/mcmpmgr/Cargo.toml b/mcmpmgr/Cargo.toml index 79685d2..b257188 100644 --- a/mcmpmgr/Cargo.toml +++ b/mcmpmgr/Cargo.toml @@ -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"] } diff --git a/mcmpmgr/src/mod_meta.rs b/mcmpmgr/src/mod_meta.rs index 05812a9..cf7d3e3 100644 --- a/mcmpmgr/src/mod_meta.rs +++ b/mcmpmgr/src/mod_meta.rs @@ -34,7 +34,9 @@ pub struct ModMeta { pub providers: Option>, pub mc_version: Option, pub loader: Option, - download_url: Option, + pub download_url: Option, + pub server_side: Option, + pub client_side: Option } 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, } } } diff --git a/mcmpmgr/src/resolver.rs b/mcmpmgr/src/resolver.rs index 6897a79..ca62450 100644 --- a/mcmpmgr/src/resolver.rs +++ b/mcmpmgr/src/resolver.rs @@ -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 { + pub async fn load_from_current_directory(ignore_transitive_versions: bool) -> Result { Self::load_from_directory(&std::env::current_dir()?, ignore_transitive_versions).await }