diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/apis/modrinth.rs | 16 | ||||
-rw-r--r-- | src/commands/download.rs | 2 | ||||
-rw-r--r-- | src/commands/io.rs | 4 | ||||
-rw-r--r-- | src/commands/modification.rs | 211 | ||||
-rw-r--r-- | src/commands/update.rs | 8 | ||||
-rw-r--r-- | src/db.rs | 22 | ||||
-rw-r--r-- | src/files.rs | 6 | ||||
-rw-r--r-- | src/input.rs | 25 |
8 files changed, 213 insertions, 81 deletions
diff --git a/src/apis/modrinth.rs b/src/apis/modrinth.rs index f3f89a7..bb5ee19 100644 --- a/src/apis/modrinth.rs +++ b/src/apis/modrinth.rs | |||
@@ -108,7 +108,7 @@ pub struct Hash { | |||
108 | pub sha1: String, | 108 | pub sha1: String, |
109 | } | 109 | } |
110 | 110 | ||
111 | async fn get(api: String, path: String) -> Result<Option<Vec<u8>>, Box<dyn std::error::Error>> { | 111 | async fn get(api: &str, path: String) -> Result<Option<Vec<u8>>, Box<dyn std::error::Error>> { |
112 | let url = format!(r#"{}{}"#, api, path); | 112 | let url = format!(r#"{}{}"#, api, path); |
113 | 113 | ||
114 | let client = Client::builder() | 114 | let client = Client::builder() |
@@ -131,14 +131,14 @@ async fn get(api: String, path: String) -> Result<Option<Vec<u8>>, Box<dyn std:: | |||
131 | Ok(data) | 131 | Ok(data) |
132 | } | 132 | } |
133 | 133 | ||
134 | pub async fn project(api: String, name: &str) -> Project { | 134 | pub async fn project(api: &str, name: &str) -> Project { |
135 | let url = format!("project/{}", name); | 135 | let url = format!("project/{}", name); |
136 | let data = get(api, url).await.unwrap().unwrap(); | 136 | let data = get(api, url).await.unwrap().unwrap(); |
137 | 137 | ||
138 | serde_json::from_slice(&data).unwrap() | 138 | serde_json::from_slice(&data).unwrap() |
139 | } | 139 | } |
140 | 140 | ||
141 | pub async fn projects(api: String, ids: Vec<String>) -> Vec<Project> { | 141 | pub async fn projects(api: &str, ids: Vec<String>) -> Vec<Project> { |
142 | let all = ids.join(r#"",""#); | 142 | let all = ids.join(r#"",""#); |
143 | let url = format!(r#"projects?ids=["{}"]"#, all); | 143 | let url = format!(r#"projects?ids=["{}"]"#, all); |
144 | 144 | ||
@@ -147,7 +147,8 @@ pub async fn projects(api: String, ids: Vec<String>) -> Vec<Project> { | |||
147 | serde_json::from_slice(&data).unwrap() | 147 | serde_json::from_slice(&data).unwrap() |
148 | } | 148 | } |
149 | 149 | ||
150 | pub async fn versions(api: String, id: String, list: List) -> Vec<Version> { | 150 | ///Get applicable versions from mod_id with list context |
151 | pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> { | ||
151 | let loaderstr = match list.modloader { | 152 | let loaderstr = match list.modloader { |
152 | Modloader::Forge => String::from("forge"), | 153 | Modloader::Forge => String::from("forge"), |
153 | Modloader::Fabric => String::from("fabric"), | 154 | Modloader::Fabric => String::from("fabric"), |
@@ -163,9 +164,8 @@ pub async fn versions(api: String, id: String, list: List) -> Vec<Version> { | |||
163 | } | 164 | } |
164 | } | 165 | } |
165 | 166 | ||
166 | pub async fn get_raw_versions(api: String, versions: Vec<String>) -> Vec<Version> { | 167 | ///Get version with the version ids |
167 | println!("Getting versions {}", &versions.join(", ")); | 168 | pub async fn get_raw_versions(api: &str, versions: Vec<String>) -> Vec<Version> { |
168 | |||
169 | let url = format!(r#"versions?ids=["{}"]"#, versions.join(r#"",""#)); | 169 | let url = format!(r#"versions?ids=["{}"]"#, versions.join(r#"",""#)); |
170 | 170 | ||
171 | let data = get(api, url).await.unwrap().unwrap(); | 171 | let data = get(api, url).await.unwrap().unwrap(); |
@@ -204,7 +204,7 @@ pub struct MCVersion { | |||
204 | pub major: bool, | 204 | pub major: bool, |
205 | } | 205 | } |
206 | 206 | ||
207 | pub async fn get_minecraft_version(api: String, version: MCVersionType) -> String { | 207 | pub async fn get_minecraft_version(api: &str, version: MCVersionType) -> String { |
208 | let data = get(api, String::from("tag/game_version")).await.unwrap().unwrap(); | 208 | let data = get(api, String::from("tag/game_version")).await.unwrap().unwrap(); |
209 | let mc_versions: Vec<MCVersion> = serde_json::from_slice(&data).unwrap(); | 209 | let mc_versions: Vec<MCVersion> = serde_json::from_slice(&data).unwrap(); |
210 | let ver = match version { | 210 | let ver = match version { |
diff --git a/src/commands/download.rs b/src/commands/download.rs index 7748d15..2714630 100644 --- a/src/commands/download.rs +++ b/src/commands/download.rs | |||
@@ -47,7 +47,7 @@ pub async fn download(config: Cfg, input: Input) -> MLE<()> { | |||
47 | if input.clean { clean_list_dir(¤t_list)? }; | 47 | if input.clean { clean_list_dir(¤t_list)? }; |
48 | 48 | ||
49 | if !to_download.is_empty() { | 49 | if !to_download.is_empty() { |
50 | download_versions(current_list.clone(), config.clone(), get_raw_versions(String::from(&config.apis.modrinth), to_download).await).await?; | 50 | download_versions(current_list.clone(), config.clone(), get_raw_versions(&config.apis.modrinth, to_download).await).await?; |
51 | } else { | 51 | } else { |
52 | println!("There are no new versions to download"); | 52 | println!("There are no new versions to download"); |
53 | } | 53 | } |
diff --git a/src/commands/io.rs b/src/commands/io.rs index 44604d1..a3d056f 100644 --- a/src/commands/io.rs +++ b/src/commands/io.rs | |||
@@ -2,7 +2,7 @@ use std::fs::File; | |||
2 | use std::io::prelude::*; | 2 | use std::io::prelude::*; |
3 | use serde::{Serialize, Deserialize}; | 3 | use serde::{Serialize, Deserialize}; |
4 | 4 | ||
5 | use crate::{input::{Input, IoOptions}, db::{lists_get, userlist_get_all_ids, lists_get_all_ids, lists_insert}, config::Cfg, Modloader, List, devdir, error::MLE, mods_add}; | 5 | use crate::{input::{Input, IoOptions}, db::{lists_get, userlist_get_all_ids, lists_get_all_ids, lists_insert}, config::Cfg, Modloader, List, devdir, error::MLE, mods_add, IDSelector}; |
6 | 6 | ||
7 | #[derive(Debug, Serialize, Deserialize)] | 7 | #[derive(Debug, Serialize, Deserialize)] |
8 | struct Export { | 8 | struct Export { |
@@ -82,7 +82,7 @@ async fn import(config: Cfg, input: Input) -> MLE<()> { | |||
82 | let mods: Vec<&str> = exportlist.mods.split('|').collect(); | 82 | let mods: Vec<&str> = exportlist.mods.split('|').collect(); |
83 | let mut mod_ids = vec![]; | 83 | let mut mod_ids = vec![]; |
84 | for mod_id in mods { | 84 | for mod_id in mods { |
85 | mod_ids.push(String::from(mod_id)); | 85 | mod_ids.push(IDSelector::ModificationID(String::from(mod_id))); |
86 | }; | 86 | }; |
87 | //TODO impl set_version and good direct download | 87 | //TODO impl set_version and good direct download |
88 | //TODO impl all at once, dafuck | 88 | //TODO impl all at once, dafuck |
diff --git a/src/commands/modification.rs b/src/commands/modification.rs index 12a635f..c815155 100644 --- a/src/commands/modification.rs +++ b/src/commands/modification.rs | |||
@@ -1,8 +1,10 @@ | |||
1 | use crate::{modrinth::{project, versions, extract_current_version, Version, projects}, config::Cfg, db::{mods_insert, userlist_remove, mods_get_id, userlist_insert, userlist_get_all_ids, userlist_get_current_version, lists_get_all_ids, mods_remove}, input::{Input, ModOptions}, files::{delete_version, download_versions}, List, error::{MLE, ErrorType, MLError}}; | 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}}; |
2 | 2 | ||
3 | //TODO DO IT | 3 | //TODO DO IT |
4 | pub struct ModVer { | 4 | #[derive(Debug, Clone, PartialEq, Eq)] |
5 | 5 | pub enum IDSelector { | |
6 | ModificationID(String), | ||
7 | VersionID(String) | ||
6 | } | 8 | } |
7 | 9 | ||
8 | pub async fn modification(config: Cfg, input: Input) -> MLE<()> { | 10 | pub async fn modification(config: Cfg, input: Input) -> MLE<()> { |
@@ -22,27 +24,148 @@ async fn add(config: Cfg, input: Input) -> MLE<()> { | |||
22 | 24 | ||
23 | Ok(()) | 25 | Ok(()) |
24 | } | 26 | } |
25 | //TODO impl specific version | 27 | |
26 | pub async fn mods_add(config: Cfg, mod_id: Vec<String>, list: List, direct_download: bool, set_version: bool) -> MLE<()> { | 28 | #[derive(Debug, Clone)] |
27 | 29 | pub struct ProjectInfo { | |
30 | pub mod_id: String, | ||
31 | pub slug: String, | ||
32 | pub title: String, | ||
33 | pub current_version: Option<Version>, | ||
34 | pub applicable_versions: Vec<String>, | ||
35 | pub download_link: String, | ||
36 | } | ||
37 | |||
38 | //TODO impl specific version... Rewrite yay | ||
39 | pub async fn mods_add(config: Cfg, ids: Vec<IDSelector>, list: List, direct_download: bool, set_version: bool) -> MLE<()> { | ||
28 | println!("Add mods to {}", list.id); | 40 | println!("Add mods to {}", list.id); |
29 | println!(" └Add mods:"); | 41 | println!(" └Add mods:"); |
30 | let projects = if mod_id.len() == 1 { | 42 | |
31 | vec![project(String::from(&config.apis.modrinth), &mod_id[0]).await] | 43 | let mut mod_ids: Vec<String> = Vec::new(); |
32 | } else { | 44 | let mut ver_ids: Vec<String> = Vec::new(); |
33 | projects(String::from(&config.apis.modrinth), mod_id).await | 45 | |
34 | }; | 46 | //"Sort" project ids from version ids to be able to handle them differently but in a batch |
47 | for id in ids { | ||
48 | match id { | ||
49 | IDSelector::ModificationID(pid) => mod_ids.push(pid), | ||
50 | IDSelector::VersionID(vid) => ver_ids.push(vid), | ||
51 | } | ||
52 | } | ||
35 | 53 | ||
36 | let mut downloadstack: Vec<Version> = Vec::new(); | 54 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); |
55 | if !mod_ids.is_empty() { projectinfo.append(&mut get_mod_infos(config.clone(), mod_ids, list.clone()).await?) }; | ||
56 | if !ver_ids.is_empty() { projectinfo.append(&mut get_ver_info(config.clone(), ver_ids).await?) }; | ||
57 | |||
58 | if projectinfo.is_empty() { return Err(MLError::new(ErrorType::ArgumentError, "NO_IDS?")) }; | ||
37 | 59 | ||
38 | for project in projects { | 60 | let mut downloadstack: Vec<Version> = Vec::new(); |
61 | |||
62 | //Adding each mod to the lists and downloadstack | ||
63 | for project in projectinfo { | ||
64 | let current_version_id = if project.current_version.is_none() { String::from("NONE") } else { project.current_version.clone().unwrap().id }; | ||
65 | |||
66 | match userlist_insert(config.clone(), &list.id, &project.mod_id, ¤t_version_id, project.clone().applicable_versions, &project.download_link, set_version) { | ||
67 | Err(e) => { | ||
68 | let expected_err = format!("SQL: UNIQUE constraint failed: {}.mod_id", list.id); | ||
69 | if e.to_string() == expected_err { Err(MLError::new(ErrorType::ModError, "MOD_ALREADY_ON_SELECTED_LIST")) } else { Err(e) } | ||
70 | }, | ||
71 | Ok(..) => { Ok(..) }, | ||
72 | }?; | ||
73 | |||
74 | match mods_insert(config.clone(), &project.mod_id, &project.slug, &project.title) { | ||
75 | Err(e) => { | ||
76 | if e.to_string() == "SQL: UNIQUE constraint failed: mods.id" { Ok(..) } else { Err(e) } | ||
77 | }, | ||
78 | Ok(..) => Ok(..), | ||
79 | }?; | ||
80 | |||
81 | if project.current_version.is_some() { downloadstack.push(project.current_version.unwrap()) }; | ||
82 | } | ||
83 | |||
84 | //Download all the added mods | ||
85 | if direct_download { | ||
86 | download_versions(list.clone(), config.clone(), downloadstack).await?; | ||
87 | }; | ||
88 | |||
89 | |||
90 | // let projects = if id.len() == 1 { | ||
91 | // vec![project(String::from(&config.apis.modrinth), &mod_id).await] | ||
92 | // } else { | ||
93 | // projects(String::from(&config.apis.modrinth), &mod_id).await | ||
94 | // }; | ||
95 | // | ||
96 | // let mut downloadstack: Vec<Version> = Vec::new(); | ||
97 | // | ||
98 | // for project in projects { | ||
99 | // println!("\t└{}", project.title); | ||
100 | // println!("\t └Get versions"); | ||
101 | // let available_versions = versions(String::from(&config.apis.modrinth), String::from(&project.id), list.clone()).await; | ||
102 | // | ||
103 | // let mut available_versions_vec: Vec<String> = Vec::new(); | ||
104 | // let current_version: Option<Version>; | ||
105 | // let current_version_id: String; | ||
106 | // let file: String; | ||
107 | // if !available_versions.is_empty() { | ||
108 | // let current_id = extract_current_version(available_versions.clone())?; | ||
109 | // println!("\t └Current version: {}", current_id); | ||
110 | // | ||
111 | // current_version = Some(available_versions.clone().into_iter().find(|v| v.id == current_id).unwrap()); | ||
112 | // | ||
113 | // current_version_id = current_version.clone().unwrap().id; | ||
114 | // | ||
115 | // file = current_version.clone().ok_or("").unwrap().files.into_iter().find(|f| f.primary).unwrap().url; | ||
116 | // for ver in available_versions { | ||
117 | // available_versions_vec.push(ver.id); | ||
118 | // }; | ||
119 | // } else { | ||
120 | // println!("\t └There's currently no mod version for your specified target"); | ||
121 | // current_version = None; | ||
122 | // current_version_id = String::from("NONE"); | ||
123 | // file = String::from("NONE"); | ||
124 | // available_versions_vec.push(String::from("NONE")); | ||
125 | // } | ||
126 | // | ||
127 | // match userlist_insert(config.clone(), &list.id, &project.id, ¤t_version_id, available_versions_vec, &file, set_version) { | ||
128 | // Err(e) => { | ||
129 | // let expected_err = format!("SQL: UNIQUE constraint failed: {}.mod_id", list.id); | ||
130 | // if e.to_string() == expected_err { Err(MLError::new(ErrorType::ModError, "MOD_ALREADY_ON_SELECTED_LIST")) } else { Err(e) } | ||
131 | // }, | ||
132 | // Ok(..) => { Ok(..) }, | ||
133 | // }?; | ||
134 | // | ||
135 | // match mods_insert(config.clone(), &project.id, &project.slug, &project.title) { | ||
136 | // Err(e) => { | ||
137 | // if e.to_string() == "SQL: UNIQUE constraint failed: mods.id" { Ok(..) } else { Err(e) } | ||
138 | // }, | ||
139 | // Ok(..) => Ok(..), | ||
140 | // }?; | ||
141 | // | ||
142 | // downloadstack.push(current_version.unwrap()); | ||
143 | // }; | ||
144 | // | ||
145 | // //Download all the added mods | ||
146 | // if direct_download { | ||
147 | // download_versions(list.clone(), config.clone(), downloadstack).await?; | ||
148 | // }; | ||
149 | // | ||
150 | Ok(()) | ||
151 | } | ||
152 | |||
153 | async fn get_mod_infos(config: Cfg, mod_ids: Vec<String>, list: List) -> MLE<Vec<ProjectInfo>> { | ||
154 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); | ||
155 | |||
156 | //Get required information from mod_ids | ||
157 | let m_projects = match mod_ids.len() { | ||
158 | 1 => vec![project(&config.apis.modrinth, &mod_ids[0]).await], | ||
159 | 2.. => projects(&config.apis.modrinth, mod_ids).await, | ||
160 | _ => panic!("PANIC"), | ||
161 | }; | ||
162 | for project in m_projects { | ||
39 | println!("\t└{}", project.title); | 163 | println!("\t└{}", project.title); |
40 | println!("\t └Get versions"); | 164 | println!("\t └Get versions"); |
41 | let available_versions = versions(String::from(&config.apis.modrinth), String::from(&project.id), list.clone()).await; | 165 | let available_versions = versions(&config.apis.modrinth, String::from(&project.id), list.clone()).await; |
42 | 166 | ||
43 | let mut available_versions_vec: Vec<String> = Vec::new(); | 167 | let mut available_versions_vec: Vec<String> = Vec::new(); |
44 | let current_version: Option<Version>; | 168 | let current_version: Option<Version>; |
45 | let current_version_id: String; | ||
46 | let file: String; | 169 | let file: String; |
47 | if !available_versions.is_empty() { | 170 | if !available_versions.is_empty() { |
48 | let current_id = extract_current_version(available_versions.clone())?; | 171 | let current_id = extract_current_version(available_versions.clone())?; |
@@ -50,49 +173,55 @@ pub async fn mods_add(config: Cfg, mod_id: Vec<String>, list: List, direct_downl | |||
50 | 173 | ||
51 | current_version = Some(available_versions.clone().into_iter().find(|v| v.id == current_id).unwrap()); | 174 | current_version = Some(available_versions.clone().into_iter().find(|v| v.id == current_id).unwrap()); |
52 | 175 | ||
53 | current_version_id = current_version.clone().unwrap().id; | ||
54 | |||
55 | file = current_version.clone().ok_or("").unwrap().files.into_iter().find(|f| f.primary).unwrap().url; | 176 | file = current_version.clone().ok_or("").unwrap().files.into_iter().find(|f| f.primary).unwrap().url; |
56 | for ver in available_versions { | 177 | for ver in available_versions { |
57 | available_versions_vec.push(ver.id); | 178 | available_versions_vec.push(ver.id); |
58 | }; | 179 | }; |
180 | |||
181 | projectinfo.push(ProjectInfo { mod_id: project.id, slug: project.slug, title: project.title, current_version, applicable_versions: available_versions_vec, download_link: file }) | ||
182 | |||
59 | } else { | 183 | } else { |
60 | println!("\t └There's currently no mod version for your specified target"); | 184 | println!("\t └There's currently no mod version for your specified target"); |
61 | current_version = None; | 185 | current_version = None; |
62 | current_version_id = String::from("NONE"); | ||
63 | file = String::from("NONE"); | 186 | file = String::from("NONE"); |
64 | available_versions_vec.push(String::from("NONE")); | 187 | available_versions_vec.push(String::from("NONE")); |
188 | projectinfo.push(ProjectInfo { mod_id: project.id, slug: project.slug, title: project.title, current_version, applicable_versions: available_versions_vec, download_link: file }) | ||
65 | } | 189 | } |
190 | }; | ||
66 | 191 | ||
67 | match userlist_insert(config.clone(), &list.id, &project.id, ¤t_version_id, available_versions_vec, &file, set_version) { | 192 | Ok(projectinfo) |
68 | Err(e) => { | 193 | } |
69 | let expected_err = format!("SQL: UNIQUE constraint failed: {}.mod_id", list.id); | ||
70 | if e.to_string() == expected_err { Err(MLError::new(ErrorType::ModError, "MOD_ALREADY_ON_SELECTED_LIST")) } else { Err(e) } | ||
71 | }, | ||
72 | Ok(..) => { Ok(..) }, | ||
73 | }?; | ||
74 | |||
75 | match mods_insert(config.clone(), &project.id, &project.slug, &project.title) { | ||
76 | Err(e) => { | ||
77 | if e.to_string() == "SQL: UNIQUE constraint failed: mods.id" { Ok(..) } else { Err(e) } | ||
78 | }, | ||
79 | Ok(..) => Ok(..), | ||
80 | }?; | ||
81 | 194 | ||
82 | downloadstack.push(current_version.unwrap()); | 195 | async fn get_ver_info(config: Cfg, ver_ids: Vec<String>) -> MLE<Vec<ProjectInfo>> { |
196 | let mut projectinfo: Vec<ProjectInfo> = Vec::new(); | ||
197 | |||
198 | //Get required information from ver_ids | ||
199 | let mut v_versions = get_raw_versions(&config.apis.modrinth, ver_ids).await; | ||
200 | let mut v_mod_ids: Vec<String> = Vec::new(); | ||
201 | for ver in v_versions.clone() { | ||
202 | v_mod_ids.push(ver.project_id); | ||
83 | }; | 203 | }; |
84 | 204 | let mut v_projects = projects(&config.apis.modrinth, v_mod_ids).await; | |
85 | //Download all the added mods | 205 | v_versions.sort_by(|a, b| a.project_id.cmp(&b.project_id)); |
86 | if direct_download { | 206 | v_projects.sort_by(|a, b| a.id.cmp(&b.id)); |
87 | download_versions(list.clone(), config.clone(), downloadstack).await?; | 207 | |
208 | for (i, project) in v_projects.into_iter().enumerate() { | ||
209 | let version = &v_versions[i]; | ||
210 | println!("\t└{}({})", project.title, version.id); | ||
211 | let file = version.clone().files.into_iter().find(|f| f.primary).unwrap().url; | ||
212 | 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 }) | ||
88 | }; | 213 | }; |
89 | 214 | Ok(projectinfo) | |
90 | Ok(()) | ||
91 | } | 215 | } |
92 | 216 | ||
93 | fn remove(config: Cfg, input: Input) -> MLE<()> { | 217 | fn remove(config: Cfg, input: Input) -> MLE<()> { |
94 | 218 | ||
95 | let mod_id = mods_get_id(&config.data, input.mod_id.as_ref().unwrap())?; | 219 | let id = match input.clone().mod_id.unwrap() { |
220 | IDSelector::ModificationID(id) => id, | ||
221 | IDSelector::VersionID(..) => return Err(MLError::new(ErrorType::ArgumentError, "NO_MOD_ID")), | ||
222 | }; | ||
223 | |||
224 | let mod_id = mods_get_id(&config.data, &id)?; | ||
96 | 225 | ||
97 | let version = userlist_get_current_version(config.clone(), input.clone().list.unwrap().id, String::from(&mod_id))?; | 226 | let version = userlist_get_current_version(config.clone(), input.clone().list.unwrap().id, String::from(&mod_id))?; |
98 | 227 | ||
diff --git a/src/commands/update.rs b/src/commands/update.rs index bc5b316..75bee39 100644 --- a/src/commands/update.rs +++ b/src/commands/update.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use crate::{config::Cfg, modrinth::{versions, extract_current_version, Version}, get_current_list, db::{userlist_get_all_ids, userlist_get_applicable_versions, userlist_change_versions, lists_get_all_ids, lists_get, userlist_get_current_version, mods_get_title, userlist_get_set_version}, List, input::Input, files::{delete_version, download_versions, disable_version, clean_list_dir}, error::{MLE, MLError, ErrorType}}; | 1 | use crate::{config::Cfg, modrinth::{versions, extract_current_version, Version}, get_current_list, db::{userlist_get_all_ids, userlist_get_applicable_versions, userlist_change_versions, lists_get_all_ids, lists_get, userlist_get_current_version, userlist_get_set_version, mods_get_info}, List, input::Input, files::{delete_version, download_versions, disable_version, clean_list_dir}, error::{MLE, MLError, ErrorType}}; |
2 | 2 | ||
3 | pub async fn update(config: Cfg, input: Input) -> MLE<()> { | 3 | pub async fn update(config: Cfg, input: Input) -> MLE<()> { |
4 | let mut liststack: Vec<List> = vec![]; | 4 | let mut liststack: Vec<List> = vec![]; |
@@ -25,8 +25,8 @@ pub async fn cmd_update(config: Cfg, liststack: Vec<List>, clean: bool, direct_d | |||
25 | let mut updatestack: Vec<Version> = vec![]; | 25 | let mut updatestack: Vec<Version> = vec![]; |
26 | 26 | ||
27 | for id in mods { | 27 | for id in mods { |
28 | let title = mods_get_title(config.clone(), &id)?; | 28 | let info = mods_get_info(config.clone(), &id)?; |
29 | println!("\t└{}", title); | 29 | println!("\t└{}", info.title); |
30 | 30 | ||
31 | if userlist_get_set_version(config.clone(), ¤t_list.id, &id)? { | 31 | if userlist_get_set_version(config.clone(), ¤t_list.id, &id)? { |
32 | println!("\t └Set version, skipping update"); | 32 | println!("\t └Set version, skipping update"); |
@@ -78,7 +78,7 @@ pub async fn cmd_update(config: Cfg, liststack: Vec<List>, clean: bool, direct_d | |||
78 | } | 78 | } |
79 | 79 | ||
80 | async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> MLE<Version> { | 80 | async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> MLE<Version> { |
81 | let applicable_versions = versions(String::from(&config.apis.modrinth), String::from(&id), list.clone()).await; | 81 | let applicable_versions = versions(&config.apis.modrinth, String::from(&id), list.clone()).await; |
82 | 82 | ||
83 | let mut versions: Vec<String> = vec![]; | 83 | let mut versions: Vec<String> = vec![]; |
84 | 84 | ||
@@ -82,23 +82,29 @@ pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { | |||
82 | Ok(mod_id) | 82 | Ok(mod_id) |
83 | } | 83 | } |
84 | 84 | ||
85 | pub fn mods_get_title(config: Cfg, id: &str) -> MLE<String> { | 85 | pub struct ModInfo { |
86 | pub slug: String, | ||
87 | pub title: String, | ||
88 | } | ||
89 | |||
90 | pub fn mods_get_info(config: Cfg, id: &str) -> MLE<ModInfo> { | ||
86 | let data = devdir(format!("{}/data.db", config.data).as_str()); | 91 | let data = devdir(format!("{}/data.db", config.data).as_str()); |
87 | let connection = Connection::open(data)?; | 92 | let connection = Connection::open(data)?; |
88 | 93 | ||
89 | let mut mod_name = String::new(); | 94 | let mut mod_info: Option<ModInfo> = None; |
90 | let mut stmt = connection.prepare("SELECT title FROM mods WHERE id = ?")?; | 95 | let mut stmt = connection.prepare("SELECT title, slug FROM mods WHERE id = ?")?; |
91 | let name_iter = stmt.query_map([id], |row| { | 96 | let name_iter = stmt.query_map([id], |row| { |
92 | row.get::<usize, String>(0) | 97 | Ok(vec![row.get::<usize, String>(0)?, row.get::<usize, String>(1)?]) |
93 | })?; | 98 | })?; |
94 | 99 | ||
95 | for name in name_iter { | 100 | for info in name_iter { |
96 | mod_name = name?; | 101 | let i = info?; |
102 | mod_info = Some(ModInfo { title: String::from(&i[0]), slug: String::from(&i[1]) }); | ||
97 | }; | 103 | }; |
98 | 104 | ||
99 | match mod_name.is_empty() { | 105 | match mod_info.is_none() { |
100 | true => Err(MLError::new(ErrorType::DBError, "GN_MOD_NOT_FOUND")), | 106 | true => Err(MLError::new(ErrorType::DBError, "GN_MOD_NOT_FOUND")), |
101 | false => Ok(mod_name), | 107 | false => Ok(mod_info.unwrap()), |
102 | } | 108 | } |
103 | } | 109 | } |
104 | 110 | ||
diff --git a/src/files.rs b/src/files.rs index b9325ea..6519c6a 100644 --- a/src/files.rs +++ b/src/files.rs | |||
@@ -2,7 +2,7 @@ use std::{fs::{File, read_dir, remove_file, rename}, io::Write, collections::Has | |||
2 | use futures_util::StreamExt; | 2 | use futures_util::StreamExt; |
3 | use reqwest::Client; | 3 | use reqwest::Client; |
4 | 4 | ||
5 | use crate::{List, modrinth::Version, db::{userlist_add_disabled_versions, mods_get_title}, config::Cfg, error::{MLE, MLError, ErrorType}}; | 5 | use crate::{List, modrinth::Version, db::{userlist_add_disabled_versions, mods_get_info}, config::Cfg, error::{MLE, MLError, ErrorType}}; |
6 | 6 | ||
7 | pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) -> MLE<String> { | 7 | pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) -> MLE<String> { |
8 | 8 | ||
@@ -11,8 +11,8 @@ pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) | |||
11 | println!(" └Download mods to {}", dl_path); | 11 | println!(" └Download mods to {}", dl_path); |
12 | 12 | ||
13 | for ver in versions { | 13 | for ver in versions { |
14 | let project_name = mods_get_title(config.clone(), &ver.project_id)?; | 14 | let project_info = mods_get_info(config.clone(), &ver.project_id)?; |
15 | print!("\t└({})Download version {}", project_name, ver.id); | 15 | print!("\t└({})Download version {}", project_info.title, ver.id); |
16 | //Force flush of stdout, else print! doesn't print instantly | 16 | //Force flush of stdout, else print! doesn't print instantly |
17 | std::io::stdout().flush().unwrap(); | 17 | std::io::stdout().flush().unwrap(); |
18 | let primary_file = ver.files.into_iter().find(|file| file.primary).unwrap(); | 18 | let primary_file = ver.files.into_iter().find(|file| file.primary).unwrap(); |
diff --git a/src/input.rs b/src/input.rs index 17fc773..6c62ab7 100644 --- a/src/input.rs +++ b/src/input.rs | |||
@@ -1,11 +1,10 @@ | |||
1 | use crate::{error::{MLE, MLError, ErrorType}, Modloader, config::Cfg, db::lists_get, get_current_list, List, modrinth::{get_minecraft_version, MCVersionType}}; | 1 | use crate::{error::{MLE, MLError, ErrorType}, Modloader, config::Cfg, db::lists_get, get_current_list, List, modrinth::{get_minecraft_version, MCVersionType}, IDSelector}; |
2 | 2 | ||
3 | #[derive(Debug, Clone, PartialEq, Eq)] | 3 | #[derive(Debug, Clone, PartialEq, Eq)] |
4 | pub struct Input { | 4 | pub struct Input { |
5 | pub command: Option<Cmd>, | 5 | pub command: Option<Cmd>, |
6 | pub mod_options: Option<ModOptions>, | 6 | pub mod_options: Option<ModOptions>, |
7 | pub mod_id: Option<String>, | 7 | pub mod_id: Option<IDSelector>, |
8 | pub mod_version: Option<String>, | ||
9 | pub set_version: bool, | 8 | pub set_version: bool, |
10 | pub all_lists: bool, | 9 | pub all_lists: bool, |
11 | pub clean: bool, | 10 | pub clean: bool, |
@@ -61,8 +60,7 @@ impl Input { | |||
61 | let mut command: Option<Cmd> = None; | 60 | let mut command: Option<Cmd> = None; |
62 | 61 | ||
63 | let mut mod_options: Option<ModOptions> = None; | 62 | let mut mod_options: Option<ModOptions> = None; |
64 | let mut mod_id: Option<String> = None; | 63 | let mut mod_id: Option<IDSelector> = None; |
65 | let mut mod_version: Option<String> = None; | ||
66 | let mut set_version = false; | 64 | let mut set_version = false; |
67 | let mut all_lists = false; | 65 | let mut all_lists = false; |
68 | let mut clean = false; | 66 | let mut clean = false; |
@@ -93,15 +91,17 @@ impl Input { | |||
93 | command = Some(Cmd::Mod); | 91 | command = Some(Cmd::Mod); |
94 | mod_options = Some(ModOptions::Add); | 92 | mod_options = Some(ModOptions::Add); |
95 | if arg_split.len() == 2 { | 93 | if arg_split.len() == 2 { |
96 | mod_id = Some(String::from(arg_split[1])); | 94 | mod_id = Some(IDSelector::ModificationID(String::from(arg_split[1]))); |
97 | } else { | 95 | } else { |
98 | return Err(MLError::new(ErrorType::ArgumentError, "Please specify a list mod slug or id")); | 96 | return Err(MLError::new(ErrorType::ArgumentError, "Please specify a list mod slug or id")); |
99 | } | 97 | } |
100 | }, | 98 | }, |
101 | //TODO impl this | 99 | //TODO impl this |
102 | "mv" => { | 100 | "mv" => { |
101 | command = Some(Cmd::Mod); | ||
102 | mod_options = Some(ModOptions::Add); | ||
103 | if arg_split.len() == 2 { | 103 | if arg_split.len() == 2 { |
104 | mod_version = Some(String::from(arg_split[1])); | 104 | mod_id = Some(IDSelector::VersionID(String::from(arg_split[1]))); |
105 | } else { | 105 | } else { |
106 | return Err(MLError::new(ErrorType::ArgumentError, "Please specify a version id")); | 106 | return Err(MLError::new(ErrorType::ArgumentError, "Please specify a version id")); |
107 | }; | 107 | }; |
@@ -110,7 +110,7 @@ impl Input { | |||
110 | command = Some(Cmd::Mod); | 110 | command = Some(Cmd::Mod); |
111 | mod_options = Some(ModOptions::Remove); | 111 | mod_options = Some(ModOptions::Remove); |
112 | if arg_split.len() == 2 { | 112 | if arg_split.len() == 2 { |
113 | mod_id = Some(String::from(arg_split[1])); | 113 | mod_id = Some(IDSelector::ModificationID(String::from(arg_split[1]))); |
114 | } else { | 114 | } else { |
115 | return Err(MLError::new(ErrorType::ArgumentError, "Please specify a mod id")); | 115 | return Err(MLError::new(ErrorType::ArgumentError, "Please specify a mod id")); |
116 | }; | 116 | }; |
@@ -206,7 +206,6 @@ impl Input { | |||
206 | command, | 206 | command, |
207 | mod_options, | 207 | mod_options, |
208 | mod_id, | 208 | mod_id, |
209 | mod_version, | ||
210 | set_version, | 209 | set_version, |
211 | all_lists, | 210 | all_lists, |
212 | clean, | 211 | clean, |
@@ -242,7 +241,7 @@ fn check_mod(mut input: Input, config: Cfg) -> MLE<Input> { | |||
242 | }; | 241 | }; |
243 | match input.clone().mod_options.unwrap() { | 242 | match input.clone().mod_options.unwrap() { |
244 | ModOptions::Add => { | 243 | ModOptions::Add => { |
245 | if input.mod_id.is_none() && input.mod_version.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "No mod id/slug or version id")); }; | 244 | if input.mod_id.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "No mod id/slug or version id")); }; |
246 | if input.list_id.is_none() { input.list = Some(get_current_list(config)?); }; | 245 | if input.list_id.is_none() { input.list = Some(get_current_list(config)?); }; |
247 | Ok(input) | 246 | Ok(input) |
248 | }, | 247 | }, |
@@ -263,7 +262,7 @@ async fn check_list(mut input: Input, config: Cfg) -> MLE<Input> { | |||
263 | if input.list_id.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "no list id specified")); }; | 262 | if input.list_id.is_none() { return Err(MLError::new(ErrorType::ArgumentError, "no list id specified")); }; |
264 | if input.list_mcversion.is_none() { | 263 | if input.list_mcversion.is_none() { |
265 | println!("No Minecraft Version specified, defaulting to latest release"); | 264 | println!("No Minecraft Version specified, defaulting to latest release"); |
266 | input.list_mcversion = Some(get_minecraft_version(config.apis.modrinth, MCVersionType::Release).await); | 265 | input.list_mcversion = Some(get_minecraft_version(&config.apis.modrinth, MCVersionType::Release).await); |
267 | }; | 266 | }; |
268 | if input.directory.is_none() { | 267 | if input.directory.is_none() { |
269 | let id = input.clone().list_id.unwrap(); | 268 | let id = input.clone().list_id.unwrap(); |
@@ -300,7 +299,6 @@ fn input_from() { | |||
300 | command: Some(Cmd::List), | 299 | command: Some(Cmd::List), |
301 | mod_options: None, | 300 | mod_options: None, |
302 | mod_id: None, | 301 | mod_id: None, |
303 | mod_version: None, | ||
304 | set_version: false, | 302 | set_version: false, |
305 | all_lists: false, | 303 | all_lists: false, |
306 | clean: false, | 304 | clean: false, |
@@ -327,8 +325,7 @@ async fn get_input_test() { | |||
327 | Input { | 325 | Input { |
328 | command: Some(Cmd::Mod), | 326 | command: Some(Cmd::Mod), |
329 | mod_options: Some(ModOptions::Add), | 327 | mod_options: Some(ModOptions::Add), |
330 | mod_id: Some(String::from("test")), | 328 | mod_id: Some(IDSelector::ModificationID(String::from("test"))), |
331 | mod_version: None, | ||
332 | set_version: false, | 329 | set_version: false, |
333 | all_lists: false, | 330 | all_lists: false, |
334 | clean: false, | 331 | clean: false, |