summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/apis/modrinth.rs101
-rw-r--r--src/commands/add.rs34
-rw-r--r--src/commands/mod.rs3
-rw-r--r--src/config.rs23
-rw-r--r--src/db.rs18
-rw-r--r--src/input.rs59
-rw-r--r--src/lib.rs11
-rw-r--r--src/main.rs7
-rw-r--r--src/update.rs8
9 files changed, 227 insertions, 37 deletions
diff --git a/src/apis/modrinth.rs b/src/apis/modrinth.rs
index ce9fdd4..3af5bbd 100644
--- a/src/apis/modrinth.rs
+++ b/src/apis/modrinth.rs
@@ -1,25 +1,6 @@
1use serde::{Deserialize, Serialize}; 1use serde::Deserialize;
2 2
3async fn get(path: String) -> Result<Vec<u8>, Box<dyn std::error::Error>> { 3use crate::Modloader;
4 dbg!(&path);
5 let api = String::from("https://api.modrinth.com/v2/");
6 //let api = String::from("localhost:8080/");
7 //let api = String::from("https://www.rust-lang.org/");
8 let url = format!(r#"{}{}"#, api, path);
9
10 println!("{}", &url);
11
12
13 let data = reqwest::get(r#"https://api.modrinth.com/v2/projects?ids=["kYuIpRLv","89Wsn8GD"]"#)
14 .await?
15 .bytes()
16 .await?
17 .to_vec();
18
19 //println!("body = {:?}", data);
20
21 Ok(data)
22}
23 4
24#[derive(Debug, Deserialize)] 5#[derive(Debug, Deserialize)]
25pub struct Project { 6pub struct Project {
@@ -86,19 +67,89 @@ pub enum Status {
86 processing, 67 processing,
87 unknown 68 unknown
88} 69}
89pub async fn project(name: &str) -> Project { 70
71#[derive(Debug, Deserialize)]
72pub struct Version {
73 pub name: String,
74 pub version_number: String,
75 pub changelog: Option<String>,
76 pub game_versions: Vec<String>,
77 pub version_type: VersionType,
78 pub loaders: Vec<String>,
79 pub featured: bool,
80 pub id: String,
81 pub project_id: String,
82 pub author_id: String,
83 pub date_published: String,
84 pub downloads: u32,
85 pub files: Vec<VersionFile>,
86}
87
88#[allow(non_camel_case_types)]
89#[derive(Debug, Deserialize)]
90pub enum VersionType {
91 release,
92 beta,
93 alpha
94}
95
96#[derive(Debug, Deserialize)]
97pub struct VersionFile {
98 pub hashes: Hash,
99 pub url: String,
100 pub filename: String,
101 pub primary: bool,
102 pub size: u32,
103}
104
105#[derive(Debug, Deserialize)]
106pub struct Hash {
107 pub sha512: String,
108 pub sha1: String,
109}
110
111async fn get(api: String, path: String) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
112 let url = format!(r#"{}{}"#, api, path);
113
114 dbg!(&url);
115
116 let data = reqwest::get(url)
117 .await?
118 .bytes()
119 .await?
120 .to_vec();
121
122 Ok(data)
123}
124
125
126pub async fn project(api: String, name: &str) -> Project {
90 let url = format!("project/{}", name); 127 let url = format!("project/{}", name);
91 let data = get(url); 128 let data = get(api, url);
92 129
93 serde_json::from_slice(&data.await.unwrap()).unwrap() 130 serde_json::from_slice(&data.await.unwrap()).unwrap()
94} 131}
95 132
96pub async fn projects(ids: Vec<&str>) -> Vec<Project> { 133pub async fn projects(api: String, ids: Vec<&str>) -> Vec<Project> {
97 let all = ids.join(r#"",""#); 134 let all = ids.join(r#"",""#);
98 let url = format!(r#"projects?ids=["{}"]"#, all); 135 let url = format!(r#"projects?ids=["{}"]"#, all);
99 println!("{}", url); 136 println!("{}", url);
100 137
101 let data = get(url); 138 let data = get(api, url);
102 139
103 serde_json::from_slice(&data.await.unwrap()).unwrap() 140 serde_json::from_slice(&data.await.unwrap()).unwrap()
104} 141}
142
143pub async fn versions(api: String, id: String, loader: Modloader, mc_version: String) -> Vec<Version> {
144
145 let loaderstr = match loader {
146 Modloader::Forge => String::from("forge"),
147 Modloader::Fabric => String::from("fabric"),
148 };
149
150 let url = format!(r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, id, loaderstr, mc_version);
151
152 let data = get(api, url);
153
154 serde_json::from_slice(&data.await.unwrap()).unwrap()
155}
diff --git a/src/commands/add.rs b/src/commands/add.rs
new file mode 100644
index 0000000..67f63de
--- /dev/null
+++ b/src/commands/add.rs
@@ -0,0 +1,34 @@
1use std::io::{Error, ErrorKind};
2
3use crate::{modrinth::{project, versions}, config::Cfg, db::insert_mod, Modloader};
4
5pub async fn add(config: Cfg, mc_mod: String) -> Result<(), Box<dyn std::error::Error>> {
6 println!("Adding");
7
8 let project = project(String::from(&config.apis.modrinth), &mc_mod).await;
9
10 dbg!(&project);
11
12 let loader = Modloader::Fabric;
13
14 if project.versions.is_empty() { panic!("This should never happen"); };
15
16 let current_version = get_current(config, String::from(&project.id)).await?;
17
18 match insert_mod(project.id, project.title, current_version, project.versions, loader, String::from("1.19.2")) {
19 Err(err) => { Err(Box::new(err)) },
20 Ok(()) => Ok(()),
21 }
22
23}
24
25async fn get_current(config: Cfg, id: String) -> Result<String, Box<dyn std::error::Error>> {
26 let available_versions = versions(config.apis.modrinth, id, Modloader::Fabric, String::from("1.19.2")).await;
27
28 match available_versions.len() {
29 0 => Err(Box::new(Error::new(ErrorKind::NotFound, "NO_VERSIONS_AVAILABLE"))),
30 //TODO compare publish dates
31 1.. => Ok(available_versions[0].id.to_string()),
32 _ => panic!("available_versions should never be negative"),
33 }
34}
diff --git a/src/commands/mod.rs b/src/commands/mod.rs
new file mode 100644
index 0000000..0cc183a
--- /dev/null
+++ b/src/commands/mod.rs
@@ -0,0 +1,3 @@
1pub mod add;
2
3pub use add::*;
diff --git a/src/config.rs b/src/config.rs
new file mode 100644
index 0000000..a0dfbbe
--- /dev/null
+++ b/src/config.rs
@@ -0,0 +1,23 @@
1use config::{Config, File, FileFormat};
2use serde::Deserialize;
3
4#[derive(Debug, Deserialize)]
5pub struct Cfg {
6 pub apis: Apis,
7}
8
9#[derive(Debug, Deserialize)]
10pub struct Apis {
11 pub modrinth: String,
12}
13
14impl Cfg {
15 pub fn init(path: &str) -> Self {
16 Config::builder()
17 .add_source(File::new(path, FileFormat::Ini))
18 .build()
19 .unwrap()
20 .try_deserialize()
21 .unwrap()
22 }
23}
diff --git a/src/db.rs b/src/db.rs
index e69de29..3d50b0f 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -0,0 +1,18 @@
1use crate::Modloader;
2
3pub 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
5 let connection = sqlite::open("./data.db").unwrap();
6
7 let loader = match mod_loader {
8 Modloader::Fabric => "fabric",
9 Modloader::Forge => "forge",
10 };
11
12 let sql = format!("INSERT INTO mods VALUES ('{}', '{}', '{}', '{}', '{}', '{}')", id, name, current_version, old_versions.join("|"), loader, desired_mc_version);
13
14 dbg!(&sql);
15
16 connection.execute(sql)
17
18}
diff --git a/src/input.rs b/src/input.rs
new file mode 100644
index 0000000..689389e
--- /dev/null
+++ b/src/input.rs
@@ -0,0 +1,59 @@
1use std::io::{stdin, Error, ErrorKind};
2use crate::{add, config::Cfg};
3
4pub struct Input {
5 pub command: String,
6 pub args: Option<Vec<String>>,
7}
8
9impl Input {
10 pub fn from(string: String) -> Result<Self, Box<dyn std::error::Error>> {
11 let mut split: Vec<&str> = string.split(' ').collect();
12
13 let command: String;
14 let mut args: Option<Vec<String>> = None;
15
16 if split[0].is_empty() { split.remove(0); };
17
18 dbg!(&split);
19
20 match split.len() {
21 0 => { Err(Box::new(Error::new(ErrorKind::InvalidInput, "NO_ARGS"))) }
22 1 => Ok( Input { command: split[0].to_string(), args }),
23 2.. => {
24 command = split[0].to_string();
25 split.remove(0);
26 let mut str_args: Vec<String> = vec![];
27 for e in split {
28 str_args.push(e.to_string());
29 }
30 args = Some(str_args);
31 Ok(Input { command, args })
32 },
33 _ => { panic!("This should never happen") }
34 }
35
36
37 }
38}
39
40pub async fn get_input(config: Cfg) -> Result<(), Box<dyn std::error::Error>> {
41 let mut user_input = String::new();
42 stdin()
43 .read_line(&mut user_input)
44 .expect("ERROR");
45
46 dbg!(&user_input);
47
48 let input = Input::from(user_input.trim().to_string())?;
49
50 match input.command.as_str() {
51 "add" => {
52 if input.args == None { return Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_FEW_ARGUMENTS"))) };
53 if input.args.as_ref().unwrap().len() != 1 { return Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_MANY_ARGUMENTS"))) };
54 add(config, input.args.unwrap()[0].to_string()).await?;
55 Ok(())
56 },
57 _ => Err(Box::new(Error::new(ErrorKind::InvalidInput, "UNKNOWN_COMMAND"))),
58 }
59}
diff --git a/src/lib.rs b/src/lib.rs
index cbb761c..52b0646 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,13 @@
1pub mod update;
2pub mod apis; 1pub mod apis;
2pub mod config;
3pub mod commands;
4pub mod input;
5pub mod db;
3 6
4pub use apis::*; 7pub use apis::*;
8pub use commands::*;
9
10pub enum Modloader {
11 Fabric,
12 Forge
13}
diff --git a/src/main.rs b/src/main.rs
index 8d1a1bd..957e5aa 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,7 +1,8 @@
1use modlist::modrinth::projects; 1use modlist::{config::Cfg, input::get_input};
2 2
3#[tokio::main] 3#[tokio::main]
4async fn main() { 4async fn main() {
5 //projects(vec!["kYuIpRLv", "89Wsn8GD"]); 5 let config = Cfg::init("config.ini");
6 println!("{:?}", projects(vec!["kYuIpRLv", "89Wsn8GD"]).await); 6 //TODO Error Handling
7 get_input(config).await.unwrap();
7} 8}
diff --git a/src/update.rs b/src/update.rs
deleted file mode 100644
index 2e70f43..0000000
--- a/src/update.rs
+++ /dev/null
@@ -1,8 +0,0 @@
1pub fn update_mods() {
2
3}
4
5fn get_version(link: String) {
6
7
8}