summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/apis/modrinth.rs6
-rw-r--r--src/commands/io.rs20
-rw-r--r--src/commands/list.rs1
-rw-r--r--src/commands/mod.rs4
-rw-r--r--src/commands/modification.rs73
-rw-r--r--src/commands/setup.rs86
-rw-r--r--src/commands/update.rs90
-rw-r--r--src/db.rs101
-rw-r--r--src/error.rs2
-rw-r--r--src/files.rs10
-rw-r--r--src/input.rs19
-rw-r--r--src/main.rs14
12 files changed, 230 insertions, 196 deletions
diff --git a/src/apis/modrinth.rs b/src/apis/modrinth.rs
index 36ab5df..f3f89a7 100644
--- a/src/apis/modrinth.rs
+++ b/src/apis/modrinth.rs
@@ -63,9 +63,7 @@ pub enum Type {
63pub enum Status { 63pub enum Status {
64 approved, 64 approved,
65 rejected, 65 rejected,
66 draft, 66 draft, unlisted, archived,
67 unlisted,
68 archived,
69 processing, 67 processing,
70 unknown 68 unknown
71} 69}
@@ -141,7 +139,6 @@ pub async fn project(api: String, name: &str) -> Project {
141} 139}
142 140
143pub async fn projects(api: String, ids: Vec<String>) -> Vec<Project> { 141pub async fn projects(api: String, ids: Vec<String>) -> Vec<Project> {
144 println!("\tGet versions from modrinth\n");
145 let all = ids.join(r#"",""#); 142 let all = ids.join(r#"",""#);
146 let url = format!(r#"projects?ids=["{}"]"#, all); 143 let url = format!(r#"projects?ids=["{}"]"#, all);
147 144
@@ -187,7 +184,6 @@ pub fn extract_current_version(versions: Vec<Version>) -> MLE<String> {
187 } 184 }
188 times.sort_by_key(|t| t.1); 185 times.sort_by_key(|t| t.1);
189 times.reverse(); 186 times.reverse();
190 println!("\t └New current version: {}", times[0].0);
191 Ok(times[0].0.to_string()) 187 Ok(times[0].0.to_string())
192 }, 188 },
193 _ => panic!("available_versions should never be negative"), 189 _ => panic!("available_versions should never be negative"),
diff --git a/src/commands/io.rs b/src/commands/io.rs
index 4835e3d..44604d1 100644
--- a/src/commands/io.rs
+++ b/src/commands/io.rs
@@ -2,7 +2,7 @@ use std::fs::File;
2use std::io::prelude::*; 2use std::io::prelude::*;
3use serde::{Serialize, Deserialize}; 3use serde::{Serialize, Deserialize};
4 4
5use crate::{input::{Input, IoOptions}, db::{lists_get, userlist_get_all_ids, lists_get_all_ids, lists_insert}, config::Cfg, Modloader, /*mod_add,*/ List, devdir, error::MLE}; 5use crate::{input::{Input, IoOptions}, db::{lists_get, userlist_get_all_ids, lists_get_all_ids, lists_insert}, config::Cfg, Modloader, List, devdir, error::MLE, mods_add};
6 6
7#[derive(Debug, Serialize, Deserialize)] 7#[derive(Debug, Serialize, Deserialize)]
8struct Export { 8struct Export {
@@ -24,7 +24,7 @@ impl ExportList {
24 let list = lists_get(config.clone(), String::from(&list_id))?; 24 let list = lists_get(config.clone(), String::from(&list_id))?;
25 25
26 let mut dl_folder = None; 26 let mut dl_folder = None;
27 if download == true { dl_folder = Some(list.download_folder) }; 27 if download{ dl_folder = Some(list.download_folder) };
28 28
29 let mods = userlist_get_all_ids(config, list_id)?.join("|"); 29 let mods = userlist_get_all_ids(config, list_id)?.join("|");
30 30
@@ -51,7 +51,7 @@ fn export(config: Cfg, input: Input) -> MLE<()> {
51 } 51 }
52 let mut lists: Vec<ExportList> = vec![]; 52 let mut lists: Vec<ExportList> = vec![];
53 for list_id in list_ids { 53 for list_id in list_ids {
54 lists.push(ExportList::from(config.clone(), String::from(list_id), true)?); 54 lists.push(ExportList::from(config.clone(), list_id, true)?);
55 } 55 }
56 56
57 let toml = toml::to_string( &Export { lists } )?; 57 let toml = toml::to_string( &Export { lists } )?;
@@ -59,7 +59,7 @@ fn export(config: Cfg, input: Input) -> MLE<()> {
59 let filestr = dirs::home_dir().unwrap().join("mlexport.toml"); 59 let filestr = dirs::home_dir().unwrap().join("mlexport.toml");
60 60
61 let mut file = File::create(devdir(filestr.into_os_string().into_string().unwrap().as_str()))?; 61 let mut file = File::create(devdir(filestr.into_os_string().into_string().unwrap().as_str()))?;
62 file.write_all(&toml.as_bytes())?; 62 file.write_all(toml.as_bytes())?;
63 63
64 Ok(()) 64 Ok(())
65} 65}
@@ -67,8 +67,8 @@ fn export(config: Cfg, input: Input) -> MLE<()> {
67async fn import(config: Cfg, input: Input) -> MLE<()> { 67async fn import(config: Cfg, input: Input) -> MLE<()> {
68 68
69 let filestr: String = match input.file { 69 let filestr: String = match input.file {
70 Some(args) => String::from(args), 70 Some(args) => args,
71 None => String::from(devdir(dirs::home_dir().unwrap().join("mlexport.toml").into_os_string().into_string().unwrap().as_str())), 71 None => devdir(dirs::home_dir().unwrap().join("mlexport.toml").into_os_string().into_string().unwrap().as_str()),
72 }; 72 };
73 73
74 let mut file = File::open(filestr)?; 74 let mut file = File::open(filestr)?;
@@ -76,17 +76,17 @@ async fn import(config: Cfg, input: Input) -> MLE<()> {
76 file.read_to_string(&mut content)?; 76 file.read_to_string(&mut content)?;
77 let export: Export = toml::from_str(&content)?; 77 let export: Export = toml::from_str(&content)?;
78 78
79 println!("{:#?}", export);
80
81 for exportlist in export.lists { 79 for exportlist in export.lists {
82 let list = List { id: exportlist.id, mc_version: exportlist.mc_version, modloader: Modloader::from(&exportlist.launcher)?, download_folder: exportlist.download_folder.ok_or("NO_DL").unwrap() }; 80 let list = List { id: exportlist.id, mc_version: exportlist.mc_version, modloader: Modloader::from(&exportlist.launcher)?, download_folder: exportlist.download_folder.ok_or("NO_DL").unwrap() };
83 lists_insert(config.clone(), list.id.clone(), list.mc_version.clone(), list.modloader.clone(), String::from(&list.download_folder))?; 81 lists_insert(config.clone(), list.id.clone(), list.mc_version.clone(), list.modloader.clone(), String::from(&list.download_folder))?;
84 let mods: Vec<&str> = exportlist.mods.split("|").collect(); 82 let mods: Vec<&str> = exportlist.mods.split('|').collect();
85 let mut mod_ids = vec![]; 83 let mut mod_ids = vec![];
86 for mod_id in mods { 84 for mod_id in mods {
87 mod_ids.push(String::from(mod_id)); 85 mod_ids.push(String::from(mod_id));
88 }; 86 };
89 //mod_add(config.clone(), mod_ids, list.clone(), false).await?; 87 //TODO impl set_version and good direct download
88 //TODO impl all at once, dafuck
89 mods_add(config.clone(), mod_ids, list, input.direct_download, false).await?;
90 } 90 }
91 Ok(()) 91 Ok(())
92} 92}
diff --git a/src/commands/list.rs b/src/commands/list.rs
index eaf6fa1..8e86973 100644
--- a/src/commands/list.rs
+++ b/src/commands/list.rs
@@ -49,6 +49,7 @@ fn remove(config: Cfg, input: Input) -> MLE<()> {
49} 49}
50 50
51///Changing the current lists version and updating it 51///Changing the current lists version and updating it
52///
52/// #Arguments 53/// #Arguments
53/// 54///
54/// * `config` - The current config 55/// * `config` - The current config
diff --git a/src/commands/mod.rs b/src/commands/mod.rs
index 38139f9..0d5bd00 100644
--- a/src/commands/mod.rs
+++ b/src/commands/mod.rs
@@ -1,13 +1,13 @@
1pub mod modification; 1pub mod modification;
2pub mod list; 2pub mod list;
3pub mod update; 3pub mod update;
4//pub mod setup; 4pub mod setup;
5pub mod download; 5pub mod download;
6pub mod io; 6pub mod io;
7 7
8pub use modification::*; 8pub use modification::*;
9pub use list::*; 9pub use list::*;
10pub use update::*; 10pub use update::*;
11//pub use setup::*; 11pub use setup::*;
12pub use download::*; 12pub use download::*;
13pub use io::*; 13pub use io::*;
diff --git a/src/commands/modification.rs b/src/commands/modification.rs
index c82d6b5..12a635f 100644
--- a/src/commands/modification.rs
+++ b/src/commands/modification.rs
@@ -1,4 +1,9 @@
1use crate::{modrinth::{project, versions, extract_current_version, Version, projects}, config::Cfg, db::{mods_insert, userlist_remove, mods_get_id, userlist_insert, mods_get_all_ids, userlist_get_all_ids, userlist_get_current_version, lists_get_all_ids, mods_remove}, input::{Input, ModOptions}, files::{delete_version, download_versions}, List, error::{MLE, ErrorType, MLError}}; 1use crate::{modrinth::{project, versions, extract_current_version, Version, projects}, config::Cfg, db::{mods_insert, userlist_remove, mods_get_id, userlist_insert, userlist_get_all_ids, userlist_get_current_version, lists_get_all_ids, mods_remove}, input::{Input, ModOptions}, files::{delete_version, download_versions}, List, error::{MLE, ErrorType, MLError}};
2
3//TODO DO IT
4pub struct ModVer {
5
6}
2 7
3pub async fn modification(config: Cfg, input: Input) -> MLE<()> { 8pub async fn modification(config: Cfg, input: Input) -> MLE<()> {
4 match input.clone().mod_options.ok_or("").unwrap() { 9 match input.clone().mod_options.ok_or("").unwrap() {
@@ -13,22 +18,26 @@ pub async fn modification(config: Cfg, input: Input) -> MLE<()> {
13 18
14async fn add(config: Cfg, input: Input) -> MLE<()> { 19async fn add(config: Cfg, input: Input) -> MLE<()> {
15 20
16 mod_add(config, vec![String::from(input.mod_id.unwrap())], input.list.unwrap(), input.direct_download).await?; 21 mods_add(config, vec![input.mod_id.unwrap()], input.list.unwrap(), input.direct_download, input.set_version).await?;
17 22
18 Ok(()) 23 Ok(())
19} 24}
20 25//TODO impl specific version
21pub async fn mod_add(config: Cfg, mod_id: Vec<String>, list: List, direct_download: bool) -> MLE<()> { 26pub async fn mods_add(config: Cfg, mod_id: Vec<String>, list: List, direct_download: bool, set_version: bool) -> MLE<()> {
22 27
23 //Fix printing (its horrible) 28 println!("Add mods to {}", list.id);
24 println!("Adding mod(s) {:?}", mod_id); 29 println!("Add mods:");
25 let projects = if mod_id.len() == 1 { 30 let projects = if mod_id.len() == 1 {
26 vec![project(String::from(&config.apis.modrinth), &mod_id[0]).await] 31 vec![project(String::from(&config.apis.modrinth), &mod_id[0]).await]
27 } else { 32 } else {
28 projects(String::from(&config.apis.modrinth), mod_id).await 33 projects(String::from(&config.apis.modrinth), mod_id).await
29 }; 34 };
35
36 let mut downloadstack: Vec<Version> = Vec::new();
30 37
31 for project in projects { 38 for project in projects {
39 println!("\t└{}", project.title);
40 println!("\t └Get versions");
32 let available_versions = versions(String::from(&config.apis.modrinth), String::from(&project.id), list.clone()).await; 41 let available_versions = versions(String::from(&config.apis.modrinth), String::from(&project.id), list.clone()).await;
33 42
34 let mut available_versions_vec: Vec<String> = Vec::new(); 43 let mut available_versions_vec: Vec<String> = Vec::new();
@@ -37,64 +46,56 @@ pub async fn mod_add(config: Cfg, mod_id: Vec<String>, list: List, direct_downlo
37 let file: String; 46 let file: String;
38 if !available_versions.is_empty() { 47 if !available_versions.is_empty() {
39 let current_id = extract_current_version(available_versions.clone())?; 48 let current_id = extract_current_version(available_versions.clone())?;
49 println!("\t └Current version: {}", current_id);
40 50
41 current_version = Some(available_versions.clone().into_iter().find(|v| v.id == current_id).unwrap()); 51 current_version = Some(available_versions.clone().into_iter().find(|v| v.id == current_id).unwrap());
42 52
43 current_version_id = current_version.clone().unwrap().id; 53 current_version_id = current_version.clone().unwrap().id;
44 54
45 file = current_version.clone().ok_or("").unwrap().files.into_iter().find(|f| f.primary).unwrap().url; 55 file = current_version.clone().ok_or("").unwrap().files.into_iter().find(|f| f.primary).unwrap().url;
46
47 for ver in available_versions { 56 for ver in available_versions {
48 available_versions_vec.push(ver.id); 57 available_versions_vec.push(ver.id);
49 }; 58 };
50 } else { 59 } else {
51 println!("There's currently no mod version for your specified target"); 60 println!("\t └There's currently no mod version for your specified target");
52 current_version = None; 61 current_version = None;
53 current_version_id = String::from("NONE"); 62 current_version_id = String::from("NONE");
54 file = String::from("NONE"); 63 file = String::from("NONE");
55 available_versions_vec.push(String::from("NONE")); 64 available_versions_vec.push(String::from("NONE"));
56 } 65 }
57 66
58 //add to current list and mod table 67 match userlist_insert(config.clone(), &list.id, &project.id, &current_version_id, available_versions_vec, &file, set_version) {
59 match userlist_get_all_ids(config.clone(), list.clone().id) { 68 Err(e) => {
60 Ok(mods) => { 69 let expected_err = format!("SQL: UNIQUE constraint failed: {}.mod_id", list.id);
61 if mods.contains(&project.id) { 70 if e.to_string() == expected_err { Err(MLError::new(ErrorType::ModError, "MOD_ALREADY_ON_SELECTED_LIST")) } else { Err(e) }
62 return Err(MLError::new(ErrorType::ModError, "MOD_ALREADY_ON_LIST")); }
63 else {
64 userlist_insert(config.clone(), String::from(&list.id), String::from(&project.id), String::from(&current_version_id), available_versions_vec, file)?;
65 }
66 }, 71 },
67 Err(..) => userlist_insert(config.clone(), String::from(&list.id), String::from(&project.id), String::from(&current_version_id), available_versions_vec, file)?, 72 Ok(..) => { Ok(..) },
68 }; 73 }?;
69 74
70 match mods_get_all_ids(config.clone()) { 75 match mods_insert(config.clone(), &project.id, &project.slug, &project.title) {
71 Ok(mods) => { 76 Err(e) => {
72 if mods.contains(&project.id) { 77 if e.to_string() == "SQL: UNIQUE constraint failed: mods.id" { Ok(..) } else { Err(e) }
73 //return Err(Box::new(Error::new(ErrorKind::Other, "MOD_ALREADY_IN_DATABASE")))
74 } else {
75 mods_insert(config.clone(), String::from(&project.id), String::from(&project.title), project.versions)?;
76 }
77 },
78 Err(..) => {
79 mods_insert(config.clone(), String::from(&project.id), String::from(&project.title), project.versions)?;
80 }, 78 },
81 }; 79 Ok(..) => Ok(..),
80 }?;
82 81
83 if direct_download && current_version.is_some() { download_versions(list.clone(), config.clone(), vec![current_version.unwrap()]).await?; }; 82 downloadstack.push(current_version.unwrap());
84 83 };
85 } 84
85 //Download all the added mods
86 if direct_download {
87 download_versions(list.clone(), config.clone(), downloadstack).await?;
88 };
86 89
87 Ok(()) 90 Ok(())
88} 91}
89 92
90fn remove(config: Cfg, input: Input) -> MLE<()> { 93fn remove(config: Cfg, input: Input) -> MLE<()> {
91 94
92 //TODO inplement deletion by slug or title 95 let mod_id = mods_get_id(&config.data, input.mod_id.as_ref().unwrap())?;
93 let mod_id = mods_get_id(config.clone(), input.clone().mod_id.unwrap())?;
94 96
95 let version = userlist_get_current_version(config.clone(), input.clone().list.unwrap().id, String::from(&mod_id))?; 97 let version = userlist_get_current_version(config.clone(), input.clone().list.unwrap().id, String::from(&mod_id))?;
96 98
97 //TODO implement remove from modlist if not in any other lists && config clean is true
98 userlist_remove(config.clone(), input.clone().list.unwrap().id, String::from(&mod_id))?; 99 userlist_remove(config.clone(), input.clone().list.unwrap().id, String::from(&mod_id))?;
99 delete_version(input.list.unwrap(), version)?; 100 delete_version(input.list.unwrap(), version)?;
100 101
diff --git a/src/commands/setup.rs b/src/commands/setup.rs
index cc7472c..0161bd7 100644
--- a/src/commands/setup.rs
+++ b/src/commands/setup.rs
@@ -1,66 +1,72 @@
1use std::{fs::File, path::Path, io::{Error, ErrorKind}}; 1use std::{fs::File, path::Path};
2 2
3use crate::{config::Cfg, db::{db_setup, s_config_get_version, s_config_create_version, s_insert_column, lists_get_all_ids, lists_get, userlist_get_all_current_version_ids, s_userlist_update_download, s_config_update_version}, modrinth::get_raw_versions, devdir}; 3use crate::{config::Cfg, db::db_setup, error::MLE, devdir};
4 4
5pub async fn setup(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { 5pub async fn setup(config: Cfg) -> MLE<()> {
6 let db_file = devdir(format!("{}/data.db", config.data).as_str()); 6 let db_file = devdir(format!("{}/data.db", config.data).as_str());
7 7
8 if !Path::new(&db_file).exists() { 8 if !Path::new(&db_file).exists() {
9 return create(config, db_file); 9 create(config, db_file)?;
10 } 10 }
11 11
12 /*
12 match s_config_get_version(config.clone()) { 13 match s_config_get_version(config.clone()) {
13 Ok(ver) => { 14 Ok(ver) => {
14 match ver.as_str() { 15 match ver.as_str() {
15 "0.2" => to_03(config)?, 16 "0.2" => to_03(config)?,
16 "0.3" => to_04(config)?, 17 "0.3" => to_04(config)?,
17 _ => return Err(Box::new(Error::new(ErrorKind::Other, "UNKNOWN_VERSION"))) 18 _ => return Err(MLError::new(ErrorType::Other, "UNKNOWN_VERSION"))
18 } 19 }
19 }, 20 },
20 Err(..) => to_02(config).await? 21 Err(..) => to_02(config).await?
21 }; 22 };
23 */
22 24
23 Ok(()) 25 Ok(())
24} 26}
25 27
26fn create(config: Cfg, db_file: String) -> Result<(), Box<dyn std::error::Error>> { 28fn create(config: Cfg, db_file: String) -> MLE<()> {
27 File::create(db_file)?;
28 db_setup(config)?;
29 Ok(())
30}
31
32async fn to_02(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
33 let lists = lists_get_all_ids(config.clone())?;
34
35 for list in lists {
36 println!("Updating {}", list);
37 s_insert_column(config.clone(), String::from(&list), String::from("current_download"), String::from("TEXT"), None)?;
38
39 let full_list = lists_get(config.clone(), String::from(&list))?;
40 29
41 let versions = userlist_get_all_current_version_ids(config.clone(), full_list.clone().id)?; 30 println!("Create database");
42
43 let raw_versions = get_raw_versions(String::from(&config.apis.modrinth), versions).await;
44
45 for ver in raw_versions {
46 println!("Adding link for {}", ver.project_id);
47 let file = ver.files.into_iter().find(|f| f.primary).unwrap();
48 s_userlist_update_download(config.clone(), String::from(&full_list.id), ver.project_id, file.url)?;
49 }
50 };
51 s_config_create_version(config)?;
52 31
32 File::create(db_file)?;
33 db_setup(config)?;
53 Ok(()) 34 Ok(())
54} 35}
55 36
56fn to_03(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { 37//async fn to_02(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
57 s_insert_column(config.clone(), String::from("lists"), String::from("download_folder"), String::from("TEXT"), None)?; 38// let lists = lists_get_all_ids(config.clone())?;
58 s_config_update_version(config, String::from("0.3")) 39//
59} 40// for list in lists {
41// println!("Updating {}", list);
42// s_insert_column(config.clone(), String::from(&list), String::from("current_download"), String::from("TEXT"), None)?;
43//
44// let full_list = lists_get(config.clone(), String::from(&list))?;
45//
46// let versions = userlist_get_all_current_version_ids(config.clone(), full_list.clone().id)?;
47//
48// let raw_versions = get_raw_versions(String::from(&config.apis.modrinth), versions).await;
49//
50// for ver in raw_versions {
51// println!("Adding link for {}", ver.project_id);
52// let file = ver.files.into_iter().find(|f| f.primary).unwrap();
53// s_userlist_update_download(config.clone(), String::from(&full_list.id), ver.project_id, file.url)?;
54// }
55// };
56// s_config_create_version(config)?;
57//
58// Ok(())
59//}
60//
61//fn to_03(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
62// s_insert_column(config.clone(), String::from("lists"), String::from("download_folder"), String::from("TEXT"), None)?;
63// s_config_update_version(config, String::from("0.3"))
64//}
65//
66//fn to_04(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
67// for list_id in lists_get_all_ids(config.clone())? {
68// s_insert_column(config.clone(), list_id, String::from("disabled_versions"), String::from("TEXT"), Some(String::from("NONE")))?;
69// }
70// s_config_update_version(config, String::from("0.4"))
71//}
60 72
61fn to_04(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
62 for list_id in lists_get_all_ids(config.clone())? {
63 s_insert_column(config.clone(), list_id, String::from("disabled_versions"), String::from("TEXT"), Some(String::from("NONE")))?;
64 }
65 s_config_update_version(config, String::from("0.4"))
66} \ No newline at end of file
diff --git a/src/commands/update.rs b/src/commands/update.rs
index d400a24..bc5b316 100644
--- a/src/commands/update.rs
+++ b/src/commands/update.rs
@@ -1,4 +1,4 @@
1use crate::{config::Cfg, modrinth::{projects, Project, versions, extract_current_version, Version}, get_current_list, db::{userlist_get_all_ids, mods_get_versions, userlist_get_applicable_versions, userlist_change_versions, lists_get_all_ids, lists_get, userlist_get_current_version, mods_change_versions}, List, input::Input, files::{delete_version, download_versions, disable_version, clean_list_dir}, error::{MLE, MLError, ErrorType}}; 1use 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}};
2 2
3pub async fn update(config: Cfg, input: Input) -> MLE<()> { 3pub async fn update(config: Cfg, input: Input) -> MLE<()> {
4 let mut liststack: Vec<List> = vec![]; 4 let mut liststack: Vec<List> = vec![];
@@ -9,7 +9,7 @@ pub async fn update(config: Cfg, input: Input) -> MLE<()> {
9 } 9 }
10 } else { 10 } else {
11 let current = get_current_list(config.clone())?; 11 let current = get_current_list(config.clone())?;
12 println!("Check for updates of mods in list {}", current.id); 12 println!("Update list {}:", current.id);
13 liststack.push(current) 13 liststack.push(current)
14 } 14 }
15 cmd_update(config, liststack, input.clean, input.direct_download, input.delete_old).await 15 cmd_update(config, liststack, input.clean, input.direct_download, input.delete_old).await
@@ -20,59 +20,41 @@ pub async fn cmd_update(config: Cfg, liststack: Vec<List>, clean: bool, direct_d
20 let mods = userlist_get_all_ids(config.clone(), current_list.clone().id)?; 20 let mods = userlist_get_all_ids(config.clone(), current_list.clone().id)?;
21 21
22 let mut current_versions: Vec<(String, String)> = vec![]; 22 let mut current_versions: Vec<(String, String)> = vec![];
23
24 println!(" └Update mods:");
25 let mut updatestack: Vec<Version> = vec![];
26
27 for id in mods {
28 let title = mods_get_title(config.clone(), &id)?;
29 println!("\t└{}", title);
23 30
24 let mut versions = mods_get_versions(config.clone(), mods.clone())?; 31 if userlist_get_set_version(config.clone(), &current_list.id, &id)? {
25 versions.sort_by_key(|ver| ver.mod_id.clone()); 32 println!("\t └Set version, skipping update");
26 33 continue;
27 let mut projects = projects(String::from(&config.apis.modrinth), mods).await; 34 }
28 projects.sort_by_key(|pro| pro.id.clone());
29 35
30 println!("Comparing mod versions:");
31 let mut updatestack: Vec<Version> = vec![];
32 for (index, project) in projects.into_iter().enumerate() {
33 //Get versions for project and check if they match up
34 let current_version = &versions[index];
35 let p_id = String::from(&project.id);
36 let v_id = &current_version.mod_id;
37 if &p_id != v_id { return Err(MLError::new(ErrorType::Other, "SORTING_ERROR")) };
38
39 println!("\t({}) Check for update", project.title);
40
41 //Getting current installed version for disable or delete 36 //Getting current installed version for disable or delete
42 let disable_version = userlist_get_current_version(config.clone(), String::from(&current_list.id), String::from(&project.id))?; 37 let disable_version = userlist_get_current_version(config.clone(), String::from(&current_list.id), String::from(&id))?;
43
44 let version_db_string = project.versions.join("|");
45 38
46 //Adding to stack if not the same versions in the list OR if clean == true 39 updatestack.push(
47 if clean || (version_db_string != current_version.versions) { 40 match specific_update(config.clone(), clean, current_list.clone(), String::from(&id)).await {
48 updatestack.push(match specific_update(config.clone(), clean, current_list.clone(), project.clone()).await {
49 Ok(ver) => { 41 Ok(ver) => {
50 current_versions.push((disable_version, p_id)); 42 current_versions.push((disable_version, id));
51 ver 43 ver
52 }, 44 },
53 Err(e) => { 45 Err(e) => {
54 //Catch no update available
55 if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" { 46 if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" {
56 mods_change_versions(config.clone(), version_db_string, project.id)?; 47 println!("\t └No new version found for the specified minecraft version");
57 println!("\t └No new version found for the specified minecraft version");
58 } else { 48 } else {
59 return Err(e); 49 return Err(e);
60 }; 50 };
61 continue; 51 continue;
62 }, 52 }
63 }); 53 }
64 } else { 54 )
65 println!("\t └No new version found");
66 };
67 }; 55 };
68
69 //Linebreak readability
70 println!("");
71 56
72 if clean { clean_list_dir(&current_list)? }; 57 if clean { clean_list_dir(&current_list)?; };
73
74 //Linebreak readability
75 println!("");
76 58
77 if direct_download && !updatestack.is_empty() { 59 if direct_download && !updatestack.is_empty() {
78 download_versions(current_list.clone(), config.clone(), updatestack).await?; 60 download_versions(current_list.clone(), config.clone(), updatestack).await?;
@@ -81,10 +63,10 @@ pub async fn cmd_update(config: Cfg, liststack: Vec<List>, clean: bool, direct_d
81 if !clean { 63 if !clean {
82 for ver in current_versions { 64 for ver in current_versions {
83 if delete_old { 65 if delete_old {
84 println!("Deleting version {} for mod {}", ver.0, ver.1); 66 println!("\t └Delete version {}", ver.0);
85 delete_version(current_list.clone(), ver.0)?; 67 delete_version(current_list.clone(), ver.0)?;
86 } else if ver.0 != "NONE" { 68 } else if ver.0 != "NONE" {
87 println!("Disabling version {} for mod {}", ver.0, ver.1); 69 println!("\t └Disable version {}", ver.0);
88 disable_version(config.clone(), current_list.clone(), ver.0, ver.1)?; 70 disable_version(config.clone(), current_list.clone(), ver.0, ver.1)?;
89 }; 71 };
90 } 72 }
@@ -95,8 +77,8 @@ pub async fn cmd_update(config: Cfg, liststack: Vec<List>, clean: bool, direct_d
95 Ok(()) 77 Ok(())
96} 78}
97 79
98async fn specific_update(config: Cfg, clean: bool, list: List, project: Project) -> MLE<Version> { 80async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> MLE<Version> {
99 let applicable_versions = versions(String::from(&config.apis.modrinth), String::from(&project.id), list.clone()).await; 81 let applicable_versions = versions(String::from(&config.apis.modrinth), String::from(&id), list.clone()).await;
100 82
101 let mut versions: Vec<String> = vec![]; 83 let mut versions: Vec<String> = vec![];
102 84
@@ -108,12 +90,20 @@ async fn specific_update(config: Cfg, clean: bool, list: List, project: Project)
108 versions.push(String::from("NONE")); 90 versions.push(String::from("NONE"));
109 } 91 }
110 92
111
112 let mut current: Vec<Version> = vec![]; 93 let mut current: Vec<Version> = vec![];
113 if clean || (versions.join("|") != userlist_get_applicable_versions(config.clone(), String::from(&list.id), String::from(&project.id))?) { 94 //TODO Split clean and no match
114 //get new versions 95 if clean || (versions.join("|") != userlist_get_applicable_versions(config.clone(), String::from(&list.id), String::from(&id))?) {
115 println!("\t └Get versions for specified minecraft versions"); 96
116 let current_str = extract_current_version(applicable_versions.clone())?; 97 let current_str = extract_current_version(applicable_versions.clone())?;
98
99 if clean {
100 println!("\t └Add version to downloadstack");
101 } else {
102 println!("\t └Get versions for specified minecraft versions");
103 println!("\t └New current version: {}", current_str);
104 };
105
106 //get new versions
117 let current_ver = match applicable_versions.into_iter().find(|ver| ver.id == current_str).ok_or("!no current version in applicable_versions") { 107 let current_ver = match applicable_versions.into_iter().find(|ver| ver.id == current_str).ok_or("!no current version in applicable_versions") {
118 Ok(v) => Ok(v), 108 Ok(v) => Ok(v),
119 Err(e) => Err(MLError::new(ErrorType::Other, e)), 109 Err(e) => Err(MLError::new(ErrorType::Other, e)),
@@ -124,7 +114,7 @@ async fn specific_update(config: Cfg, clean: bool, list: List, project: Project)
124 Ok(p) => Ok(p), 114 Ok(p) => Ok(p),
125 Err(e) => Err(MLError::new(ErrorType::Other, e)), 115 Err(e) => Err(MLError::new(ErrorType::Other, e)),
126 }?.url; 116 }?.url;
127 userlist_change_versions(config, list.id, current_str, versions.join("|"), link, project.id)?; 117 userlist_change_versions(config, list.id, current_str, versions.join("|"), link, id)?;
128 } 118 }
129 119
130 if current.is_empty() { return Err(MLError::new(ErrorType::ModError, "NO_UPDATE_AVAILABLE")) }; 120 if current.is_empty() { return Err(MLError::new(ErrorType::ModError, "NO_UPDATE_AVAILABLE")) };
@@ -139,7 +129,7 @@ async fn download_updates_test() {
139 use crate::{modrinth::{Version, VersionFile, Hash, VersionType}, Modloader, List}; 129 use crate::{modrinth::{Version, VersionFile, Hash, VersionType}, Modloader, List};
140 130
141 let config = Cfg::init("modlist.toml").unwrap(); 131 let config = Cfg::init("modlist.toml").unwrap();
142 let current_list = List { id: String::from("..."), mc_version: String::from("..."), modloader: Modloader::Forge, download_folder: String::from("./dl") }; 132 let current_list = List { id: String::from("..."), mc_version: String::from("..."), modloader: Modloader::Fabric, download_folder: String::from("./dev/tests/dl") };
143 133
144 let versions = vec![Version { 134 let versions = vec![Version {
145 id: "dEqtGnT9".to_string(), 135 id: "dEqtGnT9".to_string(),
diff --git a/src/db.rs b/src/db.rs
index f47bda6..ecc6854 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -4,17 +4,17 @@ use rusqlite::Connection;
4 4
5use crate::{Modloader, config::Cfg, List, devdir, error::{MLE, MLError, ErrorType}}; 5use crate::{Modloader, config::Cfg, List, devdir, error::{MLE, MLError, ErrorType}};
6 6
7//mods 7//MODS
8pub fn mods_insert(config: Cfg, id: String, name: String, versions: Vec<String>) -> MLE<()> { 8pub fn mods_insert(config: Cfg, id: &str, slug: &str, name: &str) -> MLE<()> {
9 9
10 println!("Inserting mod {}({}) into database", name, id); 10 println!("\t └Save mod info");
11 11
12 let data = devdir(format!("{}/data.db", config.data).as_str()); 12 let data = devdir(format!("{}/data.db", config.data).as_str());
13 let connection = Connection::open(data)?; 13 let connection = Connection::open(data)?;
14 14
15 connection.execute( 15 connection.execute(
16 "INSERT INTO mods (id, name, versions) VALUES (?1, ?2, ?3)", 16 "INSERT INTO mods (id, slug, title) VALUES (?1, ?2, ?3)",
17 [id, name.replace('\'', ""), versions.join("|")] 17 [id, slug, name.replace('\'', "").as_str()]
18 )?; 18 )?;
19 19
20 Ok(()) 20 Ok(())
@@ -41,32 +41,53 @@ pub fn mods_get_all_ids(config: Cfg) -> Result<Vec<String>, Box<dyn std::error::
41 } 41 }
42} 42}
43 43
44pub fn mods_get_id(config: Cfg, name: String) -> MLE<String> { 44///Get mod id based on the slug or name
45 let data = devdir(format!("{}/data.db", config.data).as_str()); 45///# Arguments
46///
47///* `data` - file directory of the database
48///* `slug` - Slug or Name of a mod
49///
50///# Failure
51///
52///Will return `MLError` when no mod id is found
53pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> {
54 let data = devdir(format!("{}/data.db", data).as_str());
46 let connection = Connection::open(data)?; 55 let connection = Connection::open(data)?;
47 56
48 let mut mod_id = String::new(); 57 let mut mod_id = String::new();
49 let mut stmt = connection.prepare("SELECT id FROM mods WHERE name = ?")?; 58
50 let id_iter = stmt.query_map([name], |row| { 59 //get from slug
60 let mut stmt = connection.prepare("SELECT id FROM mods WHERE slug = ?")?;
61 let id_iter = stmt.query_map([slug], |row| {
51 row.get::<usize, String>(0) 62 row.get::<usize, String>(0)
52 })?; 63 })?;
53 64
54 for id in id_iter { 65 for id in id_iter {
55 mod_id = id?; 66 mod_id = id?;
56 }; 67 };
57 68 //get from title if no id found from slug
58 match mod_id.is_empty() { 69 if mod_id.is_empty() {
59 true => Err(MLError::new(ErrorType::DBError, "GI_MOD_NOT_FOUND")), 70 let mut stmt = connection.prepare("SELECT id FROM mods WHERE title = ?")?;
60 false => Ok(mod_id), 71 let id_iter = stmt.query_map([slug], |row| {
72 row.get::<usize, String>(0)
73 })?;
74
75 for id in id_iter {
76 mod_id = id?;
77 };
61 } 78 }
79
80 if mod_id.is_empty() { return Err(MLError::new(ErrorType::DBError, "GI_MOD_NOT_FOUND")) };
81
82 Ok(mod_id)
62} 83}
63 84
64pub fn mods_get_name(config: Cfg, id: &str) -> MLE<String> { 85pub fn mods_get_title(config: Cfg, id: &str) -> MLE<String> {
65 let data = devdir(format!("{}/data.db", config.data).as_str()); 86 let data = devdir(format!("{}/data.db", config.data).as_str());
66 let connection = Connection::open(data)?; 87 let connection = Connection::open(data)?;
67 88
68 let mut mod_name = String::new(); 89 let mut mod_name = String::new();
69 let mut stmt = connection.prepare("SELECT name FROM mods WHERE id = ?")?; 90 let mut stmt = connection.prepare("SELECT title FROM mods WHERE id = ?")?;
70 let name_iter = stmt.query_map([id], |row| { 91 let name_iter = stmt.query_map([id], |row| {
71 row.get::<usize, String>(0) 92 row.get::<usize, String>(0)
72 })?; 93 })?;
@@ -81,17 +102,6 @@ pub fn mods_get_name(config: Cfg, id: &str) -> MLE<String> {
81 } 102 }
82} 103}
83 104
84pub fn mods_change_versions(config: Cfg, versions: String, mod_id: String) -> MLE<()> {
85
86 //println!("Updating versions for {} with \n {}", mod_id, versions);
87
88 let data = devdir(format!("{}/data.db", config.data).as_str());
89 let connection = Connection::open(data)?;
90
91 connection.execute("UPDATE mods SET versions = ?1 WHERE id = ?2", [versions, mod_id])?;
92 Ok(())
93}
94
95pub fn mods_remove(config: Cfg, id: String) -> MLE<()> { 105pub fn mods_remove(config: Cfg, id: String) -> MLE<()> {
96 106
97 println!("Removing mod {} from database", id); 107 println!("Removing mod {} from database", id);
@@ -124,7 +134,7 @@ pub fn mods_get_versions(config: Cfg, mods: Vec<String>) -> MLE<Vec<DBModlistVer
124 } 134 }
125 135
126 let mut versionmaps: Vec<DBModlistVersions> = Vec::new(); 136 let mut versionmaps: Vec<DBModlistVersions> = Vec::new();
127 let mut stmt = connection.prepare(format!("SELECT id, versions, name FROM mods {}", wherestr).as_str())?; 137 let mut stmt = connection.prepare(format!("SELECT id, versions, title FROM mods {}", wherestr).as_str())?;
128 let id_iter = stmt.query_map([], |row| { 138 let id_iter = stmt.query_map([], |row| {
129 Ok(vec![row.get::<usize, String>(0)?, row.get::<usize, String>(1)?, row.get::<usize, String>(2)?]) 139 Ok(vec![row.get::<usize, String>(0)?, row.get::<usize, String>(1)?, row.get::<usize, String>(2)?])
130 })?; 140 })?;
@@ -143,14 +153,18 @@ pub fn mods_get_versions(config: Cfg, mods: Vec<String>) -> MLE<Vec<DBModlistVer
143} 153}
144 154
145//userlist 155//userlist
146pub fn userlist_insert(config: Cfg, list_id: String, mod_id: String, current_version: String, applicable_versions: Vec<String>, current_link: String) -> MLE<()> { 156pub fn userlist_insert(config: Cfg, list_id: &str, mod_id: &str, current_version: &str, applicable_versions: Vec<String>, current_link: &str, set_version: bool) -> MLE<()> {
147 println!("Inserting {} into current list({})", mod_id, list_id); 157 println!("\t └Insert in list");
148 158
149 let data = devdir(format!("{}/data.db", config.data).as_str()); 159 let data = devdir(format!("{}/data.db", config.data).as_str());
150 let connection = Connection::open(data)?; 160 let connection = Connection::open(data)?;
151
152 161
153 connection.execute(format!("INSERT INTO {} VALUES (?1, ?2, ?3, ?4, 'NONE')", list_id).as_str(), [mod_id, current_version, applicable_versions.join("|"), current_link])?; 162 let sv = match set_version {
163 true => "1",
164 false => "0",
165 };
166
167 connection.execute(format!("INSERT INTO {} VALUES (?1, ?2, ?3, ?4, 'NONE', ?5)", list_id).as_str(), [mod_id, current_version, applicable_versions.join("|").as_str(), current_link, sv])?;
154 168
155 Ok(()) 169 Ok(())
156} 170}
@@ -285,6 +299,23 @@ pub fn userlist_get_all_current_versions_with_mods(config: Cfg, list_id: String)
285 Ok(versions) 299 Ok(versions)
286} 300}
287 301
302pub fn userlist_get_set_version(config:Cfg, list_id: &str, mod_id: &str) -> MLE<bool> {
303 let data = devdir(format!("{}/data.db", config.data).as_str());
304 let connection = Connection::open(data).unwrap();
305
306 let mut set_version: bool = false;
307 let mut stmt = connection.prepare(format!("SELECT set_version FROM {} WHERE mod_id = ?", list_id).as_str())?;
308 let ver_iter = stmt.query_map([&mod_id], |row| {
309 row.get::<usize, bool>(0)
310 })?;
311
312 for ver in ver_iter {
313 set_version = ver?;
314 };
315
316 Ok(set_version)
317}
318
288pub fn userlist_change_versions(config: Cfg, list_id: String, current_version: String, versions: String, link: String, mod_id: String) -> MLE<()> { 319pub fn userlist_change_versions(config: Cfg, list_id: String, current_version: String, versions: String, link: String, mod_id: String) -> MLE<()> {
289 let data = devdir(format!("{}/data.db", config.data).as_str()); 320 let data = devdir(format!("{}/data.db", config.data).as_str());
290 let connection = Connection::open(data)?; 321 let connection = Connection::open(data)?;
@@ -357,7 +388,7 @@ pub fn lists_insert(config: Cfg, id: String, mc_version: String, mod_loader: Mod
357 let connection = Connection::open(data)?; 388 let connection = Connection::open(data)?;
358 389
359 connection.execute("INSERT INTO lists VALUES (?1, ?2, ?3, ?4)", [id.clone(), mc_version, mod_loader.to_string(), download_folder])?; 390 connection.execute("INSERT INTO lists VALUES (?1, ?2, ?3, ?4)", [id.clone(), mc_version, mod_loader.to_string(), download_folder])?;
360 connection.execute(format!("CREATE TABLE {}( 'mod_id' TEXT, 'current_version' TEXT, 'applicable_versions' BLOB, 'current_download' TEXT, 'disabled_versions' TEXT DEFAULT 'NONE' )", id).as_str(), [])?; 391 connection.execute(format!("CREATE TABLE {}( 'mod_id' TEXT, 'current_version' TEXT, 'applicable_versions' BLOB, 'current_download' TEXT, 'disabled_versions' TEXT DEFAULT 'NONE', 'set_version' INTEGER, CONSTRAINT {}_PK PRIMARY KEY (mod_id) )", id, id).as_str(), [])?;
361 392
362 Ok(()) 393 Ok(())
363} 394}
@@ -505,7 +536,7 @@ pub fn s_insert_column(config: Cfg, table: String, column: String, c_type: Strin
505 Ok(()) 536 Ok(())
506} 537}
507 538
508pub fn db_setup(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { 539pub fn db_setup(config: Cfg) -> MLE<()> {
509 540
510 println!("Initiating database"); 541 println!("Initiating database");
511 542
@@ -514,9 +545,9 @@ pub fn db_setup(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
514 545
515 connection.execute_batch( 546 connection.execute_batch(
516 "CREATE TABLE 'user_config' ( 'id' TEXT, 'value' TEXT ); 547 "CREATE TABLE 'user_config' ( 'id' TEXT, 'value' TEXT );
517 CREATE TABLE 'mods' ( 'id' TEXT, 'name' TEXT, 'versions' TEXT ); 548 CREATE TABLE 'mods' ( 'id' TEXT, 'slug' TEXT, 'title' TEXT, CONSTRAINT mods_PK PRIMARY KEY (id) );
518 CREATE TABLE 'lists' ( 'id' TEXT, 'mc_version' TEXT, 'modloader' TEXT, 'download_folder' TEXT ); 549 CREATE TABLE 'lists' ( 'id' TEXT, 'mc_version' TEXT, 'modloader' TEXT, 'download_folder' TEXT );
519 INSERT INTO 'user_config' VALUES ( 'db_version', '0.4' ); 550 INSERT INTO 'user_config' VALUES ( 'db_version', '0.5' );
520 INSERT INTO 'user_config' VALUES ( 'current_list', '...' )", 551 INSERT INTO 'user_config' VALUES ( 'current_list', '...' )",
521 )?; 552 )?;
522 553
diff --git a/src/error.rs b/src/error.rs
index 612a2e2..794a919 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -39,7 +39,7 @@ impl fmt::Display for MLError {
39 ErrorType::DBError => write!(f, "Database: {}", self.message), 39 ErrorType::DBError => write!(f, "Database: {}", self.message),
40 ErrorType::ModError => write!(f, "Mod: {}", self.message), 40 ErrorType::ModError => write!(f, "Mod: {}", self.message),
41 ErrorType::LibToml => write!(f, "TOML"), 41 ErrorType::LibToml => write!(f, "TOML"),
42 ErrorType::LibSql => write!(f, "SQL"), 42 ErrorType::LibSql => write!(f, "SQL: {}", self.message),
43 ErrorType::LibReq => write!(f, "REQWEST"), 43 ErrorType::LibReq => write!(f, "REQWEST"),
44 ErrorType::LibChrono => write!(f, "Chrono error: {}", self.message), 44 ErrorType::LibChrono => write!(f, "Chrono error: {}", self.message),
45 ErrorType::IoError => write!(f, "IO"), 45 ErrorType::IoError => write!(f, "IO"),
diff --git a/src/files.rs b/src/files.rs
index 8c822b2..b9325ea 100644
--- a/src/files.rs
+++ b/src/files.rs
@@ -2,17 +2,17 @@ use std::{fs::{File, read_dir, remove_file, rename}, io::Write, collections::Has
2use futures_util::StreamExt; 2use futures_util::StreamExt;
3use reqwest::Client; 3use reqwest::Client;
4 4
5use crate::{List, modrinth::Version, db::{userlist_add_disabled_versions, mods_get_name}, config::Cfg, error::{MLE, MLError, ErrorType}}; 5use crate::{List, modrinth::Version, db::{userlist_add_disabled_versions, mods_get_title}, config::Cfg, error::{MLE, MLError, ErrorType}};
6 6
7pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) -> MLE<String> { 7pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) -> MLE<String> {
8 8
9 let dl_path = String::from(&list.download_folder); 9 let dl_path = String::from(&list.download_folder);
10 10
11 println!("Download to directory from: {} ({})", list.id, dl_path); 11 println!("Download mods to {}", dl_path);
12 12
13 for ver in versions { 13 for ver in versions {
14 let project_name = mods_get_name(config.clone(), &ver.project_id)?; 14 let project_name = mods_get_title(config.clone(), &ver.project_id)?;
15 print!("\t({})Download version {}", project_name, ver.id); 15 print!("\t({})Download version {}", project_name, ver.id);
16 //Force flush of stdout, else print! doesn't print instantly 16 //Force flush of stdout, else print! doesn't print instantly
17 std::io::stdout().flush().unwrap(); 17 std::io::stdout().flush().unwrap();
18 let primary_file = ver.files.into_iter().find(|file| file.primary).unwrap(); 18 let primary_file = ver.files.into_iter().find(|file| file.primary).unwrap();
@@ -107,7 +107,7 @@ pub fn get_downloaded_versions(list: List) -> MLE<HashMap<String, String>> {
107 107
108pub fn clean_list_dir(list: &List) -> MLE<()> { 108pub fn clean_list_dir(list: &List) -> MLE<()> {
109 let dl_path = &list.download_folder; 109 let dl_path = &list.download_folder;
110 println!("Clean directory for: {}", list.id); 110 println!("Clean directory for: {}", list.id);
111 for entry in std::fs::read_dir(dl_path)? { 111 for entry in std::fs::read_dir(dl_path)? {
112 let entry = entry?; 112 let entry = entry?;
113 std::fs::remove_file(entry.path())?; 113 std::fs::remove_file(entry.path())?;
diff --git a/src/input.rs b/src/input.rs
index 144f22a..17fc773 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -29,6 +29,7 @@ pub enum Cmd {
29 Download, 29 Download,
30 Io, 30 Io,
31 Version, 31 Version,
32 Setup,
32} 33}
33 34
34#[derive(Debug, Clone, PartialEq, Eq)] 35#[derive(Debug, Clone, PartialEq, Eq)]
@@ -58,7 +59,7 @@ impl Input {
58 args[0] = args[0].split_at(1).1; 59 args[0] = args[0].split_at(1).1;
59 60
60 let mut command: Option<Cmd> = None; 61 let mut command: Option<Cmd> = None;
61 62
62 let mut mod_options: Option<ModOptions> = None; 63 let mut mod_options: Option<ModOptions> = None;
63 let mut mod_id: Option<String> = None; 64 let mut mod_id: Option<String> = None;
64 let mut mod_version: Option<String> = None; 65 let mut mod_version: Option<String> = None;
@@ -77,7 +78,7 @@ impl Input {
77 let mut file: Option<String> = None; 78 let mut file: Option<String> = None;
78 79
79 for arg in args { 80 for arg in args {
80 let arg_split: Vec<&str> = arg.trim().split(" ").collect(); 81 let arg_split: Vec<&str> = arg.trim().split(' ').collect();
81 match arg_split[0] { 82 match arg_split[0] {
82 "v" | "version" => { 83 "v" | "version" => {
83 command = Some(Cmd::Version); 84 command = Some(Cmd::Version);
@@ -97,9 +98,8 @@ impl Input {
97 return Err(MLError::new(ErrorType::ArgumentError, "Please specify a list mod slug or id")); 98 return Err(MLError::new(ErrorType::ArgumentError, "Please specify a list mod slug or id"));
98 } 99 }
99 }, 100 },
101 //TODO impl this
100 "mv" => { 102 "mv" => {
101 command = Some(Cmd::Mod);
102 mod_options = Some(ModOptions::Add);
103 if arg_split.len() == 2 { 103 if arg_split.len() == 2 {
104 mod_version = Some(String::from(arg_split[1])); 104 mod_version = Some(String::from(arg_split[1]));
105 } else { 105 } else {
@@ -195,6 +195,9 @@ impl Input {
195 "f" => { 195 "f" => {
196 file = Some(String::from(arg_split[1])); 196 file = Some(String::from(arg_split[1]));
197 }, 197 },
198 "setup" => {
199 command = Some(Cmd::Setup);
200 }
198 _ => return Err(MLError::new(ErrorType::ArgumentError, format!("Unknown Argument ({})", arg_split[0]).as_str())), 201 _ => return Err(MLError::new(ErrorType::ArgumentError, format!("Unknown Argument ({})", arg_split[0]).as_str())),
199 } 202 }
200 } 203 }
@@ -240,11 +243,12 @@ fn check_mod(mut input: Input, config: Cfg) -> MLE<Input> {
240 match input.clone().mod_options.unwrap() { 243 match input.clone().mod_options.unwrap() {
241 ModOptions::Add => { 244 ModOptions::Add => {
242 if input.mod_id.is_none() && input.mod_version.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "No mod id/slug or version id")); }; 245 if input.mod_id.is_none() && input.mod_version.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "No mod id/slug or version id")); };
243 if input.list_id.is_none() { input.list = Some(get_current_list(config.clone())?); }; 246 if input.list_id.is_none() { input.list = Some(get_current_list(config)?); };
244 Ok(input) 247 Ok(input)
245 }, 248 },
246 ModOptions::Remove => { 249 ModOptions::Remove => {
247 if input.mod_id.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "MODS_NO_MODID")); }; 250 if input.mod_id.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "MODS_NO_MODID")); };
251 if input.list_id.is_none() { input.list = Some(get_current_list(config)?); };
248 Ok(input) 252 Ok(input)
249 }, 253 },
250 } 254 }
@@ -274,7 +278,6 @@ async fn check_list(mut input: Input, config: Cfg) -> MLE<Input> {
274 Ok(input) 278 Ok(input)
275 }, 279 },
276 ListOptions::Change => { 280 ListOptions::Change => {
277 //TODO check if no change
278 if input.list.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "NO_LIST_SPECIFIED")); }; 281 if input.list.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "NO_LIST_SPECIFIED")); };
279 Ok(input) 282 Ok(input)
280 }, 283 },
@@ -292,7 +295,7 @@ async fn check_list(mut input: Input, config: Cfg) -> MLE<Input> {
292fn input_from() { 295fn input_from() {
293 let config = Cfg::init("modlist.toml").unwrap(); 296 let config = Cfg::init("modlist.toml").unwrap();
294 assert_eq!( 297 assert_eq!(
295 Input::from(config.clone(), vec![String::from("-la test -lv 1.19.3")]).unwrap(), 298 Input::from(config, vec![String::from("-la test -lv 1.19.3")]).unwrap(),
296 Input { 299 Input {
297 command: Some(Cmd::List), 300 command: Some(Cmd::List),
298 mod_options: None, 301 mod_options: None,
@@ -310,7 +313,7 @@ fn input_from() {
310 modloader: None, 313 modloader: None,
311 directory: None, 314 directory: None,
312 io_options: None, 315 io_options: None,
313 file: None 316 file: None,
314 } 317 }
315 ); 318 );
316 319
diff --git a/src/main.rs b/src/main.rs
index d177c3e..32727c7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,15 +1,20 @@
1use std::{env, process}; 1use std::{env, process};
2 2
3use modlist::{config::Cfg, input::{get_input, Cmd}, update, download, list, io, modification}; 3use modlist::{config::Cfg, input::{get_input, Cmd}, update, download, list, io, modification, setup};
4 4
5#[tokio::main] 5#[tokio::main]
6async fn main() { 6async fn main() {
7 let config = Cfg::init("modlist.toml").unwrap(); 7 let config = Cfg::init("modlist.toml").unwrap();
8 8
9 let mut args: Vec<String> = env::args().collect(); 9 let mut args: Vec<String> = env::args().collect();
10 args.reverse(); 10 args.reverse();
11 args.pop(); 11 args.pop();
12 args.reverse(); 12 args.reverse();
13
14 if args.is_empty() {
15 println!("Please enter an argument");
16 process::exit(1);
17 };
13 18
14 let input = match get_input(config.clone(), args).await { 19 let input = match get_input(config.clone(), args).await {
15 Ok(i) => i, 20 Ok(i) => i,
@@ -19,8 +24,6 @@ async fn main() {
19 } 24 }
20 }; 25 };
21 26
22 //dbg!(&input);
23
24 match input.clone().command.unwrap() { 27 match input.clone().command.unwrap() {
25 Cmd::Mod => { 28 Cmd::Mod => {
26 modification(config, input).await 29 modification(config, input).await
@@ -41,6 +44,9 @@ async fn main() {
41 show_version(); 44 show_version();
42 Ok(()) 45 Ok(())
43 }, 46 },
47 Cmd::Setup => {
48 setup(config).await
49 },
44 }.unwrap() 50 }.unwrap()
45} 51}
46 52