Compare commits

...

2 Commits

Author SHA1 Message Date
d7c50ec8be
Added a way to add mods 2024-05-28 16:23:51 +02:00
20dddba0d5
Added ability to initialze a modpack 2024-05-28 14:44:46 +02:00
5 changed files with 131 additions and 9 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
/target /target
.packium.toml

View File

@ -24,4 +24,7 @@ pub enum Commands {
/// The name of the mod to add /// The name of the mod to add
name: String, name: String,
}, },
/// Remove a mod from the modpack
Remove,
} }

View File

@ -12,6 +12,9 @@ async fn main() {
cli::Commands::Init => { cli::Commands::Init => {
pack::Pack::init().await; pack::Pack::init().await;
} }
cli::Commands::Add { name } => {
pack::Pack::add(name).await;
}
_ => (), _ => (),
}; };
} }

View File

@ -1,3 +1,5 @@
use core::fmt;
use serde::Deserialize; use serde::Deserialize;
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
@ -8,9 +10,63 @@ pub struct MinecraftVersion {
pub major: bool, 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<Mod>,
}
#[derive(Deserialize, Debug)]
pub struct ProjectVersion {
pub name: String,
pub game_versions: Vec<String>,
pub version_type: String,
pub id: String,
pub project_id: String,
}
pub async fn get_minecraft_versions() -> Result<Vec<MinecraftVersion>, reqwest::Error> { pub async fn get_minecraft_versions() -> Result<Vec<MinecraftVersion>, reqwest::Error> {
reqwest::get("https://api.modrinth.com/v2/tag/game_version") reqwest::get("https://api.modrinth.com/v2/tag/game_version")
.await? .await?
.json::<Vec<MinecraftVersion>>() .json::<Vec<MinecraftVersion>>()
.await .await
} }
pub async fn search_projects(
query: String,
version: &String,
loader: &String,
) -> Result<Vec<Mod>, 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::<Search>().await?;
Ok(response.hits)
}
pub async fn get_project_versions(
id: &String,
version: &String,
loader: &String,
) -> Result<Vec<ProjectVersion>, 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::<Vec<ProjectVersion>>()
.await?;
Ok(response)
}

View File

@ -1,23 +1,31 @@
use crate::modrinth; use crate::modrinth;
use colored::*; use colored::*;
use inquire::Select; use inquire::Select;
use serde::Serialize; use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter}; use std::{
fmt::{Display, Formatter},
fs,
};
#[derive(Serialize)] #[derive(Serialize, Deserialize)]
pub struct Pack { pub struct Pack {
info: Info, info: Info,
mods: Vec<Mod>,
} }
#[derive(Serialize)] #[derive(Serialize, Deserialize)]
pub struct Mod {
id: String,
version_id: String,
}
#[derive(Serialize, Deserialize)]
pub struct Info { pub struct Info {
loader: Modloader, loader: Modloader,
loader_version: String,
minecraft_version: String, minecraft_version: String,
} }
#[derive(Serialize, Debug, Clone, Copy)] #[derive(Serialize, Deserialize, Debug, Clone, Copy)]
#[serde(untagged)]
pub enum Modloader { pub enum Modloader {
Fabric, Fabric,
Quilt, Quilt,
@ -37,15 +45,21 @@ impl Display for Modloader {
} }
impl Pack { 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() { pub async fn init() {
println!("Fetching Minecraft information"); println!("Fetching Minecraft information...");
let versions = modrinth::get_minecraft_versions().await.unwrap(); let versions = modrinth::get_minecraft_versions().await.unwrap();
let versions = versions let versions = versions
.iter() .iter()
.filter(|x| x.version_type == "release".to_string()) .filter(|x| x.version_type == "release".to_string())
.map(|x| x.version.clone()) .map(|x| &x.version)
.collect(); .collect();
let modloader = Select::new("Modloader?", Modloader::VARIANTS.to_vec()) let modloader = Select::new("Modloader?", Modloader::VARIANTS.to_vec())
@ -55,5 +69,50 @@ impl Pack {
let version = Select::new("Minecraft version?", versions) let version = Select::new("Minecraft version?", versions)
.prompt() .prompt()
.unwrap(); .unwrap();
let pack = Pack {
info: Info {
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();
} }
} }