summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/apis/modrinth.rs2
-rw-r--r--src/cache.rs1
-rw-r--r--src/commands/download.rs4
-rw-r--r--src/commands/io.rs2
-rw-r--r--src/commands/list.rs2
-rw-r--r--src/commands/modification.rs70
-rw-r--r--src/commands/update.rs79
-rw-r--r--src/config.rs4
-rw-r--r--src/db.rs2
-rw-r--r--src/files.rs61
-rw-r--r--src/lib.rs6
11 files changed, 145 insertions, 88 deletions
diff --git a/src/apis/modrinth.rs b/src/apis/modrinth.rs
index 525cc0d..14ff266 100644
--- a/src/apis/modrinth.rs
+++ b/src/apis/modrinth.rs
@@ -170,7 +170,7 @@ pub async fn projects(api: &str, ids: Vec<String>) -> Vec<Project> {
170pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> { 170pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> {
171 let url = format!( 171 let url = format!(
172 r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, 172 r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#,
173 id, list.modloader.to_string(), list.mc_version 173 id, list.modloader, list.mc_version
174 ); 174 );
175 175
176 let data = get(api, &url).await.unwrap(); 176 let data = get(api, &url).await.unwrap();
diff --git a/src/cache.rs b/src/cache.rs
index c928670..1e22091 100644
--- a/src/cache.rs
+++ b/src/cache.rs
@@ -32,6 +32,5 @@ pub fn get_cached_versions(path: &str) -> HashMap<String, String> {
32pub fn copy_cached_version(version_path: &str, download_path: &str) { 32pub fn copy_cached_version(version_path: &str, download_path: &str) {
33 let versplit: Vec<&str> = version_path.split('/').collect(); 33 let versplit: Vec<&str> = version_path.split('/').collect();
34 let download = format!("{}/{}", download_path, versplit[versplit.len() - 1]); 34 let download = format!("{}/{}", download_path, versplit[versplit.len() - 1]);
35 // println!("{:#?}", download);
36 copy(version_path, download).unwrap(); 35 copy(version_path, download).unwrap();
37} 36}
diff --git a/src/commands/download.rs b/src/commands/download.rs
index ebfb4eb..6831714 100644
--- a/src/commands/download.rs
+++ b/src/commands/download.rs
@@ -1,3 +1,4 @@
1
1use crate::{config::Cfg, List}; 2use crate::{config::Cfg, List};
2use crate::{ 3use crate::{
3 db::userlist_get_all_current_versions_with_mods, 4 db::userlist_get_all_current_versions_with_mods,
@@ -9,7 +10,6 @@ use crate::{
9}; 10};
10 11
11pub async fn download(config: Cfg, liststack: Vec<List>, clean: bool, delete_old: bool) -> MLE<()> { 12pub async fn download(config: Cfg, liststack: Vec<List>, clean: bool, delete_old: bool) -> MLE<()> {
12
13 for current_list in liststack { 13 for current_list in liststack {
14 println!("Downloading current versions of mods in {}", current_list.id); 14 println!("Downloading current versions of mods in {}", current_list.id);
15 let downloaded_versions = get_downloaded_versions(current_list.clone())?; 15 let downloaded_versions = get_downloaded_versions(current_list.clone())?;
@@ -63,7 +63,7 @@ pub async fn download(config: Cfg, liststack: Vec<List>, clean: bool, delete_old
63 if !to_disable.is_empty() { 63 if !to_disable.is_empty() {
64 for ver in to_disable { 64 for ver in to_disable {
65 if delete_old { 65 if delete_old {
66 println!("Deleting version {} for mod {}", ver.1, ver.0); 66 // println!("Deleting version {} for mod {}", ver.1, ver.0);
67 delete_version(current_list.clone(), ver.1)?; 67 delete_version(current_list.clone(), ver.1)?;
68 } else { 68 } else {
69 disable_version(config.clone(), current_list.clone(), ver.1, ver.0)?; 69 disable_version(config.clone(), current_list.clone(), ver.1, ver.0)?;
diff --git a/src/commands/io.rs b/src/commands/io.rs
index dd294bc..2a26f1d 100644
--- a/src/commands/io.rs
+++ b/src/commands/io.rs
@@ -24,7 +24,7 @@ impl ExportVersion {
24 fn from(config: Cfg, list_id: &str, mod_id: &str) -> MLE<Self> { 24 fn from(config: Cfg, list_id: &str, mod_id: &str) -> MLE<Self> {
25 Ok(Self { 25 Ok(Self {
26 version: userlist_get_current_version(config.clone(), list_id, mod_id)?, 26 version: userlist_get_current_version(config.clone(), list_id, mod_id)?,
27 set: userlist_get_set_version(config.clone(), list_id, mod_id)? 27 set: userlist_get_set_version(config, list_id, mod_id)?
28 }) 28 })
29 } 29 }
30} 30}
diff --git a/src/commands/list.rs b/src/commands/list.rs
index 4aa4306..c07823b 100644
--- a/src/commands/list.rs
+++ b/src/commands/list.rs
@@ -32,7 +32,7 @@ pub fn list_add(
32} 32}
33 33
34pub fn list_change(config: Cfg, id: String) -> MLE<()> { 34pub fn list_change(config: Cfg, id: String) -> MLE<()> {
35 if lists_get_all_ids(config.clone())?.into_iter().find(|l| l == &id).is_none() { 35 if !lists_get_all_ids(config.clone())?.into_iter().any(|l| l == id) {
36 return Err(MLError::new(ErrorType::ArgumentError, "List not found")); 36 return Err(MLError::new(ErrorType::ArgumentError, "List not found"));
37 }; 37 };
38 println!("Change default list to: {}", id); 38 println!("Change default list to: {}", id);
diff --git a/src/commands/modification.rs b/src/commands/modification.rs
index d4c49d6..730583d 100644
--- a/src/commands/modification.rs
+++ b/src/commands/modification.rs
@@ -1,5 +1,7 @@
1use std::{io::Write, collections::HashMap}; 1use std::{io::Write, collections::HashMap};
2 2
3use indicatif::{ProgressBar, ProgressStyle};
4
3use crate::{ 5use crate::{
4 config::Cfg, 6 config::Cfg,
5 db::{ 7 db::{
@@ -12,6 +14,8 @@ use crate::{
12 List, 14 List,
13}; 15};
14 16
17const PROGRESS_CHARS: &str = "#>-";
18
15#[derive(Debug, Clone)] 19#[derive(Debug, Clone)]
16pub struct AddMod { 20pub struct AddMod {
17 pub id: IDSelector, 21 pub id: IDSelector,
@@ -41,28 +45,45 @@ pub async fn mod_add(
41 list: List, 45 list: List,
42 direct_download: bool, 46 direct_download: bool,
43) -> MLE<()> { 47) -> MLE<()> {
44 println!("Add mods to {}", list.id); 48 let spinner_style = ProgressStyle::with_template("{spinner:.green}{msg}").unwrap();
45 println!(" └Add mods:"); 49 let bar_style = ProgressStyle::with_template("{spinner:.green}{wide_msg}{pos}/{len} [{bar:.green/lime}]").unwrap().progress_chars(PROGRESS_CHARS);
50
51 // println!("Add mods to {}", list.id);
52 // println!(" └Add mods:");
46 53
47 let mut mod_ids: Vec<(String, bool)> = Vec::new(); 54 let mut mod_ids: Vec<(String, bool)> = Vec::new();
48 let mut ver_ids: Vec<(String, bool)> = Vec::new(); 55 let mut ver_ids: Vec<(String, bool)> = Vec::new();
49 56
57 let p = ProgressBar::new(mods.len().try_into().unwrap());
58 p.set_style(spinner_style.clone());
59 p.set_message("Sort ids");
60
50 //"Sort" project ids from version ids to be able to handle them differently but in a batch 61 //"Sort" project ids from version ids to be able to handle them differently but in a batch
51 for m in mods { 62 for m in mods {
63 p.inc(1);
52 match m.id { 64 match m.id {
53 IDSelector::ModificationID(pid) => mod_ids.push((pid, m.set_version)), 65 IDSelector::ModificationID(pid) => mod_ids.push((pid, m.set_version)),
54 IDSelector::VersionID(vid) => ver_ids.push((vid, m.set_version)), 66 IDSelector::VersionID(vid) => ver_ids.push((vid, m.set_version)),
55 } 67 }
56 } 68 }
57 69
70 p.finish_with_message("Sort ids done");
71
72 let info_p = ProgressBar::new(2);
73 info_p.set_message("Get infos");
74 info_p.set_style(bar_style.clone());
58 let mut projectinfo: Vec<ProjectInfo> = Vec::new(); 75 let mut projectinfo: Vec<ProjectInfo> = Vec::new();
59 if !mod_ids.is_empty() { 76 if !mod_ids.is_empty() {
60 projectinfo.append(&mut get_mod_infos(config.clone(), mod_ids, list.clone()).await?) 77 projectinfo.append(&mut get_mod_infos(config.clone(), mod_ids, list.clone()).await?);
78 info_p.inc(1);
61 }; 79 };
62 if !ver_ids.is_empty() { 80 if !ver_ids.is_empty() {
63 projectinfo.append(&mut get_ver_info(config.clone(), ver_ids).await?) 81 projectinfo.append(&mut get_ver_info(config.clone(), ver_ids).await?);
82 info_p.inc(1);
64 }; 83 };
65 84
85 info_p.finish_with_message("Get infos done");
86
66 if projectinfo.is_empty() { 87 if projectinfo.is_empty() {
67 return Err(MLError::new(ErrorType::ArgumentError, "NO_IDS?")); 88 return Err(MLError::new(ErrorType::ArgumentError, "NO_IDS?"));
68 }; 89 };
@@ -70,18 +91,19 @@ pub async fn mod_add(
70 let mut downloadstack: Vec<Version> = Vec::new(); 91 let mut downloadstack: Vec<Version> = Vec::new();
71 92
72 //Adding each mod to the lists and downloadstack 93 //Adding each mod to the lists and downloadstack
73 if projectinfo.len() == 1 { 94 let add_p = ProgressBar::new(projectinfo.len().try_into().unwrap());
74 println!(" └Insert mod in list {} and save infos", list.id); 95 add_p.set_style(bar_style);
75 } else {
76 println!(" └Insert mods in list {} and save infos", list.id);
77 }
78 96
79 for project in projectinfo { 97 for project in projectinfo {
98
99 add_p.set_message(format!("Add {}", project.title));
100
80 let current_version_id = if project.current_version.is_none() { 101 let current_version_id = if project.current_version.is_none() {
81 String::from("NONE") 102 String::from("NONE")
82 } else { 103 } else {
83 project.current_version.clone().unwrap().id 104 project.current_version.clone().unwrap().id
84 }; 105 };
106
85 match userlist_insert( 107 match userlist_insert(
86 config.clone(), 108 config.clone(),
87 &list.id, 109 &list.id,
@@ -124,8 +146,13 @@ pub async fn mod_add(
124 if project.current_version.is_some() { 146 if project.current_version.is_some() {
125 downloadstack.push(project.current_version.unwrap()) 147 downloadstack.push(project.current_version.unwrap())
126 }; 148 };
149
150 // add_p.println(format!("Added {}", project.title));
151 add_p.inc(1);
127 } 152 }
128 153
154 add_p.finish_with_message("Added all mods");
155
129 //Download all the added mods 156 //Download all the added mods
130 if direct_download { 157 if direct_download {
131 download_versions(list.clone(), config.clone(), downloadstack).await?; 158 download_versions(list.clone(), config.clone(), downloadstack).await?;
@@ -140,7 +167,7 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) ->
140 167
141 let mut ids = vec![]; 168 let mut ids = vec![];
142 169
143 println!("{:?}", mod_ids); 170 // println!("{:?}", mod_ids);
144 171
145 for id in mod_ids { 172 for id in mod_ids {
146 setmap.insert(id.0.to_string(), id.1); 173 setmap.insert(id.0.to_string(), id.1);
@@ -156,8 +183,8 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) ->
156 _ => panic!("PANIC"), 183 _ => panic!("PANIC"),
157 }; 184 };
158 for project in m_projects { 185 for project in m_projects {
159 println!("\t└{}", project.title); 186 // println!("\t└{}", project.title);
160 println!("\t └Get versions"); 187 // println!("\t └Get versions");
161 let available_versions = versions( 188 let available_versions = versions(
162 &config.apis.modrinth, 189 &config.apis.modrinth,
163 String::from(&project.id), 190 String::from(&project.id),
@@ -170,7 +197,7 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) ->
170 let file: String; 197 let file: String;
171 if !available_versions.is_empty() { 198 if !available_versions.is_empty() {
172 let current_id = extract_current_version(available_versions.clone())?; 199 let current_id = extract_current_version(available_versions.clone())?;
173 println!("\t └Current version: {}", current_id); 200 // println!("\t └Current version: {}", current_id);
174 201
175 current_version = Some( 202 current_version = Some(
176 available_versions 203 available_versions
@@ -197,7 +224,7 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) ->
197 available_versions_vec.push(ver.id); 224 available_versions_vec.push(ver.id);
198 } 225 }
199 226
200 println!("{:?}", setmap); 227 // println!("{:?}", setmap);
201 228
202 projectinfo.push(ProjectInfo { 229 projectinfo.push(ProjectInfo {
203 mod_id: String::from(&project.id), 230 mod_id: String::from(&project.id),
@@ -206,10 +233,10 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) ->
206 current_version, 233 current_version,
207 applicable_versions: available_versions_vec, 234 applicable_versions: available_versions_vec,
208 download_link: file, 235 download_link: file,
209 set_version: setmap.get(&project.slug).unwrap().clone(), 236 set_version: *setmap.get(&project.slug).unwrap(),
210 }) 237 })
211 } else { 238 } else {
212 println!("\t └There's currently no mod version for your specified target"); 239 // println!("\t └There's currently no mod version for your specified target");
213 current_version = None; 240 current_version = None;
214 file = String::from("NONE"); 241 file = String::from("NONE");
215 available_versions_vec.push(String::from("NONE")); 242 available_versions_vec.push(String::from("NONE"));
@@ -220,7 +247,7 @@ async fn get_mod_infos(config: Cfg, mod_ids: Vec<(String, bool)>, list: List) ->
220 current_version, 247 current_version,
221 applicable_versions: available_versions_vec, 248 applicable_versions: available_versions_vec,
222 download_link: file, 249 download_link: file,
223 set_version: setmap.get(&project.id).unwrap().clone(), 250 set_version: *setmap.get(&project.id).unwrap(),
224 }) 251 })
225 } 252 }
226 } 253 }
@@ -252,7 +279,7 @@ async fn get_ver_info(config: Cfg, ver_ids: Vec<(String, bool)>) -> MLE<Vec<Proj
252 279
253 for (i, project) in v_projects.into_iter().enumerate() { 280 for (i, project) in v_projects.into_iter().enumerate() {
254 let version = &v_versions[i]; 281 let version = &v_versions[i];
255 println!("\t└{}({})", project.title, version.id); 282 // println!("\t└{}({})", project.title, version.id);
256 let file = version 283 let file = version
257 .clone() 284 .clone()
258 .files 285 .files
@@ -267,7 +294,7 @@ async fn get_ver_info(config: Cfg, ver_ids: Vec<(String, bool)>) -> MLE<Vec<Proj
267 current_version: Some(version.clone()), 294 current_version: Some(version.clone()),
268 applicable_versions: vec![String::from(&version.id)], 295 applicable_versions: vec![String::from(&version.id)],
269 download_link: file, 296 download_link: file,
270 set_version: setmap.get(&version.id).unwrap().clone(), 297 set_version: *setmap.get(&version.id).unwrap(),
271 }) 298 })
272 } 299 }
273 Ok(projectinfo) 300 Ok(projectinfo)
@@ -282,7 +309,7 @@ async fn get_ver_info(config: Cfg, ver_ids: Vec<(String, bool)>) -> MLE<Vec<Proj
282pub fn mod_remove(config: Cfg, id: &str, list: List) -> MLE<()> { 309pub fn mod_remove(config: Cfg, id: &str, list: List) -> MLE<()> {
283 let mod_id = mods_get_id(&config.data, id)?; 310 let mod_id = mods_get_id(&config.data, id)?;
284 311
285 println!("Remove mod {} from {}", mods_get_info(config.clone(), &mod_id)?.title, list.id); 312 println!("Remove mod {} from {}", mods_get_info(&config, &mod_id)?.title, list.id);
286 let version = userlist_get_current_version(config.clone(), &list.id, &mod_id)?; 313 let version = userlist_get_current_version(config.clone(), &list.id, &mod_id)?;
287 314
288 print!(" └Remove from list"); 315 print!(" └Remove from list");
@@ -300,7 +327,6 @@ pub fn mod_remove(config: Cfg, id: &str, list: List) -> MLE<()> {
300 if err.to_string() != "User input not accepted: VERSION_NOT_FOUND_IN_FILES" { 327 if err.to_string() != "User input not accepted: VERSION_NOT_FOUND_IN_FILES" {
301 return Err(err); 328 return Err(err);
302 }; 329 };
303 ()
304 }, 330 },
305 }; 331 };
306 println!(" ✓"); 332 println!(" ✓");
diff --git a/src/commands/update.rs b/src/commands/update.rs
index d3a282b..2de13f3 100644
--- a/src/commands/update.rs
+++ b/src/commands/update.rs
@@ -1,3 +1,5 @@
1use indicatif::{ProgressBar, ProgressStyle, MultiProgress};
2
1use crate::{ 3use crate::{
2 config::Cfg, 4 config::Cfg,
3 db::{ 5 db::{
@@ -10,6 +12,8 @@ use crate::{
10 List, 12 List,
11}; 13};
12 14
15const PROGRESS_CHARS: &str = "#>-";
16
13pub async fn update( 17pub async fn update(
14 config: Cfg, 18 config: Cfg,
15 liststack: Vec<List>, 19 liststack: Vec<List>,
@@ -17,20 +21,39 @@ pub async fn update(
17 direct_download: bool, 21 direct_download: bool,
18 delete_old: bool, 22 delete_old: bool,
19) -> MLE<()> { 23) -> MLE<()> {
24
25 let mp = MultiProgress::new();
26
27 let update_p = mp.add(ProgressBar::new(liststack.len().try_into().unwrap()));
28 let bar_style = ProgressStyle::with_template("{spinner:.green}{wide_msg}{pos}/{len} [{bar:.green/lime}]").unwrap().progress_chars(PROGRESS_CHARS);
29 let spinner_style = ProgressStyle::with_template("{spinner:.green}{msg}").unwrap();
30 update_p.set_style(bar_style.clone());
31 update_p.set_message("Update");
32
20 for current_list in liststack { 33 for current_list in liststack {
21 println!("Update mods in {}", current_list.id); 34
35 // println!("Update mods in {}", current_list.id);
22 let mods = userlist_get_all_ids(config.clone(), &current_list.id)?; 36 let mods = userlist_get_all_ids(config.clone(), &current_list.id)?;
23 37
38 let list_p = mp.insert_before(&update_p, ProgressBar::new(mods.len().try_into().unwrap()));
39 list_p.set_style(bar_style.clone());
40 list_p.set_message(format!("Update {}", current_list.id));
41
24 let mut current_versions: Vec<(String, String)> = vec![]; 42 let mut current_versions: Vec<(String, String)> = vec![];
25 43
26 let mut updatestack: Vec<Version> = vec![]; 44 let mut updatestack: Vec<Version> = vec![];
27 45
28 for id in mods { 46 for id in mods {
29 let info = mods_get_info(config.clone(), &id)?; 47 let mod_p = mp.insert_before(&list_p, ProgressBar::new(1));
30 println!(" ├{}", info.title); 48 mod_p.set_style(spinner_style.clone());
49
50 let info = mods_get_info(&config, &id)?;
51 mod_p.set_message(format!("Update {}", info.title));
52 // println!(" ├{}", info.title);
31 53
32 if userlist_get_set_version(config.clone(), &current_list.id, &id)? { 54 if userlist_get_set_version(config.clone(), &current_list.id, &id)? {
33 println!(" │ └Set version, skipping update"); 55 // println!(" │ └Set version, skipping update");
56 list_p.inc(1);
34 continue; 57 continue;
35 } 58 }
36 59
@@ -38,12 +61,15 @@ pub async fn update(
38 let disable_version = 61 let disable_version =
39 userlist_get_current_version(config.clone(), &current_list.id, &id)?; 62 userlist_get_current_version(config.clone(), &current_list.id, &id)?;
40 63
64 mod_p.inc(1);
65
41 updatestack.push( 66 updatestack.push(
42 match specific_update( 67 match specific_update(
43 config.clone(), 68 config.clone(),
44 clean, 69 clean,
45 current_list.clone(), 70 current_list.clone(),
46 String::from(&id), 71 String::from(&id),
72 &mod_p
47 ) 73 )
48 .await 74 .await
49 { 75 {
@@ -53,19 +79,25 @@ pub async fn update(
53 } 79 }
54 Err(e) => { 80 Err(e) => {
55 if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" { 81 if e.to_string() == "Mod: NO_UPDATE_AVAILABLE" {
56 println!( 82 // println!(
57 " │ └No new version found for the specified minecraft version" 83 // " │ └No new version found for the specified minecraft version"
58 ); 84 // );
59 } else { 85 } else {
60 return Err(e); 86 return Err(e);
61 }; 87 };
88 list_p.inc(1);
62 continue; 89 continue;
63 } 90 }
64 }, 91 },
65 ) 92 );
93 list_p.inc(1);
66 } 94 }
67 95
96 list_p.finish_with_message(format!("Updated {}", current_list.id));
97
68 if clean { 98 if clean {
99 update_p.set_message("Cleaning");
100 update_p.inc(1);
69 clean_list_dir(&current_list)?; 101 clean_list_dir(&current_list)?;
70 }; 102 };
71 103
@@ -85,12 +117,16 @@ pub async fn update(
85 } 117 }
86 } 118 }
87 }; 119 };
120 update_p.inc(1);
88 } 121 }
89 122
123 update_p.finish_with_message("Updated all lists");
124
125
90 Ok(()) 126 Ok(())
91} 127}
92 128
93async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> MLE<Version> { 129async fn specific_update(config: Cfg, clean: bool, list: List, id: String, progress: &ProgressBar) -> MLE<Version> {
94 let applicable_versions = 130 let applicable_versions =
95 versions(&config.apis.modrinth, String::from(&id), list.clone()).await; 131 versions(&config.apis.modrinth, String::from(&id), list.clone()).await;
96 132
@@ -116,10 +152,11 @@ async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> ML
116 let current_str = extract_current_version(applicable_versions.clone())?; 152 let current_str = extract_current_version(applicable_versions.clone())?;
117 153
118 if clean { 154 if clean {
119 println!("\t └Add version to downloadstack"); 155 // println!("\t └Add version to downloadstack");
120 } else { 156 } else {
121 println!("\t └Get versions for specified minecraft versions"); 157 progress.println(format!("Found new version for {}", mods_get_info(&config, &id).unwrap().title));
122 println!("\t └New current version: {}", current_str); 158 // println!("\t └Get versions for specified minecraft versions");
159 // println!("\t └New current version: {}", current_str);
123 }; 160 };
124 161
125 //get new versions 162 //get new versions
@@ -133,16 +170,14 @@ async fn specific_update(config: Cfg, clean: bool, list: List, id: String) -> ML
133 }?; 170 }?;
134 current.push(current_ver.clone()); 171 current.push(current_ver.clone());
135 172
136 let link = match current_ver 173 let files = &current_ver.files;
137 .files 174
138 .into_iter() 175 let link = match files.clone().into_iter().find(|f| f.primary) {
139 .find(|f| f.primary) 176 Some(f) => f,
140 .ok_or("!no primary in links") 177 None => { files[0].clone() }
141 { 178 }
142 Ok(p) => Ok(p), 179 .url;
143 Err(e) => Err(MLError::new(ErrorType::Other, e)), 180
144 }?
145 .url;
146 userlist_change_versions(config, list.id, current_str, versions.join("|"), link, id)?; 181 userlist_change_versions(config, list.id, current_str, versions.join("|"), link, id)?;
147 } 182 }
148 183
diff --git a/src/config.rs b/src/config.rs
index e1049d1..0cb1891 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -31,7 +31,7 @@ pub struct Defaults {
31impl Cfg { 31impl Cfg {
32 pub async fn init(path: Option<String>) -> MLE<Self> { 32 pub async fn init(path: Option<String>) -> MLE<Self> {
33 let configfile = match path.clone() { 33 let configfile = match path.clone() {
34 Some(p) => String::from(p), 34 Some(p) => p,
35 None => dirs::config_dir() 35 None => dirs::config_dir()
36 .unwrap() 36 .unwrap()
37 .join("modlist") 37 .join("modlist")
@@ -89,7 +89,7 @@ fn create_config(path: &str) -> MLE<()> {
89 let default_cfg = Cfg { 89 let default_cfg = Cfg {
90 data: cache_dir.clone(), 90 data: cache_dir.clone(),
91 cache: format!("{}/cache", cache_dir), 91 cache: format!("{}/cache", cache_dir),
92 versions: cache_dir.clone(), 92 versions: cache_dir,
93 defaults: Defaults { 93 defaults: Defaults {
94 modloader: Modloader::Fabric, 94 modloader: Modloader::Fabric,
95 version: VersionLevel::Release 95 version: VersionLevel::Release
diff --git a/src/db.rs b/src/db.rs
index 8fd21b1..dde00ab 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -93,7 +93,7 @@ pub struct ModInfo {
93 pub title: String, 93 pub title: String,
94} 94}
95 95
96pub fn mods_get_info(config: Cfg, id: &str) -> MLE<ModInfo> { 96pub fn mods_get_info(config: &Cfg, id: &str) -> MLE<ModInfo> {
97 let data = format!("{}/data.db", config.data); 97 let data = format!("{}/data.db", config.data);
98 let connection = Connection::open(data)?; 98 let connection = Connection::open(data)?;
99 99
diff --git a/src/files.rs b/src/files.rs
index a4a1d3b..04b00f0 100644
--- a/src/files.rs
+++ b/src/files.rs
@@ -17,55 +17,50 @@ use crate::{
17 List, 17 List,
18}; 18};
19 19
20const PROGRESS_CHARS: &str = "#>-";
21
20pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) -> MLE<()> { 22pub async fn download_versions(list: List, config: Cfg, versions: Vec<Version>) -> MLE<()> {
21 let cached = get_cached_versions(&config.cache); 23 let cached = get_cached_versions(&config.cache);
22 24
23 // println!("{:#?}", cached);
24
25 // println!(" └Download mods to {}", dl_path);
26
27 let mp = MultiProgress::new(); 25 let mp = MultiProgress::new();
28 26
29 let mut js = JoinSet::new(); 27 let mut js = JoinSet::new();
30 let style = ProgressStyle::with_template("{spinner:.green}{msg}\t[{bar:.green/lime}] {bytes}/{total_bytes}")
31 .unwrap()
32 .progress_chars("#>-");
33 28
29 let style_spinner = ProgressStyle::with_template("{spinner:.green}{wide_msg}").unwrap();
30
31 let all = mp.add(ProgressBar::new(versions.len().try_into().unwrap()));
32 all.set_style(ProgressStyle::with_template("{wide_msg}{pos}/{len} [{bar:.green/lime}]").unwrap().progress_chars(PROGRESS_CHARS));
33 all.set_message("Downloading");
34
34 for ver in versions { 35 for ver in versions {
35 let p = mp.add(ProgressBar::new(1)); 36 let p = mp.insert_before(&all, ProgressBar::new(1));
36 p.set_style(style.clone()); 37 p.set_style(style_spinner.clone());
37 js.spawn(download_version(config.clone(), list.clone(), ver, cached.clone(), p)); 38 js.spawn(download_version(config.clone(), list.clone(), ver, cached.clone(), p));
39 // std::thread::sleep(std::time::Duration::from_millis(200));
38 } 40 }
39 41
40 mp.clear().unwrap(); 42 while js.join_next().await.is_some() { all.inc(1) }
43
44 all.finish();
41 45
42 while js.join_next().await.is_some() {} 46 // mp.clear().unwrap();
43 47
44 Ok(()) 48 Ok(())
45} 49}
46 50
47async fn download_version(config: Cfg, list: List, version: Version, mut cached: HashMap<String, String>, progress: ProgressBar) -> MLE<()> { 51async fn download_version(config: Cfg, list: List, version: Version, mut cached: HashMap<String, String>, progress: ProgressBar) -> MLE<()> {
48 let project_info = mods_get_info(config.clone(), &version.project_id)?; 52 let project_info = mods_get_info(&config, &version.project_id)?;
49 53
50 let dl_path = String::from(&list.download_folder); 54 let dl_path = String::from(&list.download_folder);
51 55
52 progress.set_message(String::from(&version.id)); 56 progress.set_message(format!("{} - {}", project_info.title, version.id));
53 57
54 //Check cache if already downloaded 58 //Check cache if already downloaded
55 let c = cached.remove(&version.id); 59 let c = cached.remove(&version.id);
56 if c.is_some() { 60 if c.is_some() {
57 print!( 61 progress.set_message(format!("Get {} from cache", version.id));
58 "\t└({})Get version {} from cache",
59 project_info.title, version.id
60 );
61 //Force flush of stdout, else print! doesn't print instantly
62 std::io::stdout().flush()?;
63 copy_cached_version(&c.unwrap(), &dl_path); 62 copy_cached_version(&c.unwrap(), &dl_path);
64 println!(" ✓");
65 } else { 63 } else {
66 // print!("\t└({})Download version {}", project_info.title, version.id);
67 //Force flush of stdout, else print! doesn't print instantly
68 std::io::stdout().flush().unwrap();
69 let files = version.files; 64 let files = version.files;
70 let file = match files.clone().into_iter().find(|f| f.primary) { 65 let file = match files.clone().into_iter().find(|f| f.primary) {
71 Some(f) => f, 66 Some(f) => f,
@@ -91,19 +86,15 @@ async fn download_version(config: Cfg, list: List, version: Version, mut cached:
91 &progress 86 &progress
92 ) 87 )
93 .await?; 88 .await?;
94 // println!(" ✓"); 89
95 //Copy file to cache 90 progress.set_message(format!("Copy {} to cache", version.id));
96 // print!("\t └Copy to cache");
97 //Force flush of stdout, else print! doesn't print instantly
98 std::io::stdout().flush().unwrap();
99 let dl_path_file = format!("{}/{}", list.download_folder, filename); 91 let dl_path_file = format!("{}/{}", list.download_folder, filename);
100 let cache_path = format!("{}/{}", &config.clone().cache, filename); 92 let cache_path = format!("{}/{}", &config.clone().cache, filename);
101 // println!("{}:{}", dl_path_file, cache_path); 93
102 copy(dl_path_file, cache_path)?; 94 copy(dl_path_file, cache_path)?;
103 // println!(" ✓");
104 } 95 }
105 96
106 progress.finish_with_message(format!("✓{}", version.id)); 97 progress.finish_with_message(format!("✓{} - {}", project_info.title, version.id));
107 98
108 Ok(()) 99 Ok(())
109} 100}
@@ -114,8 +105,12 @@ async fn download_file(url: &str, path: &str, name: &str, progress: &ProgressBar
114 105
115 let size = res.content_length().expect("Couldn't get content length"); 106 let size = res.content_length().expect("Couldn't get content length");
116 107
108 let style_bar_byte = ProgressStyle::with_template("{spinner:.green}{wide_msg}{bytes}/{total_bytes} [{bar:.green/lime}]")
109 .unwrap()
110 .progress_chars(PROGRESS_CHARS);
111
117 progress.set_length(size); 112 progress.set_length(size);
118 // progress.set_style(ProgressStyle::with_template("{spinner:.green}{msg}\t[{wide_bar:.green/lime}] {bytes}/{total_bytes}").unwrap().progress_chars("#>-")); 113 progress.set_style(style_bar_byte);
119 114
120 // download chunks 115 // download chunks
121 let mut file = File::create(&dl_path_file)?; 116 let mut file = File::create(&dl_path_file)?;
@@ -124,7 +119,7 @@ async fn download_file(url: &str, path: &str, name: &str, progress: &ProgressBar
124 let mut downloaded: u64 = 0; 119 let mut downloaded: u64 = 0;
125 120
126 while let Some(item) = stream.next().await { 121 while let Some(item) = stream.next().await {
127 progress.inc(1); 122 // progress.inc(1);
128 let chunk = item?; 123 let chunk = item?;
129 file.write_all(&chunk)?; 124 file.write_all(&chunk)?;
130 125
diff --git a/src/lib.rs b/src/lib.rs
index 1c40ceb..f59ba89 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -14,6 +14,8 @@ pub use commands::*;
14use error::{ErrorType, MLError, MLE}; 14use error::{ErrorType, MLError, MLE};
15use serde::{Deserialize, Serialize}; 15use serde::{Deserialize, Serialize};
16 16
17pub static TICK_CHARS: &str = "#>-";
18
17#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] 19#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
18pub enum Modloader { 20pub enum Modloader {
19 #[serde(rename(serialize = "fabric", deserialize = "fabric"))] 21 #[serde(rename(serialize = "fabric", deserialize = "fabric"))]
@@ -64,7 +66,7 @@ pub async fn check_game_versions(path: &str, force: bool) -> MLE<()> {
64 let versions = get_game_versions().await; 66 let versions = get_game_versions().await;
65 remove_file(path)?; 67 remove_file(path)?;
66 let mut file = File::create(path)?; 68 let mut file = File::create(path)?;
67 file.write_all(&serde_json::to_string_pretty(&versions)?.as_bytes())?; 69 file.write_all(serde_json::to_string_pretty(&versions)?.as_bytes())?;
68 println!(" ✓"); 70 println!(" ✓");
69 Ok(()) 71 Ok(())
70} 72}
@@ -105,7 +107,7 @@ impl VersionLevel {
105 Ok(snapshot.version) 107 Ok(snapshot.version)
106 }, 108 },
107 VersionLevel::Version(v) => { 109 VersionLevel::Version(v) => {
108 if versions.find(|ver| ver.version == v).is_some() { 110 if versions.any(|ver| ver.version == v) {
109 Ok(v) 111 Ok(v)
110 } else { 112 } else {
111 Err(MLError::new(ErrorType::ConfigError, "unknown minecraft version")) 113 Err(MLError::new(ErrorType::ConfigError, "unknown minecraft version"))