legacympt-rs/mpt/src/commands/init.rs

183 lines
5.3 KiB
Rust

use crate::{config::Locations, forge};
use addonscript::{
manifest::{
installer::Installer,
link::Link,
Contributor,
File,
Manifest,
ManifestType,
Meta,
Relation,
RelationType,
Repository,
RepositoryType,
Version,
},
util::default_file_opts,
};
use anyhow::Context;
use crossterm::{
execute,
style::{
Attribute,
Color,
Print,
PrintStyledContent,
ResetColor,
SetAttribute,
SetForegroundColor,
Stylize,
},
ExecutableCommand,
};
use reqwest::Client;
use std::path::Path;
use url::Url;
use crate::config::Config;
const DEFAULT_CONFIG: &[u8] = include_bytes!("../../assets/modpacktoolsconfig.toml");
pub async fn run(
modpack_name: String,
author_name: String,
mcversion: String,
) -> anyhow::Result<()> {
let mut stdout = std::io::stdout();
execute!(
stdout,
SetForegroundColor(Color::Green),
Print("Creating modpack "),
SetForegroundColor(Color::Cyan),
SetAttribute(Attribute::Bold),
Print(&modpack_name),
ResetColor,
SetForegroundColor(Color::Green),
Print(" on minecraft version "),
SetForegroundColor(Color::Cyan),
SetAttribute(Attribute::Bold),
Print(&mcversion),
ResetColor,
Print('\n'),
)?;
let config_path = Path::new("modpacktoolsconfig.toml");
if !config_path.exists() {
tokio::fs::write(config_path, DEFAULT_CONFIG).await?;
stdout.execute(PrintStyledContent(
"Created config!\n"
.with(Color::Green)
.attribute(Attribute::Bold),
))?;
} else {
stdout.execute(PrintStyledContent(
"Config already exists, skipping...\n"
.with(Color::Red)
.attribute(Attribute::Italic),
))?;
}
let config = tokio::fs::read(config_path).await?;
let Config {
locations: Locations { src, .. },
..
} = toml::from_slice::<Config>(&config).context("failed to deserialize config")?;
let path = Path::new(&src);
if path.join("modpack.json").exists() || path.join("modpack.json5").exists() {
stdout.execute(PrintStyledContent(
"Manifest already exists, skipping...\n"
.with(Color::Red)
.attribute(Attribute::Italic),
))?;
} else {
let mut relations = vec![];
stdout.execute(PrintStyledContent(
"Trying to find newest forge version...\n".with(Color::Magenta),
))?;
if let Some(ver) = forge::newest_forge_version(&Client::new(), &mcversion).await? {
execute!(
stdout,
SetForegroundColor(Color::Green),
Print("Found newest forge version "),
SetForegroundColor(Color::Cyan),
SetAttribute(Attribute::Bold),
Print(&ver),
ResetColor,
Print('\n'),
)?;
relations.push(Relation {
id: "forge".into(),
file: None,
relation_type: RelationType::Modloader,
options: default_file_opts(),
versions: Some(format!(
"[{mcver}-{forgever}-{mcver}]",
mcver = mcversion,
forgever = ver,
)),
})
} else {
execute!(
stdout,
SetForegroundColor(Color::Red),
Print("Couldn't find forge version for minecraft "),
SetAttribute(Attribute::Bold),
SetForegroundColor(Color::Cyan),
Print(&mcversion),
ResetColor,
SetForegroundColor(Color::Red),
Print(" skipping forge...\n"),
ResetColor,
)?;
}
tokio::fs::create_dir_all(path).await?;
let data = serde_json::to_vec_pretty(&Manifest {
// TODO rename this to snake_case
id: modpack_name.clone(),
manifest_type: ManifestType::Modpack,
versions: vec![Version {
version: "1.0".into(),
mcversion: vec![mcversion],
files: vec![File::Link {
id: Some("overrides".into()),
link: Link::File("overrides".into()),
installer: Installer::Override,
options: Some(default_file_opts()),
}],
relations,
}],
repositories: vec![Repository {
id: "curseforge".into(),
repo_type: RepositoryType::Curseforge,
url: Url::parse("https://cursemaven.com").unwrap(), // unwrap is ok on fixed value
}],
meta: Meta {
name: modpack_name,
contributors: vec![Contributor {
roles: vec!["Owner".to_owned()],
name: author_name,
}],
},
})?;
tokio::fs::write(path.join("modpack.json5"), data).await?;
stdout.execute(PrintStyledContent(
"Created manifest!\n"
.with(Color::Green)
.attribute(Attribute::Bold),
))?;
}
Ok(())
}