summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfxqnlr <[email protected]>2024-09-04 11:12:04 +0200
committerfxqnlr <[email protected]>2024-09-04 11:12:04 +0200
commit6a91d0a864f9edd9d9fe50ca89ccbce4fc98e043 (patch)
treeae04cf34582f57699d12ac7b5b486ab065bf8d19
parentf5e070cdf6628a5ebd981d373929802317104e24 (diff)
downloadmodlist-6a91d0a864f9edd9d9fe50ca89ccbce4fc98e043.tar
modlist-6a91d0a864f9edd9d9fe50ca89ccbce4fc98e043.tar.gz
modlist-6a91d0a864f9edd9d9fe50ca89ccbce4fc98e043.zip
do nearly anything to shut clippy up
-rw-r--r--src/apis/modrinth.rs18
-rw-r--r--src/commands/download.rs30
-rw-r--r--src/commands/io.rs24
-rw-r--r--src/commands/list.rs33
-rw-r--r--src/commands/modification.rs57
-rw-r--r--src/commands/update.rs39
-rw-r--r--src/config.rs13
-rw-r--r--src/db.rs222
-rw-r--r--src/error.rs70
-rw-r--r--src/files.rs66
-rw-r--r--src/lib.rs52
-rw-r--r--src/main.rs13
12 files changed, 385 insertions, 252 deletions
diff --git a/src/apis/modrinth.rs b/src/apis/modrinth.rs
index 5366f3d..75e65e6 100644
--- a/src/apis/modrinth.rs
+++ b/src/apis/modrinth.rs
@@ -3,7 +3,7 @@ use reqwest::Client;
3use serde::{Deserialize, Serialize}; 3use serde::{Deserialize, Serialize};
4 4
5use crate::{ 5use crate::{
6 error::{ErrorType, MLError, MLE}, 6 error::{EType, MLErr, MLE},
7 List, 7 List,
8}; 8};
9 9
@@ -130,6 +130,8 @@ pub enum GameVersionType {
130 beta, 130 beta,
131} 131}
132 132
133/// # Errors
134/// # Panics
133async fn get( 135async fn get(
134 api: &str, 136 api: &str,
135 path: &str, 137 path: &str,
@@ -153,6 +155,8 @@ async fn get(
153 Ok(data) 155 Ok(data)
154} 156}
155 157
158/// # Errors
159/// # Panics
156pub async fn project(api: &str, name: &str) -> Project { 160pub async fn project(api: &str, name: &str) -> Project {
157 let url = format!("project/{name}"); 161 let url = format!("project/{name}");
158 let data = get(api, &url).await.unwrap().unwrap(); 162 let data = get(api, &url).await.unwrap().unwrap();
@@ -160,6 +164,8 @@ pub async fn project(api: &str, name: &str) -> Project {
160 serde_json::from_slice(&data).unwrap() 164 serde_json::from_slice(&data).unwrap()
161} 165}
162 166
167/// # Errors
168/// # Panics
163pub async fn projects(api: &str, ids: Vec<String>) -> Vec<Project> { 169pub async fn projects(api: &str, ids: Vec<String>) -> Vec<Project> {
164 let all = ids.join(r#"",""#); 170 let all = ids.join(r#"",""#);
165 let url = format!(r#"projects?ids=["{all}"]"#); 171 let url = format!(r#"projects?ids=["{all}"]"#);
@@ -170,6 +176,8 @@ pub async fn projects(api: &str, ids: Vec<String>) -> Vec<Project> {
170} 176}
171 177
172///Get applicable versions from `mod_id` with list context 178///Get applicable versions from `mod_id` with list context
179/// # Errors
180/// # Panics
173pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> { 181pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> {
174 let url = format!( 182 let url = format!(
175 r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, 183 r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#,
@@ -185,6 +193,8 @@ pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> {
185} 193}
186 194
187///Get version with the version ids 195///Get version with the version ids
196/// # Errors
197/// # Panics
188pub async fn get_raw_versions( 198pub async fn get_raw_versions(
189 api: &str, 199 api: &str,
190 versions: Vec<String>, 200 versions: Vec<String>,
@@ -196,9 +206,10 @@ pub async fn get_raw_versions(
196 serde_json::from_slice(&data).unwrap() 206 serde_json::from_slice(&data).unwrap()
197} 207}
198 208
209/// # Errors
199pub fn extract_current_version(versions: Vec<Version>) -> MLE<String> { 210pub fn extract_current_version(versions: Vec<Version>) -> MLE<String> {
200 match versions.len() { 211 match versions.len() {
201 0 => Err(MLError::new(ErrorType::ModError, "NO_VERSIONS_AVAILABLE")), 212 0 => Err(MLErr::new(EType::ModError, "NO_VERSIONS_AVAILABLE")),
202 1.. => { 213 1.. => {
203 let mut times: Vec<(String, DateTime<FixedOffset>)> = vec![]; 214 let mut times: Vec<(String, DateTime<FixedOffset>)> = vec![];
204 for ver in versions { 215 for ver in versions {
@@ -209,10 +220,11 @@ pub fn extract_current_version(versions: Vec<Version>) -> MLE<String> {
209 times.reverse(); 220 times.reverse();
210 Ok(times[0].0.to_string()) 221 Ok(times[0].0.to_string())
211 } 222 }
212 _ => panic!("available_versions should never be negative"),
213 } 223 }
214} 224}
215 225
226/// # Errors
227/// # Panics
216pub async fn get_game_versions() -> Vec<GameVersion> { 228pub async fn get_game_versions() -> Vec<GameVersion> {
217 let data = get("https://api.modrinth.com/v2/", "tag/game_version") 229 let data = get("https://api.modrinth.com/v2/", "tag/game_version")
218 .await 230 .await
diff --git a/src/commands/download.rs b/src/commands/download.rs
index 3e50c87..7321832 100644
--- a/src/commands/download.rs
+++ b/src/commands/download.rs
@@ -1,9 +1,11 @@
1#![allow(clippy::too_many_lines)]
2
1use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; 3use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
2 4
3use crate::{config::Cfg, List}; 5use crate::{config::Cfg, List};
4use crate::{ 6use crate::{
5 db::userlist_get_all_current_versions_with_mods, 7 db::userlist_get_all_current_versions_with_mods,
6 error::{ErrorType, MLError, MLE}, 8 error::{EType, MLErr, MLE},
7 files::{ 9 files::{
8 clean_list_dir, delete_version, disable_version, download_versions, 10 clean_list_dir, delete_version, disable_version, download_versions,
9 get_downloaded_versions, 11 get_downloaded_versions,
@@ -12,6 +14,8 @@ use crate::{
12}; 14};
13use crate::{PROGRESS_CHARS, STYLE_BAR_POS}; 15use crate::{PROGRESS_CHARS, STYLE_BAR_POS};
14 16
17/// # Errors
18/// # Panics
15pub async fn download( 19pub async fn download(
16 config: &Cfg, 20 config: &Cfg,
17 liststack: Vec<List>, 21 liststack: Vec<List>,
@@ -31,15 +35,15 @@ pub async fn download(
31 download_p.set_message(format!("Download in {}", current_list.id)); 35 download_p.set_message(format!("Download in {}", current_list.id));
32 36
33 let downloaded_versions = 37 let downloaded_versions =
34 get_downloaded_versions(current_list.clone())?; 38 get_downloaded_versions(&current_list)?;
35 let current_version_ids = 39 let current_version_ids =
36 match userlist_get_all_current_versions_with_mods( 40 match userlist_get_all_current_versions_with_mods(
37 config, 41 config,
38 String::from(&current_list.id), 42 &current_list.id,
39 ) { 43 ) {
40 Ok(i) => Ok(i), 44 Ok(i) => Ok(i),
41 Err(e) => Err(MLError::new( 45 Err(e) => Err(MLErr::new(
42 ErrorType::DBError, 46 EType::DBError,
43 e.to_string().as_str(), 47 e.to_string().as_str(),
44 )), 48 )),
45 }?; 49 }?;
@@ -74,7 +78,12 @@ pub async fn download(
74 clean_list_dir(&current_list)?; 78 clean_list_dir(&current_list)?;
75 }; 79 };
76 80
77 if !to_download.is_empty() { 81 if to_download.is_empty() {
82 download_p.println(format!(
83 "There are no new versions to download for {}",
84 current_list.id
85 ));
86 } else {
78 download_versions( 87 download_versions(
79 current_list.clone(), 88 current_list.clone(),
80 config.clone(), 89 config.clone(),
@@ -83,11 +92,6 @@ pub async fn download(
83 &download_p, 92 &download_p,
84 ) 93 )
85 .await?; 94 .await?;
86 } else {
87 download_p.println(format!(
88 "There are no new versions to download for {}",
89 current_list.id
90 ));
91 } 95 }
92 96
93 if !to_disable.is_empty() { 97 if !to_disable.is_empty() {
@@ -104,13 +108,13 @@ pub async fn download(
104 if delete_old { 108 if delete_old {
105 d_p.set_message(format!("Delete version {}", ver.1)); 109 d_p.set_message(format!("Delete version {}", ver.1));
106 d_p.inc(1); 110 d_p.inc(1);
107 delete_version(&current_list, ver.1)?; 111 delete_version(&current_list, &ver.1)?;
108 } else { 112 } else {
109 d_p.set_message(format!("Disable version {}", ver.1)); 113 d_p.set_message(format!("Disable version {}", ver.1));
110 d_p.inc(1); 114 d_p.inc(1);
111 disable_version( 115 disable_version(
112 config, 116 config,
113 current_list.clone(), 117 &current_list,
114 ver.1, 118 ver.1,
115 ver.0, 119 ver.0,
116 )?; 120 )?;
diff --git a/src/commands/io.rs b/src/commands/io.rs
index 1d17f7c..c9691c4 100644
--- a/src/commands/io.rs
+++ b/src/commands/io.rs
@@ -9,7 +9,7 @@ use crate::{
9 lists_get, lists_get_all_ids, lists_insert, userlist_get_all_ids, 9 lists_get, lists_get_all_ids, lists_insert, userlist_get_all_ids,
10 userlist_get_current_version, userlist_get_set_version, 10 userlist_get_current_version, userlist_get_set_version,
11 }, 11 },
12 error::MLE, 12 error::{EType, MLErr, MLE},
13 mod_add, AddMod, IDSelector, List, Modloader, STYLE_OPERATION, 13 mod_add, AddMod, IDSelector, List, Modloader, STYLE_OPERATION,
14}; 14};
15 15
@@ -67,15 +67,26 @@ impl ExportList {
67 } 67 }
68} 68}
69 69
70/// # Errors
71/// # Panics
70pub fn export(config: &Cfg, list: Option<String>) -> MLE<()> { 72pub fn export(config: &Cfg, list: Option<String>) -> MLE<()> {
71 let progress = ProgressBar::new_spinner(); 73 let progress = ProgressBar::new_spinner();
72 progress.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); 74 progress.set_style(
75 ProgressStyle::with_template(STYLE_OPERATION)
76 .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))?,
77 );
73 78
74 let mut list_ids: Vec<String> = vec![]; 79 let mut list_ids: Vec<String> = vec![];
75 if list.is_none() { 80 if list.is_none() {
76 list_ids = lists_get_all_ids(config)?; 81 list_ids = lists_get_all_ids(config)?;
77 } else { 82 } else {
78 list_ids.push(lists_get(config, &list.unwrap())?.id); 83 list_ids.push(
84 lists_get(
85 config,
86 &list.ok_or(MLErr::new(EType::Other, "nolist"))?,
87 )?
88 .id,
89 );
79 } 90 }
80 91
81 let mut lists: Vec<ExportList> = vec![]; 92 let mut lists: Vec<ExportList> = vec![];
@@ -88,7 +99,7 @@ pub fn export(config: &Cfg, list: Option<String>) -> MLE<()> {
88 let toml = toml::to_string(&Export { lists })?; 99 let toml = toml::to_string(&Export { lists })?;
89 100
90 let filestr = dirs::home_dir() 101 let filestr = dirs::home_dir()
91 .unwrap() 102 .ok_or(MLErr::new(EType::Other, "no home"))?
92 .join("mlexport.toml") 103 .join("mlexport.toml")
93 .into_os_string() 104 .into_os_string()
94 .into_string() 105 .into_string()
@@ -102,6 +113,7 @@ pub fn export(config: &Cfg, list: Option<String>) -> MLE<()> {
102 Ok(()) 113 Ok(())
103} 114}
104 115
116/// # Errors
105pub async fn import( 117pub async fn import(
106 config: &Cfg, 118 config: &Cfg,
107 file_str: &str, 119 file_str: &str,
@@ -117,7 +129,9 @@ pub async fn import(
117 id: exportlist.id, 129 id: exportlist.id,
118 mc_version: exportlist.mc_version, 130 mc_version: exportlist.mc_version,
119 modloader: Modloader::from(&exportlist.launcher)?, 131 modloader: Modloader::from(&exportlist.launcher)?,
120 download_folder: exportlist.download_folder.ok_or("NO_DL").unwrap(), 132 download_folder: exportlist
133 .download_folder
134 .ok_or(MLErr::new(EType::Other, "NO_DL"))?,
121 }; 135 };
122 lists_insert( 136 lists_insert(
123 config, 137 config,
diff --git a/src/commands/list.rs b/src/commands/list.rs
index 63105cf..47c1dc6 100644
--- a/src/commands/list.rs
+++ b/src/commands/list.rs
@@ -1,3 +1,4 @@
1#![allow(clippy::module_name_repetitions)]
1use indicatif::{ProgressBar, ProgressStyle}; 2use indicatif::{ProgressBar, ProgressStyle};
2 3
3use crate::{ 4use crate::{
@@ -6,7 +7,7 @@ use crate::{
6 config_change_current_list, config_get_current_list, lists_get, 7 config_change_current_list, config_get_current_list, lists_get,
7 lists_get_all_ids, lists_insert, lists_remove, lists_version, 8 lists_get_all_ids, lists_insert, lists_remove, lists_version,
8 }, 9 },
9 error::{ErrorType, MLError, MLE}, 10 error::{EType, MLErr, MLE},
10 update, Modloader, STYLE_OPERATION, 11 update, Modloader, STYLE_OPERATION,
11}; 12};
12 13
@@ -18,11 +19,13 @@ pub struct List {
18 pub download_folder: String, 19 pub download_folder: String,
19} 20}
20 21
22/// # Errors
21pub fn get_current_list(config: &Cfg) -> MLE<List> { 23pub fn get_current_list(config: &Cfg) -> MLE<List> {
22 let id = config_get_current_list(config)?; 24 let id = config_get_current_list(config)?;
23 lists_get(config, &id) 25 lists_get(config, &id)
24} 26}
25 27
28/// # Errors
26pub fn list_add( 29pub fn list_add(
27 config: &Cfg, 30 config: &Cfg,
28 id: &str, 31 id: &str,
@@ -31,20 +34,27 @@ pub fn list_add(
31 directory: &str, 34 directory: &str,
32) -> MLE<()> { 35) -> MLE<()> {
33 let p = ProgressBar::new_spinner(); 36 let p = ProgressBar::new_spinner();
34 p.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); 37 p.set_style(
38 ProgressStyle::with_template(STYLE_OPERATION)
39 .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))?,
40 );
35 p.set_message(format!("Create {id}")); 41 p.set_message(format!("Create {id}"));
36 lists_insert(config, id, mc_version, modloader, directory)?; 42 lists_insert(config, id, mc_version, modloader, directory)?;
37 p.finish_with_message(format!("Created {id}")); 43 p.finish_with_message(format!("Created {id}"));
38 Ok(()) 44 Ok(())
39} 45}
40 46
47/// # Errors
41pub fn list_change(config: &Cfg, id: &str) -> MLE<()> { 48pub fn list_change(config: &Cfg, id: &str) -> MLE<()> {
42 let p = ProgressBar::new_spinner(); 49 let p = ProgressBar::new_spinner();
43 p.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); 50 p.set_style(
51 ProgressStyle::with_template(STYLE_OPERATION)
52 .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))?,
53 );
44 p.set_message(format!("Change default list to {id}")); 54 p.set_message(format!("Change default list to {id}"));
45 55
46 if !lists_get_all_ids(config)?.into_iter().any(|l| l == id) { 56 if !lists_get_all_ids(config)?.into_iter().any(|l| l == id) {
47 return Err(MLError::new(ErrorType::ArgumentError, "List not found")); 57 return Err(MLErr::new(EType::ArgumentError, "List not found"));
48 }; 58 };
49 config_change_current_list(config, id)?; 59 config_change_current_list(config, id)?;
50 60
@@ -52,9 +62,13 @@ pub fn list_change(config: &Cfg, id: &str) -> MLE<()> {
52 Ok(()) 62 Ok(())
53} 63}
54 64
65/// # Errors
55pub fn list_remove(config: &Cfg, id: &str) -> MLE<()> { 66pub fn list_remove(config: &Cfg, id: &str) -> MLE<()> {
56 let p = ProgressBar::new_spinner(); 67 let p = ProgressBar::new_spinner();
57 p.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); 68 p.set_style(
69 ProgressStyle::with_template(STYLE_OPERATION)
70 .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))?,
71 );
58 p.set_message(format!("Remove {id}")); 72 p.set_message(format!("Remove {id}"));
59 lists_remove(config, id)?; 73 lists_remove(config, id)?;
60 p.finish_with_message(format!("Removed {id}")); 74 p.finish_with_message(format!("Removed {id}"));
@@ -67,6 +81,7 @@ pub fn list_remove(config: &Cfg, id: &str) -> MLE<()> {
67/// 81///
68/// * `config` - The current config 82/// * `config` - The current config
69/// * `args` - All args, to extract the new version 83/// * `args` - All args, to extract the new version
84/// # Errors
70pub async fn list_version( 85pub async fn list_version(
71 config: &Cfg, 86 config: &Cfg,
72 id: &str, 87 id: &str,
@@ -75,7 +90,10 @@ pub async fn list_version(
75 delete: bool, 90 delete: bool,
76) -> MLE<()> { 91) -> MLE<()> {
77 let p = ProgressBar::new_spinner(); 92 let p = ProgressBar::new_spinner();
78 p.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); 93 p.set_style(
94 ProgressStyle::with_template(STYLE_OPERATION)
95 .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))?,
96 );
79 p.set_message(format!( 97 p.set_message(format!(
80 "Change version for list {id} to minecraft version: {mc_version}" 98 "Change version for list {id} to minecraft version: {mc_version}"
81 )); 99 ));
@@ -90,7 +108,8 @@ pub async fn list_version(
90 update(config, vec![list], true, download, delete).await 108 update(config, vec![list], true, download, delete).await
91} 109}
92 110
93pub fn list_list(config: &Cfg) -> MLE<()> { 111/// # Errors
112pub fn list_lists(config: &Cfg) -> MLE<()> {
94 let lists = lists_get_all_ids(config)?; 113 let lists = lists_get_all_ids(config)?;
95 for list in lists { 114 for list in lists {
96 let l = lists_get(config, &list)?; 115 let l = lists_get(config, &list)?;
diff --git a/src/commands/modification.rs b/src/commands/modification.rs
index e0e54b2..6e6213f 100644
--- a/src/commands/modification.rs
+++ b/src/commands/modification.rs
@@ -1,3 +1,5 @@
1#![allow(clippy::too_many_lines)]
2
1use std::collections::HashMap; 3use std::collections::HashMap;
2 4
3use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; 5use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
@@ -9,7 +11,7 @@ use crate::{
9 mods_remove, userlist_get_all_ids, userlist_get_current_version, 11 mods_remove, userlist_get_all_ids, userlist_get_current_version,
10 userlist_insert, userlist_remove, 12 userlist_insert, userlist_remove,
11 }, 13 },
12 error::{ErrorType, MLError, MLE}, 14 error::{EType, MLErr, MLE},
13 files::{delete_version, download_versions}, 15 files::{delete_version, download_versions},
14 modrinth::{ 16 modrinth::{
15 extract_current_version, get_raw_versions, project, projects, versions, 17 extract_current_version, get_raw_versions, project, projects, versions,
@@ -41,6 +43,8 @@ pub struct ProjectInfo {
41 pub set_version: bool, 43 pub set_version: bool,
42} 44}
43 45
46/// # Errors
47/// # Panics
44pub async fn mod_add( 48pub async fn mod_add(
45 config: &Cfg, 49 config: &Cfg,
46 mods: Vec<AddMod>, 50 mods: Vec<AddMod>,
@@ -52,10 +56,11 @@ pub async fn mod_add(
52 let mut mod_ids: Vec<(String, bool)> = Vec::new(); 56 let mut mod_ids: Vec<(String, bool)> = Vec::new();
53 let mut ver_ids: Vec<(String, bool)> = Vec::new(); 57 let mut ver_ids: Vec<(String, bool)> = Vec::new();
54 58
55 let add_p = mp.add(ProgressBar::new(mods.len().try_into().unwrap())); 59 let add_p = mp.add(ProgressBar::new(mods.len().try_into().map_err(|_| MLErr::new(EType::Other, "MODSLENTRY"))?));
56 add_p.set_style( 60 add_p.set_style(
57 ProgressStyle::with_template(STYLE_BAR_POS) 61 ProgressStyle::with_template(STYLE_BAR_POS).map_err(|_| {
58 .unwrap() 62 MLErr::new(EType::LibIndicatif, "template error")
63 })?
59 .progress_chars(PROGRESS_CHARS), 64 .progress_chars(PROGRESS_CHARS),
60 ); 65 );
61 add_p.set_message("Sort ids"); 66 add_p.set_message("Sort ids");
@@ -83,7 +88,7 @@ pub async fn mod_add(
83 }; 88 };
84 89
85 if projectinfo.is_empty() { 90 if projectinfo.is_empty() {
86 return Err(MLError::new(ErrorType::ArgumentError, "NO_IDS?")); 91 return Err(MLErr::new(EType::ArgumentError, "NO_IDS?"));
87 }; 92 };
88 93
89 add_p.set_message("Add mods to database"); 94 add_p.set_message("Add mods to database");
@@ -115,7 +120,7 @@ pub async fn mod_add(
115 &list.id, 120 &list.id,
116 &project.mod_id, 121 &project.mod_id,
117 &current_version_id, 122 &current_version_id,
118 project.clone().applicable_versions, 123 &project.applicable_versions,
119 &project.download_link, 124 &project.download_link,
120 project.set_version, 125 project.set_version,
121 ) { 126 ) {
@@ -125,8 +130,8 @@ pub async fn mod_add(
125 list.id 130 list.id
126 ); 131 );
127 if e.to_string() == expected_err { 132 if e.to_string() == expected_err {
128 Err(MLError::new( 133 Err(MLErr::new(
129 ErrorType::ModError, 134 EType::ModError,
130 "MOD_ALREADY_ON_SELECTED_LIST", 135 "MOD_ALREADY_ON_SELECTED_LIST",
131 )) 136 ))
132 } else { 137 } else {
@@ -212,7 +217,20 @@ async fn get_mod_infos(
212 let mut available_versions_vec: Vec<String> = Vec::new(); 217 let mut available_versions_vec: Vec<String> = Vec::new();
213 let current_version: Option<Version>; 218 let current_version: Option<Version>;
214 let file: String; 219 let file: String;
215 if !available_versions.is_empty() { 220 if available_versions.is_empty() {
221 current_version = None;
222 file = String::from("NONE");
223 available_versions_vec.push(String::from("NONE"));
224 projectinfo.push(ProjectInfo {
225 mod_id: String::from(&project.id),
226 slug: project.slug,
227 title: project.title,
228 current_version,
229 applicable_versions: available_versions_vec,
230 download_link: file,
231 set_version: *setmap.get(&project.id).unwrap(),
232 });
233 } else {
216 let current_id = 234 let current_id =
217 extract_current_version(available_versions.clone())?; 235 extract_current_version(available_versions.clone())?;
218 236
@@ -246,19 +264,6 @@ async fn get_mod_infos(
246 download_link: file, 264 download_link: file,
247 set_version: *setmap.get(&project.slug).unwrap(), 265 set_version: *setmap.get(&project.slug).unwrap(),
248 }); 266 });
249 } else {
250 current_version = None;
251 file = String::from("NONE");
252 available_versions_vec.push(String::from("NONE"));
253 projectinfo.push(ProjectInfo {
254 mod_id: String::from(&project.id),
255 slug: project.slug,
256 title: project.title,
257 current_version,
258 applicable_versions: available_versions_vec,
259 download_link: file,
260 set_version: *setmap.get(&project.id).unwrap(),
261 });
262 } 267 }
263 } 268 }
264 269
@@ -319,9 +324,13 @@ async fn get_ver_info(
319/// * `config` - config struct 324/// * `config` - config struct
320/// * `id` - name, slug or id of the mod 325/// * `id` - name, slug or id of the mod
321/// * `list` - List struct 326/// * `list` - List struct
327///
328/// # Errors
322pub fn mod_remove(config: &Cfg, id: &str, list: &List) -> MLE<()> { 329pub fn mod_remove(config: &Cfg, id: &str, list: &List) -> MLE<()> {
323 let progress = ProgressBar::new_spinner(); 330 let progress = ProgressBar::new_spinner();
324 progress.set_style(ProgressStyle::with_template(STYLE_OPERATION).unwrap()); 331 progress.set_style(ProgressStyle::with_template(STYLE_OPERATION).map_err(|_| {
332 MLErr::new(EType::LibIndicatif, "template error")
333 })?);
325 334
326 let mod_id = mods_get_id(&config.data, id)?; 335 let mod_id = mods_get_id(&config.data, id)?;
327 336
@@ -334,7 +343,7 @@ pub fn mod_remove(config: &Cfg, id: &str, list: &List) -> MLE<()> {
334 userlist_remove(config, &list.id, &mod_id)?; 343 userlist_remove(config, &list.id, &mod_id)?;
335 344
336 progress.set_message("Delete file"); 345 progress.set_message("Delete file");
337 match delete_version(list, version) { 346 match delete_version(list, &version) {
338 Ok(()) => (), 347 Ok(()) => (),
339 Err(err) => { 348 Err(err) => {
340 if err.to_string() 349 if err.to_string()
diff --git a/src/commands/update.rs b/src/commands/update.rs
index c19c02c..d0b930d 100644
--- a/src/commands/update.rs
+++ b/src/commands/update.rs
@@ -1,3 +1,5 @@
1#![allow(clippy::too_many_lines)]
2
1use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; 3use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
2 4
3use crate::{ 5use crate::{
@@ -7,7 +9,7 @@ use crate::{
7 userlist_get_applicable_versions, userlist_get_current_version, 9 userlist_get_applicable_versions, userlist_get_current_version,
8 userlist_get_set_version, 10 userlist_get_set_version,
9 }, 11 },
10 error::{ErrorType, MLError, MLE}, 12 error::{EType, MLErr, MLE},
11 files::{ 13 files::{
12 clean_list_dir, delete_version, disable_version, download_versions, 14 clean_list_dir, delete_version, disable_version, download_versions,
13 }, 15 },
@@ -15,6 +17,8 @@ use crate::{
15 List, PROGRESS_CHARS, STYLE_BAR_POS, STYLE_OPERATION, 17 List, PROGRESS_CHARS, STYLE_BAR_POS, STYLE_OPERATION,
16}; 18};
17 19
20/// # Errors
21/// # Panics
18pub async fn update( 22pub async fn update(
19 config: &Cfg, 23 config: &Cfg,
20 liststack: Vec<List>, 24 liststack: Vec<List>,
@@ -24,11 +28,15 @@ pub async fn update(
24) -> MLE<()> { 28) -> MLE<()> {
25 let mp = MultiProgress::new(); 29 let mp = MultiProgress::new();
26 30
27 let update_p = 31 let update_p = mp.add(ProgressBar::new(
28 mp.add(ProgressBar::new(liststack.len().try_into().unwrap())); 32 liststack
33 .len()
34 .try_into()
35 .map_err(|_| MLErr::new(EType::Other, "ListStackLen"))?,
36 ));
29 update_p.set_style( 37 update_p.set_style(
30 ProgressStyle::with_template(STYLE_BAR_POS) 38 ProgressStyle::with_template(STYLE_BAR_POS)
31 .unwrap() 39 .map_err(|_| MLErr::new(EType::LibIndicatif, "template error"))?
32 .progress_chars(PROGRESS_CHARS), 40 .progress_chars(PROGRESS_CHARS),
33 ); 41 );
34 42
@@ -133,16 +141,11 @@ pub async fn update(
133 if delete_old { 141 if delete_old {
134 d_p.set_message(format!("Delete version {}", ver.0)); 142 d_p.set_message(format!("Delete version {}", ver.0));
135 d_p.inc(1); 143 d_p.inc(1);
136 delete_version(&current_list, ver.0)?; 144 delete_version(&current_list, &ver.0)?;
137 } else if ver.0 != "NONE" { 145 } else if ver.0 != "NONE" {
138 d_p.set_message(format!("Disable version {}", ver.0)); 146 d_p.set_message(format!("Disable version {}", ver.0));
139 d_p.inc(1); 147 d_p.inc(1);
140 disable_version( 148 disable_version(config, &current_list, ver.0, ver.1)?;
141 config,
142 current_list.clone(),
143 ver.0,
144 ver.1,
145 )?;
146 }; 149 };
147 } 150 }
148 151
@@ -176,12 +179,12 @@ async fn specific_update(
176 179
177 let mut versions: Vec<String> = vec![]; 180 let mut versions: Vec<String> = vec![];
178 181
179 if !applicable_versions.is_empty() { 182 if applicable_versions.is_empty() {
183 versions.push(String::from("NONE"));
184 } else {
180 for ver in &applicable_versions { 185 for ver in &applicable_versions {
181 versions.push(String::from(&ver.id)); 186 versions.push(String::from(&ver.id));
182 } 187 }
183 } else {
184 versions.push(String::from("NONE"));
185 } 188 }
186 189
187 let mut current: Vec<Version> = vec![]; 190 let mut current: Vec<Version> = vec![];
@@ -189,7 +192,7 @@ async fn specific_update(
189 || (versions.join("|") 192 || (versions.join("|")
190 != userlist_get_applicable_versions( 193 != userlist_get_applicable_versions(
191 config, 194 config,
192 String::from(&list.id), 195 &list.id,
193 String::from(id), 196 String::from(id),
194 )?) 197 )?)
195 { 198 {
@@ -209,7 +212,7 @@ async fn specific_update(
209 .ok_or("!no current version in applicable_versions") 212 .ok_or("!no current version in applicable_versions")
210 { 213 {
211 Ok(v) => Ok(v), 214 Ok(v) => Ok(v),
212 Err(e) => Err(MLError::new(ErrorType::Other, e)), 215 Err(e) => Err(MLErr::new(EType::Other, e)),
213 }?; 216 }?;
214 current.push(current_ver.clone()); 217 current.push(current_ver.clone());
215 218
@@ -223,7 +226,7 @@ async fn specific_update(
223 226
224 userlist_change_versions( 227 userlist_change_versions(
225 config, 228 config,
226 list.id, 229 &list.id,
227 current_str, 230 current_str,
228 versions.join("|"), 231 versions.join("|"),
229 link, 232 link,
@@ -232,7 +235,7 @@ async fn specific_update(
232 } 235 }
233 236
234 if current.is_empty() { 237 if current.is_empty() {
235 return Err(MLError::new(ErrorType::ModError, "NO_UPDATE_AVAILABLE")); 238 return Err(MLErr::new(EType::ModError, "NO_UPDATE_AVAILABLE"));
236 }; 239 };
237 240
238 Ok(current[0].clone()) 241 Ok(current[0].clone())
diff --git a/src/config.rs b/src/config.rs
index 3538a69..6280932 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -8,7 +8,7 @@ use indicatif::{ProgressBar, ProgressStyle};
8use serde::{Deserialize, Serialize}; 8use serde::{Deserialize, Serialize};
9 9
10use crate::{ 10use crate::{
11 check_game_versions, db::db_setup, error::MLE, Modloader, VersionLevel, 11 check_game_versions, db::setup, error::{EType, MLErr, MLE}, Modloader, VersionLevel,
12}; 12};
13 13
14#[derive(Debug, Clone, Serialize, Deserialize)] 14#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -32,11 +32,12 @@ pub struct Defaults {
32} 32}
33 33
34impl Cfg { 34impl Cfg {
35 /// # Errors
35 pub async fn init(path: Option<String>) -> MLE<Self> { 36 pub async fn init(path: Option<String>) -> MLE<Self> {
36 let configfile = match path.clone() { 37 let configfile = match path.clone() {
37 Some(p) => p, 38 Some(p) => p,
38 None => dirs::config_dir() 39 None => dirs::config_dir()
39 .unwrap() 40 .ok_or(MLErr::new(EType::Other, "config_dir"))?
40 .join("modlist") 41 .join("modlist")
41 .join("config.toml") 42 .join("config.toml")
42 .to_string_lossy() 43 .to_string_lossy()
@@ -70,8 +71,8 @@ impl Cfg {
70 }; 71 };
71 //Check versions 72 //Check versions
72 let versionfile = format!("{}/versions.json", config.versions); 73 let versionfile = format!("{}/versions.json", config.versions);
73 if let Ok(..) = File::open(&versionfile) { } else { 74 if File::open(&versionfile).is_err() {
74 create_versions_dummy(&versionfile).await?; 75 create_versions_dummy(&versionfile)?;
75 check_game_versions(&versionfile, true).await?; 76 check_game_versions(&versionfile, true).await?;
76 } 77 }
77 78
@@ -114,7 +115,7 @@ fn create_database(path: &str) -> MLE<()> {
114 p.set_message("Create database"); 115 p.set_message("Create database");
115 116
116 File::create(path)?; 117 File::create(path)?;
117 db_setup(path)?; 118 setup(path)?;
118 p.finish_with_message(format!("Created database ({path})")); 119 p.finish_with_message(format!("Created database ({path})"));
119 Ok(()) 120 Ok(())
120} 121}
@@ -129,7 +130,7 @@ fn create_cache(path: &str) -> MLE<()> {
129 Ok(()) 130 Ok(())
130} 131}
131 132
132async fn create_versions_dummy(path: &str) -> MLE<()> { 133fn create_versions_dummy(path: &str) -> MLE<()> {
133 let p = ProgressBar::new(1); 134 let p = ProgressBar::new(1);
134 p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap()); 135 p.set_style(ProgressStyle::with_template("{wide_msg}").unwrap());
135 p.set_message("Create version file"); 136 p.set_message("Create version file");
diff --git a/src/db.rs b/src/db.rs
index 6a3c9af..b150023 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -4,11 +4,12 @@ use rusqlite::Connection;
4 4
5use crate::{ 5use crate::{
6 config::Cfg, 6 config::Cfg,
7 error::{ErrorType, MLError, MLE}, 7 error::{EType, MLErr, MLE},
8 List, Modloader, 8 List, Modloader,
9}; 9};
10 10
11//MODS 11//MODS
12/// # Errors
12pub fn mods_insert(config: &Cfg, id: &str, slug: &str, name: &str) -> MLE<()> { 13pub fn mods_insert(config: &Cfg, id: &str, slug: &str, name: &str) -> MLE<()> {
13 let data = format!("{}/data.db", config.data); 14 let data = format!("{}/data.db", config.data);
14 let connection = Connection::open(data)?; 15 let connection = Connection::open(data)?;
@@ -21,11 +22,12 @@ pub fn mods_insert(config: &Cfg, id: &str, slug: &str, name: &str) -> MLE<()> {
21 Ok(()) 22 Ok(())
22} 23}
23 24
25/// # Errors
24pub fn mods_get_all_ids( 26pub fn mods_get_all_ids(
25 config: &Cfg, 27 config: &Cfg,
26) -> Result<Vec<String>, Box<dyn std::error::Error>> { 28) -> Result<Vec<String>, Box<dyn std::error::Error>> {
27 let data = format!("{}/data.db", config.data); 29 let data = format!("{}/data.db", config.data);
28 let connection = Connection::open(data).unwrap(); 30 let connection = Connection::open(data)?;
29 31
30 let mut mods: Vec<String> = Vec::new(); 32 let mut mods: Vec<String> = Vec::new();
31 33
@@ -36,21 +38,22 @@ pub fn mods_get_all_ids(
36 mods.push(id?); 38 mods.push(id?);
37 } 39 }
38 40
39 match mods.is_empty() { 41 if mods.is_empty() {
40 true => Err(Box::new(Error::new(ErrorKind::NotFound, "NO_MODS_ALL"))), 42 Err(Box::new(Error::new(ErrorKind::NotFound, "NO_MODS_ALL")))
41 false => Ok(mods), 43 } else {
44 Ok(mods)
42 } 45 }
43} 46}
44 47
45///Get mod id based on the slug or name 48/// Get mod id based on the slug or name
46///# Arguments 49/// # Arguments
47/// 50///
48///* `data` - file directory of the database 51///* `data` - file directory of the database
49///* `slug` - Slug or Name of a mod 52///* `slug` - Slug or Name of a mod
50/// 53///
51///# Failure 54/// # Errors
52/// 55///
53///Will return `MLError` when no mod id is found 56/// Will return `MLError` when no mod id is found
54pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { 57pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> {
55 let data = format!("{data}/data.db"); 58 let data = format!("{data}/data.db");
56 let connection = Connection::open(data)?; 59 let connection = Connection::open(data)?;
@@ -88,7 +91,7 @@ pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> {
88 } 91 }
89 92
90 if mod_id.is_empty() { 93 if mod_id.is_empty() {
91 return Err(MLError::new(ErrorType::DBError, "GI_MOD_NOT_FOUND")); 94 return Err(MLErr::new(EType::DBError, "GI_MOD_NOT_FOUND"));
92 }; 95 };
93 96
94 Ok(mod_id) 97 Ok(mod_id)
@@ -99,6 +102,7 @@ pub struct ModInfo {
99 pub title: String, 102 pub title: String,
100} 103}
101 104
105/// # Errors
102pub fn mods_get_info(config: &Cfg, id: &str) -> MLE<ModInfo> { 106pub fn mods_get_info(config: &Cfg, id: &str) -> MLE<ModInfo> {
103 let data = format!("{}/data.db", config.data); 107 let data = format!("{}/data.db", config.data);
104 let connection = Connection::open(data)?; 108 let connection = Connection::open(data)?;
@@ -121,12 +125,14 @@ pub fn mods_get_info(config: &Cfg, id: &str) -> MLE<ModInfo> {
121 }); 125 });
122 } 126 }
123 127
124 match mod_info.is_none() { 128 if mod_info.is_none() {
125 true => Err(MLError::new(ErrorType::DBError, "GN_MOD_NOT_FOUND")), 129 Err(MLErr::new(EType::DBError, "GN_MOD_NOT_FOUND"))
126 false => Ok(mod_info.unwrap()), 130 } else {
131 Ok(mod_info.ok_or(MLErr::new(EType::Other, "mod_info"))?)
127 } 132 }
128} 133}
129 134
135/// # Errors
130pub fn mods_remove(config: &Cfg, id: &str) -> MLE<()> { 136pub fn mods_remove(config: &Cfg, id: &str) -> MLE<()> {
131 let data = format!("{}/data.db", config.data); 137 let data = format!("{}/data.db", config.data);
132 let connection = Connection::open(data)?; 138 let connection = Connection::open(data)?;
@@ -142,15 +148,16 @@ pub struct DBModlistVersions {
142 pub versions: String, 148 pub versions: String,
143} 149}
144 150
151/// # Errors
145pub fn mods_get_versions( 152pub fn mods_get_versions(
146 config: &Cfg, 153 config: &Cfg,
147 mods: Vec<String>, 154 mods: &[String],
148) -> MLE<Vec<DBModlistVersions>> { 155) -> MLE<Vec<DBModlistVersions>> {
149 let data = format!("{}/data.db", config.data); 156 let data = format!("{}/data.db", config.data);
150 let connection = Connection::open(data)?; 157 let connection = Connection::open(data)?;
151 158
152 if mods.is_empty() { 159 if mods.is_empty() {
153 return Err(MLError::new(ErrorType::ArgumentError, "MODS_NO_INPUT")); 160 return Err(MLErr::new(EType::ArgumentError, "MODS_NO_INPUT"));
154 } 161 }
155 162
156 let mut wherestr = String::from("WHERE"); 163 let mut wherestr = String::from("WHERE");
@@ -182,35 +189,32 @@ pub fn mods_get_versions(
182 }); 189 });
183 } 190 }
184 191
185 match versionmaps.is_empty() { 192 if versionmaps.is_empty() {
186 true => Err(MLError::new(ErrorType::DBError, "MODS_MODS_NOT_FOUND")), 193 Err(MLErr::new(EType::DBError, "MODS_MODS_NOT_FOUND"))
187 false => Ok(versionmaps), 194 } else {
195 Ok(versionmaps)
188 } 196 }
189} 197}
190 198
191//userlist 199//userlist
200/// # Errors
192pub fn userlist_insert( 201pub fn userlist_insert(
193 config: &Cfg, 202 config: &Cfg,
194 list_id: &str, 203 list_id: &str,
195 mod_id: &str, 204 mod_id: &str,
196 current_version: &str, 205 current_version: &str,
197 applicable_versions: Vec<String>, 206 applicable_versions: &[String],
198 current_link: &str, 207 current_link: &str,
199 set_version: bool, 208 set_version: bool,
200) -> MLE<()> { 209) -> MLE<()> {
201 let data = format!("{}/data.db", config.data); 210 let data = format!("{}/data.db", config.data);
202 let connection = Connection::open(data)?; 211 let connection = Connection::open(data)?;
203 212
204 let sv = match set_version { 213 let sv = if set_version { "1" } else { "0" };
205 true => "1",
206 false => "0",
207 };
208 214
209 connection.execute( 215 connection.execute(
210 format!( 216 format!("INSERT INTO {list_id} VALUES (?1, ?2, ?3, ?4, 'NONE', ?5)")
211 "INSERT INTO {list_id} VALUES (?1, ?2, ?3, ?4, 'NONE', ?5)" 217 .as_str(),
212 )
213 .as_str(),
214 [ 218 [
215 mod_id, 219 mod_id,
216 current_version, 220 current_version,
@@ -223,28 +227,31 @@ pub fn userlist_insert(
223 Ok(()) 227 Ok(())
224} 228}
225 229
230/// # Errors
226pub fn userlist_get_all_ids(config: &Cfg, list_id: &str) -> MLE<Vec<String>> { 231pub fn userlist_get_all_ids(config: &Cfg, list_id: &str) -> MLE<Vec<String>> {
227 let data = format!("{}/data.db", config.data); 232 let data = format!("{}/data.db", config.data);
228 let connection = Connection::open(data).unwrap(); 233 let connection = Connection::open(data)?;
229 234
230 let mut mod_ids: Vec<String> = Vec::new(); 235 let mut mod_ids: Vec<String> = Vec::new();
231 let mut stmt = connection 236 let mut stmt =
232 .prepare(format!("SELECT mod_id FROM {list_id}").as_str())?; 237 connection.prepare(format!("SELECT mod_id FROM {list_id}").as_str())?;
233 let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; 238 let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?;
234 239
235 for id in id_iter { 240 for id in id_iter {
236 mod_ids.push(id?); 241 mod_ids.push(id?);
237 } 242 }
238 243
239 match mod_ids.is_empty() { 244 if mod_ids.is_empty() {
240 true => Err(MLError::new( 245 Err(MLErr::new(
241 ErrorType::DBError, 246 EType::DBError,
242 &format!("NO_MODS_USERLIST{list_id}"), 247 &format!("NO_MODS_USERLIST{list_id}"),
243 )), 248 ))
244 false => Ok(mod_ids), 249 } else {
250 Ok(mod_ids)
245 } 251 }
246} 252}
247 253
254/// # Errors
248pub fn userlist_remove(config: &Cfg, list_id: &str, mod_id: &str) -> MLE<()> { 255pub fn userlist_remove(config: &Cfg, list_id: &str, mod_id: &str) -> MLE<()> {
249 let data = format!("{}/data.db", config.data); 256 let data = format!("{}/data.db", config.data);
250 let connection = Connection::open(data)?; 257 let connection = Connection::open(data)?;
@@ -256,20 +263,19 @@ pub fn userlist_remove(config: &Cfg, list_id: &str, mod_id: &str) -> MLE<()> {
256 Ok(()) 263 Ok(())
257} 264}
258 265
266/// # Errors
259pub fn userlist_get_applicable_versions( 267pub fn userlist_get_applicable_versions(
260 config: &Cfg, 268 config: &Cfg,
261 list_id: String, 269 list_id: &str,
262 mod_id: String, 270 mod_id: String,
263) -> MLE<String> { 271) -> MLE<String> {
264 let data = format!("{}/data.db", config.data); 272 let data = format!("{}/data.db", config.data);
265 let connection = Connection::open(data).unwrap(); 273 let connection = Connection::open(data)?;
266 274
267 let mut version: String = String::new(); 275 let mut version: String = String::new();
268 let mut stmt = connection.prepare( 276 let mut stmt = connection.prepare(
269 format!( 277 format!("SELECT applicable_versions FROM {list_id} WHERE mod_id = ?")
270 "SELECT applicable_versions FROM {list_id} WHERE mod_id = ?" 278 .as_str(),
271 )
272 .as_str(),
273 )?; 279 )?;
274 let ver_iter = 280 let ver_iter =
275 stmt.query_map([mod_id], |row| row.get::<usize, String>(0))?; 281 stmt.query_map([mod_id], |row| row.get::<usize, String>(0))?;
@@ -278,15 +284,17 @@ pub fn userlist_get_applicable_versions(
278 version = ver?; 284 version = ver?;
279 } 285 }
280 286
281 match version.is_empty() { 287 if version.is_empty() {
282 true => Err(MLError::new(ErrorType::DBError, "GAV_MOD_NOT_FOUND")), 288 Err(MLErr::new(EType::DBError, "GAV_MOD_NOT_FOUND"))
283 false => Ok(version), 289 } else {
290 Ok(version)
284 } 291 }
285} 292}
286 293
294/// # Errors
287pub fn userlist_get_all_applicable_versions_with_mods( 295pub fn userlist_get_all_applicable_versions_with_mods(
288 config: &Cfg, 296 config: &Cfg,
289 list_id: String, 297 list_id: &str,
290) -> MLE<Vec<(String, String)>> { 298) -> MLE<Vec<(String, String)>> {
291 let data = format!("{}/data.db", config.data); 299 let data = format!("{}/data.db", config.data);
292 let connection = Connection::open(data)?; 300 let connection = Connection::open(data)?;
@@ -308,19 +316,20 @@ pub fn userlist_get_all_applicable_versions_with_mods(
308 } 316 }
309 317
310 if versions.is_empty() { 318 if versions.is_empty() {
311 return Err(MLError::new(ErrorType::DBError, "NO_MODS_ON_LIST")); 319 return Err(MLErr::new(EType::DBError, "NO_MODS_ON_LIST"));
312 }; 320 };
313 321
314 Ok(versions) 322 Ok(versions)
315} 323}
316 324
325/// # Errors
317pub fn userlist_get_current_version( 326pub fn userlist_get_current_version(
318 config: &Cfg, 327 config: &Cfg,
319 list_id: &str, 328 list_id: &str,
320 mod_id: &str, 329 mod_id: &str,
321) -> MLE<String> { 330) -> MLE<String> {
322 let data = format!("{}/data.db", config.data); 331 let data = format!("{}/data.db", config.data);
323 let connection = Connection::open(data).unwrap(); 332 let connection = Connection::open(data)?;
324 333
325 let mut version: String = String::new(); 334 let mut version: String = String::new();
326 let mut stmt = connection.prepare( 335 let mut stmt = connection.prepare(
@@ -334,15 +343,17 @@ pub fn userlist_get_current_version(
334 version = ver?; 343 version = ver?;
335 } 344 }
336 345
337 match version.is_empty() { 346 if version.is_empty() {
338 true => Err(MLError::new(ErrorType::DBError, "GCV_MOD_NOT_FOUND")), 347 Err(MLErr::new(EType::DBError, "GCV_MOD_NOT_FOUND"))
339 false => Ok(version), 348 } else {
349 Ok(version)
340 } 350 }
341} 351}
342 352
353/// # Errors
343pub fn userlist_get_all_current_version_ids( 354pub fn userlist_get_all_current_version_ids(
344 config: &Cfg, 355 config: &Cfg,
345 list_id: String, 356 list_id: &str,
346) -> MLE<Vec<String>> { 357) -> MLE<Vec<String>> {
347 let data = format!("{}/data.db", config.data); 358 let data = format!("{}/data.db", config.data);
348 let connection = Connection::open(data)?; 359 let connection = Connection::open(data)?;
@@ -357,15 +368,16 @@ pub fn userlist_get_all_current_version_ids(
357 } 368 }
358 369
359 if versions.is_empty() { 370 if versions.is_empty() {
360 return Err(MLError::new(ErrorType::DBError, "NO_MODS_ON_LIST")); 371 return Err(MLErr::new(EType::DBError, "NO_MODS_ON_LIST"));
361 }; 372 };
362 373
363 Ok(versions) 374 Ok(versions)
364} 375}
365 376
377/// # Errors
366pub fn userlist_get_all_current_versions_with_mods( 378pub fn userlist_get_all_current_versions_with_mods(
367 config: &Cfg, 379 config: &Cfg,
368 list_id: String, 380 list_id: &str,
369) -> Result<Vec<(String, String)>, Box<dyn std::error::Error>> { 381) -> Result<Vec<(String, String)>, Box<dyn std::error::Error>> {
370 let data = format!("{}/data.db", config.data); 382 let data = format!("{}/data.db", config.data);
371 let connection = Connection::open(data)?; 383 let connection = Connection::open(data)?;
@@ -396,18 +408,18 @@ pub fn userlist_get_all_current_versions_with_mods(
396 Ok(versions) 408 Ok(versions)
397} 409}
398 410
411/// # Errors
399pub fn userlist_get_set_version( 412pub fn userlist_get_set_version(
400 config: &Cfg, 413 config: &Cfg,
401 list_id: &str, 414 list_id: &str,
402 mod_id: &str, 415 mod_id: &str,
403) -> MLE<bool> { 416) -> MLE<bool> {
404 let data = format!("{}/data.db", config.data); 417 let data = format!("{}/data.db", config.data);
405 let connection = Connection::open(data).unwrap(); 418 let connection = Connection::open(data)?;
406 419
407 let mut set_version: bool = false; 420 let mut set_version: bool = false;
408 let mut stmt = connection.prepare( 421 let mut stmt = connection.prepare(
409 format!("SELECT set_version FROM {list_id} WHERE mod_id = ?") 422 format!("SELECT set_version FROM {list_id} WHERE mod_id = ?").as_str(),
410 .as_str(),
411 )?; 423 )?;
412 let ver_iter = 424 let ver_iter =
413 stmt.query_map([&mod_id], |row| row.get::<usize, bool>(0))?; 425 stmt.query_map([&mod_id], |row| row.get::<usize, bool>(0))?;
@@ -419,9 +431,10 @@ pub fn userlist_get_set_version(
419 Ok(set_version) 431 Ok(set_version)
420} 432}
421 433
434/// # Errors
422pub fn userlist_change_versions( 435pub fn userlist_change_versions(
423 config: &Cfg, 436 config: &Cfg,
424 list_id: String, 437 list_id: &str,
425 current_version: String, 438 current_version: String,
426 versions: String, 439 versions: String,
427 link: String, 440 link: String,
@@ -434,25 +447,22 @@ pub fn userlist_change_versions(
434 Ok(()) 447 Ok(())
435} 448}
436 449
450/// # Errors
437pub fn userlist_add_disabled_versions( 451pub fn userlist_add_disabled_versions(
438 config: &Cfg, 452 config: &Cfg,
439 list_id: String, 453 list_id: &str,
440 disabled_version: String, 454 disabled_version: String,
441 mod_id: String, 455 mod_id: String,
442) -> MLE<()> { 456) -> MLE<()> {
443 let data = format!("{}/data.db", config.data); 457 let data = format!("{}/data.db", config.data);
444 let connection = Connection::open(data)?; 458 let connection = Connection::open(data)?;
445 459
446 let currently_disabled_versions = userlist_get_disabled_versions( 460 let currently_disabled_versions =
447 config, 461 userlist_get_disabled_versions(config, list_id, String::from(&mod_id))?;
448 String::from(&list_id), 462 let disabled_versions = if currently_disabled_versions == "NONE" {
449 String::from(&mod_id), 463 disabled_version
450 )?; 464 } else {
451 let disabled_versions = match currently_disabled_versions == "NONE" { 465 format!("{currently_disabled_versions}|{disabled_version}")
452 true => disabled_version,
453 false => {
454 format!("{currently_disabled_versions}|{disabled_version}")
455 }
456 }; 466 };
457 467
458 connection.execute( 468 connection.execute(
@@ -465,13 +475,14 @@ pub fn userlist_add_disabled_versions(
465 Ok(()) 475 Ok(())
466} 476}
467 477
478/// # Errors
468pub fn userlist_get_disabled_versions( 479pub fn userlist_get_disabled_versions(
469 config: &Cfg, 480 config: &Cfg,
470 list_id: String, 481 list_id: &str,
471 mod_id: String, 482 mod_id: String,
472) -> MLE<String> { 483) -> MLE<String> {
473 let data = format!("{}/data.db", config.data); 484 let data = format!("{}/data.db", config.data);
474 let connection = Connection::open(data).unwrap(); 485 let connection = Connection::open(data)?;
475 486
476 let mut version: String = String::new(); 487 let mut version: String = String::new();
477 let mut stmt = connection.prepare( 488 let mut stmt = connection.prepare(
@@ -485,23 +496,24 @@ pub fn userlist_get_disabled_versions(
485 version = ver?; 496 version = ver?;
486 } 497 }
487 498
488 match version.is_empty() { 499 if version.is_empty() {
489 true => Err(MLError::new(ErrorType::DBError, "GDV_MOD_NOT_FOUND")), 500 Err(MLErr::new(EType::DBError, "GDV_MOD_NOT_FOUND"))
490 false => Ok(version), 501 } else {
502 Ok(version)
491 } 503 }
492} 504}
493 505
506/// # Errors
494pub fn userlist_get_all_downloads( 507pub fn userlist_get_all_downloads(
495 config: &Cfg, 508 config: &Cfg,
496 list_id: String, 509 list_id: &str,
497) -> Result<Vec<String>, Box<dyn std::error::Error>> { 510) -> Result<Vec<String>, Box<dyn std::error::Error>> {
498 let data = format!("{}/data.db", config.data); 511 let data = format!("{}/data.db", config.data);
499 let connection = Connection::open(data).unwrap(); 512 let connection = Connection::open(data)?;
500 513
501 let mut links: Vec<String> = Vec::new(); 514 let mut links: Vec<String> = Vec::new();
502 let mut stmt = connection.prepare( 515 let mut stmt = connection
503 format!("SELECT current_download FROM {list_id}").as_str(), 516 .prepare(format!("SELECT current_download FROM {list_id}").as_str())?;
504 )?;
505 let link_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; 517 let link_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?;
506 518
507 for link in link_iter { 519 for link in link_iter {
@@ -521,6 +533,7 @@ pub fn userlist_get_all_downloads(
521 533
522//lists 534//lists
523///Inserts into lists table and creates new table 535///Inserts into lists table and creates new table
536/// # Errors
524pub fn lists_insert( 537pub fn lists_insert(
525 config: &Cfg, 538 config: &Cfg,
526 id: &str, 539 id: &str,
@@ -540,6 +553,7 @@ pub fn lists_insert(
540 Ok(()) 553 Ok(())
541} 554}
542 555
556/// # Errors
543pub fn lists_remove(config: &Cfg, id: &str) -> MLE<()> { 557pub fn lists_remove(config: &Cfg, id: &str) -> MLE<()> {
544 let data = format!("{}/data.db", config.data); 558 let data = format!("{}/data.db", config.data);
545 let connection = Connection::open(data)?; 559 let connection = Connection::open(data)?;
@@ -549,9 +563,10 @@ pub fn lists_remove(config: &Cfg, id: &str) -> MLE<()> {
549 Ok(()) 563 Ok(())
550} 564}
551 565
566/// # Errors
552pub fn lists_get(config: &Cfg, list_id: &str) -> MLE<List> { 567pub fn lists_get(config: &Cfg, list_id: &str) -> MLE<List> {
553 let data = format!("{}/data.db", config.data); 568 let data = format!("{}/data.db", config.data);
554 let connection = Connection::open(data).unwrap(); 569 let connection = Connection::open(data)?;
555 570
556 let mut list = List { 571 let mut list = List {
557 id: String::new(), 572 id: String::new(),
@@ -582,15 +597,16 @@ pub fn lists_get(config: &Cfg, list_id: &str) -> MLE<List> {
582 } 597 }
583 598
584 if list.id.is_empty() { 599 if list.id.is_empty() {
585 return Err(MLError::new(ErrorType::DBError, "LIST_NOT_FOUND")); 600 return Err(MLErr::new(EType::DBError, "LIST_NOT_FOUND"));
586 } 601 }
587 602
588 Ok(list) 603 Ok(list)
589} 604}
590 605
606/// # Errors
591pub fn lists_version(config: &Cfg, list_id: &str, version: &str) -> MLE<()> { 607pub fn lists_version(config: &Cfg, list_id: &str, version: &str) -> MLE<()> {
592 let data = format!("{}/data.db", config.data); 608 let data = format!("{}/data.db", config.data);
593 let connection = Connection::open(data).unwrap(); 609 let connection = Connection::open(data)?;
594 610
595 connection.execute( 611 connection.execute(
596 "UPDATE lists SET mc_version = ? WHERE id = ?", 612 "UPDATE lists SET mc_version = ? WHERE id = ?",
@@ -599,9 +615,10 @@ pub fn lists_version(config: &Cfg, list_id: &str, version: &str) -> MLE<()> {
599 Ok(()) 615 Ok(())
600} 616}
601 617
618/// # Errors
602pub fn lists_get_all_ids(config: &Cfg) -> MLE<Vec<String>> { 619pub fn lists_get_all_ids(config: &Cfg) -> MLE<Vec<String>> {
603 let data = format!("{}/data.db", config.data); 620 let data = format!("{}/data.db", config.data);
604 let connection = Connection::open(data).unwrap(); 621 let connection = Connection::open(data)?;
605 622
606 let mut list_ids: Vec<String> = Vec::new(); 623 let mut list_ids: Vec<String> = Vec::new();
607 let mut stmt = connection.prepare("SELECT id FROM lists")?; 624 let mut stmt = connection.prepare("SELECT id FROM lists")?;
@@ -611,13 +628,15 @@ pub fn lists_get_all_ids(config: &Cfg) -> MLE<Vec<String>> {
611 list_ids.push(id?); 628 list_ids.push(id?);
612 } 629 }
613 630
614 match list_ids.is_empty() { 631 if list_ids.is_empty() {
615 true => Err(MLError::new(ErrorType::DBError, "NO_LISTS")), 632 Err(MLErr::new(EType::DBError, "NO_LISTS"))
616 false => Ok(list_ids), 633 } else {
634 Ok(list_ids)
617 } 635 }
618} 636}
619 637
620//config 638//config
639/// # Errors
621pub fn config_change_current_list(config: &Cfg, id: &str) -> MLE<()> { 640pub fn config_change_current_list(config: &Cfg, id: &str) -> MLE<()> {
622 let data = format!("{}/data.db", config.data); 641 let data = format!("{}/data.db", config.data);
623 let connection = Connection::open(data)?; 642 let connection = Connection::open(data)?;
@@ -629,9 +648,10 @@ pub fn config_change_current_list(config: &Cfg, id: &str) -> MLE<()> {
629 Ok(()) 648 Ok(())
630} 649}
631 650
651/// # Errors
632pub fn config_get_current_list(config: &Cfg) -> MLE<String> { 652pub fn config_get_current_list(config: &Cfg) -> MLE<String> {
633 let data = format!("{}/data.db", config.data); 653 let data = format!("{}/data.db", config.data);
634 let connection = Connection::open(data).unwrap(); 654 let connection = Connection::open(data)?;
635 655
636 let mut list_id = String::new(); 656 let mut list_id = String::new();
637 let mut stmt = connection 657 let mut stmt = connection
@@ -643,16 +663,17 @@ pub fn config_get_current_list(config: &Cfg) -> MLE<String> {
643 } 663 }
644 664
645 if list_id.is_empty() { 665 if list_id.is_empty() {
646 return Err(MLError::new(ErrorType::DBError, "NO_CURRENT_LIST")); 666 return Err(MLErr::new(EType::DBError, "NO_CURRENT_LIST"));
647 } 667 }
648 668
649 Ok(list_id) 669 Ok(list_id)
650} 670}
651 671
652//SETUP(UPDATES) 672//SETUP(UPDATES)
673/// # Errors
653pub fn s_userlist_update_download( 674pub fn s_userlist_update_download(
654 config: &Cfg, 675 config: &Cfg,
655 list_id: String, 676 list_id: &str,
656 mod_id: String, 677 mod_id: String,
657 link: String, 678 link: String,
658) -> Result<(), Box<dyn std::error::Error>> { 679) -> Result<(), Box<dyn std::error::Error>> {
@@ -660,15 +681,14 @@ pub fn s_userlist_update_download(
660 let connection = Connection::open(data)?; 681 let connection = Connection::open(data)?;
661 682
662 connection.execute( 683 connection.execute(
663 format!( 684 format!("UPDATE {list_id} SET current_download = ?1 WHERE mod_id = ?2")
664 "UPDATE {list_id} SET current_download = ?1 WHERE mod_id = ?2" 685 .as_str(),
665 )
666 .as_str(),
667 [link, mod_id], 686 [link, mod_id],
668 )?; 687 )?;
669 Ok(()) 688 Ok(())
670} 689}
671 690
691/// # Errors
672pub fn s_config_create_version( 692pub fn s_config_create_version(
673 config: &Cfg, 693 config: &Cfg,
674) -> Result<(), Box<dyn std::error::Error>> { 694) -> Result<(), Box<dyn std::error::Error>> {
@@ -682,6 +702,7 @@ pub fn s_config_create_version(
682 Ok(()) 702 Ok(())
683} 703}
684 704
705/// # Errors
685pub fn s_config_update_version( 706pub fn s_config_update_version(
686 config: &Cfg, 707 config: &Cfg,
687 ver: String, 708 ver: String,
@@ -696,6 +717,7 @@ pub fn s_config_update_version(
696 Ok(()) 717 Ok(())
697} 718}
698 719
720/// # Errors
699pub fn s_config_get_version( 721pub fn s_config_get_version(
700 config: &Cfg, 722 config: &Cfg,
701) -> Result<String, Box<dyn std::error::Error>> { 723) -> Result<String, Box<dyn std::error::Error>> {
@@ -720,11 +742,12 @@ pub fn s_config_get_version(
720 Ok(version) 742 Ok(version)
721} 743}
722 744
745/// # Errors
723pub fn s_insert_column( 746pub fn s_insert_column(
724 config: &Cfg, 747 config: &Cfg,
725 table: String, 748 table: &str,
726 column: String, 749 column: &str,
727 c_type: String, 750 c_type: &str,
728 default: Option<String>, 751 default: Option<String>,
729) -> Result<(), Box<dyn std::error::Error>> { 752) -> Result<(), Box<dyn std::error::Error>> {
730 let data = format!("{}/data.db", config.data); 753 let data = format!("{}/data.db", config.data);
@@ -733,14 +756,19 @@ pub fn s_insert_column(
733 let mut sql = format!("ALTER TABLE {table} ADD '{column}' {c_type}"); 756 let mut sql = format!("ALTER TABLE {table} ADD '{column}' {c_type}");
734 757
735 if default.is_some() { 758 if default.is_some() {
736 sql = format!("{} DEFAULT {}", sql, default.unwrap()); 759 sql = format!(
760 "{} DEFAULT {}",
761 sql,
762 default.ok_or(MLErr::new(EType::Other, "errornous default"))?
763 );
737 } 764 }
738 765
739 connection.execute(sql.as_str(), ())?; 766 connection.execute(sql.as_str(), ())?;
740 Ok(()) 767 Ok(())
741} 768}
742 769
743pub fn db_setup(path: &str) -> MLE<()> { 770/// # Errors
771pub fn setup(path: &str) -> MLE<()> {
744 let connection = Connection::open(path)?; 772 let connection = Connection::open(path)?;
745 773
746 connection.execute_batch( 774 connection.execute_batch(
diff --git a/src/error.rs b/src/error.rs
index b4cc444..652fa0c 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,16 +1,16 @@
1use core::fmt; 1use core::fmt;
2use serde::Deserialize; 2use serde::Deserialize;
3 3
4pub type MLE<T> = Result<T, MLError>; 4pub type MLE<T> = Result<T, MLErr>;
5 5
6#[derive(Debug, Deserialize)] 6#[derive(Debug, Deserialize)]
7pub struct MLError { 7pub struct MLErr {
8 etype: ErrorType, 8 etype: EType,
9 message: String, 9 message: String,
10} 10}
11 11
12#[derive(Debug, Deserialize)] 12#[derive(Debug, Deserialize)]
13pub enum ErrorType { 13pub enum EType {
14 ArgumentError, 14 ArgumentError,
15 ArgumentCountError, 15 ArgumentCountError,
16 ConfigError, 16 ConfigError,
@@ -21,104 +21,106 @@ pub enum ErrorType {
21 LibReq, 21 LibReq,
22 LibChrono, 22 LibChrono,
23 LibJson, 23 LibJson,
24 LibIndicatif,
24 IoError, 25 IoError,
25 Other, 26 Other,
26} 27}
27 28
28impl std::error::Error for MLError { 29impl std::error::Error for MLErr {
29 fn description(&self) -> &str { 30 fn description(&self) -> &str {
30 &self.message 31 &self.message
31 } 32 }
32} 33}
33 34
34impl fmt::Display for MLError { 35impl fmt::Display for MLErr {
35 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 36 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36 match self.etype { 37 match self.etype {
37 ErrorType::ArgumentError => { 38 EType::ArgumentError => {
38 write!(f, "User input not accepted: {}", self.message) 39 write!(f, "User input not accepted: {}", self.message)
39 } 40 }
40 ErrorType::ArgumentCountError => { 41 EType::ArgumentCountError => {
41 write!(f, "Too many/too few arguments") 42 write!(f, "Too many/too few arguments")
42 } 43 }
43 ErrorType::ConfigError => write!(f, "CONFIG"), 44 EType::ConfigError => write!(f, "CONFIG"),
44 ErrorType::DBError => write!(f, "Database: {}", self.message), 45 EType::DBError => write!(f, "Database: {}", self.message),
45 ErrorType::ModError => write!(f, "Mod: {}", self.message), 46 EType::ModError => write!(f, "Mod: {}", self.message),
46 ErrorType::LibToml => write!(f, "TOML"), 47 EType::LibToml => write!(f, "TOML"),
47 ErrorType::LibSql => write!(f, "SQL: {}", self.message), 48 EType::LibSql => write!(f, "SQL: {}", self.message),
48 ErrorType::LibReq => write!(f, "REQWEST"), 49 EType::LibReq => write!(f, "REQWEST"),
49 ErrorType::LibChrono => write!(f, "Chrono error: {}", self.message), 50 EType::LibChrono => write!(f, "Chrono error: {}", self.message),
50 ErrorType::LibJson => write!(f, "JSON: {}", self.message), 51 EType::LibJson => write!(f, "JSON: {}", self.message),
51 ErrorType::IoError => write!(f, "IO"), 52 EType::LibIndicatif => write!(f, "Indicativ: {}", self.message),
52 ErrorType::Other => write!(f, "OTHER"), 53 EType::IoError => write!(f, "IO"),
54 EType::Other => write!(f, "OTHER"),
53 } 55 }
54 } 56 }
55} 57}
56 58
57impl From<reqwest::Error> for MLError { 59impl From<reqwest::Error> for MLErr {
58 fn from(error: reqwest::Error) -> Self { 60 fn from(error: reqwest::Error) -> Self {
59 Self { 61 Self {
60 etype: ErrorType::LibReq, 62 etype: EType::LibReq,
61 message: error.to_string(), 63 message: error.to_string(),
62 } 64 }
63 } 65 }
64} 66}
65 67
66impl From<toml::de::Error> for MLError { 68impl From<toml::de::Error> for MLErr {
67 fn from(error: toml::de::Error) -> Self { 69 fn from(error: toml::de::Error) -> Self {
68 Self { 70 Self {
69 etype: ErrorType::LibToml, 71 etype: EType::LibToml,
70 message: error.to_string(), 72 message: error.to_string(),
71 } 73 }
72 } 74 }
73} 75}
74 76
75impl From<rusqlite::Error> for MLError { 77impl From<rusqlite::Error> for MLErr {
76 fn from(error: rusqlite::Error) -> Self { 78 fn from(error: rusqlite::Error) -> Self {
77 Self { 79 Self {
78 etype: ErrorType::LibSql, 80 etype: EType::LibSql,
79 message: error.to_string(), 81 message: error.to_string(),
80 } 82 }
81 } 83 }
82} 84}
83 85
84impl From<toml::ser::Error> for MLError { 86impl From<toml::ser::Error> for MLErr {
85 fn from(error: toml::ser::Error) -> Self { 87 fn from(error: toml::ser::Error) -> Self {
86 Self { 88 Self {
87 etype: ErrorType::LibToml, 89 etype: EType::LibToml,
88 message: error.to_string(), 90 message: error.to_string(),
89 } 91 }
90 } 92 }
91} 93}
92 94
93impl From<chrono::ParseError> for MLError { 95impl From<chrono::ParseError> for MLErr {
94 fn from(error: chrono::ParseError) -> Self { 96 fn from(error: chrono::ParseError) -> Self {
95 Self { 97 Self {
96 etype: ErrorType::LibChrono, 98 etype: EType::LibChrono,
97 message: error.to_string(), 99 message: error.to_string(),
98 } 100 }
99 } 101 }
100} 102}
101 103
102impl From<std::io::Error> for MLError { 104impl From<std::io::Error> for MLErr {
103 fn from(error: std::io::Error) -> Self { 105 fn from(error: std::io::Error) -> Self {
104 Self { 106 Self {
105 etype: ErrorType::IoError, 107 etype: EType::IoError,
106 message: error.to_string(), 108 message: error.to_string(),
107 } 109 }
108 } 110 }
109} 111}
110 112
111impl From<serde_json::error::Error> for MLError { 113impl From<serde_json::error::Error> for MLErr {
112 fn from(value: serde_json::error::Error) -> Self { 114 fn from(value: serde_json::error::Error) -> Self {
113 Self { 115 Self {
114 etype: ErrorType::LibJson, 116 etype: EType::LibJson,
115 message: value.to_string(), 117 message: value.to_string(),
116 } 118 }
117 } 119 }
118} 120}
119 121
120impl MLError { 122impl MLErr {
121 #[must_use] pub fn new(etype: ErrorType, message: &str) -> Self { 123 #[must_use] pub fn new(etype: EType, message: &str) -> Self {
122 Self { 124 Self {
123 etype, 125 etype,
124 message: String::from(message), 126 message: String::from(message),
diff --git a/src/files.rs b/src/files.rs
index bf5a0a0..59f9ed1 100644
--- a/src/files.rs
+++ b/src/files.rs
@@ -13,11 +13,13 @@ use crate::{
13 cache::{copy_cached_version, get_cached_versions}, 13 cache::{copy_cached_version, get_cached_versions},
14 config::Cfg, 14 config::Cfg,
15 db::{mods_get_info, userlist_add_disabled_versions}, 15 db::{mods_get_info, userlist_add_disabled_versions},
16 error::{ErrorType, MLError, MLE}, 16 error::{EType, MLErr, MLE},
17 modrinth::Version, 17 modrinth::Version,
18 List, PROGRESS_CHARS, STYLE_BAR_BYTE, STYLE_BAR_POS, STYLE_SPINNER, 18 List, PROGRESS_CHARS, STYLE_BAR_BYTE, STYLE_BAR_POS, STYLE_SPINNER,
19}; 19};
20 20
21/// # Errors
22/// # Panics
21pub async fn download_versions( 23pub async fn download_versions(
22 list: List, 24 list: List,
23 config: Cfg, 25 config: Cfg,
@@ -63,6 +65,8 @@ pub async fn download_versions(
63 Ok(()) 65 Ok(())
64} 66}
65 67
68/// # Errors
69/// # Panics
66async fn download_version( 70async fn download_version(
67 config: Cfg, 71 config: Cfg,
68 list: List, 72 list: List,
@@ -90,11 +94,8 @@ async fn download_version(
90 None => files[0].clone(), 94 None => files[0].clone(),
91 }; 95 };
92 let mut splitname: Vec<&str> = file.filename.split('.').collect(); 96 let mut splitname: Vec<&str> = file.filename.split('.').collect();
93 let extension = match splitname.pop().ok_or("") { 97 let Ok(extension) = splitname.pop().ok_or("") else {
94 Ok(e) => e, 98 return Err(MLErr::new(EType::Other, "NO_FILE_EXTENSION"))
95 Err(..) => {
96 return Err(MLError::new(ErrorType::Other, "NO_FILE_EXTENSION"))
97 }
98 }; 99 };
99 let filename = format!( 100 let filename = format!(
100 "{}.mr.{}.{}.{}", 101 "{}.mr.{}.{}.{}",
@@ -122,6 +123,8 @@ async fn download_version(
122 Ok(()) 123 Ok(())
123} 124}
124 125
126/// # Errors
127/// # Panics
125async fn download_file( 128async fn download_file(
126 url: &str, 129 url: &str,
127 path: &str, 130 path: &str,
@@ -162,23 +165,27 @@ async fn download_file(
162 Ok(()) 165 Ok(())
163} 166}
164 167
168/// # Errors
169/// # Panics
165pub fn disable_version( 170pub fn disable_version(
166 config: &Cfg, 171 config: &Cfg,
167 current_list: List, 172 current_list: &List,
168 versionid: String, 173 versionid: String,
169 mod_id: String, 174 mod_id: String,
170) -> MLE<()> { 175) -> MLE<()> {
171 let file = get_file_path(&current_list, String::from(&versionid))?; 176 let file = get_file_path(current_list, &versionid)?;
172 let disabled = format!("{file}.disabled"); 177 let disabled = format!("{file}.disabled");
173 178
174 rename(file, disabled)?; 179 rename(file, disabled)?;
175 180
176 userlist_add_disabled_versions(config, current_list.id, versionid, mod_id)?; 181 userlist_add_disabled_versions(config, &current_list.id, versionid, mod_id)?;
177 182
178 Ok(()) 183 Ok(())
179} 184}
180 185
181pub fn delete_version(list: &List, version: String) -> MLE<()> { 186/// # Errors
187/// # Panics
188pub fn delete_version(list: &List, version: &str) -> MLE<()> {
182 let file = get_file_path(list, version)?; 189 let file = get_file_path(list, version)?;
183 190
184 remove_file(file)?; 191 remove_file(file)?;
@@ -186,16 +193,15 @@ pub fn delete_version(list: &List, version: String) -> MLE<()> {
186 Ok(()) 193 Ok(())
187} 194}
188 195
189pub fn get_file_path(list: &List, versionid: String) -> MLE<String> { 196/// # Errors
197/// # Panics
198pub fn get_file_path(list: &List, versionid: &str) -> MLE<String> {
190 let mut names: HashMap<String, String> = HashMap::new(); 199 let mut names: HashMap<String, String> = HashMap::new();
191 for file in read_dir(&list.download_folder)? { 200 for file in read_dir(&list.download_folder)? {
192 let path = file?.path(); 201 let path = file?.path();
193 if path.is_file() { 202 if path.is_file() {
194 let pathstr = match path.to_str().ok_or("") { 203 let Ok(pathstr) = path.to_str().ok_or("") else {
195 Ok(s) => s, 204 return Err(MLErr::new(EType::Other, "INVALID_PATH"))
196 Err(..) => {
197 return Err(MLError::new(ErrorType::Other, "INVALID_PATH"))
198 }
199 }; 205 };
200 let namesplit: Vec<&str> = pathstr.split('.').collect(); 206 let namesplit: Vec<&str> = pathstr.split('.').collect();
201 let ver_id = namesplit[namesplit.len() - 2]; 207 let ver_id = namesplit[namesplit.len() - 2];
@@ -203,25 +209,29 @@ pub fn get_file_path(list: &List, versionid: String) -> MLE<String> {
203 } 209 }
204 } 210 }
205 211
206 let filename = match names.get(&versionid).ok_or("") { 212 let Ok(filename) = names.get(versionid).ok_or("") else {
207 Ok(n) => n, 213 return Err(MLErr::new(
208 Err(..) => { 214 EType::ArgumentError,
209 return Err(MLError::new( 215 "VERSION_NOT_FOUND_IN_FILES",
210 ErrorType::ArgumentError, 216 ))
211 "VERSION_NOT_FOUND_IN_FILES",
212 ))
213 }
214 }; 217 };
215 218
216 Ok(filename.to_owned()) 219 Ok(filename.to_owned())
217} 220}
218 221
219pub fn get_downloaded_versions(list: List) -> MLE<HashMap<String, String>> { 222/// # Errors
223/// # Panics
224pub fn get_downloaded_versions(list: &List) -> MLE<HashMap<String, String>> {
220 let mut versions: HashMap<String, String> = HashMap::new(); 225 let mut versions: HashMap<String, String> = HashMap::new();
221 for file in read_dir(&list.download_folder)? { 226 for file in read_dir(&list.download_folder)? {
222 let path = file?.path(); 227 let path = file?.path();
223 if path.is_file() && path.extension().ok_or("BAH").unwrap() == "jar" { 228 if path.is_file()
224 let pathstr = path.to_str().ok_or("BAH").unwrap(); 229 && path
230 .extension()
231 .ok_or(MLErr::new(EType::IoError, "extension"))?
232 == "jar"
233 {
234 let pathstr = path.to_str().ok_or(MLErr::new(EType::IoError, "path_to_str"))?;
225 let namesplit: Vec<&str> = pathstr.split('.').collect(); 235 let namesplit: Vec<&str> = pathstr.split('.').collect();
226 versions.insert( 236 versions.insert(
227 String::from(namesplit[namesplit.len() - 3]), 237 String::from(namesplit[namesplit.len() - 3]),
@@ -232,6 +242,8 @@ pub fn get_downloaded_versions(list: List) -> MLE<HashMap<String, String>> {
232 Ok(versions) 242 Ok(versions)
233} 243}
234 244
245/// # Errors
246/// # Panics
235pub fn clean_list_dir(list: &List) -> MLE<()> { 247pub fn clean_list_dir(list: &List) -> MLE<()> {
236 let dl_path = &list.download_folder; 248 let dl_path = &list.download_folder;
237 for entry in std::fs::read_dir(dl_path)? { 249 for entry in std::fs::read_dir(dl_path)? {
diff --git a/src/lib.rs b/src/lib.rs
index c51381c..750580f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -16,7 +16,7 @@ use std::{
16use apis::modrinth::{get_game_versions, GameVersion, GameVersionType}; 16use apis::modrinth::{get_game_versions, GameVersion, GameVersionType};
17pub use apis::*; 17pub use apis::*;
18pub use commands::*; 18pub use commands::*;
19use error::{ErrorType, MLError, MLE}; 19use error::{EType, MLErr, MLE};
20use indicatif::{ProgressBar, ProgressStyle}; 20use indicatif::{ProgressBar, ProgressStyle};
21use serde::{Deserialize, Serialize}; 21use serde::{Deserialize, Serialize};
22 22
@@ -39,13 +39,15 @@ pub enum Modloader {
39} 39}
40 40
41impl Modloader { 41impl Modloader {
42 /// # Errors
43 /// # Panics
42 pub fn from(string: &str) -> MLE<Modloader> { 44 pub fn from(string: &str) -> MLE<Modloader> {
43 match string { 45 match string {
44 "forge" => Ok(Modloader::Forge), 46 "forge" => Ok(Modloader::Forge),
45 "fabric" => Ok(Modloader::Fabric), 47 "fabric" => Ok(Modloader::Fabric),
46 "quilt" => Ok(Modloader::Quilt), 48 "quilt" => Ok(Modloader::Quilt),
47 _ => { 49 _ => {
48 Err(MLError::new(ErrorType::ArgumentError, "UNKNOWN_MODLOADER")) 50 Err(MLErr::new(EType::ArgumentError, "UNKNOWN_MODLOADER"))
49 } 51 }
50 } 52 }
51 } 53 }
@@ -72,14 +74,18 @@ pub enum VersionLevel {
72 74
73/// Checks if update needed (time) 75/// Checks if update needed (time)
74/// if yes: get versions, update 76/// if yes: get versions, update
77/// # Errors
78/// # Panics
75pub async fn check_game_versions(path: &str, force: bool) -> MLE<()> { 79pub async fn check_game_versions(path: &str, force: bool) -> MLE<()> {
76 let p = ProgressBar::new(1); 80 let p = ProgressBar::new(1);
77 p.set_style(ProgressStyle::with_template(STYLE_MESSAGE).unwrap()); 81 p.set_style(ProgressStyle::with_template(STYLE_MESSAGE).map_err(|_| {
82 MLErr::new(EType::LibIndicatif, "template error")
83 })?);
78 p.set_message("Update minecraft versions"); 84 p.set_message("Update minecraft versions");
79 85
80 let creation_time = fs::metadata(path)?.created()?; 86 let creation_time = fs::metadata(path)?.created()?;
81 if !force 87 if !force
82 && creation_time.elapsed().unwrap() < Duration::from_secs(60 * 60 * 24) 88 && creation_time.elapsed().map_err(|_| MLErr::new(EType::LibIndicatif, "SystemTimeError"))? < Duration::from_secs(60 * 60 * 24)
83 { 89 {
84 return Ok(()); 90 return Ok(());
85 } 91 }
@@ -94,6 +100,7 @@ pub async fn check_game_versions(path: &str, force: bool) -> MLE<()> {
94} 100}
95 101
96/// Loads game versions from file 102/// Loads game versions from file
103/// # Errors
97pub fn load_game_versions(path: &str) -> MLE<Vec<GameVersion>> { 104pub fn load_game_versions(path: &str) -> MLE<Vec<GameVersion>> {
98 let mut file = File::open(path)?; 105 let mut file = File::open(path)?;
99 let mut data = String::new(); 106 let mut data = String::new();
@@ -103,7 +110,8 @@ pub fn load_game_versions(path: &str) -> MLE<Vec<GameVersion>> {
103} 110}
104 111
105impl VersionLevel { 112impl VersionLevel {
106 #[must_use] pub fn from(str: &str) -> Self { 113 #[must_use]
114 pub fn from(str: &str) -> Self {
107 match str { 115 match str {
108 "release" => VersionLevel::Release, 116 "release" => VersionLevel::Release,
109 "snapshot" => VersionLevel::Snapshot, 117 "snapshot" => VersionLevel::Snapshot,
@@ -111,6 +119,12 @@ impl VersionLevel {
111 } 119 }
112 } 120 }
113 121
122 /// .
123 ///
124 /// # Panics
125 ///
126 /// Panics if .
127 /// # Errors
114 pub async fn get( 128 pub async fn get(
115 self, 129 self,
116 versions_path: &str, 130 versions_path: &str,
@@ -122,23 +136,35 @@ impl VersionLevel {
122 136
123 match self { 137 match self {
124 VersionLevel::Release => { 138 VersionLevel::Release => {
125 let release = versions 139 if let Some(release) = versions
126 .find(|ver| ver.version_type == GameVersionType::release) 140 .find(|ver| ver.version_type == GameVersionType::release)
127 .unwrap(); 141 {
128 Ok(release.version) 142 Ok(release.version)
143 } else {
144 Err(MLErr::new(
145 EType::Other,
146 "no minecraft release version found",
147 ))
148 }
129 } 149 }
130 VersionLevel::Snapshot => { 150 VersionLevel::Snapshot => {
131 let snapshot = versions 151 if let Some(snapshot) = versions
132 .find(|ver| ver.version_type == GameVersionType::snapshot) 152 .find(|ver| ver.version_type == GameVersionType::snapshot)
133 .unwrap(); 153 {
134 Ok(snapshot.version) 154 Ok(snapshot.version)
155 } else {
156 Err(MLErr::new(
157 EType::Other,
158 "no minecraft snapshot version found",
159 ))
160 }
135 } 161 }
136 VersionLevel::Version(v) => { 162 VersionLevel::Version(v) => {
137 if versions.any(|ver| ver.version == v) { 163 if versions.any(|ver| ver.version == v) {
138 Ok(v) 164 Ok(v)
139 } else { 165 } else {
140 Err(MLError::new( 166 Err(MLErr::new(
141 ErrorType::ConfigError, 167 EType::ConfigError,
142 "unknown minecraft version", 168 "unknown minecraft version",
143 )) 169 ))
144 } 170 }
diff --git a/src/main.rs b/src/main.rs
index 21f2a30..a478ec7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,9 +1,11 @@
1#![allow(clippy::too_many_lines)]
2
1use clap::{Parser, Subcommand}; 3use clap::{Parser, Subcommand};
2use modlist::{ 4use modlist::{
3 config::Cfg, 5 config::Cfg,
4 db::{config_get_current_list, lists_get, lists_get_all_ids}, 6 db::{config_get_current_list, lists_get, lists_get_all_ids},
5 download, export, get_current_list, import, list_add, list_change, 7 download, export, get_current_list, import, list_add, list_change,
6 list_list, list_remove, list_version, mod_add, mod_remove, update, AddMod, 8 list_lists, list_remove, list_version, mod_add, mod_remove, update, AddMod,
7 IDSelector, List, Modloader, VersionLevel, 9 IDSelector, List, Modloader, VersionLevel,
8}; 10};
9 11
@@ -178,9 +180,10 @@ async fn main() {
178 .unwrap(), 180 .unwrap(),
179 }; 181 };
180 182
181 let marked_id = match version { 183 let marked_id = if version {
182 true => IDSelector::VersionID(id), 184 IDSelector::VersionID(id)
183 false => IDSelector::ModificationID(id), 185 } else {
186 IDSelector::ModificationID(id)
184 }; 187 };
185 188
186 let add_id = AddMod { 189 let add_id = AddMod {
@@ -235,7 +238,7 @@ async fn main() {
235 list_add(&config, &id, &ver, &ml, &directory) 238 list_add(&config, &id, &ver, &ml, &directory)
236 } 239 }
237 ListCommands::Remove { id } => list_remove(&config, &id), 240 ListCommands::Remove { id } => list_remove(&config, &id),
238 ListCommands::List => list_list(&config), 241 ListCommands::List => list_lists(&config),
239 ListCommands::Change { id } => list_change(&config, &id), 242 ListCommands::Change { id } => list_change(&config, &id),
240 ListCommands::Version { 243 ListCommands::Version {
241 id, 244 id,