diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/commands/add.rs | 28 | ||||
-rw-r--r-- | src/commands/list.rs | 80 | ||||
-rw-r--r-- | src/commands/mod.rs | 2 | ||||
-rw-r--r-- | src/config.rs | 6 | ||||
-rw-r--r-- | src/db.rs | 87 | ||||
-rw-r--r-- | src/input.rs | 12 | ||||
-rw-r--r-- | src/lib.rs | 1 |
7 files changed, 199 insertions, 17 deletions
diff --git a/src/commands/add.rs b/src/commands/add.rs index 67f63de..ed4a6d8 100644 --- a/src/commands/add.rs +++ b/src/commands/add.rs | |||
@@ -1,11 +1,28 @@ | |||
1 | use std::io::{Error, ErrorKind}; | 1 | use std::io::{Error, ErrorKind}; |
2 | 2 | ||
3 | use crate::{modrinth::{project, versions}, config::Cfg, db::insert_mod, Modloader}; | 3 | use crate::{modrinth::{project, versions}, config::Cfg, db::insert_mod, Modloader, input::Input}; |
4 | 4 | ||
5 | pub async fn add(config: Cfg, mc_mod: String) -> Result<(), Box<dyn std::error::Error>> { | 5 | pub async fn modification(config: Cfg, args: Option<Vec<String>>) -> Result<(), Box<dyn std::error::Error>> { |
6 | println!("Adding"); | ||
7 | 6 | ||
8 | let project = project(String::from(&config.apis.modrinth), &mc_mod).await; | 7 | if args.is_none() { return Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_FEW_ARGUMENTS"))) } |
8 | |||
9 | let arguments = Input::from(args.unwrap().join(" "))?; | ||
10 | |||
11 | if arguments.args.is_none() { return Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_FEW_ARGUMENTS"))); }; | ||
12 | |||
13 | match arguments.command.as_str() { | ||
14 | "add" => { | ||
15 | add(config, arguments.args.unwrap()).await | ||
16 | }, | ||
17 | _ => Err(Box::new(Error::new(ErrorKind::InvalidInput, "UNKNOWN_SUBCOMMAND"))) | ||
18 | } | ||
19 | } | ||
20 | |||
21 | pub async fn add(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>> { | ||
22 | |||
23 | if args.len() < 1 { return Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_FEW_ARGUMENTS"))); }; | ||
24 | |||
25 | let project = project(String::from(&config.apis.modrinth), &args[0]).await; | ||
9 | 26 | ||
10 | dbg!(&project); | 27 | dbg!(&project); |
11 | 28 | ||
@@ -14,7 +31,8 @@ pub async fn add(config: Cfg, mc_mod: String) -> Result<(), Box<dyn std::error:: | |||
14 | if project.versions.is_empty() { panic!("This should never happen"); }; | 31 | if project.versions.is_empty() { panic!("This should never happen"); }; |
15 | 32 | ||
16 | let current_version = get_current(config, String::from(&project.id)).await?; | 33 | let current_version = get_current(config, String::from(&project.id)).await?; |
17 | 34 | ||
35 | //add to current list and mod table | ||
18 | match insert_mod(project.id, project.title, current_version, project.versions, loader, String::from("1.19.2")) { | 36 | match insert_mod(project.id, project.title, current_version, project.versions, loader, String::from("1.19.2")) { |
19 | Err(err) => { Err(Box::new(err)) }, | 37 | Err(err) => { Err(Box::new(err)) }, |
20 | Ok(()) => Ok(()), | 38 | Ok(()) => Ok(()), |
diff --git a/src/commands/list.rs b/src/commands/list.rs new file mode 100644 index 0000000..6c260ce --- /dev/null +++ b/src/commands/list.rs | |||
@@ -0,0 +1,80 @@ | |||
1 | use std::io::{Error, ErrorKind}; | ||
2 | |||
3 | use crate::{db::{insert_list, remove_list, change_list, get_lists, get_current_list}, Modloader, config::Cfg, input::Input}; | ||
4 | |||
5 | pub fn list(config: Cfg, args: Option<Vec<String>>) -> Result<(), Box<dyn std::error::Error>> { | ||
6 | |||
7 | if args.is_none() { | ||
8 | let lists = get_lists(config.clone())?; | ||
9 | let current_list = get_current_list(config)?; | ||
10 | println!("Your lists:\n{}\n-----\nCurrently selected list: \"{}\"", lists.join(",\n"), current_list); | ||
11 | return Ok(()); | ||
12 | } | ||
13 | |||
14 | let arguments = Input::from(args.unwrap().join(" "))?; | ||
15 | |||
16 | if arguments.args.is_none() { return Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_FEW_ARGUMENTS"))); }; | ||
17 | |||
18 | match arguments.command.as_str() { | ||
19 | "add" => { | ||
20 | add(config, arguments.args.unwrap()) | ||
21 | }, | ||
22 | "change" => { | ||
23 | change(config, arguments.args.unwrap()) | ||
24 | }, | ||
25 | "remove" => { | ||
26 | remove(config, arguments.args.unwrap()) | ||
27 | }, | ||
28 | _ => Err(Box::new(Error::new(ErrorKind::InvalidInput, "UNKNOWN_SUBCOMMAND"))) | ||
29 | } | ||
30 | } | ||
31 | |||
32 | fn add(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>> { | ||
33 | match args.len() { | ||
34 | 1 | 2 => Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_FEW_ARGUMENTS"))), | ||
35 | 3 => { | ||
36 | let id = String::from(&args[0]); | ||
37 | let mc_version = String::from(&args[1]); | ||
38 | let mod_loader = match args[2].as_str() { | ||
39 | "forge" => Modloader::Forge, | ||
40 | "fabric" => Modloader::Fabric, | ||
41 | _ => return Err(Box::new(Error::new(ErrorKind::InvalidInput, "UNKNOWN_MODLOADER"))) | ||
42 | }; | ||
43 | match insert_list(config, id, mc_version, mod_loader) { | ||
44 | Err(err) => { Err(Box::new(err)) }, | ||
45 | Ok(()) => Ok(()), | ||
46 | } | ||
47 | }, | ||
48 | 5.. => Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_MANY_ARGUMENTS"))), | ||
49 | _ => panic!("list arguments should never be zero or lower"), | ||
50 | } | ||
51 | } | ||
52 | |||
53 | fn change(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>> { | ||
54 | let lists = get_lists(config.clone())?; | ||
55 | match args.len() { | ||
56 | 1 => { | ||
57 | let list = String::from(&args[0]); | ||
58 | if !lists.contains(&list) { return Err(Box::new(Error::new(ErrorKind::NotFound, "LIST_DOESNT_EXIST"))); }; | ||
59 | match change_list(config, list) { | ||
60 | Err(err) => { Err(Box::new(err)) }, | ||
61 | Ok(()) => Ok(()), | ||
62 | } | ||
63 | }, | ||
64 | 2.. => Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_MANY_ARGUMENTS"))), | ||
65 | _ => panic!("list arguments should never be zero or lower"), | ||
66 | } | ||
67 | } | ||
68 | |||
69 | fn remove(config: Cfg, args: Vec<String>) -> Result<(), Box<dyn std::error::Error>> { | ||
70 | match args.len() { | ||
71 | 1 => { | ||
72 | match remove_list(config, String::from(&args[0])) { | ||
73 | Err(err) => { Err(Box::new(err)) }, | ||
74 | Ok(()) => Ok(()), | ||
75 | } | ||
76 | }, | ||
77 | 2.. => Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_MANY_ARGUMENTS"))), | ||
78 | _ => panic!("list arguments should never be zero or lower"), | ||
79 | } | ||
80 | } | ||
diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 0cc183a..6432746 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | pub mod add; | 1 | pub mod add; |
2 | pub mod list; | ||
2 | 3 | ||
3 | pub use add::*; | 4 | pub use add::*; |
5 | pub use list::*; | ||
diff --git a/src/config.rs b/src/config.rs index a0dfbbe..ba1b46a 100644 --- a/src/config.rs +++ b/src/config.rs | |||
@@ -1,18 +1,20 @@ | |||
1 | use config::{Config, File, FileFormat}; | 1 | use config::{Config, File, FileFormat}; |
2 | use serde::Deserialize; | 2 | use serde::Deserialize; |
3 | 3 | ||
4 | #[derive(Debug, Deserialize)] | 4 | #[derive(Debug, Clone,Deserialize)] |
5 | pub struct Cfg { | 5 | pub struct Cfg { |
6 | pub data: String, | ||
6 | pub apis: Apis, | 7 | pub apis: Apis, |
7 | } | 8 | } |
8 | 9 | ||
9 | #[derive(Debug, Deserialize)] | 10 | #[derive(Debug, Clone, Deserialize)] |
10 | pub struct Apis { | 11 | pub struct Apis { |
11 | pub modrinth: String, | 12 | pub modrinth: String, |
12 | } | 13 | } |
13 | 14 | ||
14 | impl Cfg { | 15 | impl Cfg { |
15 | pub fn init(path: &str) -> Self { | 16 | pub fn init(path: &str) -> Self { |
17 | //TODO Error Handling | ||
16 | Config::builder() | 18 | Config::builder() |
17 | .add_source(File::new(path, FileFormat::Ini)) | 19 | .add_source(File::new(path, FileFormat::Ini)) |
18 | .build() | 20 | .build() |
@@ -1,4 +1,8 @@ | |||
1 | use crate::Modloader; | 1 | use std::io::ErrorKind; |
2 | |||
3 | use crate::{Modloader, config::Cfg}; | ||
4 | |||
5 | //TODO use prepared statements | ||
2 | 6 | ||
3 | pub fn insert_mod(id: String, name: String, current_version: String, old_versions: Vec<String>, mod_loader: Modloader, desired_mc_version: String) -> Result<(), sqlite::Error> { | 7 | pub fn insert_mod(id: String, name: String, current_version: String, old_versions: Vec<String>, mod_loader: Modloader, desired_mc_version: String) -> Result<(), sqlite::Error> { |
4 | 8 | ||
@@ -10,9 +14,88 @@ pub fn insert_mod(id: String, name: String, current_version: String, old_version | |||
10 | }; | 14 | }; |
11 | 15 | ||
12 | let sql = format!("INSERT INTO mods VALUES ('{}', '{}', '{}', '{}', '{}', '{}')", id, name, current_version, old_versions.join("|"), loader, desired_mc_version); | 16 | let sql = format!("INSERT INTO mods VALUES ('{}', '{}', '{}', '{}', '{}', '{}')", id, name, current_version, old_versions.join("|"), loader, desired_mc_version); |
17 | |||
18 | connection.execute(sql) | ||
19 | } | ||
20 | |||
21 | //LIST | ||
22 | pub fn insert_list(config: Cfg, id: String, mc_version: String, mod_loader: Modloader) -> Result<(), sqlite::Error> { | ||
23 | let data = format!("{}/data.db", config.data); | ||
24 | let connection = sqlite::open(data).unwrap(); | ||
13 | 25 | ||
14 | dbg!(&sql); | 26 | //Setup list in table |
27 | let loader = match mod_loader { | ||
28 | Modloader::Fabric => "fabric", | ||
29 | Modloader::Forge => "forge", | ||
30 | }; | ||
31 | |||
32 | let sql_list = format!("INSERT INTO lists VALUES ('{}', '{}', '{}')", id, mc_version, loader); | ||
33 | let sql_table = format!("CREATE TABLE '{}' ( 'mod_id' TEXT, 'current_version' TEXT, 'applicable_versions' BLOB, 'mod_loader' TEXT )", id); | ||
34 | let sql = format!("{};{};", sql_list, sql_table); | ||
15 | 35 | ||
16 | connection.execute(sql) | 36 | connection.execute(sql) |
37 | } | ||
17 | 38 | ||
39 | pub fn remove_list(config: Cfg, id: String) -> Result<(), sqlite::Error> { | ||
40 | let data = format!("{}/data.db", config.data); | ||
41 | let connection = sqlite::open(data).unwrap(); | ||
42 | |||
43 | let sql_list = format!("DELETE FROM lists WHERE id = '{}'", id); | ||
44 | let sql_table = format!("DROP TABLE '{}'", id); | ||
45 | let sql = format!("{};{};", sql_list, sql_table); | ||
46 | |||
47 | connection.execute(sql) | ||
48 | } | ||
49 | |||
50 | pub fn get_lists(config: Cfg) -> Result<Vec<String>, Box<dyn std::error::Error>> { | ||
51 | let data = format!("{}/data.db", config.data); | ||
52 | let connection = sqlite::open(data).unwrap(); | ||
53 | |||
54 | let sql = "SELECT id FROM lists"; | ||
55 | |||
56 | let mut list: Vec<String> = Vec::new(); | ||
57 | //TODO catch sql errors better | ||
58 | connection.iterate(sql, |ids| { | ||
59 | if ids.is_empty() { return false; }; | ||
60 | for &(_column, value) in ids.iter() { | ||
61 | list.push(String::from(value.unwrap())); | ||
62 | } | ||
63 | true | ||
64 | }).unwrap(); | ||
65 | match list.is_empty() { | ||
66 | true => Err(Box::new(std::io::Error::new(ErrorKind::NotFound, "NO_LISTS"))), | ||
67 | false => Ok(list), | ||
68 | } | ||
69 | } | ||
70 | |||
71 | //config | ||
72 | pub fn change_list(config: Cfg, id: String) -> Result<(), sqlite::Error> { | ||
73 | let data = format!("{}/data.db", config.data); | ||
74 | let connection = sqlite::open(data).unwrap(); | ||
75 | |||
76 | let sql = format!("UPDATE user_config SET value = '{}' WHERE id = 'current_list'", id); | ||
77 | |||
78 | connection.execute(sql) | ||
79 | } | ||
80 | |||
81 | pub fn get_current_list(config: Cfg) -> Result<String, Box<dyn std::error::Error>> { | ||
82 | let data = format!("{}/data.db", config.data); | ||
83 | let connection = sqlite::open(data).unwrap(); | ||
84 | |||
85 | let sql = "SELECT id FROM lists"; | ||
86 | |||
87 | let mut list: String = String::new(); | ||
88 | //TODO catch sql errors better | ||
89 | connection.iterate(sql, |ids| { | ||
90 | if ids.is_empty() { return false; }; | ||
91 | for &(_column, value) in ids.iter() { | ||
92 | list = String::from(value.unwrap()); | ||
93 | } | ||
94 | true | ||
95 | }).unwrap(); | ||
96 | if list.is_empty() { | ||
97 | get_lists(config)?; | ||
98 | panic!("current list field should never be empty if there are other lists"); | ||
99 | }; | ||
100 | Ok(list) | ||
18 | } | 101 | } |
diff --git a/src/input.rs b/src/input.rs index 689389e..061f1fd 100644 --- a/src/input.rs +++ b/src/input.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use std::io::{stdin, Error, ErrorKind}; | 1 | use std::io::{stdin, Error, ErrorKind}; |
2 | use crate::{add, config::Cfg}; | 2 | use crate::{add, config::Cfg, list}; |
3 | 3 | ||
4 | pub struct Input { | 4 | pub struct Input { |
5 | pub command: String, | 5 | pub command: String, |
@@ -9,14 +9,9 @@ pub struct Input { | |||
9 | impl Input { | 9 | impl Input { |
10 | pub fn from(string: String) -> Result<Self, Box<dyn std::error::Error>> { | 10 | pub fn from(string: String) -> Result<Self, Box<dyn std::error::Error>> { |
11 | let mut split: Vec<&str> = string.split(' ').collect(); | 11 | let mut split: Vec<&str> = string.split(' ').collect(); |
12 | |||
13 | let command: String; | 12 | let command: String; |
14 | let mut args: Option<Vec<String>> = None; | 13 | let mut args: Option<Vec<String>> = None; |
15 | |||
16 | if split[0].is_empty() { split.remove(0); }; | 14 | if split[0].is_empty() { split.remove(0); }; |
17 | |||
18 | dbg!(&split); | ||
19 | |||
20 | match split.len() { | 15 | match split.len() { |
21 | 0 => { Err(Box::new(Error::new(ErrorKind::InvalidInput, "NO_ARGS"))) } | 16 | 0 => { Err(Box::new(Error::new(ErrorKind::InvalidInput, "NO_ARGS"))) } |
22 | 1 => Ok( Input { command: split[0].to_string(), args }), | 17 | 1 => Ok( Input { command: split[0].to_string(), args }), |
@@ -43,8 +38,6 @@ pub async fn get_input(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { | |||
43 | .read_line(&mut user_input) | 38 | .read_line(&mut user_input) |
44 | .expect("ERROR"); | 39 | .expect("ERROR"); |
45 | 40 | ||
46 | dbg!(&user_input); | ||
47 | |||
48 | let input = Input::from(user_input.trim().to_string())?; | 41 | let input = Input::from(user_input.trim().to_string())?; |
49 | 42 | ||
50 | match input.command.as_str() { | 43 | match input.command.as_str() { |
@@ -54,6 +47,9 @@ pub async fn get_input(config: Cfg) -> Result<(), Box<dyn std::error::Error>> { | |||
54 | add(config, input.args.unwrap()[0].to_string()).await?; | 47 | add(config, input.args.unwrap()[0].to_string()).await?; |
55 | Ok(()) | 48 | Ok(()) |
56 | }, | 49 | }, |
50 | "list" => { | ||
51 | list(config, input.args) | ||
52 | }, | ||
57 | _ => Err(Box::new(Error::new(ErrorKind::InvalidInput, "UNKNOWN_COMMAND"))), | 53 | _ => Err(Box::new(Error::new(ErrorKind::InvalidInput, "UNKNOWN_COMMAND"))), |
58 | } | 54 | } |
59 | } | 55 | } |
@@ -7,6 +7,7 @@ pub mod db; | |||
7 | pub use apis::*; | 7 | pub use apis::*; |
8 | pub use commands::*; | 8 | pub use commands::*; |
9 | 9 | ||
10 | #[derive(Debug)] | ||
10 | pub enum Modloader { | 11 | pub enum Modloader { |
11 | Fabric, | 12 | Fabric, |
12 | Forge | 13 | Forge |