summaryrefslogblamecommitdiff
path: root/src/commands/update.rs
blob: bc5b316429b0dd788d13e5642c5edad97fd84b2b (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                                                                                                                                                                                                                                                                                                                                                                                                                                    
 
                                                           






                                                           
                                                        
                                                
                               
     

                                                                                             
 
                                                                                                                             

                                                                                  

                                                                 






                                                             
 



                                                                                 
 
                                                                     
                                                                                                                                   
 

                                                                                                             
                                
                                                                     

                           
                               
                                                                        
                                                                                                        


                                          
                                 


                     
          
 
                                                     
 
                                                       
                                                                                        

                                  


                                             
                                                                    

                                                                     
                                                                     


                                                                                             

             
     



          

                                                                                                                   

                                           






                                                 
     
 
                                           


                                                                                                                                      
                                                                                








                                                                             



                                                                                                                                                       

                                          



                                                                                                          
                                                                                              
     
 
                                                                                                   
    
                             

                          
 


                                  
                                                                                      
    
                                                    
                                                                                                                                                                         






























                                                                                                                                                                              
                                                                            
 
use crate::{config::Cfg, modrinth::{versions, extract_current_version, Version}, get_current_list, db::{userlist_get_all_ids, userlist_get_applicable_versions, userlist_change_versions, lists_get_all_ids, lists_get, userlist_get_current_version, mods_get_title, userlist_get_set_version}, List, input::Input, files::{delete_version, download_versions, disable_version, clean_list_dir}, error::{MLE, MLError, ErrorType}};

pub async fn update(config: Cfg, input: Input) -> MLE<()> {
    let mut liststack: Vec<List> = vec![];
    if input.all_lists {
        let list_ids = lists_get_all_ids(config.clone())?;
        for id in list_ids {
            liststack.push(lists_get(config.clone(), id)?);
        }
    } else {
        let current = get_current_list(config.clone())?;
        println!("Update list {}:", current.id);
        liststack.push(current)
    }
    cmd_update(config, liststack, input.clean, input.direct_download, input.delete_old).await
}

pub async fn cmd_update(config: Cfg, liststack: Vec<List>, clean: bool, direct_download: bool, delete_old: bool) -> MLE<()> {
    for current_list in liststack {
        let mods = userlist_get_all_ids(config.clone(), current_list.clone().id)?;
        
        let mut current_versions: Vec<(String, String)> = vec![];
        
        println!("  └Update mods:");
        let mut updatestack: Vec<Version> = vec![];
        
        for id in mods {
            let title = mods_get_title(config.clone(), &id)?;
            println!("\t└{}", title);

            if userlist_get_set_version(config.clone(), &current_list.id, &id)? {
                println!("\t  └Set version, skipping update");
                continue;
            }

            //Getting current installed version for disable or delete
            let disable_version = userlist_get_current_version(config.clone(), String::from(&current_list.id), String::from(&id))?;

            updatestack.push(
                match specific_update(config.clone(), clean, current_list.clone(), String::from(&id)).await {
                    Ok(ver) => {
                        current_versions.push((disable_version, id));
                        ver
                    },
                    Err(e) => {
                        if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" {
                            println!("\t  └No new version found for the specified minecraft version");
                        } else {
                            return Err(e);
                        };
                        continue;
                    }
                }
            )
        };

        if clean { clean_list_dir(&current_list)?; };

        if direct_download && !updatestack.is_empty() {
            download_versions(current_list.clone(), config.clone(), updatestack).await?;

            //Disable old versions
            if !clean {
                for ver in current_versions {
                    if delete_old {
                        println!("\t  └Delete version {}", ver.0);
                        delete_version(current_list.clone(), ver.0)?;
                    } else if ver.0 != "NONE" { 
                        println!("\t  └Disable version {}", ver.0);
                        disable_version(config.clone(), current_list.clone(), ver.0, ver.1)?;
                    };
                }
            }
        };
    }

    Ok(())
}

async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> MLE<Version> {
    let applicable_versions = versions(String::from(&config.apis.modrinth), String::from(&id), list.clone()).await;
    
    let mut versions: Vec<String> = vec![];
    
    if !applicable_versions.is_empty() {
        for ver in &applicable_versions {
            versions.push(String::from(&ver.id));
        }
    } else {
        versions.push(String::from("NONE"));
    }

    let mut current: Vec<Version> = vec![];
    //TODO Split clean and no match
    if clean || (versions.join("|") != userlist_get_applicable_versions(config.clone(), String::from(&list.id), String::from(&id))?) {

        let current_str = extract_current_version(applicable_versions.clone())?;

        if clean {
            println!("\t  └Add version to downloadstack");
        } else {
            println!("\t  └Get versions for specified minecraft versions");
            println!("\t  └New current version: {}", current_str);
        };

        //get new versions
        let current_ver = match applicable_versions.into_iter().find(|ver| ver.id == current_str).ok_or("!no current version in applicable_versions") {
            Ok(v) => Ok(v),
            Err(e) => Err(MLError::new(ErrorType::Other, e)),
        }?;
        current.push(current_ver.clone());

        let link = match current_ver.files.into_iter().find(|f| f.primary).ok_or("!no primary in links") {
            Ok(p) => Ok(p),
            Err(e) => Err(MLError::new(ErrorType::Other, e)),
        }?.url;
        userlist_change_versions(config, list.id, current_str, versions.join("|"), link, id)?;
    }

    if current.is_empty() { return Err(MLError::new(ErrorType::ModError, "NO_UPDATE_AVAILABLE")) };
    
    //println!(" └✔️");
    Ok(current[0].clone())
}

#[tokio::test]
async fn download_updates_test() {

    use crate::{modrinth::{Version, VersionFile, Hash, VersionType}, Modloader, List};
    
    let config = Cfg::init("modlist.toml").unwrap();
    let current_list = List { id: String::from("..."), mc_version: String::from("..."), modloader: Modloader::Fabric, download_folder: String::from("./dev/tests/dl") }; 

    let versions = vec![Version { 
            id: "dEqtGnT9".to_string(),
            project_id: "kYuIpRLv".to_string(),
            author_id: "Qnt13hO8".to_string(),
            featured: true,
            name: "1.2.2-1.19 - Fabric".to_string(),
            version_number: "1.2.2-1.19".to_string(),
            changelog: None,
            date_published: "2022-11-02T17:41:43.072267Z".to_string(),
            downloads: 58,
            version_type: VersionType::release,
            files: vec![VersionFile {
                    hashes: Hash {
                        sha1: "fdc6dc39427fc92cc1d7ad8b275b5b83325e712b".to_string(),
                        sha512: "5b372f00d6e5d6a5ef225c3897826b9f6a2be5506905f7f71b9e939779765b41be6f2a9b029cfc752ad0751d0d2d5f8bb4544408df1363eebdde15641e99a849".to_string()
                    },
                    url: "https://cdn.modrinth.com/data/kYuIpRLv/versions/dEqtGnT9/waveycapes-fabric-1.2.2-mc1.19.2.jar".to_string(),
                    filename: "waveycapes-fabric-1.2.2-mc1.19.2.jar".to_string(),
                    primary: true,
                    size: 323176
            }],
            game_versions: vec![
                "1.19".to_string(),
                "1.19.1".to_string(),
                "1.19.2".to_string()
            ],
            loaders: vec![
                "fabric".to_string()
            ]
        }];
    assert!(download_versions(current_list, config, versions).await.is_ok())
}