diff --git a/src/cli.rs b/src/cli.rs index abec52a..a4b9e4b 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -24,4 +24,7 @@ pub enum Commands { /// The name of the mod to add name: String, }, + + /// Remove a mod from the modpack + Remove, } diff --git a/src/main.rs b/src/main.rs index 3c4fda9..b716c0a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,9 @@ async fn main() { cli::Commands::Init => { pack::Pack::init().await; } + cli::Commands::Add { name } => { + pack::Pack::add(name).await; + } _ => (), }; } diff --git a/src/modrinth.rs b/src/modrinth.rs index 205e8d0..ccf8f53 100644 --- a/src/modrinth.rs +++ b/src/modrinth.rs @@ -1,3 +1,5 @@ +use core::fmt; + use serde::Deserialize; #[derive(Deserialize, Debug)] @@ -8,9 +10,63 @@ pub struct MinecraftVersion { pub major: bool, } +#[derive(Deserialize, Debug)] +pub struct Mod { + pub title: String, + pub description: String, + pub project_id: String, +} + +impl fmt::Display for Mod { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.title) + } +} + +#[derive(Deserialize, Debug)] +pub struct Search { + hits: Vec, +} + +#[derive(Deserialize, Debug)] +pub struct ProjectVersion { + pub name: String, + pub game_versions: Vec, + pub version_type: String, + pub id: String, + pub project_id: String, +} + pub async fn get_minecraft_versions() -> Result, reqwest::Error> { reqwest::get("https://api.modrinth.com/v2/tag/game_version") .await? .json::>() .await } + +pub async fn search_projects( + query: String, + version: &String, + loader: &String, +) -> Result, reqwest::Error> { + let url = format!("https://api.modrinth.com/v2/search?query={query}&facets=[[\"project_type:mod\"],[\"versions:{version}\"],[\"categories:{loader}\"]]"); + + let response = reqwest::get(url).await?.json::().await?; + + Ok(response.hits) +} + +pub async fn get_project_versions( + id: &String, + version: &String, + loader: &String, +) -> Result, reqwest::Error> { + let url = format!("https://api.modrinth.com/v2/project/{id}/version?loaders=[\"{loader}\"]&game_versions=[\"{version}\"]"); + + let response = reqwest::get(url) + .await? + .json::>() + .await?; + + Ok(response) +} diff --git a/src/pack.rs b/src/pack.rs index 83be6e0..39b35a5 100644 --- a/src/pack.rs +++ b/src/pack.rs @@ -1,21 +1,31 @@ use crate::modrinth; use colored::*; use inquire::Select; -use serde::Serialize; -use std::fmt::{Display, Formatter}; +use serde::{Deserialize, Serialize}; +use std::{ + fmt::{Display, Formatter}, + fs, +}; -#[derive(Serialize)] +#[derive(Serialize, Deserialize)] pub struct Pack { info: Info, + mods: Vec, } -#[derive(Serialize)] +#[derive(Serialize, Deserialize)] +pub struct Mod { + id: String, + version_id: String, +} + +#[derive(Serialize, Deserialize)] pub struct Info { loader: Modloader, minecraft_version: String, } -#[derive(Serialize, Debug, Clone, Copy)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub enum Modloader { Fabric, Quilt, @@ -35,6 +45,12 @@ impl Display for Modloader { } impl Pack { + pub fn get() -> Self { + let pack_string = fs::read_to_string(".packium.toml").unwrap(); + + toml::from_str(&pack_string).unwrap() + } + pub async fn init() { println!("Fetching Minecraft information..."); @@ -43,7 +59,7 @@ impl Pack { let versions = versions .iter() .filter(|x| x.version_type == "release".to_string()) - .map(|x| x.version.clone()) + .map(|x| &x.version) .collect(); let modloader = Select::new("Modloader?", Modloader::VARIANTS.to_vec()) @@ -56,13 +72,47 @@ impl Pack { let pack = Pack { info: Info { - minecraft_version: version, + minecraft_version: version.to_owned(), loader: modloader, }, + mods: vec![], }; let pack_toml = toml::to_string_pretty(&pack).unwrap(); std::fs::write(".packium.toml", pack_toml).unwrap(); } + + pub async fn add(name: &String) { + let mut pack = Self::get(); + + let mods = modrinth::search_projects( + name.to_owned(), + &pack.info.minecraft_version, + &pack.info.loader.to_string().to_lowercase(), + ) + .await + .unwrap(); + + let project = Select::new("Choose a mod", mods).prompt().unwrap(); + + let versions = modrinth::get_project_versions( + &project.project_id, + &pack.info.minecraft_version, + &pack.info.loader.to_string().to_lowercase(), + ) + .await + .unwrap(); + + let version = versions.get(0).unwrap(); + + pack.mods.push(Mod { + id: project.project_id.clone(), + version_id: version.id.clone(), + }); + + let pack_toml = toml::to_string_pretty(&pack).unwrap(); + + std::fs::write(".packium.toml", pack_toml).unwrap(); + } }