summaryrefslogblamecommitdiff
path: root/src/input.rs
blob: 6c62ab7ebd62663175934649cacafaa17f67b744 (plain) (tree)
1
2
3
4
5
6
7
8
                                                                                                                                                                           
 
                                      
                  
                             
                                        
                                   
                          



                              





                                          
                                      
                             







                                      
       
            
          

 



                                      


                                      
                      

           
           
            

 





                                      


                                                           

                                                                     

                                            
        
                                                       
                                                  
                                    



                                       





                                                         
                                                     


                                            
                                                                       
                                


                                                 




                                                  
                  


                                                        
                                             
                                                                                              

                                                                                                                   

                     
                                
                         

                                                        
                                             
                                                                                         

                                                                                                          

                      


                                                           
                                             
                                                                                              


                                                                                                      
                  
                                  
                                       
                  





                                     
                                  
                                            



                                      
                        




                                                                                                                



                                                          




                                                                                                             



                                                             



                                                             

                         













                                                                                                                 

                         




                                                                                                         

                          




                                                                                                         











                                                            


                                               
                                                                                                                                 




                    

                        
                        



                            





                           
                       

                


     

                                                                      


                                                                                                               

                                             
                                                     
                       



                                                           
                                    
                                                                            


                                              
                                                                                                                              
                                                                                         
                     
          
                               
                                                                                                               
                                                                                         
                     
          


     
                                                                  




                                                                               


                                                                                                                       
                                                                                                                        




                                                                                              

                                                                                                                           
                     
          
                                
                                                                                                                 
                     
          
                                







                                                                                                                 
                     
         

     


                 

                                                    
                                                                                

                                     

                              
                               



                                   





                                                         
                             
                       

         
 








                                                                                 
                                               
                                                                           
                               



                                   





                                                                                
                             


                      
 
use crate::{error::{MLE, MLError, ErrorType}, Modloader, config::Cfg, db::lists_get, get_current_list, List, modrinth::{get_minecraft_version, MCVersionType}, IDSelector};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Input {
    pub command: Option<Cmd>,
    pub mod_options: Option<ModOptions>,
    pub mod_id: Option<IDSelector>,
    pub set_version: bool,
    pub all_lists: bool,
    pub clean: bool,
    pub direct_download: bool,
    pub delete_old: bool,
    pub list: Option<List>,
    pub list_options: Option<ListOptions>,
    pub list_id: Option<String>,
    pub list_mcversion: Option<String>,
    pub modloader: Option<Modloader>,
    pub directory: Option<String>,
    pub io_options: Option<IoOptions>,
    pub file: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Cmd {
    Mod,
    List,
    Update,
    Download,
    Io,
    Version,
    Setup,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ModOptions {
    Add,
    Remove
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ListOptions {
    Add,
    Remove,
    Change,
    Version,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum IoOptions {
    Export,
    Import
}

impl Input {
    fn from(config: Cfg, input: Vec<String>) -> MLE<Self> {
        let input_string = input.join(" ");
        let mut args: Vec<&str> = input_string.split(" -").collect();
        args[0] = args[0].split_at(1).1;
        
        let mut command: Option<Cmd> = None;
        
        let mut mod_options: Option<ModOptions> = None;
        let mut mod_id: Option<IDSelector> = None;
        let mut set_version = false;
        let mut all_lists = false;
        let mut clean = false;
        let mut direct_download = true;
        let mut delete_old = false;
        let mut list: Option<List> = None;
        let mut list_options: Option<ListOptions> = None;
        let mut list_id: Option<String> = None;
        let mut list_mcversion: Option<String> = None;
        let mut modloader: Option<Modloader> = None;
        let mut directory: Option<String> = None;
        let mut io_options: Option<IoOptions> = None;
        let mut file: Option<String> = None;
        
        for arg in args {
            let arg_split: Vec<&str> = arg.trim().split(' ').collect();
            match arg_split[0] {
                "v" | "version" => {
                    command = Some(Cmd::Version);
                },
                "d" | "download" => {
                    command = Some(Cmd::Download);
                },
                "u" | "update" => {
                    command = Some(Cmd::Update);
                },
                "ma" => {
                    command = Some(Cmd::Mod);
                    mod_options = Some(ModOptions::Add);
                    if arg_split.len() == 2 {
                        mod_id = Some(IDSelector::ModificationID(String::from(arg_split[1])));
                    } else {
                        return Err(MLError::new(ErrorType::ArgumentError, "Please specify a list mod slug or id"));
                    }
                },
                //TODO impl this
                "mv" => {
                    command = Some(Cmd::Mod);
                    mod_options = Some(ModOptions::Add);
                    if arg_split.len() == 2 {
                        mod_id = Some(IDSelector::VersionID(String::from(arg_split[1])));
                    } else {
                        return Err(MLError::new(ErrorType::ArgumentError, "Please specify a version id"));
                    };
                },
                "mr" => {
                    command = Some(Cmd::Mod);
                    mod_options = Some(ModOptions::Remove);
                    if arg_split.len() == 2 {
                        mod_id = Some(IDSelector::ModificationID(String::from(arg_split[1])));
                    } else {
                        return Err(MLError::new(ErrorType::ArgumentError, "Please specify a mod id"));
                    };
                },
                "set_version" => {
                    set_version = true;
                },
                "all_lists" => {
                    all_lists = true;
                },
                "clean" => {
                    clean = true;
                },
                "no_download" => {
                    direct_download = false;
                },
                "delete_old" => {
                    delete_old = true;
                },
                "l" => {
                    if arg_split.len() == 2 {
                        list = Some(lists_get(config.clone(), String::from(arg_split[1]))?);
                    } else {
                        return Err(MLError::new(ErrorType::ArgumentError, "Please specify a list via it's id"));
                    }
                }
                "la" => {
                    command = Some(Cmd::List);
                    list_options = Some(ListOptions::Add);
                    if arg_split.len() == 2 {
                        list_id = Some(String::from(arg_split[1]));
                    } else {
                        return Err(MLError::new(ErrorType::ArgumentError, "Please give the new list an id"));
                    }
                },
                "lr" => {
                    command = Some(Cmd::List);
                    list_options = Some(ListOptions::Remove);
                },
                "lc" => {
                    command = Some(Cmd::List);
                    list_options = Some(ListOptions::Change);
                },
                "lv" => {
                    command = Some(Cmd::List);
                    list_options = Some(ListOptions::Version);
                    if arg_split.len() == 2 {
                        list_mcversion = Some(String::from(arg_split[1]));
                    } else {
                        return Err(MLError::new(ErrorType::ArgumentError, "Please specify a minecraft version"));
                    }
                },
                "mcv" => {
                    if arg_split.len() == 2 {
                        list_mcversion = Some(String::from(arg_split[1]));
                    } else {
                        return Err(MLError::new(ErrorType::ArgumentError, "Please specify a minecraft version"));
                    }
                },
                "ml" => {
                    if arg_split.len() == 2 {
                        modloader = Some(Modloader::from(arg_split[1])?);
                    } else {
                        return Err(MLError::new(ErrorType::ArgumentError, "Please specify a modloader"));
                    }
                },
                "dir" => {
                    if arg_split.len() == 2 {
                        directory = Some(String::from(arg_split[1]));
                    } else {
                        return Err(MLError::new(ErrorType::ArgumentError, "Please specify a directory"));
                    }
                },
                "export" => {
                    command = Some(Cmd::Io);
                    io_options = Some(IoOptions::Export);
                },
                "import" => {
                    command = Some(Cmd::Io);
                    io_options = Some(IoOptions::Import);
                },
                "f" => {
                    file = Some(String::from(arg_split[1]));
                },
                "setup" => {
                    command = Some(Cmd::Setup);
                }
                _ => return Err(MLError::new(ErrorType::ArgumentError, format!("Unknown Argument ({})", arg_split[0]).as_str())),
            }
        }

        Ok(Self {
            command,
            mod_options,
            mod_id,
            set_version,
            all_lists,
            clean,
            direct_download,
            delete_old,
            list,
            list_options,
            list_id,
            list_mcversion,
            modloader,
            directory,
            io_options,
            file
        })
    }
}

pub async fn get_input(config: Cfg, args: Vec<String>) -> MLE<Input> {
    let input = Input::from(config.clone(), args)?;
    
    if input.command.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "No command specified")); };
    
    match input.clone().command.unwrap() {
        Cmd::Mod => check_mod(input, config),
        Cmd::List => check_list(input, config).await,
        _ => Ok(input),
    }
}

fn check_mod(mut input: Input, config: Cfg) -> MLE<Input> {
    if input.mod_options.is_none() {
        return Err(MLError::new(ErrorType::ArgumentError, "No mod option"));
    };
    match input.clone().mod_options.unwrap() {
        ModOptions::Add => {
            if input.mod_id.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "No mod id/slug or version id")); };
            if input.list_id.is_none() { input.list = Some(get_current_list(config)?); };
            Ok(input)
        },
        ModOptions::Remove => {
            if input.mod_id.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "MODS_NO_MODID")); };
            if input.list_id.is_none() { input.list = Some(get_current_list(config)?); };
            Ok(input)
        },
    }
}

async fn check_list(mut input: Input, config: Cfg) -> MLE<Input> {
    if input.list_options.is_none() {
        return Err(MLError::new(ErrorType::ArgumentError, "NO_LIST_ARGUMENT"));
    };
    match input.clone().list_options.unwrap() {
        ListOptions::Add => {
            if input.list_id.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "no list id specified")); };
            if input.list_mcversion.is_none() {
                println!("No Minecraft Version specified, defaulting to latest release");
                input.list_mcversion = Some(get_minecraft_version(&config.apis.modrinth, MCVersionType::Release).await);
            };
            if input.directory.is_none() {
                let id = input.clone().list_id.unwrap();
                println!("No download directory specified, defaulting to ./downloads/{}", id);
                input.directory = Some(format!("./downloads/{}", id))
            };
            if input.modloader.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "no modloader specified")); };
            Ok(input)
        },
        ListOptions::Remove => {
            if input.list.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "NO_LIST_SPECIFIED")); };
            Ok(input)
        },
        ListOptions::Change => {
            if input.list.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "NO_LIST_SPECIFIED")); };
            Ok(input)
        },
        ListOptions::Version => {
            if input.list.is_none() {
                println!("No list specified, using default");
                input.list = Some(get_current_list(config)?);
            };
            Ok(input)
        }
    }
}

#[test]
fn input_from() {
    let config = Cfg::init("modlist.toml").unwrap();
    assert_eq!(
        Input::from(config, vec![String::from("-la test -lv 1.19.3")]).unwrap(),
        Input {
            command: Some(Cmd::List),
            mod_options: None,
            mod_id: None,
            set_version: false,
            all_lists: false,
            clean: false,
            direct_download: false,
            delete_old: false,
            list: None,
            list_options: Some(ListOptions::Add),
            list_id: Some(String::from("test")),
            list_mcversion: Some(String::from("1.19.3")),
            modloader: None,
            directory: None,
            io_options: None,
            file: None,
        }
    );

}

#[tokio::test]
async fn get_input_test() {
    let config = Cfg::init("modlist.toml").unwrap();
    assert_eq!(
        get_input(config.clone(), vec![String::from("-ma test")]).await.unwrap(),
        Input {
            command: Some(Cmd::Mod),
            mod_options: Some(ModOptions::Add),
            mod_id: Some(IDSelector::ModificationID(String::from("test"))),
            set_version: false,
            all_lists: false,
            clean: false,
            direct_download: false,
            delete_old: false,
            list: Some(lists_get(config.clone(), String::from("one")).unwrap()),
            list_options: None,
            list_id: None,
            list_mcversion: None,
            modloader: None,
            directory: None,
            io_options: None,
            file: None
        }
    )
}