diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/apis/modrinth.rs | 56 | ||||
-rw-r--r-- | src/commands/download.rs | 38 | ||||
-rw-r--r-- | src/commands/io.rs | 51 | ||||
-rw-r--r-- | src/commands/list.rs | 38 | ||||
-rw-r--r-- | src/commands/mod.rs | 16 | ||||
-rw-r--r-- | src/commands/modification.rs | 181 | ||||
-rw-r--r-- | src/commands/setup.rs | 12 | ||||
-rw-r--r-- | src/commands/update.rs | 116 | ||||
-rw-r--r-- | src/config.rs | 16 | ||||
-rw-r--r-- | src/db.rs | 423 | ||||
-rw-r--r-- | src/error.rs | 37 | ||||
-rw-r--r-- | src/files.rs | 59 | ||||
-rw-r--r-- | src/lib.rs | 10 | ||||
-rw-r--r-- | src/main.rs | 115 |
14 files changed, 823 insertions, 345 deletions
diff --git a/src/apis/modrinth.rs b/src/apis/modrinth.rs index bb5ee19..9afe7f3 100644 --- a/src/apis/modrinth.rs +++ b/src/apis/modrinth.rs | |||
@@ -2,7 +2,10 @@ use chrono::{DateTime, FixedOffset}; | |||
2 | use reqwest::Client; | 2 | use reqwest::Client; |
3 | use serde::Deserialize; | 3 | use serde::Deserialize; |
4 | 4 | ||
5 | use crate::{Modloader, List, error::{MLE, MLError, ErrorType}}; | 5 | use crate::{ |
6 | error::{ErrorType, MLError, MLE}, | ||
7 | List, Modloader, | ||
8 | }; | ||
6 | 9 | ||
7 | #[derive(Debug, Deserialize, Clone)] | 10 | #[derive(Debug, Deserialize, Clone)] |
8 | pub struct Project { | 11 | pub struct Project { |
@@ -47,7 +50,7 @@ pub struct ModeratorMessage { | |||
47 | pub enum Side { | 50 | pub enum Side { |
48 | required, | 51 | required, |
49 | optional, | 52 | optional, |
50 | unsupported | 53 | unsupported, |
51 | } | 54 | } |
52 | 55 | ||
53 | #[allow(non_camel_case_types)] | 56 | #[allow(non_camel_case_types)] |
@@ -55,7 +58,7 @@ pub enum Side { | |||
55 | pub enum Type { | 58 | pub enum Type { |
56 | r#mod, | 59 | r#mod, |
57 | modpack, | 60 | modpack, |
58 | recourcepack | 61 | recourcepack, |
59 | } | 62 | } |
60 | 63 | ||
61 | #[allow(non_camel_case_types)] | 64 | #[allow(non_camel_case_types)] |
@@ -63,9 +66,11 @@ pub enum Type { | |||
63 | pub enum Status { | 66 | pub enum Status { |
64 | approved, | 67 | approved, |
65 | rejected, | 68 | rejected, |
66 | draft, unlisted, archived, | 69 | draft, |
70 | unlisted, | ||
71 | archived, | ||
67 | processing, | 72 | processing, |
68 | unknown | 73 | unknown, |
69 | } | 74 | } |
70 | 75 | ||
71 | #[derive(Debug, Clone, Deserialize)] | 76 | #[derive(Debug, Clone, Deserialize)] |
@@ -90,7 +95,7 @@ pub struct Version { | |||
90 | pub enum VersionType { | 95 | pub enum VersionType { |
91 | release, | 96 | release, |
92 | beta, | 97 | beta, |
93 | alpha | 98 | alpha, |
94 | } | 99 | } |
95 | 100 | ||
96 | #[derive(Debug, Clone, Deserialize)] | 101 | #[derive(Debug, Clone, Deserialize)] |
@@ -110,22 +115,19 @@ pub struct Hash { | |||
110 | 115 | ||
111 | async fn get(api: &str, path: String) -> Result<Option<Vec<u8>>, Box<dyn std::error::Error>> { | 116 | async fn get(api: &str, path: String) -> Result<Option<Vec<u8>>, Box<dyn std::error::Error>> { |
112 | let url = format!(r#"{}{}"#, api, path); | 117 | let url = format!(r#"{}{}"#, api, path); |
113 | 118 | ||
114 | let client = Client::builder() | 119 | let client = Client::builder() |
115 | .user_agent(format!("fxqnlr/modlistcli/{} ([email protected])", env!("CARGO_PKG_VERSION"))) | 120 | .user_agent(format!( |
121 | "fxqnlr/modlistcli/{} ([email protected])", | ||
122 | env!("CARGO_PKG_VERSION") | ||
123 | )) | ||
116 | .build()?; | 124 | .build()?; |
117 | let res = client.get(url) | 125 | let res = client.get(url).send().await?; |
118 | .send() | 126 | |
119 | .await?; | ||
120 | |||
121 | let mut data: Option<Vec<u8>> = None; | 127 | let mut data: Option<Vec<u8>> = None; |
122 | 128 | ||
123 | if res.status() == 200 { | 129 | if res.status() == 200 { |
124 | data = Some(res | 130 | data = Some(res.bytes().await?.to_vec()); |
125 | .bytes() | ||
126 | .await? | ||
127 | .to_vec() | ||
128 | ); | ||
129 | } | 131 | } |
130 | 132 | ||
131 | Ok(data) | 133 | Ok(data) |
@@ -143,7 +145,7 @@ pub async fn projects(api: &str, ids: Vec<String>) -> Vec<Project> { | |||
143 | let url = format!(r#"projects?ids=["{}"]"#, all); | 145 | let url = format!(r#"projects?ids=["{}"]"#, all); |
144 | 146 | ||
145 | let data = get(api, url).await.unwrap().unwrap(); | 147 | let data = get(api, url).await.unwrap().unwrap(); |
146 | 148 | ||
147 | serde_json::from_slice(&data).unwrap() | 149 | serde_json::from_slice(&data).unwrap() |
148 | } | 150 | } |
149 | 151 | ||
@@ -154,7 +156,10 @@ pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> { | |||
154 | Modloader::Fabric => String::from("fabric"), | 156 | Modloader::Fabric => String::from("fabric"), |
155 | }; | 157 | }; |
156 | 158 | ||
157 | let url = format!(r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, id, loaderstr, list.mc_version); | 159 | let url = format!( |
160 | r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, | ||
161 | id, loaderstr, list.mc_version | ||
162 | ); | ||
158 | 163 | ||
159 | let data = get(api, url).await.unwrap(); | 164 | let data = get(api, url).await.unwrap(); |
160 | 165 | ||
@@ -185,7 +190,7 @@ pub fn extract_current_version(versions: Vec<Version>) -> MLE<String> { | |||
185 | times.sort_by_key(|t| t.1); | 190 | times.sort_by_key(|t| t.1); |
186 | times.reverse(); | 191 | times.reverse(); |
187 | Ok(times[0].0.to_string()) | 192 | Ok(times[0].0.to_string()) |
188 | }, | 193 | } |
189 | _ => panic!("available_versions should never be negative"), | 194 | _ => panic!("available_versions should never be negative"), |
190 | } | 195 | } |
191 | } | 196 | } |
@@ -205,16 +210,19 @@ pub struct MCVersion { | |||
205 | } | 210 | } |
206 | 211 | ||
207 | pub async fn get_minecraft_version(api: &str, version: MCVersionType) -> String { | 212 | pub async fn get_minecraft_version(api: &str, version: MCVersionType) -> String { |
208 | let data = get(api, String::from("tag/game_version")).await.unwrap().unwrap(); | 213 | let data = get(api, String::from("tag/game_version")) |
214 | .await | ||
215 | .unwrap() | ||
216 | .unwrap(); | ||
209 | let mc_versions: Vec<MCVersion> = serde_json::from_slice(&data).unwrap(); | 217 | let mc_versions: Vec<MCVersion> = serde_json::from_slice(&data).unwrap(); |
210 | let ver = match version { | 218 | let ver = match version { |
211 | MCVersionType::Release => { | 219 | MCVersionType::Release => { |
212 | let mut i = 0; | 220 | let mut i = 0; |
213 | while !mc_versions[i].major { | 221 | while !mc_versions[i].major { |
214 | i += 1; | 222 | i += 1; |
215 | }; | 223 | } |
216 | &mc_versions[i] | 224 | &mc_versions[i] |
217 | }, | 225 | } |
218 | MCVersionType::Latest => &mc_versions[0], | 226 | MCVersionType::Latest => &mc_versions[0], |
219 | MCVersionType::Specific => { | 227 | MCVersionType::Specific => { |
220 | println!("Not inplemented"); | 228 | println!("Not inplemented"); |
diff --git a/src/commands/download.rs b/src/commands/download.rs index 4baecee..9434591 100644 --- a/src/commands/download.rs +++ b/src/commands/download.rs | |||
@@ -1,8 +1,14 @@ | |||
1 | use crate::{files::{get_downloaded_versions, download_versions, delete_version, disable_version, clean_list_dir}, db::{userlist_get_all_current_versions_with_mods, lists_get_all_ids, lists_get}, modrinth::get_raw_versions, error::{MLE, ErrorType, MLError}}; | 1 | use crate::{config::Cfg, get_current_list, List}; |
2 | use crate::{List, get_current_list, config::Cfg}; | 2 | use crate::{ |
3 | db::{lists_get, lists_get_all_ids, userlist_get_all_current_versions_with_mods}, | ||
4 | error::{ErrorType, MLError, MLE}, | ||
5 | files::{ | ||
6 | clean_list_dir, delete_version, disable_version, download_versions, get_downloaded_versions, | ||
7 | }, | ||
8 | modrinth::get_raw_versions, | ||
9 | }; | ||
3 | 10 | ||
4 | pub async fn download(config: Cfg, all_lists: bool, clean: bool, delete_old: bool) -> MLE<()> { | 11 | pub async fn download(config: Cfg, all_lists: bool, clean: bool, delete_old: bool) -> MLE<()> { |
5 | |||
6 | let mut liststack: Vec<List> = vec![]; | 12 | let mut liststack: Vec<List> = vec![]; |
7 | if all_lists { | 13 | if all_lists { |
8 | let list_ids = lists_get_all_ids(config.clone())?; | 14 | let list_ids = lists_get_all_ids(config.clone())?; |
@@ -18,7 +24,10 @@ pub async fn download(config: Cfg, all_lists: bool, clean: bool, delete_old: boo | |||
18 | for current_list in liststack { | 24 | for current_list in liststack { |
19 | let downloaded_versions = get_downloaded_versions(current_list.clone())?; | 25 | let downloaded_versions = get_downloaded_versions(current_list.clone())?; |
20 | println!("To download: {:#?}", downloaded_versions); | 26 | println!("To download: {:#?}", downloaded_versions); |
21 | let current_version_ids = match userlist_get_all_current_versions_with_mods(config.clone(), String::from(¤t_list.id)) { | 27 | let current_version_ids = match userlist_get_all_current_versions_with_mods( |
28 | config.clone(), | ||
29 | String::from(¤t_list.id), | ||
30 | ) { | ||
22 | Ok(i) => Ok(i), | 31 | Ok(i) => Ok(i), |
23 | Err(e) => Err(MLError::new(ErrorType::DBError, e.to_string().as_str())), | 32 | Err(e) => Err(MLError::new(ErrorType::DBError, e.to_string().as_str())), |
24 | }?; | 33 | }?; |
@@ -36,28 +45,37 @@ pub async fn download(config: Cfg, all_lists: bool, clean: bool, delete_old: boo | |||
36 | if current_download.is_none() || clean { | 45 | if current_download.is_none() || clean { |
37 | to_download.push(current_version); | 46 | to_download.push(current_version); |
38 | } else { | 47 | } else { |
39 | let downloaded_version = current_download.ok_or("SOMETHING_HAS_REALLY_GONE_WRONG").unwrap(); | 48 | let downloaded_version = current_download |
49 | .ok_or("SOMETHING_HAS_REALLY_GONE_WRONG") | ||
50 | .unwrap(); | ||
40 | if ¤t_version != downloaded_version { | 51 | if ¤t_version != downloaded_version { |
41 | to_disable.push((mod_id.clone(), String::from(downloaded_version))); | 52 | to_disable.push((mod_id.clone(), String::from(downloaded_version))); |
42 | to_download.push(current_version); | 53 | to_download.push(current_version); |
43 | } | 54 | } |
44 | } | 55 | } |
45 | } | 56 | } |
46 | 57 | ||
47 | if clean { clean_list_dir(¤t_list)? }; | 58 | if clean { |
59 | clean_list_dir(¤t_list)? | ||
60 | }; | ||
48 | 61 | ||
49 | if !to_download.is_empty() { | 62 | if !to_download.is_empty() { |
50 | download_versions(current_list.clone(), config.clone(), get_raw_versions(&config.apis.modrinth, to_download).await).await?; | 63 | download_versions( |
64 | current_list.clone(), | ||
65 | config.clone(), | ||
66 | get_raw_versions(&config.apis.modrinth, to_download).await, | ||
67 | ) | ||
68 | .await?; | ||
51 | } else { | 69 | } else { |
52 | println!("There are no new versions to download"); | 70 | println!("There are no new versions to download"); |
53 | } | 71 | } |
54 | 72 | ||
55 | if !to_disable.is_empty() { | 73 | if !to_disable.is_empty() { |
56 | for ver in to_disable { | 74 | for ver in to_disable { |
57 | if delete_old { | 75 | if delete_old { |
58 | println!("Deleting version {} for mod {}", ver.1, ver.0); | 76 | println!("Deleting version {} for mod {}", ver.1, ver.0); |
59 | delete_version(current_list.clone(), ver.1)?; | 77 | delete_version(current_list.clone(), ver.1)?; |
60 | } else { | 78 | } else { |
61 | disable_version(config.clone(), current_list.clone(), ver.1, ver.0)?; | 79 | disable_version(config.clone(), current_list.clone(), ver.1, ver.0)?; |
62 | }; | 80 | }; |
63 | } | 81 | } |
diff --git a/src/commands/io.rs b/src/commands/io.rs index 5de8dd1..7f03eec 100644 --- a/src/commands/io.rs +++ b/src/commands/io.rs | |||
@@ -1,12 +1,18 @@ | |||
1 | use serde::{Deserialize, Serialize}; | ||
1 | use std::fs::File; | 2 | use std::fs::File; |
2 | use std::io::prelude::*; | 3 | use std::io::prelude::*; |
3 | use serde::{Serialize, Deserialize}; | ||
4 | 4 | ||
5 | use crate::{db::{lists_get, userlist_get_all_ids, lists_get_all_ids, lists_insert}, config::Cfg, Modloader, List, devdir, error::MLE, mod_add, IDSelector}; | 5 | use crate::{ |
6 | config::Cfg, | ||
7 | db::{lists_get, lists_get_all_ids, lists_insert, userlist_get_all_ids}, | ||
8 | devdir, | ||
9 | error::MLE, | ||
10 | mod_add, IDSelector, List, Modloader, | ||
11 | }; | ||
6 | 12 | ||
7 | #[derive(Debug, Serialize, Deserialize)] | 13 | #[derive(Debug, Serialize, Deserialize)] |
8 | struct Export { | 14 | struct Export { |
9 | lists: Vec<ExportList> | 15 | lists: Vec<ExportList>, |
10 | } | 16 | } |
11 | 17 | ||
12 | #[derive(Debug, Serialize, Deserialize)] | 18 | #[derive(Debug, Serialize, Deserialize)] |
@@ -20,15 +26,22 @@ struct ExportList { | |||
20 | 26 | ||
21 | impl ExportList { | 27 | impl ExportList { |
22 | pub fn from(config: Cfg, list_id: String, download: bool) -> MLE<Self> { | 28 | pub fn from(config: Cfg, list_id: String, download: bool) -> MLE<Self> { |
23 | |||
24 | let list = lists_get(config.clone(), String::from(&list_id))?; | 29 | let list = lists_get(config.clone(), String::from(&list_id))?; |
25 | 30 | ||
26 | let mut dl_folder = None; | 31 | let mut dl_folder = None; |
27 | if download{ dl_folder = Some(list.download_folder) }; | 32 | if download { |
33 | dl_folder = Some(list.download_folder) | ||
34 | }; | ||
28 | 35 | ||
29 | let mods = userlist_get_all_ids(config, list_id)?.join("|"); | 36 | let mods = userlist_get_all_ids(config, list_id)?.join("|"); |
30 | 37 | ||
31 | Ok(Self { id: list.id, mods, launcher: list.modloader.to_string(), mc_version: list.mc_version, download_folder: dl_folder }) | 38 | Ok(Self { |
39 | id: list.id, | ||
40 | mods, | ||
41 | launcher: list.modloader.to_string(), | ||
42 | mc_version: list.mc_version, | ||
43 | download_folder: dl_folder, | ||
44 | }) | ||
32 | } | 45 | } |
33 | } | 46 | } |
34 | 47 | ||
@@ -43,32 +56,44 @@ pub fn export(config: Cfg, list: Option<String>) -> MLE<()> { | |||
43 | for list_id in list_ids { | 56 | for list_id in list_ids { |
44 | lists.push(ExportList::from(config.clone(), list_id, true)?); | 57 | lists.push(ExportList::from(config.clone(), list_id, true)?); |
45 | } | 58 | } |
46 | 59 | ||
47 | let toml = toml::to_string( &Export { lists } )?; | 60 | let toml = toml::to_string(&Export { lists })?; |
48 | 61 | ||
49 | let filestr = dirs::home_dir().unwrap().join("mlexport.toml"); | 62 | let filestr = dirs::home_dir().unwrap().join("mlexport.toml"); |
50 | 63 | ||
51 | let mut file = File::create(devdir(filestr.into_os_string().into_string().unwrap().as_str()))?; | 64 | let mut file = File::create(devdir( |
65 | filestr.into_os_string().into_string().unwrap().as_str(), | ||
66 | ))?; | ||
52 | file.write_all(toml.as_bytes())?; | 67 | file.write_all(toml.as_bytes())?; |
53 | 68 | ||
54 | Ok(()) | 69 | Ok(()) |
55 | } | 70 | } |
56 | 71 | ||
57 | pub async fn import(config: Cfg, file_str: String, direct_download: bool) -> MLE<()> { | 72 | pub async fn import(config: Cfg, file_str: String, direct_download: bool) -> MLE<()> { |
58 | |||
59 | let mut file = File::open(file_str)?; | 73 | let mut file = File::open(file_str)?; |
60 | let mut content = String::new(); | 74 | let mut content = String::new(); |
61 | file.read_to_string(&mut content)?; | 75 | file.read_to_string(&mut content)?; |
62 | let export: Export = toml::from_str(&content)?; | 76 | let export: Export = toml::from_str(&content)?; |
63 | 77 | ||
64 | for exportlist in export.lists { | 78 | for exportlist in export.lists { |
65 | 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() }; | 79 | let list = List { |
66 | lists_insert(config.clone(), list.id.clone(), list.mc_version.clone(), list.modloader.clone(), String::from(&list.download_folder))?; | 80 | id: exportlist.id, |
81 | mc_version: exportlist.mc_version, | ||
82 | modloader: Modloader::from(&exportlist.launcher)?, | ||
83 | download_folder: exportlist.download_folder.ok_or("NO_DL").unwrap(), | ||
84 | }; | ||
85 | lists_insert( | ||
86 | config.clone(), | ||
87 | list.id.clone(), | ||
88 | list.mc_version.clone(), | ||
89 | list.modloader.clone(), | ||
90 | String::from(&list.download_folder), | ||
91 | )?; | ||
67 | let mods: Vec<&str> = exportlist.mods.split('|').collect(); | 92 | let mods: Vec<&str> = exportlist.mods.split('|').collect(); |
68 | let mut mod_ids = vec![]; | 93 | let mut mod_ids = vec![]; |
69 | for mod_id in mods { | 94 | for mod_id in mods { |
70 | mod_ids.push(IDSelector::ModificationID(String::from(mod_id))); | 95 | mod_ids.push(IDSelector::ModificationID(String::from(mod_id))); |
71 | }; | 96 | } |
72 | //TODO impl set_version and good direct download | 97 | //TODO impl set_version and good direct download |
73 | //TODO impl all at once, dafuck | 98 | //TODO impl all at once, dafuck |
74 | mod_add(config.clone(), mod_ids, list, direct_download, false).await?; | 99 | mod_add(config.clone(), mod_ids, list, direct_download, false).await?; |
diff --git a/src/commands/list.rs b/src/commands/list.rs index 80e801a..13176f4 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs | |||
@@ -1,4 +1,12 @@ | |||
1 | use crate::{db::{lists_insert, lists_remove, config_change_current_list, config_get_current_list, lists_get, lists_version}, Modloader, config::Cfg, update, error::MLE}; | 1 | use crate::{ |
2 | config::Cfg, | ||
3 | db::{ | ||
4 | config_change_current_list, config_get_current_list, lists_get, lists_insert, lists_remove, | ||
5 | lists_version, | ||
6 | }, | ||
7 | error::MLE, | ||
8 | update, Modloader, | ||
9 | }; | ||
2 | 10 | ||
3 | #[derive(Debug, Clone, PartialEq, Eq)] | 11 | #[derive(Debug, Clone, PartialEq, Eq)] |
4 | pub struct List { | 12 | pub struct List { |
@@ -13,7 +21,13 @@ pub fn get_current_list(config: Cfg) -> MLE<List> { | |||
13 | lists_get(config, id) | 21 | lists_get(config, id) |
14 | } | 22 | } |
15 | 23 | ||
16 | pub fn list_add(config: Cfg, id: String, mc_version: String, modloader: Modloader, directory: String) -> MLE<()> { | 24 | pub fn list_add( |
25 | config: Cfg, | ||
26 | id: String, | ||
27 | mc_version: String, | ||
28 | modloader: Modloader, | ||
29 | directory: String, | ||
30 | ) -> MLE<()> { | ||
17 | lists_insert(config, id, mc_version, modloader, directory) | 31 | lists_insert(config, id, mc_version, modloader, directory) |
18 | } | 32 | } |
19 | 33 | ||
@@ -30,15 +44,27 @@ pub fn list_remove(config: Cfg, id: String) -> MLE<()> { | |||
30 | ///Changing the current lists version and updating it | 44 | ///Changing the current lists version and updating it |
31 | /// | 45 | /// |
32 | /// #Arguments | 46 | /// #Arguments |
33 | /// | 47 | /// |
34 | /// * `config` - The current config | 48 | /// * `config` - The current config |
35 | /// * `args` - All args, to extract the new version | 49 | /// * `args` - All args, to extract the new version |
36 | pub async fn list_version(config: Cfg, id: String, mc_version: String, download: bool, delete: bool) -> MLE<()> { | 50 | pub async fn list_version( |
37 | println!("Change version for list {} to minecraft version: {}", id, mc_version); | 51 | config: Cfg, |
52 | id: String, | ||
53 | mc_version: String, | ||
54 | download: bool, | ||
55 | delete: bool, | ||
56 | ) -> MLE<()> { | ||
57 | println!( | ||
58 | "Change version for list {} to minecraft version: {}", | ||
59 | id, mc_version | ||
60 | ); | ||
38 | 61 | ||
39 | lists_version(config.clone(), &id, &mc_version)?; | 62 | lists_version(config.clone(), &id, &mc_version)?; |
40 | 63 | ||
41 | println!("\nCheck for updates for new minecraft version in list {}", id); | 64 | println!( |
65 | "\nCheck for updates for new minecraft version in list {}", | ||
66 | id | ||
67 | ); | ||
42 | let list = lists_get(config.clone(), id)?; | 68 | let list = lists_get(config.clone(), id)?; |
43 | update(config, vec![list], true, download, delete).await | 69 | update(config, vec![list], true, download, delete).await |
44 | } | 70 | } |
diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 0d5bd00..1c7c012 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs | |||
@@ -1,13 +1,13 @@ | |||
1 | pub mod modification; | ||
2 | pub mod list; | ||
3 | pub mod update; | ||
4 | pub mod setup; | ||
5 | pub mod download; | 1 | pub mod download; |
6 | pub mod io; | 2 | pub mod io; |
3 | pub mod list; | ||
4 | pub mod modification; | ||
5 | pub mod setup; | ||
6 | pub mod update; | ||
7 | 7 | ||
8 | pub use modification::*; | ||
9 | pub use list::*; | ||
10 | pub use update::*; | ||
11 | pub use setup::*; | ||
12 | pub use download::*; | 8 | pub use download::*; |
13 | pub use io::*; | 9 | pub use io::*; |
10 | pub use list::*; | ||
11 | pub use modification::*; | ||
12 | pub use setup::*; | ||
13 | pub use update::*; | ||
diff --git a/src/commands/modification.rs b/src/commands/modification.rs index 454e148..ffc4e10 100644 --- a/src/commands/modification.rs +++ b/src/commands/modification.rs | |||
@@ -1,9 +1,19 @@ | |||
1 | use crate::{modrinth::{versions, extract_current_version, Version, projects, get_raw_versions, project}, 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}, files::{delete_version, download_versions}, List, error::{MLE, ErrorType, MLError}}; | 1 | use crate::{ |
2 | config::Cfg, | ||
3 | db::{ | ||
4 | lists_get_all_ids, mods_get_id, mods_insert, mods_remove, userlist_get_all_ids, | ||
5 | userlist_get_current_version, userlist_insert, userlist_remove, | ||
6 | }, | ||
7 | error::{ErrorType, MLError, MLE}, | ||
8 | files::{delete_version, download_versions}, | ||
9 | modrinth::{extract_current_version, get_raw_versions, project, projects, versions, Version}, | ||
10 | List, | ||
11 | }; | ||
2 | 12 | ||
3 | #[derive(Debug, Clone, PartialEq, Eq)] | 13 | #[derive(Debug, Clone, PartialEq, Eq)] |
4 | pub enum IDSelector { | 14 | pub enum IDSelector { |
5 | ModificationID(String), | 15 | ModificationID(String), |
6 | VersionID(String) | 16 | VersionID(String), |
7 | } | 17 | } |
8 | 18 | ||
9 | #[derive(Debug, Clone)] | 19 | #[derive(Debug, Clone)] |
@@ -16,10 +26,16 @@ pub struct ProjectInfo { | |||
16 | pub download_link: String, | 26 | pub download_link: String, |
17 | } | 27 | } |
18 | 28 | ||
19 | pub async fn mod_add(config: Cfg, ids: Vec<IDSelector>, list: List, direct_download: bool, set_version: bool) -> MLE<()> { | 29 | pub async fn mod_add( |
30 | config: Cfg, | ||
31 | ids: Vec<IDSelector>, | ||
32 | list: List, | ||
33 | direct_download: bool, | ||
34 | set_version: bool, | ||
35 | ) -> MLE<()> { | ||
20 | println!("Add mods to {}", list.id); | 36 | println!("Add mods to {}", list.id); |
21 | println!(" └Add mods:"); | 37 | println!(" └Add mods:"); |
22 | 38 | ||
23 | let mut mod_ids: Vec<String> = Vec::new(); | 39 | let mut mod_ids: Vec<String> = Vec::new(); |
24 | let mut ver_ids: Vec<String> = Vec::new(); | 40 | let mut ver_ids: Vec<String> = Vec::new(); |
25 | 41 | ||
@@ -32,11 +48,17 @@ pub async fn mod_add(config: Cfg, ids: Vec<IDSelector>, list: List, direct_downl | |||
32 | } | 48 | } |
33 | 49 | ||
34 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); | 50 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); |
35 | if !mod_ids.is_empty() { projectinfo.append(&mut get_mod_infos(config.clone(), mod_ids, list.clone()).await?) }; | 51 | if !mod_ids.is_empty() { |
36 | if !ver_ids.is_empty() { projectinfo.append(&mut get_ver_info(config.clone(), ver_ids).await?) }; | 52 | projectinfo.append(&mut get_mod_infos(config.clone(), mod_ids, list.clone()).await?) |
53 | }; | ||
54 | if !ver_ids.is_empty() { | ||
55 | projectinfo.append(&mut get_ver_info(config.clone(), ver_ids).await?) | ||
56 | }; | ||
57 | |||
58 | if projectinfo.is_empty() { | ||
59 | return Err(MLError::new(ErrorType::ArgumentError, "NO_IDS?")); | ||
60 | }; | ||
37 | 61 | ||
38 | if projectinfo.is_empty() { return Err(MLError::new(ErrorType::ArgumentError, "NO_IDS?")) }; | ||
39 | |||
40 | let mut downloadstack: Vec<Version> = Vec::new(); | 62 | let mut downloadstack: Vec<Version> = Vec::new(); |
41 | 63 | ||
42 | //Adding each mod to the lists and downloadstack | 64 | //Adding each mod to the lists and downloadstack |
@@ -45,29 +67,59 @@ pub async fn mod_add(config: Cfg, ids: Vec<IDSelector>, list: List, direct_downl | |||
45 | } else { | 67 | } else { |
46 | println!(" └Insert mods in list {} and save infos", list.id); | 68 | println!(" └Insert mods in list {} and save infos", list.id); |
47 | } | 69 | } |
48 | 70 | ||
49 | for project in projectinfo { | 71 | for project in projectinfo { |
50 | let current_version_id = if project.current_version.is_none() { String::from("NONE") } else { project.current_version.clone().unwrap().id }; | 72 | let current_version_id = if project.current_version.is_none() { |
51 | match userlist_insert(config.clone(), &list.id, &project.mod_id, ¤t_version_id, project.clone().applicable_versions, &project.download_link, set_version) { | 73 | String::from("NONE") |
74 | } else { | ||
75 | project.current_version.clone().unwrap().id | ||
76 | }; | ||
77 | match userlist_insert( | ||
78 | config.clone(), | ||
79 | &list.id, | ||
80 | &project.mod_id, | ||
81 | ¤t_version_id, | ||
82 | project.clone().applicable_versions, | ||
83 | &project.download_link, | ||
84 | set_version, | ||
85 | ) { | ||
52 | Err(e) => { | 86 | Err(e) => { |
53 | let expected_err = format!("SQL: UNIQUE constraint failed: {}.mod_id", list.id); | 87 | let expected_err = format!("SQL: UNIQUE constraint failed: {}.mod_id", list.id); |
54 | if e.to_string() == expected_err { Err(MLError::new(ErrorType::ModError, "MOD_ALREADY_ON_SELECTED_LIST")) } else { Err(e) } | 88 | if e.to_string() == expected_err { |
55 | }, | 89 | Err(MLError::new( |
56 | Ok(..) => { Ok(..) }, | 90 | ErrorType::ModError, |
91 | "MOD_ALREADY_ON_SELECTED_LIST", | ||
92 | )) | ||
93 | } else { | ||
94 | Err(e) | ||
95 | } | ||
96 | } | ||
97 | Ok(..) => Ok(..), | ||
57 | }?; | 98 | }?; |
58 | 99 | ||
59 | match mods_insert(config.clone(), &project.mod_id, &project.slug, &project.title) { | 100 | match mods_insert( |
101 | config.clone(), | ||
102 | &project.mod_id, | ||
103 | &project.slug, | ||
104 | &project.title, | ||
105 | ) { | ||
60 | Err(e) => { | 106 | Err(e) => { |
61 | if e.to_string() == "SQL: UNIQUE constraint failed: mods.id" { Ok(..) } else { Err(e) } | 107 | if e.to_string() == "SQL: UNIQUE constraint failed: mods.id" { |
62 | }, | 108 | Ok(..) |
109 | } else { | ||
110 | Err(e) | ||
111 | } | ||
112 | } | ||
63 | Ok(..) => Ok(..), | 113 | Ok(..) => Ok(..), |
64 | }?; | 114 | }?; |
65 | 115 | ||
66 | if project.current_version.is_some() { downloadstack.push(project.current_version.unwrap()) }; | 116 | if project.current_version.is_some() { |
117 | downloadstack.push(project.current_version.unwrap()) | ||
118 | }; | ||
67 | } | 119 | } |
68 | 120 | ||
69 | //Download all the added mods | 121 | //Download all the added mods |
70 | if direct_download { | 122 | if direct_download { |
71 | download_versions(list.clone(), config.clone(), downloadstack).await?; | 123 | download_versions(list.clone(), config.clone(), downloadstack).await?; |
72 | }; | 124 | }; |
73 | 125 | ||
@@ -86,7 +138,12 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<String>, list: List) -> MLE<Vec | |||
86 | for project in m_projects { | 138 | for project in m_projects { |
87 | println!("\t└{}", project.title); | 139 | println!("\t└{}", project.title); |
88 | println!("\t └Get versions"); | 140 | println!("\t └Get versions"); |
89 | let available_versions = versions(&config.apis.modrinth, String::from(&project.id), list.clone()).await; | 141 | let available_versions = versions( |
142 | &config.apis.modrinth, | ||
143 | String::from(&project.id), | ||
144 | list.clone(), | ||
145 | ) | ||
146 | .await; | ||
90 | 147 | ||
91 | let mut available_versions_vec: Vec<String> = Vec::new(); | 148 | let mut available_versions_vec: Vec<String> = Vec::new(); |
92 | let current_version: Option<Version>; | 149 | let current_version: Option<Version>; |
@@ -95,36 +152,63 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<String>, list: List) -> MLE<Vec | |||
95 | let current_id = extract_current_version(available_versions.clone())?; | 152 | let current_id = extract_current_version(available_versions.clone())?; |
96 | println!("\t └Current version: {}", current_id); | 153 | println!("\t └Current version: {}", current_id); |
97 | 154 | ||
98 | current_version = Some(available_versions.clone().into_iter().find(|v| v.id == current_id).unwrap()); | 155 | current_version = Some( |
156 | available_versions | ||
157 | .clone() | ||
158 | .into_iter() | ||
159 | .find(|v| v.id == current_id) | ||
160 | .unwrap(), | ||
161 | ); | ||
99 | 162 | ||
100 | file = current_version.clone().ok_or("").unwrap().files.into_iter().find(|f| f.primary).unwrap().url; | 163 | file = current_version |
164 | .clone() | ||
165 | .ok_or("") | ||
166 | .unwrap() | ||
167 | .files | ||
168 | .into_iter() | ||
169 | .find(|f| f.primary) | ||
170 | .unwrap() | ||
171 | .url; | ||
101 | for ver in available_versions { | 172 | for ver in available_versions { |
102 | available_versions_vec.push(ver.id); | 173 | available_versions_vec.push(ver.id); |
103 | }; | 174 | } |
104 | |||
105 | projectinfo.push(ProjectInfo { mod_id: project.id, slug: project.slug, title: project.title, current_version, applicable_versions: available_versions_vec, download_link: file }) | ||
106 | 175 | ||
176 | projectinfo.push(ProjectInfo { | ||
177 | mod_id: project.id, | ||
178 | slug: project.slug, | ||
179 | title: project.title, | ||
180 | current_version, | ||
181 | applicable_versions: available_versions_vec, | ||
182 | download_link: file, | ||
183 | }) | ||
107 | } else { | 184 | } else { |
108 | println!("\t └There's currently no mod version for your specified target"); | 185 | println!("\t └There's currently no mod version for your specified target"); |
109 | current_version = None; | 186 | current_version = None; |
110 | file = String::from("NONE"); | 187 | file = String::from("NONE"); |
111 | available_versions_vec.push(String::from("NONE")); | 188 | available_versions_vec.push(String::from("NONE")); |
112 | projectinfo.push(ProjectInfo { mod_id: project.id, slug: project.slug, title: project.title, current_version, applicable_versions: available_versions_vec, download_link: file }) | 189 | projectinfo.push(ProjectInfo { |
190 | mod_id: project.id, | ||
191 | slug: project.slug, | ||
192 | title: project.title, | ||
193 | current_version, | ||
194 | applicable_versions: available_versions_vec, | ||
195 | download_link: file, | ||
196 | }) | ||
113 | } | 197 | } |
114 | }; | 198 | } |
115 | 199 | ||
116 | Ok(projectinfo) | 200 | Ok(projectinfo) |
117 | } | 201 | } |
118 | 202 | ||
119 | async fn get_ver_info(config: Cfg, ver_ids: Vec<String>) -> MLE<Vec<ProjectInfo>> { | 203 | async fn get_ver_info(config: Cfg, ver_ids: Vec<String>) -> MLE<Vec<ProjectInfo>> { |
120 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); | 204 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); |
121 | 205 | ||
122 | //Get required information from ver_ids | 206 | //Get required information from ver_ids |
123 | let mut v_versions = get_raw_versions(&config.apis.modrinth, ver_ids).await; | 207 | let mut v_versions = get_raw_versions(&config.apis.modrinth, ver_ids).await; |
124 | let mut v_mod_ids: Vec<String> = Vec::new(); | 208 | let mut v_mod_ids: Vec<String> = Vec::new(); |
125 | for ver in v_versions.clone() { | 209 | for ver in v_versions.clone() { |
126 | v_mod_ids.push(ver.project_id); | 210 | v_mod_ids.push(ver.project_id); |
127 | }; | 211 | } |
128 | let mut v_projects = projects(&config.apis.modrinth, v_mod_ids).await; | 212 | let mut v_projects = projects(&config.apis.modrinth, v_mod_ids).await; |
129 | v_versions.sort_by(|a, b| a.project_id.cmp(&b.project_id)); | 213 | v_versions.sort_by(|a, b| a.project_id.cmp(&b.project_id)); |
130 | v_projects.sort_by(|a, b| a.id.cmp(&b.id)); | 214 | v_projects.sort_by(|a, b| a.id.cmp(&b.id)); |
@@ -132,9 +216,22 @@ async fn get_ver_info(config: Cfg, ver_ids: Vec<String>) -> MLE<Vec<ProjectInfo> | |||
132 | for (i, project) in v_projects.into_iter().enumerate() { | 216 | for (i, project) in v_projects.into_iter().enumerate() { |
133 | let version = &v_versions[i]; | 217 | let version = &v_versions[i]; |
134 | println!("\t└{}({})", project.title, version.id); | 218 | println!("\t└{}({})", project.title, version.id); |
135 | let file = version.clone().files.into_iter().find(|f| f.primary).unwrap().url; | 219 | let file = version |
136 | projectinfo.push(ProjectInfo { mod_id: project.id, slug: project.slug, title: project.title, current_version: Some(version.clone()), applicable_versions: vec![String::from(&version.id)], download_link: file }) | 220 | .clone() |
137 | }; | 221 | .files |
222 | .into_iter() | ||
223 | .find(|f| f.primary) | ||
224 | .unwrap() | ||
225 | .url; | ||
226 | projectinfo.push(ProjectInfo { | ||
227 | mod_id: project.id, | ||
228 | slug: project.slug, | ||
229 | title: project.title, | ||
230 | current_version: Some(version.clone()), | ||
231 | applicable_versions: vec![String::from(&version.id)], | ||
232 | download_link: file, | ||
233 | }) | ||
234 | } | ||
138 | Ok(projectinfo) | 235 | Ok(projectinfo) |
139 | } | 236 | } |
140 | 237 | ||
@@ -145,24 +242,28 @@ async fn get_ver_info(config: Cfg, ver_ids: Vec<String>) -> MLE<Vec<ProjectInfo> | |||
145 | /// * `id` - name, slug or id of the mod | 242 | /// * `id` - name, slug or id of the mod |
146 | /// * `list` - List struct | 243 | /// * `list` - List struct |
147 | pub fn mod_remove(config: Cfg, id: &str, list: List) -> MLE<()> { | 244 | pub fn mod_remove(config: Cfg, id: &str, list: List) -> MLE<()> { |
148 | |||
149 | let mod_id = mods_get_id(&config.data, id)?; | 245 | let mod_id = mods_get_id(&config.data, id)?; |
150 | 246 | ||
151 | let version = userlist_get_current_version(config.clone(), &list.id, &mod_id)?; | 247 | let version = userlist_get_current_version(config.clone(), &list.id, &mod_id)?; |
152 | 248 | ||
153 | userlist_remove(config.clone(), &list.id, &mod_id)?; | 249 | userlist_remove(config.clone(), &list.id, &mod_id)?; |
154 | delete_version(list, version)?; | 250 | delete_version(list, version)?; |
155 | 251 | ||
156 | let list_ids = lists_get_all_ids(config.clone())?; | 252 | let list_ids = lists_get_all_ids(config.clone())?; |
157 | 253 | ||
158 | // Remove mod from main list if not used elsewhere | 254 | // Remove mod from main list if not used elsewhere |
159 | let mut mod_used = false; | 255 | let mut mod_used = false; |
160 | for id in list_ids { | 256 | for id in list_ids { |
161 | let mods = userlist_get_all_ids(config.clone(), id)?; | 257 | let mods = userlist_get_all_ids(config.clone(), id)?; |
162 | if mods.contains(&mod_id) { mod_used = true; break; }; | 258 | if mods.contains(&mod_id) { |
163 | }; | 259 | mod_used = true; |
260 | break; | ||
261 | }; | ||
262 | } | ||
164 | 263 | ||
165 | if !mod_used { mods_remove(config, mod_id)?; }; | 264 | if !mod_used { |
265 | mods_remove(config, mod_id)?; | ||
266 | }; | ||
166 | 267 | ||
167 | Ok(()) | 268 | Ok(()) |
168 | } | 269 | } |
diff --git a/src/commands/setup.rs b/src/commands/setup.rs index 0161bd7..40e8c0a 100644 --- a/src/commands/setup.rs +++ b/src/commands/setup.rs | |||
@@ -1,14 +1,14 @@ | |||
1 | use std::{fs::File, path::Path}; | 1 | use std::{fs::File, path::Path}; |
2 | 2 | ||
3 | use crate::{config::Cfg, db::db_setup, error::MLE, devdir}; | 3 | use crate::{config::Cfg, db::db_setup, devdir, error::MLE}; |
4 | 4 | ||
5 | pub async fn setup(config: Cfg) -> MLE<()> { | 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 | create(config, db_file)?; | 9 | create(config, db_file)?; |
10 | } | 10 | } |
11 | 11 | ||
12 | /* | 12 | /* |
13 | match s_config_get_version(config.clone()) { | 13 | match s_config_get_version(config.clone()) { |
14 | Ok(ver) => { | 14 | Ok(ver) => { |
@@ -21,12 +21,11 @@ pub async fn setup(config: Cfg) -> MLE<()> { | |||
21 | Err(..) => to_02(config).await? | 21 | Err(..) => to_02(config).await? |
22 | }; | 22 | }; |
23 | */ | 23 | */ |
24 | 24 | ||
25 | Ok(()) | 25 | Ok(()) |
26 | } | 26 | } |
27 | 27 | ||
28 | fn create(config: Cfg, db_file: String) -> MLE<()> { | 28 | fn create(config: Cfg, db_file: String) -> MLE<()> { |
29 | |||
30 | println!("Create database"); | 29 | println!("Create database"); |
31 | 30 | ||
32 | File::create(db_file)?; | 31 | File::create(db_file)?; |
@@ -44,7 +43,7 @@ fn create(config: Cfg, db_file: String) -> MLE<()> { | |||
44 | // let full_list = lists_get(config.clone(), String::from(&list))?; | 43 | // let full_list = lists_get(config.clone(), String::from(&list))?; |
45 | // | 44 | // |
46 | // let versions = userlist_get_all_current_version_ids(config.clone(), full_list.clone().id)?; | 45 | // let versions = userlist_get_all_current_version_ids(config.clone(), full_list.clone().id)?; |
47 | // | 46 | // |
48 | // let raw_versions = get_raw_versions(String::from(&config.apis.modrinth), versions).await; | 47 | // let raw_versions = get_raw_versions(String::from(&config.apis.modrinth), versions).await; |
49 | // | 48 | // |
50 | // for ver in raw_versions { | 49 | // for ver in raw_versions { |
@@ -69,4 +68,3 @@ fn create(config: Cfg, db_file: String) -> MLE<()> { | |||
69 | // } | 68 | // } |
70 | // s_config_update_version(config, String::from("0.4")) | 69 | // s_config_update_version(config, String::from("0.4")) |
71 | //} | 70 | //} |
72 | |||
diff --git a/src/commands/update.rs b/src/commands/update.rs index e5751c0..3d9578b 100644 --- a/src/commands/update.rs +++ b/src/commands/update.rs | |||
@@ -1,14 +1,30 @@ | |||
1 | use crate::{config::Cfg, modrinth::{versions, extract_current_version, Version}, db::{userlist_get_all_ids, userlist_get_applicable_versions, userlist_change_versions, userlist_get_current_version, userlist_get_set_version, mods_get_info}, List, files::{delete_version, download_versions, disable_version, clean_list_dir}, error::{MLE, MLError, ErrorType}}; | 1 | use crate::{ |
2 | 2 | config::Cfg, | |
3 | pub async fn update(config: Cfg, liststack: Vec<List>, clean: bool, direct_download: bool, delete_old: bool) -> MLE<()> { | 3 | db::{ |
4 | mods_get_info, userlist_change_versions, userlist_get_all_ids, | ||
5 | userlist_get_applicable_versions, userlist_get_current_version, userlist_get_set_version, | ||
6 | }, | ||
7 | error::{ErrorType, MLError, MLE}, | ||
8 | files::{clean_list_dir, delete_version, disable_version, download_versions}, | ||
9 | modrinth::{extract_current_version, versions, Version}, | ||
10 | List, | ||
11 | }; | ||
12 | |||
13 | pub async fn update( | ||
14 | config: Cfg, | ||
15 | liststack: Vec<List>, | ||
16 | clean: bool, | ||
17 | direct_download: bool, | ||
18 | delete_old: bool, | ||
19 | ) -> MLE<()> { | ||
4 | for current_list in liststack { | 20 | for current_list in liststack { |
5 | let mods = userlist_get_all_ids(config.clone(), current_list.clone().id)?; | 21 | let mods = userlist_get_all_ids(config.clone(), current_list.clone().id)?; |
6 | 22 | ||
7 | let mut current_versions: Vec<(String, String)> = vec![]; | 23 | let mut current_versions: Vec<(String, String)> = vec![]; |
8 | 24 | ||
9 | println!(" └Update mods:"); | 25 | println!(" └Update mods:"); |
10 | let mut updatestack: Vec<Version> = vec![]; | 26 | let mut updatestack: Vec<Version> = vec![]; |
11 | 27 | ||
12 | for id in mods { | 28 | for id in mods { |
13 | let info = mods_get_info(config.clone(), &id)?; | 29 | let info = mods_get_info(config.clone(), &id)?; |
14 | println!("\t└{}", info.title); | 30 | println!("\t└{}", info.title); |
@@ -19,27 +35,39 @@ pub async fn update(config: Cfg, liststack: Vec<List>, clean: bool, direct_downl | |||
19 | } | 35 | } |
20 | 36 | ||
21 | //Getting current installed version for disable or delete | 37 | //Getting current installed version for disable or delete |
22 | let disable_version = userlist_get_current_version(config.clone(), ¤t_list.id, &id)?; | 38 | let disable_version = |
39 | userlist_get_current_version(config.clone(), ¤t_list.id, &id)?; | ||
23 | 40 | ||
24 | updatestack.push( | 41 | updatestack.push( |
25 | match specific_update(config.clone(), clean, current_list.clone(), String::from(&id)).await { | 42 | match specific_update( |
43 | config.clone(), | ||
44 | clean, | ||
45 | current_list.clone(), | ||
46 | String::from(&id), | ||
47 | ) | ||
48 | .await | ||
49 | { | ||
26 | Ok(ver) => { | 50 | Ok(ver) => { |
27 | current_versions.push((disable_version, id)); | 51 | current_versions.push((disable_version, id)); |
28 | ver | 52 | ver |
29 | }, | 53 | } |
30 | Err(e) => { | 54 | Err(e) => { |
31 | if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" { | 55 | if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" { |
32 | println!("\t └No new version found for the specified minecraft version"); | 56 | println!( |
57 | "\t └No new version found for the specified minecraft version" | ||
58 | ); | ||
33 | } else { | 59 | } else { |
34 | return Err(e); | 60 | return Err(e); |
35 | }; | 61 | }; |
36 | continue; | 62 | continue; |
37 | } | 63 | } |
38 | } | 64 | }, |
39 | ) | 65 | ) |
40 | }; | 66 | } |
41 | 67 | ||
42 | if clean { clean_list_dir(¤t_list)?; }; | 68 | if clean { |
69 | clean_list_dir(¤t_list)?; | ||
70 | }; | ||
43 | 71 | ||
44 | if direct_download && !updatestack.is_empty() { | 72 | if direct_download && !updatestack.is_empty() { |
45 | download_versions(current_list.clone(), config.clone(), updatestack).await?; | 73 | download_versions(current_list.clone(), config.clone(), updatestack).await?; |
@@ -50,7 +78,7 @@ pub async fn update(config: Cfg, liststack: Vec<List>, clean: bool, direct_downl | |||
50 | if delete_old { | 78 | if delete_old { |
51 | println!("\t └Delete version {}", ver.0); | 79 | println!("\t └Delete version {}", ver.0); |
52 | delete_version(current_list.clone(), ver.0)?; | 80 | delete_version(current_list.clone(), ver.0)?; |
53 | } else if ver.0 != "NONE" { | 81 | } else if ver.0 != "NONE" { |
54 | println!("\t └Disable version {}", ver.0); | 82 | println!("\t └Disable version {}", ver.0); |
55 | disable_version(config.clone(), current_list.clone(), ver.0, ver.1)?; | 83 | disable_version(config.clone(), current_list.clone(), ver.0, ver.1)?; |
56 | }; | 84 | }; |
@@ -63,10 +91,11 @@ pub async fn update(config: Cfg, liststack: Vec<List>, clean: bool, direct_downl | |||
63 | } | 91 | } |
64 | 92 | ||
65 | async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> MLE<Version> { | 93 | async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> MLE<Version> { |
66 | let applicable_versions = versions(&config.apis.modrinth, String::from(&id), list.clone()).await; | 94 | let applicable_versions = |
67 | 95 | versions(&config.apis.modrinth, String::from(&id), list.clone()).await; | |
96 | |||
68 | let mut versions: Vec<String> = vec![]; | 97 | let mut versions: Vec<String> = vec![]; |
69 | 98 | ||
70 | if !applicable_versions.is_empty() { | 99 | if !applicable_versions.is_empty() { |
71 | for ver in &applicable_versions { | 100 | for ver in &applicable_versions { |
72 | versions.push(String::from(&ver.id)); | 101 | versions.push(String::from(&ver.id)); |
@@ -77,8 +106,14 @@ async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> ML | |||
77 | 106 | ||
78 | let mut current: Vec<Version> = vec![]; | 107 | let mut current: Vec<Version> = vec![]; |
79 | //TODO Split clean and no match | 108 | //TODO Split clean and no match |
80 | if clean || (versions.join("|") != userlist_get_applicable_versions(config.clone(), String::from(&list.id), String::from(&id))?) { | 109 | if clean |
81 | 110 | || (versions.join("|") | |
111 | != userlist_get_applicable_versions( | ||
112 | config.clone(), | ||
113 | String::from(&list.id), | ||
114 | String::from(&id), | ||
115 | )?) | ||
116 | { | ||
82 | let current_str = extract_current_version(applicable_versions.clone())?; | 117 | let current_str = extract_current_version(applicable_versions.clone())?; |
83 | 118 | ||
84 | if clean { | 119 | if clean { |
@@ -89,35 +124,54 @@ async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> ML | |||
89 | }; | 124 | }; |
90 | 125 | ||
91 | //get new versions | 126 | //get new versions |
92 | let current_ver = match applicable_versions.into_iter().find(|ver| ver.id == current_str).ok_or("!no current version in applicable_versions") { | 127 | let current_ver = match applicable_versions |
128 | .into_iter() | ||
129 | .find(|ver| ver.id == current_str) | ||
130 | .ok_or("!no current version in applicable_versions") | ||
131 | { | ||
93 | Ok(v) => Ok(v), | 132 | Ok(v) => Ok(v), |
94 | Err(e) => Err(MLError::new(ErrorType::Other, e)), | 133 | Err(e) => Err(MLError::new(ErrorType::Other, e)), |
95 | }?; | 134 | }?; |
96 | current.push(current_ver.clone()); | 135 | current.push(current_ver.clone()); |
97 | 136 | ||
98 | //TODO implement version selection if no primary | 137 | //TODO implement version selection if no primary |
99 | let link = match current_ver.files.into_iter().find(|f| f.primary).ok_or("!no primary in links") { | 138 | let link = match current_ver |
139 | .files | ||
140 | .into_iter() | ||
141 | .find(|f| f.primary) | ||
142 | .ok_or("!no primary in links") | ||
143 | { | ||
100 | Ok(p) => Ok(p), | 144 | Ok(p) => Ok(p), |
101 | Err(e) => Err(MLError::new(ErrorType::Other, e)), | 145 | Err(e) => Err(MLError::new(ErrorType::Other, e)), |
102 | }?.url; | 146 | }? |
147 | .url; | ||
103 | userlist_change_versions(config, list.id, current_str, versions.join("|"), link, id)?; | 148 | userlist_change_versions(config, list.id, current_str, versions.join("|"), link, id)?; |
104 | } | 149 | } |
105 | 150 | ||
106 | if current.is_empty() { return Err(MLError::new(ErrorType::ModError, "NO_UPDATE_AVAILABLE")) }; | 151 | if current.is_empty() { |
107 | 152 | return Err(MLError::new(ErrorType::ModError, "NO_UPDATE_AVAILABLE")); | |
153 | }; | ||
154 | |||
108 | //println!(" └✔️"); | 155 | //println!(" └✔️"); |
109 | Ok(current[0].clone()) | 156 | Ok(current[0].clone()) |
110 | } | 157 | } |
111 | 158 | ||
112 | #[tokio::test] | 159 | #[tokio::test] |
113 | async fn download_updates_test() { | 160 | async fn download_updates_test() { |
161 | use crate::{ | ||
162 | modrinth::{Hash, Version, VersionFile, VersionType}, | ||
163 | List, Modloader, | ||
164 | }; | ||
114 | 165 | ||
115 | use crate::{modrinth::{Version, VersionFile, Hash, VersionType}, Modloader, List}; | ||
116 | |||
117 | let config = Cfg::init("modlist.toml").unwrap(); | 166 | let config = Cfg::init("modlist.toml").unwrap(); |
118 | let current_list = List { id: String::from("..."), mc_version: String::from("..."), modloader: Modloader::Fabric, download_folder: String::from("./dev/tests/dl") }; | 167 | let current_list = List { |
119 | 168 | id: String::from("..."), | |
120 | let versions = vec![Version { | 169 | mc_version: String::from("..."), |
170 | modloader: Modloader::Fabric, | ||
171 | download_folder: String::from("./dev/tests/dl"), | ||
172 | }; | ||
173 | |||
174 | let versions = vec![Version { | ||
121 | id: "dEqtGnT9".to_string(), | 175 | id: "dEqtGnT9".to_string(), |
122 | project_id: "kYuIpRLv".to_string(), | 176 | project_id: "kYuIpRLv".to_string(), |
123 | author_id: "Qnt13hO8".to_string(), | 177 | author_id: "Qnt13hO8".to_string(), |
@@ -147,5 +201,7 @@ async fn download_updates_test() { | |||
147 | "fabric".to_string() | 201 | "fabric".to_string() |
148 | ] | 202 | ] |
149 | }]; | 203 | }]; |
150 | assert!(download_versions(current_list, config, versions).await.is_ok()) | 204 | assert!(download_versions(current_list, config, versions) |
205 | .await | ||
206 | .is_ok()) | ||
151 | } | 207 | } |
diff --git a/src/config.rs b/src/config.rs index 075d884..1b54d5f 100644 --- a/src/config.rs +++ b/src/config.rs | |||
@@ -1,8 +1,11 @@ | |||
1 | use std::{fs::File, io::{Read, Write}}; | 1 | use std::{ |
2 | fs::File, | ||
3 | io::{Read, Write}, | ||
4 | }; | ||
2 | 5 | ||
3 | use serde::{Serialize, Deserialize}; | 6 | use serde::{Deserialize, Serialize}; |
4 | 7 | ||
5 | use crate::{error::MLE, devdir}; | 8 | use crate::{devdir, error::MLE}; |
6 | 9 | ||
7 | #[derive(Debug, Clone, Serialize, Deserialize)] | 10 | #[derive(Debug, Clone, Serialize, Deserialize)] |
8 | pub struct Cfg { | 11 | pub struct Cfg { |
@@ -24,7 +27,12 @@ impl Cfg { | |||
24 | Err(err) => { | 27 | Err(err) => { |
25 | if err.kind() == std::io::ErrorKind::NotFound { | 28 | if err.kind() == std::io::ErrorKind::NotFound { |
26 | println!("No config file found, creating one"); | 29 | println!("No config file found, creating one"); |
27 | let default_cfg = Cfg { data: String::from("./"), apis: Apis { modrinth: String::from("https://api.modrinth.com/v2/") } }; | 30 | let default_cfg = Cfg { |
31 | data: String::from("./"), | ||
32 | apis: Apis { | ||
33 | modrinth: String::from("https://api.modrinth.com/v2/"), | ||
34 | }, | ||
35 | }; | ||
28 | let mut file = File::create(devdir(configfile.to_str().unwrap()))?; | 36 | let mut file = File::create(devdir(configfile.to_str().unwrap()))?; |
29 | println!("Created config file"); | 37 | println!("Created config file"); |
30 | file.write_all(toml::to_string(&default_cfg)?.as_bytes())?; | 38 | file.write_all(toml::to_string(&default_cfg)?.as_bytes())?; |
@@ -2,17 +2,21 @@ use std::io::{Error, ErrorKind}; | |||
2 | 2 | ||
3 | use rusqlite::Connection; | 3 | use rusqlite::Connection; |
4 | 4 | ||
5 | use crate::{Modloader, config::Cfg, List, devdir, error::{MLE, MLError, ErrorType}}; | 5 | use crate::{ |
6 | config::Cfg, | ||
7 | devdir, | ||
8 | error::{ErrorType, MLError, MLE}, | ||
9 | List, Modloader, | ||
10 | }; | ||
6 | 11 | ||
7 | //MODS | 12 | //MODS |
8 | pub fn mods_insert(config: Cfg, id: &str, slug: &str, name: &str) -> MLE<()> { | 13 | pub fn mods_insert(config: Cfg, id: &str, slug: &str, name: &str) -> MLE<()> { |
9 | |||
10 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 14 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
11 | let connection = Connection::open(data)?; | 15 | let connection = Connection::open(data)?; |
12 | 16 | ||
13 | connection.execute( | 17 | connection.execute( |
14 | "INSERT INTO mods (id, slug, title) VALUES (?1, ?2, ?3)", | 18 | "INSERT INTO mods (id, slug, title) VALUES (?1, ?2, ?3)", |
15 | [id, slug, name.replace('\'', "").as_str()] | 19 | [id, slug, name.replace('\'', "").as_str()], |
16 | )?; | 20 | )?; |
17 | 21 | ||
18 | Ok(()) | 22 | Ok(()) |
@@ -21,13 +25,11 @@ pub fn mods_insert(config: Cfg, id: &str, slug: &str, name: &str) -> MLE<()> { | |||
21 | pub fn mods_get_all_ids(config: Cfg) -> Result<Vec<String>, Box<dyn std::error::Error>> { | 25 | pub fn mods_get_all_ids(config: Cfg) -> Result<Vec<String>, Box<dyn std::error::Error>> { |
22 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 26 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
23 | let connection = Connection::open(data).unwrap(); | 27 | let connection = Connection::open(data).unwrap(); |
24 | 28 | ||
25 | let mut mods: Vec<String> = Vec::new(); | 29 | let mut mods: Vec<String> = Vec::new(); |
26 | 30 | ||
27 | let mut stmt = connection.prepare("SELECT id FROM mods")?; | 31 | let mut stmt = connection.prepare("SELECT id FROM mods")?; |
28 | let id_iter = stmt.query_map([], |row| { | 32 | let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
29 | row.get::<usize, String>(0) | ||
30 | })?; | ||
31 | 33 | ||
32 | for id in id_iter { | 34 | for id in id_iter { |
33 | mods.push(id?); | 35 | mods.push(id?); |
@@ -49,36 +51,33 @@ pub fn mods_get_all_ids(config: Cfg) -> Result<Vec<String>, Box<dyn std::error:: | |||
49 | /// | 51 | /// |
50 | ///Will return `MLError` when no mod id is found | 52 | ///Will return `MLError` when no mod id is found |
51 | pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { | 53 | pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { |
52 | |||
53 | //TODO check if "slug" is id | 54 | //TODO check if "slug" is id |
54 | 55 | ||
55 | let data = devdir(format!("{}/data.db", data).as_str()); | 56 | let data = devdir(format!("{}/data.db", data).as_str()); |
56 | let connection = Connection::open(data)?; | 57 | let connection = Connection::open(data)?; |
57 | 58 | ||
58 | let mut mod_id = String::new(); | 59 | let mut mod_id = String::new(); |
59 | 60 | ||
60 | //get from slug | 61 | //get from slug |
61 | let mut stmt = connection.prepare("SELECT id FROM mods WHERE slug = ?")?; | 62 | let mut stmt = connection.prepare("SELECT id FROM mods WHERE slug = ?")?; |
62 | let id_iter = stmt.query_map([slug], |row| { | 63 | let id_iter = stmt.query_map([slug], |row| row.get::<usize, String>(0))?; |
63 | row.get::<usize, String>(0) | ||
64 | })?; | ||
65 | 64 | ||
66 | for id in id_iter { | 65 | for id in id_iter { |
67 | mod_id = id?; | 66 | mod_id = id?; |
68 | }; | 67 | } |
69 | //get from title if no id found from slug | 68 | //get from title if no id found from slug |
70 | if mod_id.is_empty() { | 69 | if mod_id.is_empty() { |
71 | let mut stmt = connection.prepare("SELECT id FROM mods WHERE title = ?")?; | 70 | let mut stmt = connection.prepare("SELECT id FROM mods WHERE title = ?")?; |
72 | let id_iter = stmt.query_map([slug], |row| { | 71 | let id_iter = stmt.query_map([slug], |row| row.get::<usize, String>(0))?; |
73 | row.get::<usize, String>(0) | ||
74 | })?; | ||
75 | 72 | ||
76 | for id in id_iter { | 73 | for id in id_iter { |
77 | mod_id = id?; | 74 | mod_id = id?; |
78 | }; | 75 | } |
79 | } | 76 | } |
80 | 77 | ||
81 | if mod_id.is_empty() { return Err(MLError::new(ErrorType::DBError, "GI_MOD_NOT_FOUND")) }; | 78 | if mod_id.is_empty() { |
79 | return Err(MLError::new(ErrorType::DBError, "GI_MOD_NOT_FOUND")); | ||
80 | }; | ||
82 | 81 | ||
83 | Ok(mod_id) | 82 | Ok(mod_id) |
84 | } | 83 | } |
@@ -91,17 +90,23 @@ pub struct ModInfo { | |||
91 | pub fn mods_get_info(config: Cfg, id: &str) -> MLE<ModInfo> { | 90 | pub fn mods_get_info(config: Cfg, id: &str) -> MLE<ModInfo> { |
92 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 91 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
93 | let connection = Connection::open(data)?; | 92 | let connection = Connection::open(data)?; |
94 | 93 | ||
95 | let mut mod_info: Option<ModInfo> = None; | 94 | let mut mod_info: Option<ModInfo> = None; |
96 | let mut stmt = connection.prepare("SELECT title, slug FROM mods WHERE id = ?")?; | 95 | let mut stmt = connection.prepare("SELECT title, slug FROM mods WHERE id = ?")?; |
97 | let name_iter = stmt.query_map([id], |row| { | 96 | let name_iter = stmt.query_map([id], |row| { |
98 | Ok(vec![row.get::<usize, String>(0)?, row.get::<usize, String>(1)?]) | 97 | Ok(vec![ |
98 | row.get::<usize, String>(0)?, | ||
99 | row.get::<usize, String>(1)?, | ||
100 | ]) | ||
99 | })?; | 101 | })?; |
100 | 102 | ||
101 | for info in name_iter { | 103 | for info in name_iter { |
102 | let i = info?; | 104 | let i = info?; |
103 | mod_info = Some(ModInfo { title: String::from(&i[0]), slug: String::from(&i[1]) }); | 105 | mod_info = Some(ModInfo { |
104 | }; | 106 | title: String::from(&i[0]), |
107 | slug: String::from(&i[1]), | ||
108 | }); | ||
109 | } | ||
105 | 110 | ||
106 | match mod_info.is_none() { | 111 | match mod_info.is_none() { |
107 | true => Err(MLError::new(ErrorType::DBError, "GN_MOD_NOT_FOUND")), | 112 | true => Err(MLError::new(ErrorType::DBError, "GN_MOD_NOT_FOUND")), |
@@ -110,7 +115,6 @@ pub fn mods_get_info(config: Cfg, id: &str) -> MLE<ModInfo> { | |||
110 | } | 115 | } |
111 | 116 | ||
112 | pub fn mods_remove(config: Cfg, id: String) -> MLE<()> { | 117 | pub fn mods_remove(config: Cfg, id: String) -> MLE<()> { |
113 | |||
114 | println!("Removing mod {} from database", id); | 118 | println!("Removing mod {} from database", id); |
115 | 119 | ||
116 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 120 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
@@ -131,27 +135,42 @@ pub fn mods_get_versions(config: Cfg, mods: Vec<String>) -> MLE<Vec<DBModlistVer | |||
131 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 135 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
132 | let connection = Connection::open(data)?; | 136 | let connection = Connection::open(data)?; |
133 | 137 | ||
134 | if mods.is_empty() { return Err(MLError::new(ErrorType::ArgumentError, "MODS_NO_INPUT")); } | 138 | if mods.is_empty() { |
139 | return Err(MLError::new(ErrorType::ArgumentError, "MODS_NO_INPUT")); | ||
140 | } | ||
135 | 141 | ||
136 | let mut wherestr = String::from("WHERE"); | 142 | let mut wherestr = String::from("WHERE"); |
137 | for (i, id) in mods.iter().enumerate() { | 143 | for (i, id) in mods.iter().enumerate() { |
138 | let mut or = " OR"; | 144 | let mut or = " OR"; |
139 | if i == mods.len() - 1 { or = "" }; | 145 | if i == mods.len() - 1 { |
146 | or = "" | ||
147 | }; | ||
140 | wherestr = format!("{} id = '{}'{}", wherestr, id, or); | 148 | wherestr = format!("{} id = '{}'{}", wherestr, id, or); |
141 | } | 149 | } |
142 | 150 | ||
143 | let mut versionmaps: Vec<DBModlistVersions> = Vec::new(); | 151 | let mut versionmaps: Vec<DBModlistVersions> = Vec::new(); |
144 | let mut stmt = connection.prepare(format!("SELECT id, versions, title FROM mods {}", wherestr).as_str())?; | 152 | let mut stmt = connection |
153 | .prepare(format!("SELECT id, versions, title FROM mods {}", wherestr).as_str())?; | ||
145 | let id_iter = stmt.query_map([], |row| { | 154 | let id_iter = stmt.query_map([], |row| { |
146 | Ok(vec![row.get::<usize, String>(0)?, row.get::<usize, String>(1)?, row.get::<usize, String>(2)?]) | 155 | Ok(vec![ |
156 | row.get::<usize, String>(0)?, | ||
157 | row.get::<usize, String>(1)?, | ||
158 | row.get::<usize, String>(2)?, | ||
159 | ]) | ||
147 | })?; | 160 | })?; |
148 | 161 | ||
149 | for ver in id_iter { | 162 | for ver in id_iter { |
150 | let version = ver?; | 163 | let version = ver?; |
151 | println!("\t({}) Get versions from the database", String::from(&version[2])); | 164 | println!( |
165 | "\t({}) Get versions from the database", | ||
166 | String::from(&version[2]) | ||
167 | ); | ||
152 | //println!("Found versions {} for mod {}", version[1], version[0]); | 168 | //println!("Found versions {} for mod {}", version[1], version[0]); |
153 | versionmaps.push(DBModlistVersions { mod_id: String::from(&version[0]), versions: String::from(&version[1]) }) | 169 | versionmaps.push(DBModlistVersions { |
154 | }; | 170 | mod_id: String::from(&version[0]), |
171 | versions: String::from(&version[1]), | ||
172 | }) | ||
173 | } | ||
155 | 174 | ||
156 | match versionmaps.is_empty() { | 175 | match versionmaps.is_empty() { |
157 | true => Err(MLError::new(ErrorType::DBError, "MODS_MODS_NOT_FOUND")), | 176 | true => Err(MLError::new(ErrorType::DBError, "MODS_MODS_NOT_FOUND")), |
@@ -160,16 +179,37 @@ pub fn mods_get_versions(config: Cfg, mods: Vec<String>) -> MLE<Vec<DBModlistVer | |||
160 | } | 179 | } |
161 | 180 | ||
162 | //userlist | 181 | //userlist |
163 | 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<()> { | 182 | pub fn userlist_insert( |
183 | config: Cfg, | ||
184 | list_id: &str, | ||
185 | mod_id: &str, | ||
186 | current_version: &str, | ||
187 | applicable_versions: Vec<String>, | ||
188 | current_link: &str, | ||
189 | set_version: bool, | ||
190 | ) -> MLE<()> { | ||
164 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 191 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
165 | let connection = Connection::open(data)?; | 192 | let connection = Connection::open(data)?; |
166 | 193 | ||
167 | let sv = match set_version { | 194 | let sv = match set_version { |
168 | true => "1", | 195 | true => "1", |
169 | false => "0", | 196 | false => "0", |
170 | }; | 197 | }; |
171 | 198 | ||
172 | 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])?; | 199 | connection.execute( |
200 | format!( | ||
201 | "INSERT INTO {} VALUES (?1, ?2, ?3, ?4, 'NONE', ?5)", | ||
202 | list_id | ||
203 | ) | ||
204 | .as_str(), | ||
205 | [ | ||
206 | mod_id, | ||
207 | current_version, | ||
208 | applicable_versions.join("|").as_str(), | ||
209 | current_link, | ||
210 | sv, | ||
211 | ], | ||
212 | )?; | ||
173 | 213 | ||
174 | Ok(()) | 214 | Ok(()) |
175 | } | 215 | } |
@@ -180,14 +220,12 @@ pub fn userlist_get_all_ids(config: Cfg, list_id: String) -> MLE<Vec<String>> { | |||
180 | 220 | ||
181 | let mut mod_ids: Vec<String> = Vec::new(); | 221 | let mut mod_ids: Vec<String> = Vec::new(); |
182 | let mut stmt = connection.prepare(format!("SELECT mod_id FROM {}", list_id).as_str())?; | 222 | let mut stmt = connection.prepare(format!("SELECT mod_id FROM {}", list_id).as_str())?; |
183 | let id_iter = stmt.query_map([], |row| { | 223 | let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
184 | row.get::<usize, String>(0) | ||
185 | })?; | ||
186 | 224 | ||
187 | for id in id_iter { | 225 | for id in id_iter { |
188 | //println!("Found id {:?}", id.as_ref().unwrap()); | 226 | //println!("Found id {:?}", id.as_ref().unwrap()); |
189 | mod_ids.push(id?) | 227 | mod_ids.push(id?) |
190 | }; | 228 | } |
191 | 229 | ||
192 | match mod_ids.is_empty() { | 230 | match mod_ids.is_empty() { |
193 | true => Err(MLError::new(ErrorType::DBError, "NO_MODS")), | 231 | true => Err(MLError::new(ErrorType::DBError, "NO_MODS")), |
@@ -199,24 +237,34 @@ pub fn userlist_remove(config: Cfg, list_id: &str, mod_id: &str) -> MLE<()> { | |||
199 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 237 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
200 | let connection = Connection::open(data)?; | 238 | let connection = Connection::open(data)?; |
201 | 239 | ||
202 | connection.execute(format!("DELETE FROM {} WHERE mod_id = ?", list_id).as_str(), [mod_id])?; | 240 | connection.execute( |
241 | format!("DELETE FROM {} WHERE mod_id = ?", list_id).as_str(), | ||
242 | [mod_id], | ||
243 | )?; | ||
203 | Ok(()) | 244 | Ok(()) |
204 | } | 245 | } |
205 | 246 | ||
206 | 247 | pub fn userlist_get_applicable_versions( | |
207 | pub fn userlist_get_applicable_versions(config: Cfg, list_id: String, mod_id: String) -> MLE<String> { | 248 | config: Cfg, |
249 | list_id: String, | ||
250 | mod_id: String, | ||
251 | ) -> MLE<String> { | ||
208 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 252 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
209 | let connection = Connection::open(data).unwrap(); | 253 | let connection = Connection::open(data).unwrap(); |
210 | 254 | ||
211 | let mut version: String = String::new(); | 255 | let mut version: String = String::new(); |
212 | let mut stmt = connection.prepare(format!("SELECT applicable_versions FROM {} WHERE mod_id = ?", list_id).as_str())?; | 256 | let mut stmt = connection.prepare( |
213 | let ver_iter = stmt.query_map([mod_id], |row| { | 257 | format!( |
214 | row.get::<usize, String>(0) | 258 | "SELECT applicable_versions FROM {} WHERE mod_id = ?", |
215 | })?; | 259 | list_id |
260 | ) | ||
261 | .as_str(), | ||
262 | )?; | ||
263 | let ver_iter = stmt.query_map([mod_id], |row| row.get::<usize, String>(0))?; | ||
216 | 264 | ||
217 | for ver in ver_iter { | 265 | for ver in ver_iter { |
218 | version = ver?; | 266 | version = ver?; |
219 | }; | 267 | } |
220 | 268 | ||
221 | match version.is_empty() { | 269 | match version.is_empty() { |
222 | true => Err(MLError::new(ErrorType::DBError, "GAV_MOD_NOT_FOUND")), | 270 | true => Err(MLError::new(ErrorType::DBError, "GAV_MOD_NOT_FOUND")), |
@@ -224,22 +272,31 @@ pub fn userlist_get_applicable_versions(config: Cfg, list_id: String, mod_id: St | |||
224 | } | 272 | } |
225 | } | 273 | } |
226 | 274 | ||
227 | pub fn userlist_get_all_applicable_versions_with_mods(config: Cfg, list_id: String) -> MLE<Vec<(String, String)>> { | 275 | pub fn userlist_get_all_applicable_versions_with_mods( |
276 | config: Cfg, | ||
277 | list_id: String, | ||
278 | ) -> MLE<Vec<(String, String)>> { | ||
228 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 279 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
229 | let connection = Connection::open(data)?; | 280 | let connection = Connection::open(data)?; |
230 | 281 | ||
231 | let mut versions: Vec<(String, String)> = Vec::new(); | 282 | let mut versions: Vec<(String, String)> = Vec::new(); |
232 | let mut stmt = connection.prepare(format!("SELECT mod_id, applicable_versions FROM {}", list_id).as_str())?; | 283 | let mut stmt = connection |
284 | .prepare(format!("SELECT mod_id, applicable_versions FROM {}", list_id).as_str())?; | ||
233 | let id_iter = stmt.query_map([], |row| { | 285 | let id_iter = stmt.query_map([], |row| { |
234 | Ok(vec![row.get::<usize, String>(0)?, row.get::<usize, String>(1)?]) | 286 | Ok(vec![ |
287 | row.get::<usize, String>(0)?, | ||
288 | row.get::<usize, String>(1)?, | ||
289 | ]) | ||
235 | })?; | 290 | })?; |
236 | 291 | ||
237 | for ver in id_iter { | 292 | for ver in id_iter { |
238 | let out = ver?; | 293 | let out = ver?; |
239 | versions.push((out[0].to_owned(), out[1].to_owned())); | 294 | versions.push((out[0].to_owned(), out[1].to_owned())); |
240 | }; | 295 | } |
241 | 296 | ||
242 | if versions.is_empty() { return Err(MLError::new(ErrorType::DBError, "NO_MODS_ON_LIST")); }; | 297 | if versions.is_empty() { |
298 | return Err(MLError::new(ErrorType::DBError, "NO_MODS_ON_LIST")); | ||
299 | }; | ||
243 | 300 | ||
244 | Ok(versions) | 301 | Ok(versions) |
245 | } | 302 | } |
@@ -249,14 +306,13 @@ pub fn userlist_get_current_version(config: Cfg, list_id: &str, mod_id: &str) -> | |||
249 | let connection = Connection::open(data).unwrap(); | 306 | let connection = Connection::open(data).unwrap(); |
250 | 307 | ||
251 | let mut version: String = String::new(); | 308 | let mut version: String = String::new(); |
252 | let mut stmt = connection.prepare(format!("SELECT current_version FROM {} WHERE mod_id = ?", list_id).as_str())?; | 309 | let mut stmt = connection |
253 | let ver_iter = stmt.query_map([&mod_id], |row| { | 310 | .prepare(format!("SELECT current_version FROM {} WHERE mod_id = ?", list_id).as_str())?; |
254 | row.get::<usize, String>(0) | 311 | let ver_iter = stmt.query_map([&mod_id], |row| row.get::<usize, String>(0))?; |
255 | })?; | ||
256 | 312 | ||
257 | for ver in ver_iter { | 313 | for ver in ver_iter { |
258 | version = ver?; | 314 | version = ver?; |
259 | }; | 315 | } |
260 | 316 | ||
261 | match version.is_empty() { | 317 | match version.is_empty() { |
262 | true => Err(MLError::new(ErrorType::DBError, "GCV_MOD_NOT_FOUND")), | 318 | true => Err(MLError::new(ErrorType::DBError, "GCV_MOD_NOT_FOUND")), |
@@ -264,63 +320,88 @@ pub fn userlist_get_current_version(config: Cfg, list_id: &str, mod_id: &str) -> | |||
264 | } | 320 | } |
265 | } | 321 | } |
266 | 322 | ||
267 | pub fn userlist_get_all_current_version_ids(config: Cfg, list_id: String) -> Result<Vec<String>, Box<dyn std::error::Error>> { | 323 | pub fn userlist_get_all_current_version_ids( |
324 | config: Cfg, | ||
325 | list_id: String, | ||
326 | ) -> Result<Vec<String>, Box<dyn std::error::Error>> { | ||
268 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 327 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
269 | let connection = Connection::open(data)?; | 328 | let connection = Connection::open(data)?; |
270 | 329 | ||
271 | let mut versions: Vec<String> = Vec::new(); | 330 | let mut versions: Vec<String> = Vec::new(); |
272 | let mut stmt = connection.prepare(format!("SELECT current_version FROM {}", list_id).as_str())?; | 331 | let mut stmt = |
273 | let id_iter = stmt.query_map([], |row| { | 332 | connection.prepare(format!("SELECT current_version FROM {}", list_id).as_str())?; |
274 | row.get::<usize, String>(0) | 333 | let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
275 | })?; | ||
276 | 334 | ||
277 | for id in id_iter { | 335 | for id in id_iter { |
278 | versions.push(id?); | 336 | versions.push(id?); |
279 | }; | 337 | } |
280 | 338 | ||
281 | if versions.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; | 339 | if versions.is_empty() { |
340 | return Err(Box::new(std::io::Error::new( | ||
341 | ErrorKind::Other, | ||
342 | "NO_MODS_ON_LIST", | ||
343 | ))); | ||
344 | }; | ||
282 | 345 | ||
283 | Ok(versions) | 346 | Ok(versions) |
284 | } | 347 | } |
285 | 348 | ||
286 | pub fn userlist_get_all_current_versions_with_mods(config: Cfg, list_id: String) -> Result<Vec<(String, String)>, Box<dyn std::error::Error>> { | 349 | pub fn userlist_get_all_current_versions_with_mods( |
350 | config: Cfg, | ||
351 | list_id: String, | ||
352 | ) -> Result<Vec<(String, String)>, Box<dyn std::error::Error>> { | ||
287 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 353 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
288 | let connection = Connection::open(data)?; | 354 | let connection = Connection::open(data)?; |
289 | 355 | ||
290 | let mut versions: Vec<(String, String)> = Vec::new(); | 356 | let mut versions: Vec<(String, String)> = Vec::new(); |
291 | let mut stmt = connection.prepare(format!("SELECT mod_id, current_version FROM {}", list_id).as_str())?; | 357 | let mut stmt = |
358 | connection.prepare(format!("SELECT mod_id, current_version FROM {}", list_id).as_str())?; | ||
292 | let id_iter = stmt.query_map([], |row| { | 359 | let id_iter = stmt.query_map([], |row| { |
293 | Ok(vec![row.get::<usize, String>(0)?, row.get::<usize, String>(1)?]) | 360 | Ok(vec![ |
361 | row.get::<usize, String>(0)?, | ||
362 | row.get::<usize, String>(1)?, | ||
363 | ]) | ||
294 | })?; | 364 | })?; |
295 | 365 | ||
296 | for ver in id_iter { | 366 | for ver in id_iter { |
297 | let out = ver?; | 367 | let out = ver?; |
298 | versions.push((out[0].to_owned(), out[1].to_owned())); | 368 | versions.push((out[0].to_owned(), out[1].to_owned())); |
299 | }; | 369 | } |
300 | 370 | ||
301 | if versions.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; | 371 | if versions.is_empty() { |
372 | return Err(Box::new(std::io::Error::new( | ||
373 | ErrorKind::Other, | ||
374 | "NO_MODS_ON_LIST", | ||
375 | ))); | ||
376 | }; | ||
302 | 377 | ||
303 | Ok(versions) | 378 | Ok(versions) |
304 | } | 379 | } |
305 | 380 | ||
306 | pub fn userlist_get_set_version(config:Cfg, list_id: &str, mod_id: &str) -> MLE<bool> { | 381 | pub fn userlist_get_set_version(config: Cfg, list_id: &str, mod_id: &str) -> MLE<bool> { |
307 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 382 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
308 | let connection = Connection::open(data).unwrap(); | 383 | let connection = Connection::open(data).unwrap(); |
309 | 384 | ||
310 | let mut set_version: bool = false; | 385 | let mut set_version: bool = false; |
311 | let mut stmt = connection.prepare(format!("SELECT set_version FROM {} WHERE mod_id = ?", list_id).as_str())?; | 386 | let mut stmt = connection |
312 | let ver_iter = stmt.query_map([&mod_id], |row| { | 387 | .prepare(format!("SELECT set_version FROM {} WHERE mod_id = ?", list_id).as_str())?; |
313 | row.get::<usize, bool>(0) | 388 | let ver_iter = stmt.query_map([&mod_id], |row| row.get::<usize, bool>(0))?; |
314 | })?; | ||
315 | 389 | ||
316 | for ver in ver_iter { | 390 | for ver in ver_iter { |
317 | set_version = ver?; | 391 | set_version = ver?; |
318 | }; | 392 | } |
319 | 393 | ||
320 | Ok(set_version) | 394 | Ok(set_version) |
321 | } | 395 | } |
322 | 396 | ||
323 | pub fn userlist_change_versions(config: Cfg, list_id: String, current_version: String, versions: String, link: String, mod_id: String) -> MLE<()> { | 397 | pub fn userlist_change_versions( |
398 | config: Cfg, | ||
399 | list_id: String, | ||
400 | current_version: String, | ||
401 | versions: String, | ||
402 | link: String, | ||
403 | mod_id: String, | ||
404 | ) -> MLE<()> { | ||
324 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 405 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
325 | let connection = Connection::open(data)?; | 406 | let connection = Connection::open(data)?; |
326 | 407 | ||
@@ -328,33 +409,45 @@ pub fn userlist_change_versions(config: Cfg, list_id: String, current_version: S | |||
328 | Ok(()) | 409 | Ok(()) |
329 | } | 410 | } |
330 | 411 | ||
331 | pub fn userlist_add_disabled_versions(config: Cfg, list_id: String, disabled_version: String, mod_id: String) -> MLE<()> { | 412 | pub fn userlist_add_disabled_versions( |
413 | config: Cfg, | ||
414 | list_id: String, | ||
415 | disabled_version: String, | ||
416 | mod_id: String, | ||
417 | ) -> MLE<()> { | ||
332 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 418 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
333 | let connection = Connection::open(data)?; | 419 | let connection = Connection::open(data)?; |
334 | 420 | ||
335 | let currently_disabled_versions = userlist_get_disabled_versions(config, String::from(&list_id), String::from(&mod_id))?; | 421 | let currently_disabled_versions = |
336 | let disabled_versions = match currently_disabled_versions == "NONE" { | 422 | userlist_get_disabled_versions(config, String::from(&list_id), String::from(&mod_id))?; |
423 | let disabled_versions = match currently_disabled_versions == "NONE" { | ||
337 | true => disabled_version, | 424 | true => disabled_version, |
338 | false => format!("{}|{}", currently_disabled_versions, disabled_version), | 425 | false => format!("{}|{}", currently_disabled_versions, disabled_version), |
339 | }; | 426 | }; |
340 | 427 | ||
341 | connection.execute(format!("UPDATE {} SET disabled_versions = ?1 WHERE mod_id = ?2", list_id).as_str(), [disabled_versions, mod_id])?; | 428 | connection.execute( |
429 | format!( | ||
430 | "UPDATE {} SET disabled_versions = ?1 WHERE mod_id = ?2", | ||
431 | list_id | ||
432 | ) | ||
433 | .as_str(), | ||
434 | [disabled_versions, mod_id], | ||
435 | )?; | ||
342 | Ok(()) | 436 | Ok(()) |
343 | } | 437 | } |
344 | 438 | ||
345 | pub fn userlist_get_disabled_versions(config:Cfg, list_id: String, mod_id: String) -> MLE<String> { | 439 | pub fn userlist_get_disabled_versions(config: Cfg, list_id: String, mod_id: String) -> MLE<String> { |
346 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 440 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
347 | let connection = Connection::open(data).unwrap(); | 441 | let connection = Connection::open(data).unwrap(); |
348 | 442 | ||
349 | let mut version: String = String::new(); | 443 | let mut version: String = String::new(); |
350 | let mut stmt = connection.prepare(format!("SELECT disabled_versions FROM {} WHERE mod_id = ?", list_id).as_str())?; | 444 | let mut stmt = connection |
351 | let ver_iter = stmt.query_map([mod_id], |row| { | 445 | .prepare(format!("SELECT disabled_versions FROM {} WHERE mod_id = ?", list_id).as_str())?; |
352 | row.get::<usize, String>(0) | 446 | let ver_iter = stmt.query_map([mod_id], |row| row.get::<usize, String>(0))?; |
353 | })?; | ||
354 | 447 | ||
355 | for ver in ver_iter { | 448 | for ver in ver_iter { |
356 | version = ver?; | 449 | version = ver?; |
357 | }; | 450 | } |
358 | 451 | ||
359 | match version.is_empty() { | 452 | match version.is_empty() { |
360 | true => Err(MLError::new(ErrorType::DBError, "GDV_MOD_NOT_FOUND")), | 453 | true => Err(MLError::new(ErrorType::DBError, "GDV_MOD_NOT_FOUND")), |
@@ -362,36 +455,57 @@ pub fn userlist_get_disabled_versions(config:Cfg, list_id: String, mod_id: Strin | |||
362 | } | 455 | } |
363 | } | 456 | } |
364 | 457 | ||
365 | pub fn userlist_get_all_downloads(config: Cfg, list_id: String) -> Result<Vec<String>, Box<dyn std::error::Error>> { | 458 | pub fn userlist_get_all_downloads( |
459 | config: Cfg, | ||
460 | list_id: String, | ||
461 | ) -> Result<Vec<String>, Box<dyn std::error::Error>> { | ||
366 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 462 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
367 | let connection = Connection::open(data).unwrap(); | 463 | let connection = Connection::open(data).unwrap(); |
368 | 464 | ||
369 | let mut links: Vec<String> = Vec::new(); | 465 | let mut links: Vec<String> = Vec::new(); |
370 | let mut stmt = connection.prepare(format!("SELECT current_download FROM {}", list_id).as_str())?; | 466 | let mut stmt = |
371 | let link_iter = stmt.query_map([], |row| { | 467 | connection.prepare(format!("SELECT current_download FROM {}", list_id).as_str())?; |
372 | row.get::<usize, String>(0) | 468 | let link_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
373 | })?; | ||
374 | 469 | ||
375 | for link in link_iter { | 470 | for link in link_iter { |
376 | let l = link?; | 471 | let l = link?; |
377 | println!("Found link {}", String::from(&l)); | 472 | println!("Found link {}", String::from(&l)); |
378 | links.push(l) | 473 | links.push(l) |
379 | }; | 474 | } |
380 | 475 | ||
381 | if links.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_MODS_ON_LIST"))); }; | 476 | if links.is_empty() { |
477 | return Err(Box::new(std::io::Error::new( | ||
478 | ErrorKind::Other, | ||
479 | "NO_MODS_ON_LIST", | ||
480 | ))); | ||
481 | }; | ||
382 | 482 | ||
383 | Ok(links) | 483 | Ok(links) |
384 | } | 484 | } |
385 | 485 | ||
386 | //lists | 486 | //lists |
387 | ///Inserts into lists table and creates new table | 487 | ///Inserts into lists table and creates new table |
388 | pub fn lists_insert(config: Cfg, id: String, mc_version: String, mod_loader: Modloader, download_folder: String) -> MLE<()> { | 488 | pub fn lists_insert( |
489 | config: Cfg, | ||
490 | id: String, | ||
491 | mc_version: String, | ||
492 | mod_loader: Modloader, | ||
493 | download_folder: String, | ||
494 | ) -> MLE<()> { | ||
389 | println!("Creating list {}", id); | 495 | println!("Creating list {}", id); |
390 | 496 | ||
391 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 497 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
392 | let connection = Connection::open(data)?; | 498 | let connection = Connection::open(data)?; |
393 | 499 | ||
394 | connection.execute("INSERT INTO lists VALUES (?1, ?2, ?3, ?4)", [id.clone(), mc_version, mod_loader.to_string(), download_folder])?; | 500 | connection.execute( |
501 | "INSERT INTO lists VALUES (?1, ?2, ?3, ?4)", | ||
502 | [ | ||
503 | id.clone(), | ||
504 | mc_version, | ||
505 | mod_loader.to_string(), | ||
506 | download_folder, | ||
507 | ], | ||
508 | )?; | ||
395 | 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(), [])?; | 509 | 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(), [])?; |
396 | 510 | ||
397 | Ok(()) | 511 | Ok(()) |
@@ -410,20 +524,37 @@ pub fn lists_get(config: Cfg, list_id: String) -> MLE<List> { | |||
410 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 524 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
411 | let connection = Connection::open(data).unwrap(); | 525 | let connection = Connection::open(data).unwrap(); |
412 | 526 | ||
413 | let mut list = List { id: String::new(), mc_version: String::new(), modloader: Modloader::Fabric, download_folder: String::new() }; | 527 | let mut list = List { |
414 | let mut stmt = connection.prepare("SELECT mc_version, modloader, download_folder FROM lists WHERE id = ?")?; | 528 | id: String::new(), |
529 | mc_version: String::new(), | ||
530 | modloader: Modloader::Fabric, | ||
531 | download_folder: String::new(), | ||
532 | }; | ||
533 | let mut stmt = connection | ||
534 | .prepare("SELECT mc_version, modloader, download_folder FROM lists WHERE id = ?")?; | ||
415 | 535 | ||
416 | let list_iter = stmt.query_map([&list_id], |row| { | 536 | let list_iter = stmt.query_map([&list_id], |row| { |
417 | Ok(vec![row.get::<usize, String>(0)?, row.get::<usize, String>(1)?, row.get::<usize, String>(2)?]) | 537 | Ok(vec![ |
538 | row.get::<usize, String>(0)?, | ||
539 | row.get::<usize, String>(1)?, | ||
540 | row.get::<usize, String>(2)?, | ||
541 | ]) | ||
418 | })?; | 542 | })?; |
419 | 543 | ||
420 | for l in list_iter { | 544 | for l in list_iter { |
421 | let li = l?; | 545 | let li = l?; |
422 | list = List { id: String::from(&list_id), mc_version: String::from(&li[0]), modloader: Modloader::from(&li[1])?, download_folder: String::from(&li[2]) }; | 546 | list = List { |
423 | }; | 547 | id: String::from(&list_id), |
548 | mc_version: String::from(&li[0]), | ||
549 | modloader: Modloader::from(&li[1])?, | ||
550 | download_folder: String::from(&li[2]), | ||
551 | }; | ||
552 | } | ||
553 | |||
554 | if list.id.is_empty() { | ||
555 | return Err(MLError::new(ErrorType::DBError, "LIST_NOT_FOUND")); | ||
556 | } | ||
424 | 557 | ||
425 | if list.id.is_empty() { return Err(MLError::new(ErrorType::DBError, "LIST_NOT_FOUND")); } | ||
426 | |||
427 | Ok(list) | 558 | Ok(list) |
428 | } | 559 | } |
429 | 560 | ||
@@ -431,23 +562,24 @@ pub fn lists_version(config: Cfg, list_id: &str, version: &str) -> MLE<()> { | |||
431 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 562 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
432 | let connection = Connection::open(data).unwrap(); | 563 | let connection = Connection::open(data).unwrap(); |
433 | 564 | ||
434 | connection.execute("UPDATE lists SET mc_version = ? WHERE id = ?", [version, list_id])?; | 565 | connection.execute( |
566 | "UPDATE lists SET mc_version = ? WHERE id = ?", | ||
567 | [version, list_id], | ||
568 | )?; | ||
435 | Ok(()) | 569 | Ok(()) |
436 | } | 570 | } |
437 | 571 | ||
438 | pub fn lists_get_all_ids(config: Cfg) -> MLE<Vec<String>> { | 572 | pub fn lists_get_all_ids(config: Cfg) -> MLE<Vec<String>> { |
439 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 573 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
440 | let connection = Connection::open(data).unwrap(); | 574 | let connection = Connection::open(data).unwrap(); |
441 | 575 | ||
442 | let mut list_ids: Vec<String> = Vec::new(); | 576 | let mut list_ids: Vec<String> = Vec::new(); |
443 | let mut stmt = connection.prepare("SELECT id FROM lists")?; | 577 | let mut stmt = connection.prepare("SELECT id FROM lists")?; |
444 | let id_iter = stmt.query_map([], |row| { | 578 | let id_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
445 | row.get::<usize, String>(0) | ||
446 | })?; | ||
447 | 579 | ||
448 | for id in id_iter { | 580 | for id in id_iter { |
449 | list_ids.push(id?) | 581 | list_ids.push(id?) |
450 | }; | 582 | } |
451 | 583 | ||
452 | match list_ids.is_empty() { | 584 | match list_ids.is_empty() { |
453 | true => Err(MLError::new(ErrorType::DBError, "NO_LISTS")), | 585 | true => Err(MLError::new(ErrorType::DBError, "NO_LISTS")), |
@@ -460,35 +592,50 @@ pub fn config_change_current_list(config: Cfg, id: String) -> MLE<()> { | |||
460 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 592 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
461 | let connection = Connection::open(data)?; | 593 | let connection = Connection::open(data)?; |
462 | 594 | ||
463 | connection.execute("UPDATE user_config SET value = ? WHERE id = 'current_list'", [id])?; | 595 | connection.execute( |
596 | "UPDATE user_config SET value = ? WHERE id = 'current_list'", | ||
597 | [id], | ||
598 | )?; | ||
464 | Ok(()) | 599 | Ok(()) |
465 | } | 600 | } |
466 | 601 | ||
467 | pub fn config_get_current_list(config: Cfg) -> MLE<String> { | 602 | pub fn config_get_current_list(config: Cfg) -> MLE<String> { |
468 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 603 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
469 | let connection = Connection::open(data).unwrap(); | 604 | let connection = Connection::open(data).unwrap(); |
470 | 605 | ||
471 | let mut list_id = String::new(); | 606 | let mut list_id = String::new(); |
472 | let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'current_list'")?; | 607 | let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'current_list'")?; |
473 | let list_iter = stmt.query_map([], |row| { | 608 | let list_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
474 | row.get::<usize, String>(0) | ||
475 | })?; | ||
476 | 609 | ||
477 | for list in list_iter { | 610 | for list in list_iter { |
478 | list_id = list?; | 611 | list_id = list?; |
479 | }; | 612 | } |
613 | |||
614 | if list_id.is_empty() { | ||
615 | return Err(MLError::new(ErrorType::DBError, "NO_CURRENT_LIST")); | ||
616 | } | ||
480 | 617 | ||
481 | if list_id.is_empty() { return Err(MLError::new(ErrorType::DBError, "NO_CURRENT_LIST")); } | ||
482 | |||
483 | Ok(list_id) | 618 | Ok(list_id) |
484 | } | 619 | } |
485 | 620 | ||
486 | //SETUP(UPDATES) | 621 | //SETUP(UPDATES) |
487 | pub fn s_userlist_update_download(config: Cfg, list_id: String, mod_id: String, link: String) -> Result<(), Box<dyn std::error::Error>> { | 622 | pub fn s_userlist_update_download( |
623 | config: Cfg, | ||
624 | list_id: String, | ||
625 | mod_id: String, | ||
626 | link: String, | ||
627 | ) -> Result<(), Box<dyn std::error::Error>> { | ||
488 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 628 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
489 | let connection = Connection::open(data)?; | 629 | let connection = Connection::open(data)?; |
490 | 630 | ||
491 | connection.execute(format!("UPDATE {} SET current_download = ?1 WHERE mod_id = ?2", list_id).as_str(), [link, mod_id])?; | 631 | connection.execute( |
632 | format!( | ||
633 | "UPDATE {} SET current_download = ?1 WHERE mod_id = ?2", | ||
634 | list_id | ||
635 | ) | ||
636 | .as_str(), | ||
637 | [link, mod_id], | ||
638 | )?; | ||
492 | Ok(()) | 639 | Ok(()) |
493 | } | 640 | } |
494 | 641 | ||
@@ -496,7 +643,10 @@ pub fn s_config_create_version(config: Cfg) -> Result<(), Box<dyn std::error::Er | |||
496 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 643 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
497 | let connection = Connection::open(data)?; | 644 | let connection = Connection::open(data)?; |
498 | 645 | ||
499 | connection.execute("INSERT INTO 'user_config' VALUES ( 'db_version', '0.2' )", ())?; | 646 | connection.execute( |
647 | "INSERT INTO 'user_config' VALUES ( 'db_version', '0.2' )", | ||
648 | (), | ||
649 | )?; | ||
500 | Ok(()) | 650 | Ok(()) |
501 | } | 651 | } |
502 | 652 | ||
@@ -504,34 +654,46 @@ pub fn s_config_update_version(config: Cfg, ver: String) -> Result<(), Box<dyn s | |||
504 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 654 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
505 | let connection = Connection::open(data)?; | 655 | let connection = Connection::open(data)?; |
506 | 656 | ||
507 | connection.execute("UPDATE user_config SET value = ? WHERE id = 'db_version'", [ver])?; | 657 | connection.execute( |
658 | "UPDATE user_config SET value = ? WHERE id = 'db_version'", | ||
659 | [ver], | ||
660 | )?; | ||
508 | Ok(()) | 661 | Ok(()) |
509 | } | 662 | } |
510 | 663 | ||
511 | pub fn s_config_get_version(config: Cfg) -> Result<String, Box<dyn std::error::Error>> { | 664 | pub fn s_config_get_version(config: Cfg) -> Result<String, Box<dyn std::error::Error>> { |
512 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 665 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
513 | let connection = Connection::open(data)?; | 666 | let connection = Connection::open(data)?; |
514 | 667 | ||
515 | let mut version: String = String::new(); | 668 | let mut version: String = String::new(); |
516 | let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'db_version'")?; | 669 | let mut stmt = connection.prepare("SELECT value FROM user_config WHERE id = 'db_version'")?; |
517 | let ver_iter = stmt.query_map([], |row| { | 670 | let ver_iter = stmt.query_map([], |row| row.get::<usize, String>(0))?; |
518 | row.get::<usize, String>(0) | ||
519 | })?; | ||
520 | 671 | ||
521 | for ver in ver_iter { | 672 | for ver in ver_iter { |
522 | version = ver?; | 673 | version = ver?; |
523 | }; | 674 | } |
524 | 675 | ||
525 | if version.is_empty() { return Err(Box::new(std::io::Error::new(ErrorKind::Other, "NO_DBVERSION"))); }; | 676 | if version.is_empty() { |
677 | return Err(Box::new(std::io::Error::new( | ||
678 | ErrorKind::Other, | ||
679 | "NO_DBVERSION", | ||
680 | ))); | ||
681 | }; | ||
526 | Ok(version) | 682 | Ok(version) |
527 | } | 683 | } |
528 | 684 | ||
529 | pub fn s_insert_column(config: Cfg, table: String, column: String, c_type: String, default: Option<String>) -> Result<(), Box<dyn std::error::Error>> { | 685 | pub fn s_insert_column( |
686 | config: Cfg, | ||
687 | table: String, | ||
688 | column: String, | ||
689 | c_type: String, | ||
690 | default: Option<String>, | ||
691 | ) -> Result<(), Box<dyn std::error::Error>> { | ||
530 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 692 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
531 | let connection = Connection::open(data)?; | 693 | let connection = Connection::open(data)?; |
532 | 694 | ||
533 | let mut sql = format!("ALTER TABLE {} ADD '{}' {}", table, column, c_type); | 695 | let mut sql = format!("ALTER TABLE {} ADD '{}' {}", table, column, c_type); |
534 | 696 | ||
535 | if default.is_some() { | 697 | if default.is_some() { |
536 | sql = format!("{} DEFAULT {}", sql, default.unwrap()); | 698 | sql = format!("{} DEFAULT {}", sql, default.unwrap()); |
537 | } | 699 | } |
@@ -541,7 +703,6 @@ pub fn s_insert_column(config: Cfg, table: String, column: String, c_type: Strin | |||
541 | } | 703 | } |
542 | 704 | ||
543 | pub fn db_setup(config: Cfg) -> MLE<()> { | 705 | pub fn db_setup(config: Cfg) -> MLE<()> { |
544 | |||
545 | println!("Initiating database"); | 706 | println!("Initiating database"); |
546 | 707 | ||
547 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 708 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
@@ -554,6 +715,6 @@ pub fn db_setup(config: Cfg) -> MLE<()> { | |||
554 | INSERT INTO 'user_config' VALUES ( 'db_version', '0.5' ); | 715 | INSERT INTO 'user_config' VALUES ( 'db_version', '0.5' ); |
555 | INSERT INTO 'user_config' VALUES ( 'current_list', '...' )", | 716 | INSERT INTO 'user_config' VALUES ( 'current_list', '...' )", |
556 | )?; | 717 | )?; |
557 | 718 | ||
558 | Ok(()) | 719 | Ok(()) |
559 | } | 720 | } |
diff --git a/src/error.rs b/src/error.rs index 794a919..bd6e3da 100644 --- a/src/error.rs +++ b/src/error.rs | |||
@@ -43,49 +43,70 @@ impl fmt::Display for MLError { | |||
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"), |
46 | ErrorType::Other => write!(f, "OTHER") | 46 | ErrorType::Other => write!(f, "OTHER"), |
47 | } | 47 | } |
48 | } | 48 | } |
49 | } | 49 | } |
50 | 50 | ||
51 | impl From<reqwest::Error> for MLError { | 51 | impl From<reqwest::Error> for MLError { |
52 | fn from(error: reqwest::Error) -> Self { | 52 | fn from(error: reqwest::Error) -> Self { |
53 | Self { etype: ErrorType::LibReq, message: error.to_string() } | 53 | Self { |
54 | etype: ErrorType::LibReq, | ||
55 | message: error.to_string(), | ||
56 | } | ||
54 | } | 57 | } |
55 | } | 58 | } |
56 | 59 | ||
57 | impl From<toml::de::Error> for MLError { | 60 | impl From<toml::de::Error> for MLError { |
58 | fn from(error: toml::de::Error) -> Self { | 61 | fn from(error: toml::de::Error) -> Self { |
59 | Self { etype: ErrorType::LibToml, message: error.to_string() } | 62 | Self { |
63 | etype: ErrorType::LibToml, | ||
64 | message: error.to_string(), | ||
65 | } | ||
60 | } | 66 | } |
61 | } | 67 | } |
62 | 68 | ||
63 | impl From<rusqlite::Error> for MLError { | 69 | impl From<rusqlite::Error> for MLError { |
64 | fn from(error: rusqlite::Error) -> Self { | 70 | fn from(error: rusqlite::Error) -> Self { |
65 | Self { etype: ErrorType::LibSql, message: error.to_string() } | 71 | Self { |
72 | etype: ErrorType::LibSql, | ||
73 | message: error.to_string(), | ||
74 | } | ||
66 | } | 75 | } |
67 | } | 76 | } |
68 | 77 | ||
69 | impl From<toml::ser::Error> for MLError { | 78 | impl From<toml::ser::Error> for MLError { |
70 | fn from(error: toml::ser::Error) -> Self { | 79 | fn from(error: toml::ser::Error) -> Self { |
71 | Self { etype: ErrorType::LibToml, message: error.to_string() } | 80 | Self { |
81 | etype: ErrorType::LibToml, | ||
82 | message: error.to_string(), | ||
83 | } | ||
72 | } | 84 | } |
73 | } | 85 | } |
74 | 86 | ||
75 | impl From<chrono::ParseError> for MLError { | 87 | impl From<chrono::ParseError> for MLError { |
76 | fn from(error: chrono::ParseError) -> Self { | 88 | fn from(error: chrono::ParseError) -> Self { |
77 | Self { etype: ErrorType::LibChrono, message: error.to_string() } | 89 | Self { |
90 | etype: ErrorType::LibChrono, | ||
91 | message: error.to_string(), | ||
92 | } | ||
78 | } | 93 | } |
79 | } | 94 | } |
80 | 95 | ||
81 | impl From<std::io::Error> for MLError { | 96 | impl From<std::io::Error> for MLError { |
82 | fn from(error: std::io::Error) -> Self { | 97 | fn from(error: std::io::Error) -> Self { |
83 | Self { etype: ErrorType::IoError, message: error.to_string() } | 98 | Self { |
99 | etype: ErrorType::IoError, | ||
100 | message: error.to_string(), | ||
101 | } | ||
84 | } | 102 | } |
85 | } | 103 | } |
86 | 104 | ||
87 | impl MLError { | 105 | impl MLError { |
88 | pub fn new(etype: ErrorType, message: &str) -> Self { | 106 | pub fn new(etype: ErrorType, message: &str) -> Self { |
89 | Self { etype, message: String::from(message) } | 107 | Self { |
108 | etype, | ||
109 | message: String::from(message), | ||
110 | } | ||
90 | } | 111 | } |
91 | } | 112 | } |
diff --git a/src/files.rs b/src/files.rs index 6519c6a..6160cb4 100644 --- a/src/files.rs +++ b/src/files.rs | |||
@@ -1,11 +1,20 @@ | |||
1 | use std::{fs::{File, read_dir, remove_file, rename}, io::Write, collections::HashMap}; | ||
2 | use futures_util::StreamExt; | 1 | use futures_util::StreamExt; |
3 | use reqwest::Client; | 2 | use reqwest::Client; |
4 | 3 | use std::{ | |
5 | use crate::{List, modrinth::Version, db::{userlist_add_disabled_versions, mods_get_info}, config::Cfg, error::{MLE, MLError, ErrorType}}; | 4 | collections::HashMap, |
5 | fs::{read_dir, remove_file, rename, File}, | ||
6 | io::Write, | ||
7 | }; | ||
8 | |||
9 | use crate::{ | ||
10 | config::Cfg, | ||
11 | db::{mods_get_info, userlist_add_disabled_versions}, | ||
12 | error::{ErrorType, MLError, MLE}, | ||
13 | modrinth::Version, | ||
14 | List, | ||
15 | }; | ||
6 | 16 | ||
7 | pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) -> MLE<String> { | 17 | pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) -> MLE<String> { |
8 | |||
9 | let dl_path = String::from(&list.download_folder); | 18 | let dl_path = String::from(&list.download_folder); |
10 | 19 | ||
11 | println!(" └Download mods to {}", dl_path); | 20 | println!(" └Download mods to {}", dl_path); |
@@ -21,7 +30,13 @@ pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) | |||
21 | Ok(e) => e, | 30 | Ok(e) => e, |
22 | Err(..) => return Err(MLError::new(ErrorType::Other, "NO_FILE_EXTENSION")), | 31 | Err(..) => return Err(MLError::new(ErrorType::Other, "NO_FILE_EXTENSION")), |
23 | }; | 32 | }; |
24 | let filename = format!("{}.mr.{}.{}.{}", splitname.join("."), ver.project_id, ver.id, extension); | 33 | let filename = format!( |
34 | "{}.mr.{}.{}.{}", | ||
35 | splitname.join("."), | ||
36 | ver.project_id, | ||
37 | ver.id, | ||
38 | extension | ||
39 | ); | ||
25 | download_file(primary_file.url, list.clone().download_folder, filename).await?; | 40 | download_file(primary_file.url, list.clone().download_folder, filename).await?; |
26 | //tokio::time::sleep(std::time::Duration::new(3, 0)).await; | 41 | //tokio::time::sleep(std::time::Duration::new(3, 0)).await; |
27 | println!(" ✓"); | 42 | println!(" ✓"); |
@@ -32,10 +47,7 @@ pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) | |||
32 | 47 | ||
33 | async fn download_file(url: String, path: String, name: String) -> MLE<()> { | 48 | async fn download_file(url: String, path: String, name: String) -> MLE<()> { |
34 | let dl_path_file = format!("{}/{}", path, name); | 49 | let dl_path_file = format!("{}/{}", path, name); |
35 | let res = Client::new() | 50 | let res = Client::new().get(String::from(&url)).send().await?; |
36 | .get(String::from(&url)) | ||
37 | .send() | ||
38 | .await?; | ||
39 | 51 | ||
40 | // download chunks | 52 | // download chunks |
41 | let mut file = File::create(&dl_path_file)?; | 53 | let mut file = File::create(&dl_path_file)?; |
@@ -49,7 +61,12 @@ async fn download_file(url: String, path: String, name: String) -> MLE<()> { | |||
49 | Ok(()) | 61 | Ok(()) |
50 | } | 62 | } |
51 | 63 | ||
52 | pub fn disable_version(config: Cfg, current_list: List, versionid: String, mod_id: String) -> MLE<()> { | 64 | pub fn disable_version( |
65 | config: Cfg, | ||
66 | current_list: List, | ||
67 | versionid: String, | ||
68 | mod_id: String, | ||
69 | ) -> MLE<()> { | ||
53 | //println!("Disabling version {} for mod {}", versionid, mod_id); | 70 | //println!("Disabling version {} for mod {}", versionid, mod_id); |
54 | let file = get_file_path(current_list.clone(), String::from(&versionid))?; | 71 | let file = get_file_path(current_list.clone(), String::from(&versionid))?; |
55 | let disabled = format!("{}.disabled", file); | 72 | let disabled = format!("{}.disabled", file); |
@@ -63,7 +80,7 @@ pub fn disable_version(config: Cfg, current_list: List, versionid: String, mod_i | |||
63 | 80 | ||
64 | pub fn delete_version(list: List, version: String) -> MLE<()> { | 81 | pub fn delete_version(list: List, version: String) -> MLE<()> { |
65 | let file = get_file_path(list, version)?; | 82 | let file = get_file_path(list, version)?; |
66 | 83 | ||
67 | remove_file(file)?; | 84 | remove_file(file)?; |
68 | 85 | ||
69 | Ok(()) | 86 | Ok(()) |
@@ -76,19 +93,24 @@ pub fn get_file_path(list: List, versionid: String) -> MLE<String> { | |||
76 | if path.is_file() { | 93 | if path.is_file() { |
77 | let pathstr = match path.to_str().ok_or("") { | 94 | let pathstr = match path.to_str().ok_or("") { |
78 | Ok(s) => s, | 95 | Ok(s) => s, |
79 | Err(..) => return Err(MLError::new(ErrorType::Other, "INVALID_PATH")) | 96 | Err(..) => return Err(MLError::new(ErrorType::Other, "INVALID_PATH")), |
80 | }; | 97 | }; |
81 | let namesplit: Vec<&str> = pathstr.split('.').collect(); | 98 | let namesplit: Vec<&str> = pathstr.split('.').collect(); |
82 | let ver_id = namesplit[namesplit.len() - 2]; | 99 | let ver_id = namesplit[namesplit.len() - 2]; |
83 | names.insert(String::from(ver_id), String::from(pathstr)); | 100 | names.insert(String::from(ver_id), String::from(pathstr)); |
84 | } | 101 | } |
85 | }; | 102 | } |
86 | 103 | ||
87 | let filename = match names.get(&versionid).ok_or("") { | 104 | let filename = match names.get(&versionid).ok_or("") { |
88 | Ok(n) => n, | 105 | Ok(n) => n, |
89 | Err(..) => return Err(MLError::new(ErrorType::ArgumentError, "VERSION_NOT_FOUND_IN_FILES")) | 106 | Err(..) => { |
107 | return Err(MLError::new( | ||
108 | ErrorType::ArgumentError, | ||
109 | "VERSION_NOT_FOUND_IN_FILES", | ||
110 | )) | ||
111 | } | ||
90 | }; | 112 | }; |
91 | 113 | ||
92 | Ok(filename.to_owned()) | 114 | Ok(filename.to_owned()) |
93 | } | 115 | } |
94 | 116 | ||
@@ -99,7 +121,10 @@ pub fn get_downloaded_versions(list: List) -> MLE<HashMap<String, String>> { | |||
99 | if path.is_file() && path.extension().ok_or("BAH").unwrap() == "jar" { | 121 | if path.is_file() && path.extension().ok_or("BAH").unwrap() == "jar" { |
100 | let pathstr = path.to_str().ok_or("BAH").unwrap(); | 122 | let pathstr = path.to_str().ok_or("BAH").unwrap(); |
101 | let namesplit: Vec<&str> = pathstr.split('.').collect(); | 123 | let namesplit: Vec<&str> = pathstr.split('.').collect(); |
102 | versions.insert(String::from(namesplit[namesplit.len() - 3]), String::from(namesplit[namesplit.len() - 2])); | 124 | versions.insert( |
125 | String::from(namesplit[namesplit.len() - 3]), | ||
126 | String::from(namesplit[namesplit.len() - 2]), | ||
127 | ); | ||
103 | } | 128 | } |
104 | } | 129 | } |
105 | Ok(versions) | 130 | Ok(versions) |
@@ -111,6 +136,6 @@ pub fn clean_list_dir(list: &List) -> MLE<()> { | |||
111 | for entry in std::fs::read_dir(dl_path)? { | 136 | for entry in std::fs::read_dir(dl_path)? { |
112 | let entry = entry?; | 137 | let entry = entry?; |
113 | std::fs::remove_file(entry.path())?; | 138 | std::fs::remove_file(entry.path())?; |
114 | }; | 139 | } |
115 | Ok(()) | 140 | Ok(()) |
116 | } | 141 | } |
@@ -1,20 +1,20 @@ | |||
1 | pub mod apis; | 1 | pub mod apis; |
2 | pub mod config; | ||
3 | pub mod commands; | 2 | pub mod commands; |
3 | pub mod config; | ||
4 | pub mod db; | 4 | pub mod db; |
5 | pub mod error; | 5 | pub mod error; |
6 | pub mod files; | 6 | pub mod files; |
7 | 7 | ||
8 | use std::{path::Path, fmt::Display}; | 8 | use std::{fmt::Display, path::Path}; |
9 | 9 | ||
10 | pub use apis::*; | 10 | pub use apis::*; |
11 | pub use commands::*; | 11 | pub use commands::*; |
12 | use error::{MLE, ErrorType, MLError}; | 12 | use error::{ErrorType, MLError, MLE}; |
13 | 13 | ||
14 | #[derive(Debug, Clone, PartialEq, Eq)] | 14 | #[derive(Debug, Clone, PartialEq, Eq)] |
15 | pub enum Modloader { | 15 | pub enum Modloader { |
16 | Fabric, | 16 | Fabric, |
17 | Forge | 17 | Forge, |
18 | } | 18 | } |
19 | 19 | ||
20 | impl Modloader { | 20 | impl Modloader { |
@@ -22,7 +22,7 @@ impl Modloader { | |||
22 | match string { | 22 | match string { |
23 | "forge" => Ok(Modloader::Forge), | 23 | "forge" => Ok(Modloader::Forge), |
24 | "fabric" => Ok(Modloader::Fabric), | 24 | "fabric" => Ok(Modloader::Fabric), |
25 | _ => Err(MLError::new(ErrorType::ArgumentError, "UNKNOWN_MODLOADER")) | 25 | _ => Err(MLError::new(ErrorType::ArgumentError, "UNKNOWN_MODLOADER")), |
26 | } | 26 | } |
27 | } | 27 | } |
28 | } | 28 | } |
diff --git a/src/main.rs b/src/main.rs index e845be1..eb5ee0b 100644 --- a/src/main.rs +++ b/src/main.rs | |||
@@ -1,5 +1,10 @@ | |||
1 | use clap::{Parser, Subcommand}; | 1 | use clap::{Parser, Subcommand}; |
2 | use modlist::{config::Cfg, mod_add, mod_remove, db::{lists_get, config_get_current_list, lists_get_all_ids}, IDSelector, download, update, List, get_current_list, import, devdir, export, list_add, Modloader, list_version, list_remove, list_change}; | 2 | use modlist::{ |
3 | config::Cfg, | ||
4 | db::{config_get_current_list, lists_get, lists_get_all_ids}, | ||
5 | devdir, download, export, get_current_list, import, list_add, list_change, list_remove, | ||
6 | list_version, mod_add, mod_remove, update, IDSelector, List, Modloader, | ||
7 | }; | ||
3 | 8 | ||
4 | //TODO make default list optional | 9 | //TODO make default list optional |
5 | #[derive(Parser)] | 10 | #[derive(Parser)] |
@@ -17,13 +22,13 @@ enum Commands { | |||
17 | }, | 22 | }, |
18 | List { | 23 | List { |
19 | #[command(subcommand)] | 24 | #[command(subcommand)] |
20 | command: ListCommands | 25 | command: ListCommands, |
21 | }, | 26 | }, |
22 | Download { | 27 | Download { |
23 | /// download all lists | 28 | /// download all lists |
24 | #[arg(short, long)] | 29 | #[arg(short, long)] |
25 | all: bool, | 30 | all: bool, |
26 | 31 | ||
27 | /// clean all mods before downloading them | 32 | /// clean all mods before downloading them |
28 | #[arg(short, long)] | 33 | #[arg(short, long)] |
29 | clean: bool, | 34 | clean: bool, |
@@ -36,11 +41,11 @@ enum Commands { | |||
36 | /// download all lists | 41 | /// download all lists |
37 | #[arg(short, long)] | 42 | #[arg(short, long)] |
38 | all: bool, | 43 | all: bool, |
39 | 44 | ||
40 | /// directly download updated mods | 45 | /// directly download updated mods |
41 | #[arg(short, long)] | 46 | #[arg(short, long)] |
42 | download: bool, | 47 | download: bool, |
43 | 48 | ||
44 | /// clean all mods before downloading them | 49 | /// clean all mods before downloading them |
45 | #[arg(short, long)] | 50 | #[arg(short, long)] |
46 | clean: bool, | 51 | clean: bool, |
@@ -59,7 +64,7 @@ enum Commands { | |||
59 | }, | 64 | }, |
60 | Export { | 65 | Export { |
61 | /// the list you want to export | 66 | /// the list you want to export |
62 | list: Option<String> | 67 | list: Option<String>, |
63 | }, | 68 | }, |
64 | } | 69 | } |
65 | 70 | ||
@@ -68,7 +73,7 @@ enum ModCommands { | |||
68 | Add { | 73 | Add { |
69 | /// id of the mod/version | 74 | /// id of the mod/version |
70 | id: String, | 75 | id: String, |
71 | 76 | ||
72 | /// set id mode to version | 77 | /// set id mode to version |
73 | #[arg(short, long)] | 78 | #[arg(short, long)] |
74 | version: bool, | 79 | version: bool, |
@@ -83,7 +88,7 @@ enum ModCommands { | |||
83 | 88 | ||
84 | /// optional List selection, else default list will be used | 89 | /// optional List selection, else default list will be used |
85 | #[arg(short, long)] | 90 | #[arg(short, long)] |
86 | list: Option<String> | 91 | list: Option<String>, |
87 | }, | 92 | }, |
88 | Remove { | 93 | Remove { |
89 | /// id, name or title of the mod | 94 | /// id, name or title of the mod |
@@ -91,8 +96,8 @@ enum ModCommands { | |||
91 | 96 | ||
92 | /// optional List selection, else default list will be used | 97 | /// optional List selection, else default list will be used |
93 | #[arg(short, long)] | 98 | #[arg(short, long)] |
94 | list: Option<String> | 99 | list: Option<String>, |
95 | } | 100 | }, |
96 | } | 101 | } |
97 | 102 | ||
98 | #[derive(Subcommand)] | 103 | #[derive(Subcommand)] |
@@ -109,12 +114,12 @@ enum ListCommands { | |||
109 | }, | 114 | }, |
110 | Remove { | 115 | Remove { |
111 | /// id, name or title of the list | 116 | /// id, name or title of the list |
112 | id: String | 117 | id: String, |
113 | }, | 118 | }, |
114 | List, | 119 | List, |
115 | Change { | 120 | Change { |
116 | /// id of the list to change to | 121 | /// id of the list to change to |
117 | id: String | 122 | id: String, |
118 | }, | 123 | }, |
119 | Version { | 124 | Version { |
120 | /// list id | 125 | /// list id |
@@ -129,12 +134,11 @@ enum ListCommands { | |||
129 | /// delete disabled versions | 134 | /// delete disabled versions |
130 | #[arg(short, long)] | 135 | #[arg(short, long)] |
131 | remove: bool, | 136 | remove: bool, |
132 | } | 137 | }, |
133 | } | 138 | } |
134 | 139 | ||
135 | #[tokio::main] | 140 | #[tokio::main] |
136 | async fn main() { | 141 | async fn main() { |
137 | |||
138 | let cli = Cli::parse(); | 142 | let cli = Cli::parse(); |
139 | 143 | ||
140 | let config = Cfg::init("modlist.toml").unwrap(); | 144 | let config = Cfg::init("modlist.toml").unwrap(); |
@@ -143,13 +147,22 @@ async fn main() { | |||
143 | //TODO setup? maybe setup on install | 147 | //TODO setup? maybe setup on install |
144 | match cli.command { | 148 | match cli.command { |
145 | Commands::Mod { command } => { | 149 | Commands::Mod { command } => { |
146 | |||
147 | match command { | 150 | match command { |
148 | #[allow(unused_variables)] | 151 | #[allow(unused_variables)] |
149 | ModCommands::Add { id, version, list, download, lock } => { | 152 | ModCommands::Add { |
153 | id, | ||
154 | version, | ||
155 | list, | ||
156 | download, | ||
157 | lock, | ||
158 | } => { | ||
150 | let listf = match list { | 159 | let listf = match list { |
151 | Some(list) => lists_get(config.clone(), list).unwrap(), | 160 | Some(list) => lists_get(config.clone(), list).unwrap(), |
152 | None => lists_get(config.clone(), config_get_current_list(config.clone()).unwrap()).unwrap(), | 161 | None => lists_get( |
162 | config.clone(), | ||
163 | config_get_current_list(config.clone()).unwrap(), | ||
164 | ) | ||
165 | .unwrap(), | ||
153 | }; | 166 | }; |
154 | 167 | ||
155 | let marked_id = match version { | 168 | let marked_id = match version { |
@@ -164,15 +177,24 @@ async fn main() { | |||
164 | //TODO add success even if no file found | 177 | //TODO add success even if no file found |
165 | let listf = match list { | 178 | let listf = match list { |
166 | Some(list) => lists_get(config.clone(), list).unwrap(), | 179 | Some(list) => lists_get(config.clone(), list).unwrap(), |
167 | None => lists_get(config.clone(), config_get_current_list(config.clone()).unwrap()).unwrap(), | 180 | None => lists_get( |
181 | config.clone(), | ||
182 | config_get_current_list(config.clone()).unwrap(), | ||
183 | ) | ||
184 | .unwrap(), | ||
168 | }; | 185 | }; |
169 | mod_remove(config, &id, listf) | 186 | mod_remove(config, &id, listf) |
170 | } | 187 | } |
171 | } | 188 | } |
172 | }, | 189 | } |
173 | Commands::List { command } => { | 190 | Commands::List { command } => { |
174 | match command { | 191 | match command { |
175 | ListCommands::Add { id, directory, modloader, version } => { | 192 | ListCommands::Add { |
193 | id, | ||
194 | directory, | ||
195 | modloader, | ||
196 | version, | ||
197 | } => { | ||
176 | let ml = match modloader { | 198 | let ml = match modloader { |
177 | Some(ml) => Modloader::from(&ml).unwrap(), | 199 | Some(ml) => Modloader::from(&ml).unwrap(), |
178 | //TODO add default modloader to config | 200 | //TODO add default modloader to config |
@@ -187,23 +209,27 @@ async fn main() { | |||
187 | }; | 209 | }; |
188 | 210 | ||
189 | list_add(config, id, ver, ml, directory) | 211 | list_add(config, id, ver, ml, directory) |
190 | }, | 212 | } |
191 | ListCommands::Remove { id } => { | 213 | ListCommands::Remove { id } => list_remove(config, id), |
192 | list_remove(config, id) | ||
193 | }, | ||
194 | ListCommands::List => { | 214 | ListCommands::List => { |
195 | todo!() | 215 | todo!() |
196 | }, | ||
197 | ListCommands::Change { id } => { | ||
198 | list_change(config, id) | ||
199 | }, | ||
200 | ListCommands::Version { id, version, download, remove } => { | ||
201 | list_version(config, id, version, download, remove).await | ||
202 | } | 216 | } |
217 | ListCommands::Change { id } => list_change(config, id), | ||
218 | ListCommands::Version { | ||
219 | id, | ||
220 | version, | ||
221 | download, | ||
222 | remove, | ||
223 | } => list_version(config, id, version, download, remove).await, | ||
203 | } | 224 | } |
204 | }, | 225 | } |
205 | //TODO a add specific list | 226 | //TODO a add specific list |
206 | Commands::Update { all, download, clean, remove } => { | 227 | Commands::Update { |
228 | all, | ||
229 | download, | ||
230 | clean, | ||
231 | remove, | ||
232 | } => { | ||
207 | let mut liststack: Vec<List> = vec![]; | 233 | let mut liststack: Vec<List> = vec![]; |
208 | if all { | 234 | if all { |
209 | let list_ids = lists_get_all_ids(config.clone()).unwrap(); | 235 | let list_ids = lists_get_all_ids(config.clone()).unwrap(); |
@@ -216,21 +242,26 @@ async fn main() { | |||
216 | liststack.push(current) | 242 | liststack.push(current) |
217 | } | 243 | } |
218 | update(config, liststack, clean, download, remove).await | 244 | update(config, liststack, clean, download, remove).await |
219 | }, | 245 | } |
220 | //TODO add specific list | 246 | //TODO add specific list |
221 | Commands::Download { all, clean, remove } => { | 247 | Commands::Download { all, clean, remove } => download(config, all, clean, remove).await, |
222 | download(config, all, clean, remove).await | ||
223 | }, | ||
224 | Commands::Import { file, download } => { | 248 | Commands::Import { file, download } => { |
225 | let filestr: String = match file { | 249 | let filestr: String = match file { |
226 | Some(args) => args, | 250 | Some(args) => args, |
227 | None => devdir(dirs::home_dir().unwrap().join("mlexport.toml").into_os_string().into_string().unwrap().as_str()), | 251 | None => devdir( |
252 | dirs::home_dir() | ||
253 | .unwrap() | ||
254 | .join("mlexport.toml") | ||
255 | .into_os_string() | ||
256 | .into_string() | ||
257 | .unwrap() | ||
258 | .as_str(), | ||
259 | ), | ||
228 | }; | 260 | }; |
229 | 261 | ||
230 | import(config, filestr, download).await | 262 | import(config, filestr, download).await |
231 | }, | 263 | } |
232 | Commands::Export { list } => { | 264 | Commands::Export { list } => export(config, list), |
233 | export(config, list) | 265 | } |
234 | }, | 266 | .unwrap(); |
235 | }.unwrap(); | ||
236 | } | 267 | } |