diff options
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/apis/modrinth.rs | 75 | ||||
-rw-r--r-- | src/commands/io.rs | 2 | ||||
-rw-r--r-- | src/config.rs | 51 | ||||
-rw-r--r-- | src/db.rs | 11 | ||||
-rw-r--r-- | src/error.rs | 9 | ||||
-rw-r--r-- | src/lib.rs | 81 | ||||
-rw-r--r-- | src/main.rs | 22 |
9 files changed, 184 insertions, 71 deletions
@@ -798,7 +798,7 @@ dependencies = [ | |||
798 | 798 | ||
799 | [[package]] | 799 | [[package]] |
800 | name = "modlist" | 800 | name = "modlist" |
801 | version = "0.13.1" | 801 | version = "0.14.1" |
802 | dependencies = [ | 802 | dependencies = [ |
803 | "chrono", | 803 | "chrono", |
804 | "clap", | 804 | "clap", |
@@ -1,6 +1,6 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "modlist" | 2 | name = "modlist" |
3 | version = "0.13.1" | 3 | version = "0.14.1" |
4 | edition = "2021" | 4 | edition = "2021" |
5 | 5 | ||
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
diff --git a/src/apis/modrinth.rs b/src/apis/modrinth.rs index 9afe7f3..525cc0d 100644 --- a/src/apis/modrinth.rs +++ b/src/apis/modrinth.rs | |||
@@ -1,10 +1,10 @@ | |||
1 | use chrono::{DateTime, FixedOffset}; | 1 | use chrono::{DateTime, FixedOffset}; |
2 | use reqwest::Client; | 2 | use reqwest::Client; |
3 | use serde::Deserialize; | 3 | use serde::{Deserialize, Serialize}; |
4 | 4 | ||
5 | use crate::{ | 5 | use crate::{ |
6 | error::{ErrorType, MLError, MLE}, | 6 | error::{ErrorType, MLError, MLE}, |
7 | List, Modloader, | 7 | List, |
8 | }; | 8 | }; |
9 | 9 | ||
10 | #[derive(Debug, Deserialize, Clone)] | 10 | #[derive(Debug, Deserialize, Clone)] |
@@ -113,7 +113,24 @@ pub struct Hash { | |||
113 | pub sha1: String, | 113 | pub sha1: String, |
114 | } | 114 | } |
115 | 115 | ||
116 | async fn get(api: &str, path: String) -> Result<Option<Vec<u8>>, Box<dyn std::error::Error>> { | 116 | #[derive(Debug, Clone, Serialize, Deserialize)] |
117 | pub struct GameVersion { | ||
118 | pub version: String, | ||
119 | pub version_type: GameVersionType, | ||
120 | pub date: String, | ||
121 | pub major: bool, | ||
122 | } | ||
123 | |||
124 | #[allow(non_camel_case_types)] | ||
125 | #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] | ||
126 | pub enum GameVersionType { | ||
127 | release, | ||
128 | snapshot, | ||
129 | alpha, | ||
130 | beta | ||
131 | } | ||
132 | |||
133 | async fn get(api: &str, path: &str) -> Result<Option<Vec<u8>>, Box<dyn std::error::Error>> { | ||
117 | let url = format!(r#"{}{}"#, api, path); | 134 | let url = format!(r#"{}{}"#, api, path); |
118 | 135 | ||
119 | let client = Client::builder() | 136 | let client = Client::builder() |
@@ -135,7 +152,7 @@ async fn get(api: &str, path: String) -> Result<Option<Vec<u8>>, Box<dyn std::er | |||
135 | 152 | ||
136 | pub async fn project(api: &str, name: &str) -> Project { | 153 | pub async fn project(api: &str, name: &str) -> Project { |
137 | let url = format!("project/{}", name); | 154 | let url = format!("project/{}", name); |
138 | let data = get(api, url).await.unwrap().unwrap(); | 155 | let data = get(api, &url).await.unwrap().unwrap(); |
139 | 156 | ||
140 | serde_json::from_slice(&data).unwrap() | 157 | serde_json::from_slice(&data).unwrap() |
141 | } | 158 | } |
@@ -144,24 +161,19 @@ pub async fn projects(api: &str, ids: Vec<String>) -> Vec<Project> { | |||
144 | let all = ids.join(r#"",""#); | 161 | let all = ids.join(r#"",""#); |
145 | let url = format!(r#"projects?ids=["{}"]"#, all); | 162 | let url = format!(r#"projects?ids=["{}"]"#, all); |
146 | 163 | ||
147 | let data = get(api, url).await.unwrap().unwrap(); | 164 | let data = get(api, &url).await.unwrap().unwrap(); |
148 | 165 | ||
149 | serde_json::from_slice(&data).unwrap() | 166 | serde_json::from_slice(&data).unwrap() |
150 | } | 167 | } |
151 | 168 | ||
152 | ///Get applicable versions from mod_id with list context | 169 | ///Get applicable versions from mod_id with list context |
153 | pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> { | 170 | pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> { |
154 | let loaderstr = match list.modloader { | ||
155 | Modloader::Forge => String::from("forge"), | ||
156 | Modloader::Fabric => String::from("fabric"), | ||
157 | }; | ||
158 | |||
159 | let url = format!( | 171 | let url = format!( |
160 | r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, | 172 | r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, |
161 | id, loaderstr, list.mc_version | 173 | id, list.modloader.to_string(), list.mc_version |
162 | ); | 174 | ); |
163 | 175 | ||
164 | let data = get(api, url).await.unwrap(); | 176 | let data = get(api, &url).await.unwrap(); |
165 | 177 | ||
166 | match data { | 178 | match data { |
167 | Some(data) => serde_json::from_slice(&data).unwrap(), | 179 | Some(data) => serde_json::from_slice(&data).unwrap(), |
@@ -173,7 +185,7 @@ pub async fn versions(api: &str, id: String, list: List) -> Vec<Version> { | |||
173 | pub async fn get_raw_versions(api: &str, versions: Vec<String>) -> Vec<Version> { | 185 | pub async fn get_raw_versions(api: &str, versions: Vec<String>) -> Vec<Version> { |
174 | let url = format!(r#"versions?ids=["{}"]"#, versions.join(r#"",""#)); | 186 | let url = format!(r#"versions?ids=["{}"]"#, versions.join(r#"",""#)); |
175 | 187 | ||
176 | let data = get(api, url).await.unwrap().unwrap(); | 188 | let data = get(api, &url).await.unwrap().unwrap(); |
177 | 189 | ||
178 | serde_json::from_slice(&data).unwrap() | 190 | serde_json::from_slice(&data).unwrap() |
179 | } | 191 | } |
@@ -195,39 +207,8 @@ pub fn extract_current_version(versions: Vec<Version>) -> MLE<String> { | |||
195 | } | 207 | } |
196 | } | 208 | } |
197 | 209 | ||
198 | pub enum MCVersionType { | 210 | pub async fn get_game_versions() -> Vec<GameVersion> { |
199 | Release, | 211 | let data = get("https://api.modrinth.com/v2/", "tag/game_version").await.unwrap().unwrap(); |
200 | Latest, | ||
201 | Specific, | ||
202 | } | ||
203 | |||
204 | #[derive(Debug, Deserialize)] | ||
205 | pub struct MCVersion { | ||
206 | pub version: String, | ||
207 | pub version_type: String, | ||
208 | pub date: String, | ||
209 | pub major: bool, | ||
210 | } | ||
211 | 212 | ||
212 | pub async fn get_minecraft_version(api: &str, version: MCVersionType) -> String { | 213 | serde_json::from_slice(&data).unwrap() |
213 | let data = get(api, String::from("tag/game_version")) | ||
214 | .await | ||
215 | .unwrap() | ||
216 | .unwrap(); | ||
217 | let mc_versions: Vec<MCVersion> = serde_json::from_slice(&data).unwrap(); | ||
218 | let ver = match version { | ||
219 | MCVersionType::Release => { | ||
220 | let mut i = 0; | ||
221 | while !mc_versions[i].major { | ||
222 | i += 1; | ||
223 | } | ||
224 | &mc_versions[i] | ||
225 | } | ||
226 | MCVersionType::Latest => &mc_versions[0], | ||
227 | MCVersionType::Specific => { | ||
228 | println!("Not inplemented"); | ||
229 | &mc_versions[0] | ||
230 | } | ||
231 | }; | ||
232 | String::from(&ver.version) | ||
233 | } | 214 | } |
diff --git a/src/commands/io.rs b/src/commands/io.rs index 82b30ce..e072f00 100644 --- a/src/commands/io.rs +++ b/src/commands/io.rs | |||
@@ -92,7 +92,7 @@ pub async fn import(config: Cfg, file_str: String, direct_download: bool) -> MLE | |||
92 | mod_ids.push(IDSelector::ModificationID(String::from(mod_id))); | 92 | mod_ids.push(IDSelector::ModificationID(String::from(mod_id))); |
93 | } | 93 | } |
94 | //TODO impl set_version and good direct download | 94 | //TODO impl set_version and good direct download |
95 | //TODO impl all at once, dafuck | 95 | //TODO impl all at once, dafuck ?done? |
96 | mod_add(config.clone(), mod_ids, list, direct_download, false).await?; | 96 | mod_add(config.clone(), mod_ids, list, direct_download, false).await?; |
97 | } | 97 | } |
98 | Ok(()) | 98 | Ok(()) |
diff --git a/src/config.rs b/src/config.rs index 61db1c7..e1049d1 100644 --- a/src/config.rs +++ b/src/config.rs | |||
@@ -6,12 +6,14 @@ use std::{ | |||
6 | 6 | ||
7 | use serde::{Deserialize, Serialize}; | 7 | use serde::{Deserialize, Serialize}; |
8 | 8 | ||
9 | use crate::{db::db_setup, error::MLE}; | 9 | use crate::{db::db_setup, error::MLE, Modloader, VersionLevel, check_game_versions}; |
10 | 10 | ||
11 | #[derive(Debug, Clone, Serialize, Deserialize)] | 11 | #[derive(Debug, Clone, Serialize, Deserialize)] |
12 | pub struct Cfg { | 12 | pub struct Cfg { |
13 | pub data: String, | 13 | pub data: String, |
14 | pub cache: String, | 14 | pub cache: String, |
15 | pub versions: String, | ||
16 | pub defaults: Defaults, | ||
15 | pub apis: Apis, | 17 | pub apis: Apis, |
16 | } | 18 | } |
17 | 19 | ||
@@ -20,13 +22,20 @@ pub struct Apis { | |||
20 | pub modrinth: String, | 22 | pub modrinth: String, |
21 | } | 23 | } |
22 | 24 | ||
25 | #[derive(Debug, Clone, Serialize, Deserialize)] | ||
26 | pub struct Defaults { | ||
27 | pub modloader: Modloader, | ||
28 | pub version: VersionLevel, | ||
29 | } | ||
30 | |||
23 | impl Cfg { | 31 | impl Cfg { |
24 | pub fn init(path: Option<String>) -> MLE<Self> { | 32 | pub async fn init(path: Option<String>) -> MLE<Self> { |
25 | let configfile = match path.clone() { | 33 | let configfile = match path.clone() { |
26 | Some(p) => String::from(p), | 34 | Some(p) => String::from(p), |
27 | None => dirs::config_dir() | 35 | None => dirs::config_dir() |
28 | .unwrap() | 36 | .unwrap() |
29 | .join("modlist.toml") | 37 | .join("modlist") |
38 | .join("config.toml") | ||
30 | .to_string_lossy() | 39 | .to_string_lossy() |
31 | .to_string(), | 40 | .to_string(), |
32 | }; | 41 | }; |
@@ -50,12 +59,20 @@ impl Cfg { | |||
50 | create_cache(&config.cache)?; | 59 | create_cache(&config.cache)?; |
51 | }; | 60 | }; |
52 | //Check database | 61 | //Check database |
53 | //TODO check file | ||
54 | let datafile = format!("{}/data.db", config.data); | 62 | let datafile = format!("{}/data.db", config.data); |
55 | match File::open(&datafile) { | 63 | match File::open(&datafile) { |
56 | Ok(..) => (), | 64 | Ok(..) => (), |
57 | Err(..) => create_database(&datafile)?, | 65 | Err(..) => create_database(&datafile)?, |
58 | }; | 66 | }; |
67 | //Check versions | ||
68 | let versionfile = format!("{}/versions.json", config.versions); | ||
69 | match File::open(&versionfile) { | ||
70 | Ok(..) => (), | ||
71 | Err(..) => { | ||
72 | create_versions_dummy(&versionfile).await?; | ||
73 | check_game_versions(&versionfile, true).await?; | ||
74 | }, | ||
75 | } | ||
59 | Ok(config) | 76 | Ok(config) |
60 | } | 77 | } |
61 | } | 78 | } |
@@ -64,14 +81,24 @@ fn create_config(path: &str) -> MLE<()> { | |||
64 | print!("No config file found, create default"); | 81 | print!("No config file found, create default"); |
65 | //Force flush of stdout, else print! doesn't print instantly | 82 | //Force flush of stdout, else print! doesn't print instantly |
66 | std::io::stdout().flush()?; | 83 | std::io::stdout().flush()?; |
84 | let cache_dir = dirs::cache_dir() | ||
85 | .unwrap() | ||
86 | .join("modlist") | ||
87 | .to_string_lossy() | ||
88 | .to_string(); | ||
67 | let default_cfg = Cfg { | 89 | let default_cfg = Cfg { |
68 | //TODO get home dir | 90 | data: cache_dir.clone(), |
69 | data: String::from("$HOME/.cache/modlist/"), | 91 | cache: format!("{}/cache", cache_dir), |
70 | cache: String::from("$HOME/.cache/modlist/cache"), | 92 | versions: cache_dir.clone(), |
93 | defaults: Defaults { | ||
94 | modloader: Modloader::Fabric, | ||
95 | version: VersionLevel::Release | ||
96 | }, | ||
71 | apis: Apis { | 97 | apis: Apis { |
72 | modrinth: String::from("https://api.modrinth.com/v2/"), | 98 | modrinth: String::from("https://api.modrinth.com/v2/"), |
73 | }, | 99 | }, |
74 | }; | 100 | }; |
101 | create_dir_all(path.split("config.toml").collect::<Vec<&str>>()[0])?; | ||
75 | let mut file = File::create(path)?; | 102 | let mut file = File::create(path)?; |
76 | file.write_all(toml::to_string(&default_cfg)?.as_bytes())?; | 103 | file.write_all(toml::to_string(&default_cfg)?.as_bytes())?; |
77 | println!(" ✓"); | 104 | println!(" ✓"); |
@@ -98,3 +125,13 @@ fn create_cache(path: &str) -> MLE<()> { | |||
98 | println!(" ✓"); | 125 | println!(" ✓"); |
99 | Ok(()) | 126 | Ok(()) |
100 | } | 127 | } |
128 | |||
129 | async fn create_versions_dummy(path: &str) -> MLE<()> { | ||
130 | print!("No version file found, create dummy"); | ||
131 | //Force flush of stdout, else print! doesn't print instantly | ||
132 | std::io::stdout().flush()?; | ||
133 | |||
134 | File::create(path)?; | ||
135 | println!(" ✓"); | ||
136 | Ok(()) | ||
137 | } | ||
@@ -50,8 +50,6 @@ pub fn mods_get_all_ids(config: Cfg) -> Result<Vec<String>, Box<dyn std::error:: | |||
50 | /// | 50 | /// |
51 | ///Will return `MLError` when no mod id is found | 51 | ///Will return `MLError` when no mod id is found |
52 | pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { | 52 | pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { |
53 | //TODO check if "slug" is id | ||
54 | |||
55 | let data = format!("{}/data.db", data); | 53 | let data = format!("{}/data.db", data); |
56 | let connection = Connection::open(data)?; | 54 | let connection = Connection::open(data)?; |
57 | 55 | ||
@@ -64,6 +62,15 @@ pub fn mods_get_id(data: &str, slug: &str) -> MLE<String> { | |||
64 | for id in id_iter { | 62 | for id in id_iter { |
65 | mod_id = id?; | 63 | mod_id = id?; |
66 | } | 64 | } |
65 | //get from id if no slug found | ||
66 | if mod_id.is_empty() { | ||
67 | let mut stmt = connection.prepare("SELECT id FROM mods WHERE id = ?")?; | ||
68 | let id_iter = stmt.query_map([slug], |row| row.get::<usize, String>(0))?; | ||
69 | |||
70 | for id in id_iter { | ||
71 | mod_id = id?; | ||
72 | } | ||
73 | } | ||
67 | //get from title if no id found from slug | 74 | //get from title if no id found from slug |
68 | if mod_id.is_empty() { | 75 | if mod_id.is_empty() { |
69 | let mut stmt = connection.prepare("SELECT id FROM mods WHERE title = ?")?; | 76 | let mut stmt = connection.prepare("SELECT id FROM mods WHERE title = ?")?; |
diff --git a/src/error.rs b/src/error.rs index bd6e3da..e6afeaa 100644 --- a/src/error.rs +++ b/src/error.rs | |||
@@ -20,6 +20,7 @@ pub enum ErrorType { | |||
20 | LibSql, | 20 | LibSql, |
21 | LibReq, | 21 | LibReq, |
22 | LibChrono, | 22 | LibChrono, |
23 | LibJson, | ||
23 | IoError, | 24 | IoError, |
24 | Other, | 25 | Other, |
25 | } | 26 | } |
@@ -42,6 +43,7 @@ impl fmt::Display for MLError { | |||
42 | ErrorType::LibSql => write!(f, "SQL: {}", self.message), | 43 | ErrorType::LibSql => write!(f, "SQL: {}", self.message), |
43 | ErrorType::LibReq => write!(f, "REQWEST"), | 44 | ErrorType::LibReq => write!(f, "REQWEST"), |
44 | ErrorType::LibChrono => write!(f, "Chrono error: {}", self.message), | 45 | ErrorType::LibChrono => write!(f, "Chrono error: {}", self.message), |
46 | ErrorType::LibJson => write!(f, "JSON: {}", self.message), | ||
45 | ErrorType::IoError => write!(f, "IO"), | 47 | ErrorType::IoError => write!(f, "IO"), |
46 | ErrorType::Other => write!(f, "OTHER"), | 48 | ErrorType::Other => write!(f, "OTHER"), |
47 | } | 49 | } |
@@ -102,6 +104,13 @@ impl From<std::io::Error> for MLError { | |||
102 | } | 104 | } |
103 | } | 105 | } |
104 | 106 | ||
107 | impl From<serde_json::error::Error> for MLError { | ||
108 | fn from(value: serde_json::error::Error) -> Self { | ||
109 | Self { etype: ErrorType::LibJson, message: value.to_string() } | ||
110 | } | ||
111 | |||
112 | } | ||
113 | |||
105 | impl MLError { | 114 | impl MLError { |
106 | pub fn new(etype: ErrorType, message: &str) -> Self { | 115 | pub fn new(etype: ErrorType, message: &str) -> Self { |
107 | Self { | 116 | Self { |
@@ -6,16 +6,22 @@ pub mod db; | |||
6 | pub mod error; | 6 | pub mod error; |
7 | pub mod files; | 7 | pub mod files; |
8 | 8 | ||
9 | use std::fmt::Display; | 9 | use std::{fmt::Display, fs::{File, remove_file, self}, io::{Write, Read}, time::Duration}; |
10 | 10 | ||
11 | pub use apis::*; | 11 | pub use apis::*; |
12 | use apis::modrinth::{get_game_versions, GameVersion, GameVersionType}; | ||
12 | pub use commands::*; | 13 | pub use commands::*; |
13 | use error::{ErrorType, MLError, MLE}; | 14 | use error::{ErrorType, MLError, MLE}; |
15 | use serde::{Deserialize, Serialize}; | ||
14 | 16 | ||
15 | #[derive(Debug, Clone, PartialEq, Eq)] | 17 | #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] |
16 | pub enum Modloader { | 18 | pub enum Modloader { |
19 | #[serde(rename(serialize = "fabric", deserialize = "fabric"))] | ||
17 | Fabric, | 20 | Fabric, |
21 | #[serde(rename(serialize = "forge", deserialize = "forge"))] | ||
18 | Forge, | 22 | Forge, |
23 | #[serde(rename(serialize = "quilt", deserialize = "quilt"))] | ||
24 | Quilt, | ||
19 | } | 25 | } |
20 | 26 | ||
21 | impl Modloader { | 27 | impl Modloader { |
@@ -33,6 +39,77 @@ impl Display for Modloader { | |||
33 | match self { | 39 | match self { |
34 | Modloader::Fabric => write!(f, "fabric"), | 40 | Modloader::Fabric => write!(f, "fabric"), |
35 | Modloader::Forge => write!(f, "forge"), | 41 | Modloader::Forge => write!(f, "forge"), |
42 | Modloader::Quilt => write!(f, "quilt"), | ||
43 | } | ||
44 | } | ||
45 | } | ||
46 | |||
47 | #[derive(Debug, Clone, Deserialize, Serialize)] | ||
48 | pub enum VersionLevel { | ||
49 | #[serde(rename(serialize = "release", deserialize = "release"))] | ||
50 | Release, | ||
51 | #[serde(rename(serialize = "snapshot", deserialize = "snapshot"))] | ||
52 | Snapshot, | ||
53 | Version(String) | ||
54 | } | ||
55 | |||
56 | /// Checks if update needed (time) | ||
57 | /// if yes: get versions, update | ||
58 | pub async fn check_game_versions(path: &str, force: bool) -> MLE<()> { | ||
59 | let creation_time = fs::metadata(path)?.created()?; | ||
60 | if !force && creation_time.elapsed().unwrap() < Duration::from_secs(60 * 60 * 24) { return Ok(()); } | ||
61 | print!("Update minecraft versions"); | ||
62 | std::io::stdout().flush()?; | ||
63 | let versions = get_game_versions().await; | ||
64 | remove_file(path)?; | ||
65 | let mut file = File::create(path)?; | ||
66 | file.write_all(&serde_json::to_string_pretty(&versions)?.as_bytes())?; | ||
67 | println!(" ✓"); | ||
68 | Ok(()) | ||
69 | } | ||
70 | |||
71 | /// Loads game versions from file | ||
72 | pub fn load_game_versions(path: &str) -> MLE<Vec<GameVersion>> { | ||
73 | let mut file = File::open(path)?; | ||
74 | let mut data = String::new(); | ||
75 | file.read_to_string(&mut data)?; | ||
76 | let versions: Vec<GameVersion> = serde_json::from_str(&data)?; | ||
77 | Ok(versions) | ||
78 | } | ||
79 | |||
80 | impl VersionLevel { | ||
81 | |||
82 | pub fn from(str: &str) -> Self { | ||
83 | match str { | ||
84 | "release" => VersionLevel::Release, | ||
85 | "snapshot" => VersionLevel::Snapshot, | ||
86 | _ => VersionLevel::Version(String::from(str)), | ||
87 | } | ||
88 | } | ||
89 | |||
90 | pub async fn get(self, versions_path: &str, force_update: bool) -> MLE<String> { | ||
91 | let path = format!("{}/versions.json", versions_path); | ||
92 | check_game_versions(&path, force_update).await?; | ||
93 | let mut versions = load_game_versions(&path)?.into_iter(); | ||
94 | |||
95 | match self { | ||
96 | VersionLevel::Release => { | ||
97 | let release = versions.find(|ver| ver.version_type == GameVersionType::release).unwrap(); | ||
98 | println!("{:?}", release); | ||
99 | Ok(release.version) | ||
100 | }, | ||
101 | VersionLevel::Snapshot => { | ||
102 | let snapshot = versions.find(|ver| ver.version_type == GameVersionType::snapshot).unwrap(); | ||
103 | println!("{:?}", snapshot); | ||
104 | Ok(snapshot.version) | ||
105 | }, | ||
106 | VersionLevel::Version(v) => { | ||
107 | if versions.find(|ver| ver.version == v).is_some() { | ||
108 | Ok(v) | ||
109 | } else { | ||
110 | Err(MLError::new(ErrorType::ConfigError, "unknown minecraft version")) | ||
111 | } | ||
112 | }, | ||
36 | } | 113 | } |
37 | } | 114 | } |
38 | } | 115 | } |
diff --git a/src/main.rs b/src/main.rs index 53cbe71..3bc2ba0 100644 --- a/src/main.rs +++ b/src/main.rs | |||
@@ -3,11 +3,9 @@ use modlist::{ | |||
3 | config::Cfg, | 3 | config::Cfg, |
4 | db::{config_get_current_list, lists_get, lists_get_all_ids}, | 4 | db::{config_get_current_list, lists_get, lists_get_all_ids}, |
5 | download, export, get_current_list, import, list_add, list_change, list_remove, list_version, | 5 | download, export, get_current_list, import, list_add, list_change, list_remove, list_version, |
6 | mod_add, mod_remove, update, IDSelector, List, Modloader, | 6 | mod_add, mod_remove, update, IDSelector, List, Modloader, VersionLevel, |
7 | }; | 7 | }; |
8 | 8 | ||
9 | //TODO implement remote sql db | ||
10 | |||
11 | //TODO make default list optional | 9 | //TODO make default list optional |
12 | #[derive(Parser)] | 10 | #[derive(Parser)] |
13 | #[command(author, version, about)] | 11 | #[command(author, version, about)] |
@@ -18,6 +16,10 @@ struct Cli { | |||
18 | /// config file path | 16 | /// config file path |
19 | #[arg(short, long)] | 17 | #[arg(short, long)] |
20 | config: Option<String>, | 18 | config: Option<String>, |
19 | |||
20 | /// Force GameVersion update | ||
21 | #[arg(long)] | ||
22 | force_gameupdate: bool, | ||
21 | } | 23 | } |
22 | 24 | ||
23 | #[derive(Subcommand)] | 25 | #[derive(Subcommand)] |
@@ -72,6 +74,7 @@ enum Commands { | |||
72 | /// the list you want to export | 74 | /// the list you want to export |
73 | list: Option<String>, | 75 | list: Option<String>, |
74 | }, | 76 | }, |
77 | Test | ||
75 | } | 78 | } |
76 | 79 | ||
77 | #[derive(Subcommand)] | 80 | #[derive(Subcommand)] |
@@ -147,7 +150,7 @@ enum ListCommands { | |||
147 | async fn main() { | 150 | async fn main() { |
148 | let cli = Cli::parse(); | 151 | let cli = Cli::parse(); |
149 | 152 | ||
150 | let config = Cfg::init(cli.config).unwrap(); | 153 | let config = Cfg::init(cli.config).await.unwrap(); |
151 | 154 | ||
152 | match cli.command { | 155 | match cli.command { |
153 | Commands::Mod { command } => { | 156 | Commands::Mod { command } => { |
@@ -201,15 +204,13 @@ async fn main() { | |||
201 | } => { | 204 | } => { |
202 | let ml = match modloader { | 205 | let ml = match modloader { |
203 | Some(ml) => Modloader::from(&ml).unwrap(), | 206 | Some(ml) => Modloader::from(&ml).unwrap(), |
204 | //TODO add default modloader to config | 207 | None => config.clone().defaults.modloader, |
205 | None => Modloader::Fabric, | ||
206 | }; | 208 | }; |
207 | 209 | ||
210 | let versions_path = &config.versions; | ||
208 | let ver = match version { | 211 | let ver = match version { |
209 | Some(ver) => ver, | 212 | Some(ver) => VersionLevel::from(&ver).get(versions_path, cli.force_gameupdate).await.unwrap(), |
210 | //TODO get latest version | 213 | None => config.clone().defaults.version.get(versions_path, cli.force_gameupdate).await.unwrap(), |
211 | //TODO impl config for specific version or latest or latest snap | ||
212 | None => "1.19.4".to_string(), | ||
213 | }; | 214 | }; |
214 | 215 | ||
215 | list_add(config, id, ver, ml, directory) | 216 | list_add(config, id, ver, ml, directory) |
@@ -263,6 +264,7 @@ async fn main() { | |||
263 | import(config, filestr, download).await | 264 | import(config, filestr, download).await |
264 | } | 265 | } |
265 | Commands::Export { list } => export(config, list), | 266 | Commands::Export { list } => export(config, list), |
267 | Commands::Test => Ok(()), | ||
266 | } | 268 | } |
267 | .unwrap(); | 269 | .unwrap(); |
268 | } | 270 | } |