diff --git a/src/pack.rs b/src/config.rs similarity index 65% rename from src/pack.rs rename to src/config.rs index 39b35a5..94a6363 100644 --- a/src/pack.rs +++ b/src/config.rs @@ -1,5 +1,5 @@ use crate::modrinth; -use colored::*; +use crate::pack; use inquire::Select; use serde::{Deserialize, Serialize}; use std::{ @@ -8,15 +8,15 @@ use std::{ }; #[derive(Serialize, Deserialize)] -pub struct Pack { - info: Info, - mods: Vec, +pub struct Config { + pub info: Info, + pub mods: Vec, } #[derive(Serialize, Deserialize)] pub struct Mod { - id: String, - version_id: String, + pub id: String, + pub version_id: String, } #[derive(Serialize, Deserialize)] @@ -44,13 +44,19 @@ impl Display for Modloader { } } -impl Pack { +impl Config { pub fn get() -> Self { let pack_string = fs::read_to_string(".packium.toml").unwrap(); toml::from_str(&pack_string).unwrap() } + pub async fn mods(&self) -> Vec { + modrinth::get_multiple_project(self.mods.iter().map(|x| x.id.clone()).collect()) + .await + .unwrap() + } + pub async fn init() { println!("Fetching Minecraft information..."); @@ -70,7 +76,7 @@ impl Pack { .prompt() .unwrap(); - let pack = Pack { + let pack = Config { info: Info { minecraft_version: version.to_owned(), loader: modloader, @@ -84,12 +90,12 @@ impl Pack { } pub async fn add(name: &String) { - let mut pack = Self::get(); + let mut config = Self::get(); let mods = modrinth::search_projects( name.to_owned(), - &pack.info.minecraft_version, - &pack.info.loader.to_string().to_lowercase(), + &config.info.minecraft_version, + &config.info.loader.to_string().to_lowercase(), ) .await .unwrap(); @@ -98,21 +104,36 @@ impl Pack { let versions = modrinth::get_project_versions( &project.project_id, - &pack.info.minecraft_version, - &pack.info.loader.to_string().to_lowercase(), + &config.info.minecraft_version, + &config.info.loader.to_string().to_lowercase(), ) .await .unwrap(); let version = versions.get(0).unwrap(); - pack.mods.push(Mod { + config.mods.push(Mod { id: project.project_id.clone(), version_id: version.id.clone(), }); - let pack_toml = toml::to_string_pretty(&pack).unwrap(); + let config_toml = toml::to_string_pretty(&config).unwrap(); - std::fs::write(".packium.toml", pack_toml).unwrap(); + std::fs::write(".packium.toml", config_toml).unwrap(); + } + + pub async fn remove() { + let mut config = Self::get(); + let mods = config.mods().await; + + let project = Select::new("Choose a mod to remove", mods) + .prompt() + .unwrap(); + + config.mods.retain(|x| x.id != project.id); + + let config_toml = toml::to_string_pretty(&config).unwrap(); + + std::fs::write(".packium.toml", config_toml).unwrap(); } } diff --git a/src/main.rs b/src/main.rs index b716c0a..e77fc12 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ mod cli; +mod config; mod modrinth; mod pack; @@ -10,10 +11,13 @@ async fn main() { match &args.command { cli::Commands::Init => { - pack::Pack::init().await; + config::Config::init().await; } cli::Commands::Add { name } => { - pack::Pack::add(name).await; + config::Config::add(name).await; + } + cli::Commands::Remove => { + config::Config::remove().await; } _ => (), }; diff --git a/src/modrinth.rs b/src/modrinth.rs index ccf8f53..6a57401 100644 --- a/src/modrinth.rs +++ b/src/modrinth.rs @@ -1,5 +1,5 @@ +use crate::config; use core::fmt; - use serde::Deserialize; #[derive(Deserialize, Debug)] @@ -11,13 +11,30 @@ pub struct MinecraftVersion { } #[derive(Deserialize, Debug)] -pub struct Mod { +pub struct SearchProject { pub title: String, pub description: String, pub project_id: String, + pub game_versions: Vec, + pub versions: Vec, } -impl fmt::Display for Mod { +impl fmt::Display for SearchProject { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.title) + } +} + +#[derive(Deserialize, Debug)] +pub struct Project { + pub title: String, + pub description: String, + pub id: String, + pub game_versions: Vec, + pub versions: Vec, +} + +impl fmt::Display for Project { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.title) } @@ -25,7 +42,7 @@ impl fmt::Display for Mod { #[derive(Deserialize, Debug)] pub struct Search { - hits: Vec, + hits: Vec, } #[derive(Deserialize, Debug)] @@ -48,7 +65,7 @@ pub async fn search_projects( query: String, version: &String, loader: &String, -) -> Result, reqwest::Error> { +) -> 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?; @@ -70,3 +87,15 @@ pub async fn get_project_versions( Ok(response) } + +pub async fn get_multiple_project( + project_ids: Vec, +) -> Result, reqwest::Error> { + let ids = project_ids.join("\", \""); + + let url = format!("https://api.modrinth.com/v2/projects?ids=[\"{ids}\"]"); + + let response = reqwest::get(url).await?.json::>().await?; + + Ok(response) +}