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


                                        
                          



                              





                                          
                                      
                             







                                      
       
            

 



                                      


                                      
                      

           
           
            

 





                                      









                                                                    


                                                       
                                    



                                       





                                                         
                                                     




                                                                       


                                                 




                                                  
                  


                                                        
                                             


                                                                  






                                                                       


                                                           
                                             


                                                                  
                                  
                                       
                  





                                     

                                            



                                      
                        




                                                                                                                








                                                               



                                                             

                         













                                                                                                                 

















                                                                     
                                                                                                                                 




                    


                        
                        



                            





                           
                       

                


     

                                                                      


                                                                                                               

                                             
                                               
                       


     
                                                        
                                                           
                                    
                                                                            

                                              
                                           
                            

                                                                                                                                                             
                     
          
                               
                                                                                                               
                     
          


     
                                                            




                                                                               






                                                                                                                           

                                                                                                                                                  
          
                                
                                                                                                                 
                     
          

                                     







                                                                                                                 
                     
         

     


                 




                                                                                        


                              
                               



                                   





                                                         
                             


                      
 








                                                                                 


                                               
                               



                                   





                                                                                
                             


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

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Input {
    pub command: Option<Cmd>,
    pub mod_options: Option<ModOptions>,
    pub mod_id: Option<String>,
    pub mod_version: Option<String>,
    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,
}

#[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.reverse();
        args.pop();
        args.reverse();
        
        let mut command: Option<Cmd> = None;

        let mut mod_options: Option<ModOptions> = None;
        let mut mod_id: Option<String> = None;
        let mut mod_version: Option<String> = 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(String::from(arg_split[1]));
                    }
                },
                "mv" => {
                    command = Some(Cmd::Mod);
                    mod_options = Some(ModOptions::Add);
                    if arg_split.len() == 2 {
                        mod_version = Some(String::from(arg_split[1]));
                    };
                },
                "mr" => {
                    command = Some(Cmd::Mod);
                    mod_options = Some(ModOptions::Remove);
                    if arg_split.len() == 2 {
                        mod_id = Some(String::from(arg_split[1]));
                    }
                },
                "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);
                    list_id = Some(String::from(arg_split[1]));
                },
                "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" => {
                    modloader = Some(Modloader::from(arg_split[1])?);
                },
                "dir" => {
                    directory = Some(String::from(arg_split[1]));
                },
                "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]));
                },
                _ => return Err(MLError::new(ErrorType::ArgumentError, format!("Unknown Argument ({})", arg_split[0]).as_str())),
            }
        }

        Ok(Self {
            command,
            mod_options,
            mod_id,
            mod_version,
            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),
        _ => Ok(input),
    }
}

//Move checks to commands? translate to variables there?
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() {
        //Check for MV if no mod-id on both
        ModOptions::Add => {
            if input.mod_id.is_none() && input.mod_version.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.clone())?); };
            Ok(input)
        },
        ModOptions::Remove => {
            if input.mod_id.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "MODS_NO_MODID")); };
            Ok(input)
        },
    }
}

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");
                //TODO Get latest version
                input.list_mcversion = Some(String::from("1.19.3"));
            };
            if input.modloader.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "no modloader specified")); };
            if input.directory.is_none() { input.directory = Some(format!("./downloads/{}", input.clone().list_id.expect("earlier if failed"))) };
            Ok(input)
        },
        ListOptions::Remove => {
            if input.list.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "NO_LIST_SPECIFIED")); };
            Ok(input)
        },
        ListOptions::Change => {
            //TODO check if no 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.clone(), vec![String::from("-la test -lv 1.19.3")]).unwrap(),
        Input {
            command: Some(Cmd::List),
            mod_options: None,
            mod_id: None,
            mod_version: 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(String::from("test")),
            mod_version: None,
            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
        }
    )
}