diff options
Diffstat (limited to 'src/commands/modification.rs')
-rw-r--r-- | src/commands/modification.rs | 223 |
1 files changed, 154 insertions, 69 deletions
diff --git a/src/commands/modification.rs b/src/commands/modification.rs index 31e50af..ffc4e10 100644 --- a/src/commands/modification.rs +++ b/src/commands/modification.rs | |||
@@ -1,27 +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}, input::{Input, ModOptions}, 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 | } | ||
8 | |||
9 | pub async fn modification(config: Cfg, input: Input) -> MLE<()> { | ||
10 | match input.clone().mod_options.ok_or("").unwrap() { | ||
11 | ModOptions::Add => { | ||
12 | add(config, input).await | ||
13 | }, | ||
14 | ModOptions::Remove => { | ||
15 | remove(config, input) | ||
16 | }, | ||
17 | } | ||
18 | } | ||
19 | |||
20 | async fn add(config: Cfg, input: Input) -> MLE<()> { | ||
21 | |||
22 | mods_add(config, vec![input.mod_id.unwrap()], input.list.unwrap(), input.direct_download, input.set_version).await?; | ||
23 | |||
24 | Ok(()) | ||
25 | } | 17 | } |
26 | 18 | ||
27 | #[derive(Debug, Clone)] | 19 | #[derive(Debug, Clone)] |
@@ -34,10 +26,16 @@ pub struct ProjectInfo { | |||
34 | pub download_link: String, | 26 | pub download_link: String, |
35 | } | 27 | } |
36 | 28 | ||
37 | pub async fn mods_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<()> { | ||
38 | println!("Add mods to {}", list.id); | 36 | println!("Add mods to {}", list.id); |
39 | println!(" └Add mods:"); | 37 | println!(" └Add mods:"); |
40 | 38 | ||
41 | let mut mod_ids: Vec<String> = Vec::new(); | 39 | let mut mod_ids: Vec<String> = Vec::new(); |
42 | let mut ver_ids: Vec<String> = Vec::new(); | 40 | let mut ver_ids: Vec<String> = Vec::new(); |
43 | 41 | ||
@@ -50,11 +48,17 @@ pub async fn mods_add(config: Cfg, ids: Vec<IDSelector>, list: List, direct_down | |||
50 | } | 48 | } |
51 | 49 | ||
52 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); | 50 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); |
53 | if !mod_ids.is_empty() { projectinfo.append(&mut get_mod_infos(config.clone(), mod_ids, list.clone()).await?) }; | 51 | if !mod_ids.is_empty() { |
54 | 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 | }; | ||
55 | 61 | ||
56 | if projectinfo.is_empty() { return Err(MLError::new(ErrorType::ArgumentError, "NO_IDS?")) }; | ||
57 | |||
58 | let mut downloadstack: Vec<Version> = Vec::new(); | 62 | let mut downloadstack: Vec<Version> = Vec::new(); |
59 | 63 | ||
60 | //Adding each mod to the lists and downloadstack | 64 | //Adding each mod to the lists and downloadstack |
@@ -63,29 +67,59 @@ pub async fn mods_add(config: Cfg, ids: Vec<IDSelector>, list: List, direct_down | |||
63 | } else { | 67 | } else { |
64 | println!(" └Insert mods in list {} and save infos", list.id); | 68 | println!(" └Insert mods in list {} and save infos", list.id); |
65 | } | 69 | } |
66 | 70 | ||
67 | for project in projectinfo { | 71 | for project in projectinfo { |
68 | 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() { |
69 | 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 | ) { | ||
70 | Err(e) => { | 86 | Err(e) => { |
71 | 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); |
72 | 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 { |
73 | }, | 89 | Err(MLError::new( |
74 | Ok(..) => { Ok(..) }, | 90 | ErrorType::ModError, |
91 | "MOD_ALREADY_ON_SELECTED_LIST", | ||
92 | )) | ||
93 | } else { | ||
94 | Err(e) | ||
95 | } | ||
96 | } | ||
97 | Ok(..) => Ok(..), | ||
75 | }?; | 98 | }?; |
76 | 99 | ||
77 | 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 | ) { | ||
78 | Err(e) => { | 106 | Err(e) => { |
79 | 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" { |
80 | }, | 108 | Ok(..) |
109 | } else { | ||
110 | Err(e) | ||
111 | } | ||
112 | } | ||
81 | Ok(..) => Ok(..), | 113 | Ok(..) => Ok(..), |
82 | }?; | 114 | }?; |
83 | 115 | ||
84 | 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 | }; | ||
85 | } | 119 | } |
86 | 120 | ||
87 | //Download all the added mods | 121 | //Download all the added mods |
88 | if direct_download { | 122 | if direct_download { |
89 | download_versions(list.clone(), config.clone(), downloadstack).await?; | 123 | download_versions(list.clone(), config.clone(), downloadstack).await?; |
90 | }; | 124 | }; |
91 | 125 | ||
@@ -104,7 +138,12 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<String>, list: List) -> MLE<Vec | |||
104 | for project in m_projects { | 138 | for project in m_projects { |
105 | println!("\t└{}", project.title); | 139 | println!("\t└{}", project.title); |
106 | println!("\t └Get versions"); | 140 | println!("\t └Get versions"); |
107 | 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; | ||
108 | 147 | ||
109 | let mut available_versions_vec: Vec<String> = Vec::new(); | 148 | let mut available_versions_vec: Vec<String> = Vec::new(); |
110 | let current_version: Option<Version>; | 149 | let current_version: Option<Version>; |
@@ -113,36 +152,63 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<String>, list: List) -> MLE<Vec | |||
113 | let current_id = extract_current_version(available_versions.clone())?; | 152 | let current_id = extract_current_version(available_versions.clone())?; |
114 | println!("\t └Current version: {}", current_id); | 153 | println!("\t └Current version: {}", current_id); |
115 | 154 | ||
116 | 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 | ); | ||
117 | 162 | ||
118 | 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; | ||
119 | for ver in available_versions { | 172 | for ver in available_versions { |
120 | available_versions_vec.push(ver.id); | 173 | available_versions_vec.push(ver.id); |
121 | }; | 174 | } |
122 | |||
123 | projectinfo.push(ProjectInfo { mod_id: project.id, slug: project.slug, title: project.title, current_version, applicable_versions: available_versions_vec, download_link: file }) | ||
124 | 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 | }) | ||
125 | } else { | 184 | } else { |
126 | 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"); |
127 | current_version = None; | 186 | current_version = None; |
128 | file = String::from("NONE"); | 187 | file = String::from("NONE"); |
129 | available_versions_vec.push(String::from("NONE")); | 188 | available_versions_vec.push(String::from("NONE")); |
130 | 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 | }) | ||
131 | } | 197 | } |
132 | }; | 198 | } |
133 | 199 | ||
134 | Ok(projectinfo) | 200 | Ok(projectinfo) |
135 | } | 201 | } |
136 | 202 | ||
137 | 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>> { |
138 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); | 204 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); |
139 | 205 | ||
140 | //Get required information from ver_ids | 206 | //Get required information from ver_ids |
141 | 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; |
142 | let mut v_mod_ids: Vec<String> = Vec::new(); | 208 | let mut v_mod_ids: Vec<String> = Vec::new(); |
143 | for ver in v_versions.clone() { | 209 | for ver in v_versions.clone() { |
144 | v_mod_ids.push(ver.project_id); | 210 | v_mod_ids.push(ver.project_id); |
145 | }; | 211 | } |
146 | 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; |
147 | 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)); |
148 | v_projects.sort_by(|a, b| a.id.cmp(&b.id)); | 214 | v_projects.sort_by(|a, b| a.id.cmp(&b.id)); |
@@ -150,35 +216,54 @@ async fn get_ver_info(config: Cfg, ver_ids: Vec<String>) -> MLE<Vec<ProjectInfo> | |||
150 | for (i, project) in v_projects.into_iter().enumerate() { | 216 | for (i, project) in v_projects.into_iter().enumerate() { |
151 | let version = &v_versions[i]; | 217 | let version = &v_versions[i]; |
152 | println!("\t└{}({})", project.title, version.id); | 218 | println!("\t└{}({})", project.title, version.id); |
153 | let file = version.clone().files.into_iter().find(|f| f.primary).unwrap().url; | 219 | let file = version |
154 | 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() |
155 | }; | 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 | } | ||
156 | Ok(projectinfo) | 235 | Ok(projectinfo) |
157 | } | 236 | } |
158 | 237 | ||
159 | fn remove(config: Cfg, input: Input) -> MLE<()> { | 238 | /// Remove mod from a list |
160 | 239 | /// # Arguments | |
161 | let id = match input.clone().mod_id.unwrap() { | 240 | /// |
162 | IDSelector::ModificationID(id) => id, | 241 | /// * `config` - config struct |
163 | IDSelector::VersionID(..) => return Err(MLError::new(ErrorType::ArgumentError, "NO_MOD_ID")), | 242 | /// * `id` - name, slug or id of the mod |
164 | }; | 243 | /// * `list` - List struct |
165 | 244 | pub fn mod_remove(config: Cfg, id: &str, list: List) -> MLE<()> { | |
166 | let mod_id = mods_get_id(&config.data, &id)?; | 245 | let mod_id = mods_get_id(&config.data, id)?; |
167 | 246 | ||
168 | let version = userlist_get_current_version(config.clone(), input.clone().list.unwrap().id, String::from(&mod_id))?; | 247 | let version = userlist_get_current_version(config.clone(), &list.id, &mod_id)?; |
169 | 248 | ||
170 | userlist_remove(config.clone(), input.clone().list.unwrap().id, String::from(&mod_id))?; | 249 | userlist_remove(config.clone(), &list.id, &mod_id)?; |
171 | delete_version(input.list.unwrap(), version)?; | 250 | delete_version(list, version)?; |
172 | 251 | ||
173 | let list_ids = lists_get_all_ids(config.clone())?; | 252 | let list_ids = lists_get_all_ids(config.clone())?; |
174 | 253 | ||
254 | // Remove mod from main list if not used elsewhere | ||
175 | let mut mod_used = false; | 255 | let mut mod_used = false; |
176 | for id in list_ids { | 256 | for id in list_ids { |
177 | let mods = userlist_get_all_ids(config.clone(), id)?; | 257 | let mods = userlist_get_all_ids(config.clone(), id)?; |
178 | if mods.contains(&mod_id) { mod_used = true; break; }; | 258 | if mods.contains(&mod_id) { |
179 | }; | 259 | mod_used = true; |
260 | break; | ||
261 | }; | ||
262 | } | ||
180 | 263 | ||
181 | if !mod_used { mods_remove(config, mod_id)?; }; | 264 | if !mod_used { |
265 | mods_remove(config, mod_id)?; | ||
266 | }; | ||
182 | 267 | ||
183 | Ok(()) | 268 | Ok(()) |
184 | } | 269 | } |