summaryrefslogtreecommitdiff
path: root/src/commands
diff options
context:
space:
mode:
Diffstat (limited to 'src/commands')
-rw-r--r--src/commands/download.rs17
-rw-r--r--src/commands/modification.rs25
-rw-r--r--src/commands/setup.rs12
-rw-r--r--src/commands/update.rs67
4 files changed, 89 insertions, 32 deletions
diff --git a/src/commands/download.rs b/src/commands/download.rs
index 13ba0e1..b0efdc2 100644
--- a/src/commands/download.rs
+++ b/src/commands/download.rs
@@ -1,3 +1,4 @@
1use crate::{modrinth::Version, files::download_file};
1#[allow(unused_imports)] 2#[allow(unused_imports)]
2use crate::{List, get_current_list, config::Cfg, db::userlist_get_all_downloads, input::Input}; 3use crate::{List, get_current_list, config::Cfg, db::userlist_get_all_downloads, input::Input};
3 4
@@ -32,3 +33,19 @@ async fn download_links(_config: Cfg, _input: Input, _current_list: List, _links
32 33
33 Ok(String::new()) 34 Ok(String::new())
34} 35}
36
37pub async fn download_versions(current_list: List, versions: Vec<Version>) -> Result<String, Box<dyn std::error::Error>> {
38
39 let dl_path = String::from(&current_list.download_folder);
40
41 for ver in versions {
42 let primary_file = ver.files.into_iter().find(|file| file.primary).unwrap();
43 let mut splitname: Vec<&str> = primary_file.filename.split('.').collect();
44 let extension = splitname.pop().ok_or("NO_FILE_EXTENSION")?;
45 let filename = format!("{}.mr{}.{}", splitname.join("."), ver.id, extension);
46 download_file(primary_file.url, current_list.clone().download_folder, filename).await?;
47 }
48
49 Ok(dl_path)
50}
51
diff --git a/src/commands/modification.rs b/src/commands/modification.rs
index 519a0cb..8e39d11 100644
--- a/src/commands/modification.rs
+++ b/src/commands/modification.rs
@@ -1,12 +1,12 @@
1use std::io::{Error, ErrorKind}; 1use std::io::{Error, ErrorKind};
2 2
3use crate::{modrinth::{project, versions, extract_current_version}, config::Cfg, db::{mods_insert, userlist_remove, mods_get_id, userlist_insert, mods_get_all_ids, userlist_get_all_ids}, input::{Input, Subcmd}, get_current_list}; 3use crate::{modrinth::{project, versions, extract_current_version}, config::Cfg, db::{mods_insert, userlist_remove, mods_get_id, userlist_insert, mods_get_all_ids, userlist_get_all_ids}, input::{Input, Subcmd}, get_current_list, download_versions};
4 4
5pub async fn modification(config: Cfg, input: Input) -> Result<(), Box<dyn std::error::Error>> { 5pub async fn modification(config: Cfg, input: Input) -> Result<(), Box<dyn std::error::Error>> {
6 6
7 match input.subcommand.ok_or("")? { 7 match input.subcommand.as_ref().ok_or("")? {
8 Subcmd::Add => { 8 Subcmd::Add => {
9 add(config, input.args.ok_or("")?).await 9 add(config, input).await
10 }, 10 },
11 Subcmd::Remove => { 11 Subcmd::Remove => {
12 remove(config, input.args.ok_or("")?) 12 remove(config, input.args.ok_or("")?)
@@ -15,23 +15,23 @@ pub async fn modification(config: Cfg, input: Input) -> Result<(), Box<dyn std::
15 } 15 }
16} 16}
17 17
18async fn add(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>> { 18async fn add(config: Cfg, input: Input) -> Result<(), Box<dyn std::error::Error>> {
19 //TODO! DO NOT PANIC IF MOD IS ALREADY IN MODS DB 19
20 let args = input.args.ok_or("")?;
21
20 if args.is_empty() { return Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_FEW_ARGUMENTS"))); }; 22 if args.is_empty() { return Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_FEW_ARGUMENTS"))); };
21 23
22 let current_list = get_current_list(config.clone())?; 24 let current_list = get_current_list(config.clone())?;
23 25
24 let project = project(String::from(&config.apis.modrinth), &args[0]).await; 26 let project = project(String::from(&config.apis.modrinth), &args[0]).await;
25 27
26 if project.versions.is_empty() { panic!("This should never happen"); };
27
28 let available_versions = versions(String::from(&config.apis.modrinth), String::from(&project.id), current_list.clone()).await; 28 let available_versions = versions(String::from(&config.apis.modrinth), String::from(&project.id), current_list.clone()).await;
29 29
30 let current_id = extract_current_version(available_versions.clone())?; 30 let current_id = extract_current_version(available_versions.clone())?;
31 31
32 let current_version = available_versions.clone().into_iter().find(|v| v.id == current_id).unwrap(); 32 let current_version = available_versions.clone().into_iter().find(|v| v.id == current_id).unwrap();
33 33
34 let file = current_version.files.into_iter().find(|f| f.primary).unwrap().url; 34 let file = current_version.clone().files.into_iter().find(|f| f.primary).unwrap().url;
35 35
36 let mut available_versions_vec: Vec<String> = Vec::new(); 36 let mut available_versions_vec: Vec<String> = Vec::new();
37 for ver in available_versions { 37 for ver in available_versions {
@@ -43,16 +43,16 @@ async fn add(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::E
43 if mods.contains(&project.id) { 43 if mods.contains(&project.id) {
44 return Err(Box::new(Error::new(ErrorKind::Other, "MOD_ALREADY_ON_LIST"))); } 44 return Err(Box::new(Error::new(ErrorKind::Other, "MOD_ALREADY_ON_LIST"))); }
45 else { 45 else {
46 userlist_insert(config.clone(), current_list.id, String::from(&project.id), current_version.id, available_versions_vec, file)?; 46 userlist_insert(config.clone(), String::from(&current_list.id), String::from(&project.id), String::from(&current_version.id), available_versions_vec, file)?;
47 } 47 }
48 }, 48 },
49 Err(..) => userlist_insert(config.clone(), current_list.id, String::from(&project.id), current_version.id, available_versions_vec, file)?, 49 Err(..) => userlist_insert(config.clone(), String::from(&current_list.id), String::from(&project.id), String::from(&current_version.id), available_versions_vec, file)?,
50 }; 50 };
51 51
52 match mods_get_all_ids(config.clone()) { 52 match mods_get_all_ids(config.clone()) {
53 Ok(mods) => { 53 Ok(mods) => {
54 if mods.contains(&project.id) { 54 if mods.contains(&project.id) {
55 return Err(Box::new(Error::new(ErrorKind::Other, "MOD_ALREADY_IN_DATABASE"))) 55 //return Err(Box::new(Error::new(ErrorKind::Other, "MOD_ALREADY_IN_DATABASE")))
56 } else { 56 } else {
57 mods_insert(config.clone(), String::from(&project.id), String::from(&project.title), project.versions)?; 57 mods_insert(config.clone(), String::from(&project.id), String::from(&project.title), project.versions)?;
58 } 58 }
@@ -61,6 +61,9 @@ async fn add(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::E
61 mods_insert(config.clone(), String::from(&project.id), String::from(&project.title), project.versions)?; 61 mods_insert(config.clone(), String::from(&project.id), String::from(&project.title), project.versions)?;
62 }, 62 },
63 }; 63 };
64
65 if !input.disable_download { download_versions(current_list, vec![current_version]).await?; }
66
64 Ok(()) 67 Ok(())
65} 68}
66 69
diff --git a/src/commands/setup.rs b/src/commands/setup.rs
index be06040..c7f1bed 100644
--- a/src/commands/setup.rs
+++ b/src/commands/setup.rs
@@ -13,6 +13,7 @@ pub async fn setup(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
13 Ok(ver) => { 13 Ok(ver) => {
14 match ver.as_str() { 14 match ver.as_str() {
15 "0.2" => to_03(config)?, 15 "0.2" => to_03(config)?,
16 "0.3" => to_04(config)?,
16 _ => return Err(Box::new(Error::new(ErrorKind::Other, "UNKNOWN_VERSION"))) 17 _ => return Err(Box::new(Error::new(ErrorKind::Other, "UNKNOWN_VERSION")))
17 } 18 }
18 }, 19 },
@@ -33,7 +34,7 @@ async fn to_02(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
33 34
34 for list in lists { 35 for list in lists {
35 println!("Updating {}", list); 36 println!("Updating {}", list);
36 s_insert_column(config.clone(), String::from(&list), String::from("current_download"), String::from("TEXT"))?; 37 s_insert_column(config.clone(), String::from(&list), String::from("current_download"), String::from("TEXT"), None)?;
37 38
38 let full_list = lists_get(config.clone(), String::from(&list))?; 39 let full_list = lists_get(config.clone(), String::from(&list))?;
39 40
@@ -53,6 +54,13 @@ async fn to_02(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
53} 54}
54 55
55fn to_03(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { 56fn to_03(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
56 s_insert_column(config.clone(), String::from("lists"), String::from("download_folder"), String::from("TEXT"))?; 57 s_insert_column(config.clone(), String::from("lists"), String::from("download_folder"), String::from("TEXT"), None)?;
57 s_config_update_version(config, String::from("0.3")) 58 s_config_update_version(config, String::from("0.3"))
58} 59}
60
61fn to_04(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
62 for list_id in lists_get_all_ids(config.clone())? {
63 s_insert_column(config.clone(), list_id, String::from("disabled_versions"), String::from("TEXT"), Some(String::from("NONE")))?;
64 }
65 s_config_update_version(config, String::from("0.4"))
66}
diff --git a/src/commands/update.rs b/src/commands/update.rs
index 42d19aa..c8f0880 100644
--- a/src/commands/update.rs
+++ b/src/commands/update.rs
@@ -1,9 +1,9 @@
1use std::io::{Error, ErrorKind}; 1use std::{io::{Error, ErrorKind}, fs::{rename, remove_file}};
2 2
3use crate::{config::Cfg, modrinth::{projects, Project, versions, extract_current_version, Version}, get_current_list, db::{userlist_get_all_ids, mods_get_versions, userlist_get_applicable_versions, userlist_change_versions, lists_get_all_ids, lists_get}, List, input::Input, download_file}; 3use crate::{config::Cfg, modrinth::{projects, Project, versions, extract_current_version, Version}, get_current_list, db::{userlist_get_all_ids, mods_get_versions, userlist_get_applicable_versions, userlist_change_versions, lists_get_all_ids, lists_get, userlist_get_current_version, userlist_add_disabled_versions, mods_change_versions}, List, input::Input, files::get_file_path, download_versions};
4 4
5pub async fn update(config: Cfg, input: Input) -> Result<(), Box<dyn std::error::Error>> { 5pub async fn update(config: Cfg, input: Input) -> Result<(), Box<dyn std::error::Error>> {
6 6
7 let mut liststack: Vec<List> = vec![]; 7 let mut liststack: Vec<List> = vec![];
8 if input.all_lists { 8 if input.all_lists {
9 let list_ids = lists_get_all_ids(config.clone())?; 9 let list_ids = lists_get_all_ids(config.clone())?;
@@ -11,18 +11,22 @@ pub async fn update(config: Cfg, input: Input) -> Result<(), Box<dyn std::error:
11 liststack.push(lists_get(config.clone(), id)?); 11 liststack.push(lists_get(config.clone(), id)?);
12 } 12 }
13 } else { 13 } else {
14 liststack.push(get_current_list(config.clone())?) 14 let current = get_current_list(config.clone())?;
15 println!("Checking for updates of mods in {}", current.id);
16 liststack.push(current)
15 } 17 }
16 18
17 for current_list in liststack { 19 for current_list in liststack {
18 let mods = userlist_get_all_ids(config.clone(), current_list.clone().id)?; 20 let mods = userlist_get_all_ids(config.clone(), current_list.clone().id)?;
21
22 let mut current_versions: Vec<(String, String)> = vec![];
19 23
20 let mut versions = mods_get_versions(config.clone(), mods.clone())?; 24 let mut versions = mods_get_versions(config.clone(), mods.clone())?;
21 versions.sort_by_key(|ver| ver.mod_id.clone()); 25 versions.sort_by_key(|ver| ver.mod_id.clone());
22 26
23 let mut projects = projects(String::from(&config.apis.modrinth), mods).await; 27 let mut projects = projects(String::from(&config.apis.modrinth), mods).await;
24 projects.sort_by_key(|pro| pro.id.clone()); 28 projects.sort_by_key(|pro| pro.id.clone());
25 29
26 let mut updatestack: Vec<Version> = vec![]; 30 let mut updatestack: Vec<Version> = vec![];
27 for (index, project) in projects.into_iter().enumerate() { 31 for (index, project) in projects.into_iter().enumerate() {
28 //Get versions for project and check if they match up 32 //Get versions for project and check if they match up
@@ -30,14 +34,26 @@ pub async fn update(config: Cfg, input: Input) -> Result<(), Box<dyn std::error:
30 let p_id = String::from(&project.id); 34 let p_id = String::from(&project.id);
31 let v_id = &current_version.mod_id; 35 let v_id = &current_version.mod_id;
32 if &p_id != v_id { return Err(Box::new(Error::new(ErrorKind::Other, "SORTING_ERROR"))) }; 36 if &p_id != v_id { return Err(Box::new(Error::new(ErrorKind::Other, "SORTING_ERROR"))) };
33 37
38 //Getting current installed version for disable or delete
39 let disable_version = userlist_get_current_version(config.clone(), String::from(&current_list.id), String::from(&project.id))?;
40
41 let version_db_string = project.versions.join("|");
34 42
35 //Adding to stack if not the same versions in the list OR if clean == true 43 //Adding to stack if not the same versions in the list OR if clean == true
36 if input.clone().clean || (project.versions.join("|") != current_version.versions) { 44 if input.clone().clean || (version_db_string != current_version.versions) {
37 updatestack.push(match specific_update(config.clone(), input.clone(), current_list.clone(), project.clone()).await { 45 updatestack.push(match specific_update(config.clone(), input.clone(), current_list.clone(), project.clone()).await {
38 Ok(ver) => ver, 46 Ok(ver) => {
47 current_versions.push((disable_version, p_id));
48 ver
49 },
39 //TODO handle errors (only continue on "NO_UPDATE_AVAILABLE") 50 //TODO handle errors (only continue on "NO_UPDATE_AVAILABLE")
40 Err(_) => { println!("({}) No new version found for the specified minecraft version", project.title); continue; }, 51 Err(e) => {
52 //Updating versions in modlist for no repeating version calls
53 mods_change_versions(config.clone(), version_db_string, project.id)?;
54 println!("({}) No new version found for the specified minecraft version({})", project.title, e);
55 continue;
56 },
41 }); 57 });
42 } else { 58 } else {
43 println!("({}) No new version found", project.title); 59 println!("({}) No new version found", project.title);
@@ -53,14 +69,19 @@ pub async fn update(config: Cfg, input: Input) -> Result<(), Box<dyn std::error:
53 } 69 }
54 } 70 }
55 71
56 if input.direct_download { download_updates(current_list, updatestack).await?; }; 72 if input.direct_download { download_versions(current_list.clone(), updatestack).await?; };
73
74 //Disable old versions
75 for ver in current_versions {
76 if input.delete_old { delete_old(current_list.clone(), ver.0, ver.1)? } else { disable_old(config.clone(), current_list.clone(), ver.0, ver.1)? };
77 }
57 } 78 }
58 79
59 Ok(()) 80 Ok(())
60} 81}
61 82
62async fn specific_update(config: Cfg, input: Input, list: List, project: Project) -> Result<Version, Box<dyn std::error::Error>> { 83async fn specific_update(config: Cfg, input: Input, list: List, project: Project) -> Result<Version, Box<dyn std::error::Error>> {
63 print!("Checking update for '{}' in {}", project.title, list.id); 84 println!("Checking update for '{}' in {}", project.title, list.id);
64 85
65 let applicable_versions = versions(String::from(&config.apis.modrinth), String::from(&project.id), list.clone()).await; 86 let applicable_versions = versions(String::from(&config.apis.modrinth), String::from(&project.id), list.clone()).await;
66 87
@@ -88,17 +109,25 @@ async fn specific_update(config: Cfg, input: Input, list: List, project: Project
88 Ok(current[0].clone()) 109 Ok(current[0].clone())
89} 110}
90 111
91async fn download_updates(current_list: List, versions: Vec<Version>) -> Result<String, Box<dyn std::error::Error>> { 112fn disable_old(config: Cfg, current_list: List, versionid: String, mod_id: String) -> Result<(), Box<dyn std::error::Error>> {
113 println!("Disabling version {} for mod {}", versionid, mod_id);
114 let file = get_file_path(current_list.clone(), String::from(&versionid))?;
115 let disabled = format!("{}.disabled", file);
92 116
93 let dl_path = String::from(&current_list.download_folder); 117 rename(file, disabled)?;
94 118
95 for ver in versions { 119 userlist_add_disabled_versions(config, current_list.id, versionid, mod_id)?;
96 let primary_file = ver.files.into_iter().find(|file| file.primary).unwrap(); 120
97 download_file(primary_file.url, current_list.clone().download_folder, primary_file.filename).await?; 121 Ok(())
98 } 122}
99 123
124fn delete_old(current_list: List, versionid: String, mod_id: String) -> Result<(), Box<dyn std::error::Error>> {
125 println!("Deleting version {} for mod {}", versionid, mod_id);
126 let file = get_file_path(current_list, String::from(&versionid))?;
127
128 remove_file(file)?;
100 129
101 Ok(dl_path) 130 Ok(())
102} 131}
103 132
104#[tokio::test] 133#[tokio::test]
@@ -138,5 +167,5 @@ async fn download_updates_test() {
138 "fabric".to_string() 167 "fabric".to_string()
139 ] 168 ]
140 }]; 169 }];
141 assert!(download_updates(current_list, versions).await.is_ok()) 170 assert!(download_versions(current_list, versions).await.is_ok())
142} 171}