diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/apis/modrinth.rs | 6 | ||||
-rw-r--r-- | src/commands/io.rs | 20 | ||||
-rw-r--r-- | src/commands/list.rs | 1 | ||||
-rw-r--r-- | src/commands/mod.rs | 4 | ||||
-rw-r--r-- | src/commands/modification.rs | 73 | ||||
-rw-r--r-- | src/commands/setup.rs | 86 | ||||
-rw-r--r-- | src/commands/update.rs | 90 | ||||
-rw-r--r-- | src/db.rs | 101 | ||||
-rw-r--r-- | src/error.rs | 2 | ||||
-rw-r--r-- | src/files.rs | 10 | ||||
-rw-r--r-- | src/input.rs | 19 | ||||
-rw-r--r-- | src/main.rs | 14 |
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 { | |||
63 | pub enum Status { | 63 | pub 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 | ||
143 | pub async fn projects(api: String, ids: Vec<String>) -> Vec<Project> { | 141 | pub 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; | |||
2 | use std::io::prelude::*; | 2 | use std::io::prelude::*; |
3 | use serde::{Serialize, Deserialize}; | 3 | use serde::{Serialize, Deserialize}; |
4 | 4 | ||
5 | use 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}; | 5 | use 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)] |
8 | struct Export { | 8 | struct 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<()> { | |||
67 | async fn import(config: Cfg, input: Input) -> MLE<()> { | 67 | async 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 @@ | |||
1 | pub mod modification; | 1 | pub mod modification; |
2 | pub mod list; | 2 | pub mod list; |
3 | pub mod update; | 3 | pub mod update; |
4 | //pub mod setup; | 4 | pub mod setup; |
5 | pub mod download; | 5 | pub mod download; |
6 | pub mod io; | 6 | pub mod io; |
7 | 7 | ||
8 | pub use modification::*; | 8 | pub use modification::*; |
9 | pub use list::*; | 9 | pub use list::*; |
10 | pub use update::*; | 10 | pub use update::*; |
11 | //pub use setup::*; | 11 | pub use setup::*; |
12 | pub use download::*; | 12 | pub use download::*; |
13 | pub use io::*; | 13 | pub 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 @@ | |||
1 | use 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}}; | 1 | use 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 | ||
4 | pub struct ModVer { | ||
5 | |||
6 | } | ||
2 | 7 | ||
3 | pub async fn modification(config: Cfg, input: Input) -> MLE<()> { | 8 | pub 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 | ||
14 | async fn add(config: Cfg, input: Input) -> MLE<()> { | 19 | async 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 | |
21 | pub async fn mod_add(config: Cfg, mod_id: Vec<String>, list: List, direct_download: bool) -> MLE<()> { | 26 | pub 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, ¤t_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(¤t_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(¤t_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 | ||
90 | fn remove(config: Cfg, input: Input) -> MLE<()> { | 93 | fn 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 @@ | |||
1 | use std::{fs::File, path::Path, io::{Error, ErrorKind}}; | 1 | use std::{fs::File, path::Path}; |
2 | 2 | ||
3 | use 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}; | 3 | use crate::{config::Cfg, db::db_setup, error::MLE, devdir}; |
4 | 4 | ||
5 | pub async fn setup(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { | 5 | pub 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 | ||
26 | fn create(config: Cfg, db_file: String) -> Result<(), Box<dyn std::error::Error>> { | 28 | fn create(config: Cfg, db_file: String) -> MLE<()> { |
27 | File::create(db_file)?; | ||
28 | db_setup(config)?; | ||
29 | Ok(()) | ||
30 | } | ||
31 | |||
32 | async 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 | ||
56 | fn 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 | ||
61 | fn 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 @@ | |||
1 | use 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}}; | 1 | use crate::{config::Cfg, modrinth::{versions, extract_current_version, Version}, get_current_list, db::{userlist_get_all_ids, userlist_get_applicable_versions, userlist_change_versions, lists_get_all_ids, lists_get, userlist_get_current_version, mods_get_title, userlist_get_set_version}, List, input::Input, files::{delete_version, download_versions, disable_version, clean_list_dir}, error::{MLE, MLError, ErrorType}}; |
2 | 2 | ||
3 | pub async fn update(config: Cfg, input: Input) -> MLE<()> { | 3 | pub 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(), ¤t_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 = ¤t_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(¤t_list.id), String::from(&project.id))?; | 37 | let disable_version = userlist_get_current_version(config.clone(), String::from(¤t_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(¤t_list)? }; | 57 | if clean { clean_list_dir(¤t_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 | ||
98 | async fn specific_update(config: Cfg, clean: bool, list: List, project: Project) -> MLE<Version> { | 80 | async 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(), |
@@ -4,17 +4,17 @@ use rusqlite::Connection; | |||
4 | 4 | ||
5 | use crate::{Modloader, config::Cfg, List, devdir, error::{MLE, MLError, ErrorType}}; | 5 | use crate::{Modloader, config::Cfg, List, devdir, error::{MLE, MLError, ErrorType}}; |
6 | 6 | ||
7 | //mods | 7 | //MODS |
8 | pub fn mods_insert(config: Cfg, id: String, name: String, versions: Vec<String>) -> MLE<()> { | 8 | pub 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 | ||
44 | pub 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 | ||
53 | pub 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 | ||
64 | pub fn mods_get_name(config: Cfg, id: &str) -> MLE<String> { | 85 | pub 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 | ||
84 | pub 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 | |||
95 | pub fn mods_remove(config: Cfg, id: String) -> MLE<()> { | 105 | pub 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 |
146 | pub fn userlist_insert(config: Cfg, list_id: String, mod_id: String, current_version: String, applicable_versions: Vec<String>, current_link: String) -> MLE<()> { | 156 | pub 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 | ||
302 | pub 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 | |||
288 | pub fn userlist_change_versions(config: Cfg, list_id: String, current_version: String, versions: String, link: String, mod_id: String) -> MLE<()> { | 319 | pub 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 | ||
508 | pub fn db_setup(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { | 539 | pub 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 | |||
2 | use futures_util::StreamExt; | 2 | use futures_util::StreamExt; |
3 | use reqwest::Client; | 3 | use reqwest::Client; |
4 | 4 | ||
5 | use crate::{List, modrinth::Version, db::{userlist_add_disabled_versions, mods_get_name}, config::Cfg, error::{MLE, MLError, ErrorType}}; | 5 | use crate::{List, modrinth::Version, db::{userlist_add_disabled_versions, mods_get_title}, config::Cfg, error::{MLE, MLError, ErrorType}}; |
6 | 6 | ||
7 | pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) -> MLE<String> { | 7 | pub 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 | ||
108 | pub fn clean_list_dir(list: &List) -> MLE<()> { | 108 | pub 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> { | |||
292 | fn input_from() { | 295 | fn 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 @@ | |||
1 | use std::{env, process}; | 1 | use std::{env, process}; |
2 | 2 | ||
3 | use modlist::{config::Cfg, input::{get_input, Cmd}, update, download, list, io, modification}; | 3 | use modlist::{config::Cfg, input::{get_input, Cmd}, update, download, list, io, modification, setup}; |
4 | 4 | ||
5 | #[tokio::main] | 5 | #[tokio::main] |
6 | async fn main() { | 6 | async 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 | ||