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

                                                           








                                                                                                 
                                        


                    
                 




                          



                                                                                 
                                                                                                        


                                          
                                   


                                                                                                              
 
                                                                   
 


                                                                                                   
 
                                                                 
 
                                                   
 
                        
                                                   


                                                                   
                                                                         
                                

                         
 
                                                                     
                                 
                                                                             
 
                             
                                      
                           

                                         
                        
                             


                      
                                
                                                                     
                           
                     
                               
                                                                        


                                          
                                        
                                 
                     
                  
              
                            
         
 

                                                                                     
 
                  
                                           

                                           
 
                                                       
                                                                                                            

                                  
                       

                                                                                                                  

                                             

                                                                             
                                                                     
                                               

                                                                              
                                                                                     

                      







                                                 

             

                                                                           
                        
     
 


                                                      


          
                                                                                                                   
                             
                                                                              
 
                                           
 





                                                 
     
 
                                           


                                                
                       
                                       
                                 

               
                                                                                
 
                                                                                                                      

                          




                                                                


                                                             

                                          







                                                                        
                                                                                                          
     
 



                                                                             

                          
use indicatif::{ProgressBar, ProgressStyle, MultiProgress};

use crate::{
    config::Cfg,
    db::{
        mods_get_info, userlist_change_versions, userlist_get_all_ids,
        userlist_get_applicable_versions, userlist_get_current_version, userlist_get_set_version,
    },
    error::{ErrorType, MLError, MLE},
    files::{clean_list_dir, delete_version, disable_version, download_versions},
    modrinth::{extract_current_version, versions, Version},
    List, PROGRESS_CHARS, STYLE_BAR_POS,
};

pub async fn update(
    config: &Cfg,
    liststack: Vec<List>,
    clean: bool,
    direct_download: bool,
    delete_old: bool,
) -> MLE<()> {

    let mp = MultiProgress::new();

    let update_p = mp.add(ProgressBar::new(liststack.len().try_into().unwrap()));
    let bar_style = ProgressStyle::with_template(STYLE_BAR_POS).unwrap().progress_chars(PROGRESS_CHARS);
    update_p.set_style(bar_style.clone());
    update_p.set_message("Update");

    for current_list in liststack {
        let list_p = mp.insert_before(&update_p, ProgressBar::new(2));
        list_p.set_style(ProgressStyle::with_template(STYLE_BAR_POS).unwrap().progress_chars(PROGRESS_CHARS));
        list_p.set_message(format!("Update {}", current_list.id));

        let mods = userlist_get_all_ids(config, &current_list.id)?;

        let list_u_p = mp.insert_before(&list_p, ProgressBar::new(mods.len().try_into().unwrap()));
        list_u_p.set_style(bar_style.clone());
        list_u_p.set_message(format!("Update {}", current_list.id));

        let mut current_versions: Vec<(String, String)> = vec![];

        let mut updatestack: Vec<Version> = vec![];

        for id in mods {
            let info = mods_get_info(config, &id)?;
            list_u_p.set_message(format!("Update {}", info.title));
            
            //Skip check if version is set
            if userlist_get_set_version(config, &current_list.id, &id)? {
                list_u_p.inc(1);
                continue;
            }

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

            updatestack.push(
                match specific_update(
                    config,
                    clean,
                    current_list.clone(),
                    &id,
                    &list_u_p
                )
                .await
                {
                    Ok(ver) => {
                        current_versions.push((disable_version, id));
                        ver
                    }
                    Err(e) => {
                        if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" {
                        } else {
                            return Err(e);
                        };
                        list_u_p.inc(1);
                        continue;
                    }
                },
            );
            list_u_p.inc(1);
        }

        list_u_p.finish_with_message(format!("Updated mods in {}", current_list.id));
        list_p.inc(1);

        if clean {
            list_p.set_message("Cleaning");
            clean_list_dir(&current_list)?;
        };

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

            //Disable old versions
            if !clean {
                let d_p = mp.insert_before(&list_p, ProgressBar::new(current_versions.len().try_into().unwrap()));
                d_p.set_style(bar_style.clone());
                for ver in current_versions {
                    if delete_old {
                        d_p.set_message(format!("Delete version {}", ver.0));
                        d_p.inc(1);
                        delete_version(current_list.clone(), ver.0)?;
                    } else if ver.0 != "NONE" {
                        d_p.set_message(format!("Disable version {}", ver.0));
                        d_p.inc(1);
                        disable_version(config, current_list.clone(), ver.0, ver.1)?;
                    };
                }

                let del_msg = if delete_old {
                    "Deleted all old versions"
                } else {
                    "Disabled all old versions"
                };

                d_p.finish_with_message(del_msg);
            }
        };
        list_p.inc(1);
        list_p.finish_with_message(format!("Updated {}", current_list.id));
        update_p.inc(1);
    }

    update_p.finish_with_message("Updated all lists");


    Ok(())
}

async fn specific_update(config: &Cfg, clean: bool, list: List, id: &str, progress: &ProgressBar) -> MLE<Version> {
    let applicable_versions =
        versions(&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![];
    if clean
        || (versions.join("|")
            != userlist_get_applicable_versions(
                config,
                String::from(&list.id),
                String::from(id),
            )?)
    {
        let current_str = extract_current_version(applicable_versions.clone())?;

        if !clean { progress.println(format!("Found new version for {}", mods_get_info(config, id).unwrap().title)); }

        //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 files = &current_ver.files;

        let link = match files.clone().into_iter().find(|f| f.primary) {
                Some(f) => f,
                None => { files[0].clone() }
            }
            .url;

        userlist_change_versions(config, list.id, current_str, versions.join("|"), link, id.to_string())?;
    }

    if current.is_empty() {
        return Err(MLError::new(ErrorType::ModError, "NO_UPDATE_AVAILABLE"));
    };

    Ok(current[0].clone())
}