diff --git a/src/modpack.rs b/src/modpack.rs index 7618a3c..7257ba7 100644 --- a/src/modpack.rs +++ b/src/modpack.rs @@ -80,15 +80,15 @@ impl ModpackMeta { } pub fn add_mod(mut self, mod_meta: &ModMeta) -> Self { - if let Some(old_mod_meta) = self.mods.get(&mod_meta.name) { - println!("Updating {} version constraints: {} -> {}", mod_meta.name, old_mod_meta.version, mod_meta.version); - } - else { - println!( - "Adding {}@{} to modpack '{}'...", - mod_meta.name, mod_meta.version, self.pack_name - ); - } + // if let Some(old_mod_meta) = self.mods.get(&mod_meta.name) { + // println!("Updating {} version constraints: {} -> {}", mod_meta.name, old_mod_meta.version, mod_meta.version); + // } + // else { + // println!( + // "Adding {}@{} to modpack '{}'...", + // mod_meta.name, mod_meta.version, self.pack_name + // ); + // } self.mods.insert(mod_meta.name.to_string(), mod_meta.clone()); self } @@ -113,7 +113,7 @@ impl ModpackMeta { path, toml::to_string(self).expect("MC Modpack Meta should be serializable"), )?; - println!("Saved modpack metadata to {}", path.display()); + // println!("Saved modpack metadata to {}", path.display()); Ok(()) } diff --git a/src/providers/mod.rs b/src/providers/mod.rs index 01ad441..65b06f5 100644 --- a/src/providers/mod.rs +++ b/src/providers/mod.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::{collections::HashSet, path::PathBuf}; use serde::{Deserialize, Serialize}; use crate::mod_meta::ModMeta; @@ -18,5 +18,5 @@ pub struct PinnedMod { /// Version of mod pub version: semver::Version, /// Pinned dependencies of a pinned mod - pub deps: Option> + pub deps: Option> } \ No newline at end of file diff --git a/src/providers/modrinth.rs b/src/providers/modrinth.rs index 4d0c7f8..d4be37a 100644 --- a/src/providers/modrinth.rs +++ b/src/providers/modrinth.rs @@ -1,13 +1,43 @@ use serde::{Deserialize, Serialize}; -use std::error::Error; +use std::{collections::HashSet, error::Error}; use super::PinnedMod; -use crate::{mod_meta::ModMeta, modpack::ModpackMeta, providers::FileSource}; +use crate::{ + mod_meta::{ModMeta, ModProvider}, + modpack::ModpackMeta, + providers::FileSource, +}; pub struct Modrinth { client: reqwest::Client, } +#[derive(Serialize, Deserialize)] +struct DonationUrls1 { + id: String, + platform: String, + url: String, +} +#[derive(Serialize, Deserialize)] +struct Gallery1 { + created: String, + description: String, + featured: bool, + ordering: i64, + title: String, + url: String, +} +#[derive(Serialize, Deserialize)] +struct License1 { + id: String, + name: String, + url: String, +} +#[derive(Serialize, Deserialize)] +struct ModrinthProject { + slug: String, +} + #[derive(Serialize, Deserialize, Debug)] struct VersionDeps { dependency_type: String, @@ -40,8 +70,9 @@ struct ModrinthProjectVersion { // downloads: i64, files: Vec, // loaders: Vec, - // name: String, - // project_id: String, + name: String, + project_id: String, + id: String, version_number: semver::Version, // version_type: String, } @@ -53,15 +84,49 @@ impl Modrinth { } } + pub async fn get_project_slug(&self, project_id: &str) -> Result> { + let mut project: ModrinthProject = self + .client + .get(format!("https://api.modrinth.com/v2/project/{project_id}")) + .send() + .await? + .json() + .await?; + + Ok(project.slug) + } + + pub async fn get_mod_meta( + &self, + project_id: &str, + project_version: Option<&str>, + pack_meta: &ModpackMeta, + ) -> Result> { + let project_versions = self.get_project_versions(project_id, pack_meta).await?; + let project_slug = self.get_project_slug(project_id).await?; + + for version in project_versions.into_iter() { + if project_version.is_none() || project_version.unwrap_or("*") == version.id { + return Ok(ModMeta::new(&project_slug)? + .provider(ModProvider::Modrinth) + .version(&version.version_number.to_string())); + } + } + Err(format!( + "Couldn't find project '{}' with version '{}'", + project_id, + project_version.unwrap_or("*") + ) + .into()) + } + /// Resolve a list of mod candidates in order of newest to oldest pub async fn resolve( &self, mod_meta: &ModMeta, pack_meta: &ModpackMeta, ) -> Result> { - let mut versions = self.get_project_versions(&mod_meta.name, pack_meta).await?; - versions.sort_by_key(|v| v.version_number.clone()); - versions.reverse(); + let versions = self.get_project_versions(&mod_meta.name, pack_meta).await?; let package = if mod_meta.version == "*" { versions.last().ok_or(format!( @@ -82,6 +147,18 @@ impl Modrinth { ))? }; + let mut deps_meta = HashSet::new(); + for dep in package + .dependencies + .iter() + .filter(|dep| dep.dependency_type == "required") + { + deps_meta.insert( + self.get_mod_meta(&dep.project_id, dep.version_id.as_deref(), pack_meta) + .await?, + ); + } + Ok(PinnedMod { source: package .files @@ -93,7 +170,11 @@ impl Modrinth { }) .collect(), version: package.version_number.clone(), - deps: None, // TODO: Get deps + deps: if package.dependencies.len() > 0 { + Some(deps_meta) + } else { + None + }, }) } @@ -102,7 +183,7 @@ impl Modrinth { mod_id: &str, pack_meta: &ModpackMeta, ) -> Result, Box> { - let project_Versions: Vec = self + let mut project_versions: Vec = self .client .get(format!( "https://api.modrinth.com/v2/project/{mod_id}/version" @@ -119,7 +200,10 @@ impl Modrinth { .json() .await?; - Ok(project_Versions) + project_versions.sort_by_key(|v| v.version_number.clone()); + project_versions.reverse(); + + Ok(project_versions) } } diff --git a/src/resolver.rs b/src/resolver.rs index 643344c..7f7a130 100644 --- a/src/resolver.rs +++ b/src/resolver.rs @@ -45,12 +45,19 @@ impl PinnedPackMeta { let mut deps = HashSet::from_iter(self.pin_mod(mod_metadata, pack_metadata).await?.into_iter()); + let pinned_version = self + .mods + .get(&mod_metadata.name) + .expect("should be in pinned mods") + .version + .clone(); + while !deps.is_empty() { let mut next_deps = HashSet::new(); for dep in deps.iter() { println!( "Adding mod {}@{} (dependency of {}@{})", - dep.name, dep.version, mod_metadata.name, mod_metadata.version + dep.name, dep.version, mod_metadata.name, pinned_version ); next_deps.extend(self.pin_mod(dep, &pack_metadata).await?); } @@ -129,7 +136,7 @@ impl PinnedPackMeta { path, toml::to_string(self).expect("Pinned pack meta should be serializable"), )?; - println!("Saved modpack.lock to {}", path.display()); + // println!("Saved modpack.lock to {}", path.display()); Ok(()) }