diff options
Diffstat (limited to 'src/commands')
-rw-r--r-- | src/commands/download.rs | 17 | ||||
-rw-r--r-- | src/commands/modification.rs | 25 | ||||
-rw-r--r-- | src/commands/setup.rs | 12 | ||||
-rw-r--r-- | src/commands/update.rs | 67 |
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 @@ | |||
1 | use crate::{modrinth::Version, files::download_file}; | ||
1 | #[allow(unused_imports)] | 2 | #[allow(unused_imports)] |
2 | use crate::{List, get_current_list, config::Cfg, db::userlist_get_all_downloads, input::Input}; | 3 | use 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 | |||
37 | pub async fn download_versions(current_list: List, versions: Vec<Version>) -> Result<String, Box<dyn std::error::Error>> { | ||
38 | |||
39 | let dl_path = String::from(¤t_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 @@ | |||
1 | use std::io::{Error, ErrorKind}; | 1 | use std::io::{Error, ErrorKind}; |
2 | 2 | ||
3 | use 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}; | 3 | use 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 | ||
5 | pub async fn modification(config: Cfg, input: Input) -> Result<(), Box<dyn std::error::Error>> { | 5 | pub 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 | ||
18 | async fn add(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>> { | 18 | async 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(¤t_list.id), String::from(&project.id), String::from(¤t_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(¤t_list.id), String::from(&project.id), String::from(¤t_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 | ||
55 | fn to_03(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { | 56 | fn 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 | |||
61 | fn 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 @@ | |||
1 | use std::io::{Error, ErrorKind}; | 1 | use std::{io::{Error, ErrorKind}, fs::{rename, remove_file}}; |
2 | 2 | ||
3 | use 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}; | 3 | use 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 | ||
5 | pub async fn update(config: Cfg, input: Input) -> Result<(), Box<dyn std::error::Error>> { | 5 | pub 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 = ¤t_version.mod_id; | 35 | let v_id = ¤t_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(¤t_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 | ||
62 | async fn specific_update(config: Cfg, input: Input, list: List, project: Project) -> Result<Version, Box<dyn std::error::Error>> { | 83 | async 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 | ||
91 | async fn download_updates(current_list: List, versions: Vec<Version>) -> Result<String, Box<dyn std::error::Error>> { | 112 | fn 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(¤t_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 | ||
124 | fn 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 | } |