From 5affc42cd3f0323f84bf81ee6a57e208ac6edbca Mon Sep 17 00:00:00 2001 From: Tuxinal <24763016+tuxinal@users.noreply.github.com> Date: Mon, 12 Sep 2022 11:54:57 +0430 Subject: [PATCH] Add scanning functionality --- src/cli.rs | 7 +++ src/main.rs | 11 ++++ src/subcommands/mod.rs | 2 + src/subcommands/scan.rs | 127 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+) create mode 100644 src/subcommands/scan.rs diff --git a/src/cli.rs b/src/cli.rs index 2d74d46..cb31a93 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -82,6 +82,13 @@ pub enum SubCommands { }, /// Download and install the latest version of the mods specified Upgrade, + #[clap(about("Scan profile for mods"))] + Scan { + #[clap(long)] + #[clap(arg_enum)] + #[clap(help("Preferred platform to scan mods from (default: modrinth)"))] + preferred_platform: Option + } } #[derive(Subcommand)] diff --git a/src/main.rs b/src/main.rs index 641c29d..825aa73 100644 --- a/src/main.rs +++ b/src/main.rs @@ -347,6 +347,17 @@ async fn actual_main(cli_app: Ferium) -> Result<()> { check_empty_profile(profile)?; subcommands::upgrade(modrinth, curseforge, github, profile).await?; }, + SubCommands::Scan { preferred_platform } => { + check_internet().await?; + let profile = get_active_profile(&mut config)?; + subcommands::scan( + modrinth, + curseforge, + profile, + preferred_platform.unwrap_or(libium::config::structs::ModPlatform::Modrinth), + ) + .await?; + }, }; config.profiles.iter_mut().for_each(|profile| { diff --git a/src/subcommands/mod.rs b/src/subcommands/mod.rs index e3940ca..c4cf30c 100644 --- a/src/subcommands/mod.rs +++ b/src/subcommands/mod.rs @@ -4,5 +4,7 @@ pub mod modpack; pub mod profile; mod remove; mod upgrade; +mod scan; pub use remove::remove; pub use upgrade::upgrade; +pub use scan::scan; \ No newline at end of file diff --git a/src/subcommands/scan.rs b/src/subcommands/scan.rs new file mode 100644 index 0000000..db8c404 --- /dev/null +++ b/src/subcommands/scan.rs @@ -0,0 +1,127 @@ +use std::{ffi::OsStr, fs, sync::Arc}; + +use anyhow::{bail, Result}; +use colored::Colorize; +use ferinth::Ferinth; +use furse::Furse; +use libium::{ + add, + config::structs::{Mod, ModIdentifier, ModPlatform, Profile}, + scan, +}; + +use crate::{CROSS, TICK, YELLOW_TICK}; +pub async fn scan( + modrinth: Arc, + curseforge: Arc, + profile: &mut Profile, + preferred_platform: libium::config::structs::ModPlatform, +) -> Result<()> { + let mods = scan::scan( + modrinth.clone(), + curseforge.clone(), + fs::read_dir(&profile.output_dir)? + .filter_map(|path| { + if let Ok(entry) = path { + let file_path = entry.path(); + if matches!(file_path.extension().and_then(OsStr::to_str), Some("jar")) { + Some(file_path) + } else { + None + } + } else { + None + } + }) + .collect(), + ) + .await?; + let mut mods_to_add: Vec<(std::path::PathBuf, ModIdentifier)> = vec![]; + for (path, mod_) in mods { + if !matches!(mod_, (None, None)) { + let mod_to_add = match (&mod_, &preferred_platform) { + ((Some(modrinth_mod), _), ModPlatform::Modrinth) => { + ModIdentifier::ModrinthProject(modrinth_mod.project_id.clone()) + }, + ((_, Some(curseforge_mod)), ModPlatform::Curseforge) => { + ModIdentifier::CurseForgeProject(curseforge_mod.mod_id) + }, + _ => match &mod_ { + (Some(modrinth_mod), _) => { + ModIdentifier::ModrinthProject(modrinth_mod.project_id.clone()) + }, + (_, Some(curseforge_mod)) => { + ModIdentifier::CurseForgeProject(curseforge_mod.mod_id) + }, + _ => unreachable!(), + }, + }; + mods_to_add.push((path, mod_to_add)); + } else { + eprintln!( + "{}", + format!( + "{} Could not find {} on any platform", + CROSS, + path.display() + ) + .red() + ); + } + } + for (path, mod_) in mods_to_add { + match add_mod(modrinth.clone(), curseforge.clone(), mod_, profile).await { + Ok(mod_) => { + println!( + "{} found {} on {}", + TICK.clone(), + &mod_.name, + match &mod_.identifier { + ModIdentifier::CurseForgeProject(_) => "CurseForge", + ModIdentifier::ModrinthProject(_) => "Modrinth", + _ => unreachable!(), + } + ); + profile.mods.push(mod_); + }, + Err(add::Error::AlreadyAdded) => { + println!( + "{} {} is already added", + YELLOW_TICK.clone(), + path.display() + ) + }, + Err(err) => bail!(err), + } + } + Ok(()) +} + +async fn add_mod( + modrinth: Arc, + curseforge: Arc, + mod_: ModIdentifier, + profile: &Profile, +) -> Result { + match &mod_ { + ModIdentifier::ModrinthProject(id) => { + let (project, _version) = add::modrinth(modrinth, id, profile, None, None).await?; + Ok(Mod { + check_game_version: None, + check_mod_loader: None, + identifier: mod_, + name: project.title, + }) + }, + ModIdentifier::CurseForgeProject(id) => { + let (project, _file) = add::curseforge(curseforge, *id, profile, None, None).await?; + Ok(Mod { + check_game_version: None, + check_mod_loader: None, + identifier: mod_, + name: project.name, + }) + }, + _ => unreachable!(), + } +}