unpack and add downloaded mod

This commit is contained in:
2026-03-12 00:09:21 +01:00
parent 1eb9341d93
commit c8fdf0bc23
3 changed files with 63 additions and 8 deletions

View File

@@ -92,7 +92,7 @@ fn command_order(root_config: &RootConfig, instance_id: &str) -> anyhow::Result<
Ok(())
}
fn command_download(root_config: &RootConfig, nxm_url: &str) -> anyhow::Result<()> {
fn command_download(root_config: &mut RootConfig, nxm_url: &str) -> anyhow::Result<()> {
let Some(dl_location) = root_config.download_location() else {
return Err(anyhow!("No download location set"));
};
@@ -101,7 +101,22 @@ fn command_download(root_config: &RootConfig, nxm_url: &str) -> anyhow::Result<(
return Err(anyhow!("No API key provided"));
};
download_nxm(api_key, nxm_url, dl_location)?;
let (dl_file, mod_info) = download_nxm(api_key, nxm_url, dl_location)?;
let mod_id = mod_info.generate_id();
if root_config.game_by_id(&mod_id).is_some() {
error!(
"Generated mod id already exists. Pleas install downloaded mod manually. Downloaded at {}",
&dl_file.to_string_lossy()
);
return Err(anyhow!("Mod with generated already exists"));
}
let new_mod = unpack(root_config, &mod_id, dl_file)?;
root_config.add_mod(&new_mod);
root_config.save_to_file()?;
Ok(())
}
@@ -156,7 +171,7 @@ fn main() -> Result<(), Box<dyn Error>> {
api.validate_key()?;
}
cli::Commands::Download { url } => {
command_download(&root_config, &url)?;
command_download(&mut root_config, &url)?;
}
cli::Commands::Unpack { id, path } => {
command_unpack(&mut root_config, &id, path)?;

View File

@@ -101,8 +101,8 @@ pub struct ModInfo {
// pub endorsement_count: u64,
// pub created_timestamp: u64,
// pub created_time: String,
pub updated_timestamp: u64,
pub updated_time: String,
// pub updated_timestamp: u64,
// pub updated_time: String,
// pub author: String,
// pub uploaded_by: String,
// pub uploaded_users_profile_url: String,
@@ -112,3 +112,39 @@ pub struct ModInfo {
// pub user: String /* Complex struct */,
// pub endorsement: String /* Complex struct*/ ,
}
impl ModInfo {
/// Try to generate a id for a mod based on name, mod_id and version
pub fn generate_id(&self) -> String {
const MAX_CHARS: usize = 16;
const MIN_CHARS: usize = 8;
let mut short_name = String::new();
for word in self.name.split_whitespace() {
let cleaned: String = word.chars().filter(|c| !c.is_ascii_punctuation()).collect();
if cleaned.is_empty() {
continue;
}
if short_name.is_empty() {
short_name.push_str(&cleaned);
} else {
short_name.push('_');
short_name.push_str(&cleaned);
}
// Ensure at least two words, then stop when >= 8 chars
let words = short_name.matches('_').count() + 1;
if words >= 2 && short_name.len() >= MIN_CHARS {
break;
}
}
if short_name.len() > MAX_CHARS {
short_name.truncate(MAX_CHARS);
}
format!("{}-{}-{}", short_name, self.mod_id, self.version)
}
}

View File

@@ -12,7 +12,11 @@ use crate::nexus::{
api::{DownloadLocation, ModInfo},
};
pub fn download_nxm(api_key: &str, link: &str, target_dir: impl AsRef<Path>) -> anyhow::Result<()> {
pub fn download_nxm(
api_key: &str,
link: &str,
target_dir: impl AsRef<Path>,
) -> anyhow::Result<(PathBuf, ModInfo)> {
let api = NexusAPI::new(api_key);
let Some(parsed_url) = NXMUrl::parse_url(link) else {
return Err(anyhow!("Failed to parse url"));
@@ -30,9 +34,9 @@ pub fn download_nxm(api_key: &str, link: &str, target_dir: impl AsRef<Path>) ->
create_dir_all(parent)?;
}
download_mod(selected_mirror, download_path)?;
download_mod(selected_mirror, &download_path)?;
Ok(())
Ok((download_path, mod_info))
}
fn download_mod(mod_dl_link: &DownloadLocation, target: impl AsRef<Path>) -> anyhow::Result<()> {