From fc1cb1acc0dce412e948475002666bcd1d4b0348 Mon Sep 17 00:00:00 2001 From: fxqnlr Date: Mon, 31 Oct 2022 22:41:18 +0100 Subject: add first impl --- src/apis/modrinth.rs | 101 ++++++++++++++++++++++++++++++++++++++------------- src/commands/add.rs | 34 +++++++++++++++++ src/commands/mod.rs | 3 ++ src/config.rs | 23 ++++++++++++ src/db.rs | 18 +++++++++ src/input.rs | 59 ++++++++++++++++++++++++++++++ src/lib.rs | 11 +++++- src/main.rs | 7 ++-- src/update.rs | 8 ---- 9 files changed, 227 insertions(+), 37 deletions(-) create mode 100644 src/commands/add.rs create mode 100644 src/commands/mod.rs create mode 100644 src/config.rs create mode 100644 src/input.rs delete mode 100644 src/update.rs (limited to 'src') 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 @@ -use serde::{Deserialize, Serialize}; +use serde::Deserialize; -async fn get(path: String) -> Result, Box> { - dbg!(&path); - let api = String::from("https://api.modrinth.com/v2/"); - //let api = String::from("localhost:8080/"); - //let api = String::from("https://www.rust-lang.org/"); - let url = format!(r#"{}{}"#, api, path); - - println!("{}", &url); - - - let data = reqwest::get(r#"https://api.modrinth.com/v2/projects?ids=["kYuIpRLv","89Wsn8GD"]"#) - .await? - .bytes() - .await? - .to_vec(); - - //println!("body = {:?}", data); - - Ok(data) -} +use crate::Modloader; #[derive(Debug, Deserialize)] pub struct Project { @@ -86,19 +67,89 @@ pub enum Status { processing, unknown } -pub async fn project(name: &str) -> Project { + +#[derive(Debug, Deserialize)] +pub struct Version { + pub name: String, + pub version_number: String, + pub changelog: Option, + pub game_versions: Vec, + pub version_type: VersionType, + pub loaders: Vec, + pub featured: bool, + pub id: String, + pub project_id: String, + pub author_id: String, + pub date_published: String, + pub downloads: u32, + pub files: Vec, +} + +#[allow(non_camel_case_types)] +#[derive(Debug, Deserialize)] +pub enum VersionType { + release, + beta, + alpha +} + +#[derive(Debug, Deserialize)] +pub struct VersionFile { + pub hashes: Hash, + pub url: String, + pub filename: String, + pub primary: bool, + pub size: u32, +} + +#[derive(Debug, Deserialize)] +pub struct Hash { + pub sha512: String, + pub sha1: String, +} + +async fn get(api: String, path: String) -> Result, Box> { + let url = format!(r#"{}{}"#, api, path); + + dbg!(&url); + + let data = reqwest::get(url) + .await? + .bytes() + .await? + .to_vec(); + + Ok(data) +} + + +pub async fn project(api: String, name: &str) -> Project { let url = format!("project/{}", name); - let data = get(url); + let data = get(api, url); serde_json::from_slice(&data.await.unwrap()).unwrap() } -pub async fn projects(ids: Vec<&str>) -> Vec { +pub async fn projects(api: String, ids: Vec<&str>) -> Vec { let all = ids.join(r#"",""#); let url = format!(r#"projects?ids=["{}"]"#, all); println!("{}", url); - let data = get(url); + let data = get(api, url); serde_json::from_slice(&data.await.unwrap()).unwrap() } + +pub async fn versions(api: String, id: String, loader: Modloader, mc_version: String) -> Vec { + + let loaderstr = match loader { + Modloader::Forge => String::from("forge"), + Modloader::Fabric => String::from("fabric"), + }; + + let url = format!(r#"project/{}/version?loaders=["{}"]&game_versions=["{}"]"#, id, loaderstr, mc_version); + + let data = get(api, url); + + serde_json::from_slice(&data.await.unwrap()).unwrap() +} 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 @@ +use std::io::{Error, ErrorKind}; + +use crate::{modrinth::{project, versions}, config::Cfg, db::insert_mod, Modloader}; + +pub async fn add(config: Cfg, mc_mod: String) -> Result<(), Box> { + println!("Adding"); + + let project = project(String::from(&config.apis.modrinth), &mc_mod).await; + + dbg!(&project); + + let loader = Modloader::Fabric; + + if project.versions.is_empty() { panic!("This should never happen"); }; + + let current_version = get_current(config, String::from(&project.id)).await?; + + match insert_mod(project.id, project.title, current_version, project.versions, loader, String::from("1.19.2")) { + Err(err) => { Err(Box::new(err)) }, + Ok(()) => Ok(()), + } + +} + +async fn get_current(config: Cfg, id: String) -> Result> { + let available_versions = versions(config.apis.modrinth, id, Modloader::Fabric, String::from("1.19.2")).await; + + match available_versions.len() { + 0 => Err(Box::new(Error::new(ErrorKind::NotFound, "NO_VERSIONS_AVAILABLE"))), + //TODO compare publish dates + 1.. => Ok(available_versions[0].id.to_string()), + _ => panic!("available_versions should never be negative"), + } +} 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 @@ +pub mod add; + +pub 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 @@ +use config::{Config, File, FileFormat}; +use serde::Deserialize; + +#[derive(Debug, Deserialize)] +pub struct Cfg { + pub apis: Apis, +} + +#[derive(Debug, Deserialize)] +pub struct Apis { + pub modrinth: String, +} + +impl Cfg { + pub fn init(path: &str) -> Self { + Config::builder() + .add_source(File::new(path, FileFormat::Ini)) + .build() + .unwrap() + .try_deserialize() + .unwrap() + } +} 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 @@ +use crate::Modloader; + +pub fn insert_mod(id: String, name: String, current_version: String, old_versions: Vec, mod_loader: Modloader, desired_mc_version: String) -> Result<(), sqlite::Error> { + + let connection = sqlite::open("./data.db").unwrap(); + + let loader = match mod_loader { + Modloader::Fabric => "fabric", + Modloader::Forge => "forge", + }; + + let sql = format!("INSERT INTO mods VALUES ('{}', '{}', '{}', '{}', '{}', '{}')", id, name, current_version, old_versions.join("|"), loader, desired_mc_version); + + dbg!(&sql); + + connection.execute(sql) + +} 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 @@ +use std::io::{stdin, Error, ErrorKind}; +use crate::{add, config::Cfg}; + +pub struct Input { + pub command: String, + pub args: Option>, +} + +impl Input { + pub fn from(string: String) -> Result> { + let mut split: Vec<&str> = string.split(' ').collect(); + + let command: String; + let mut args: Option> = None; + + if split[0].is_empty() { split.remove(0); }; + + dbg!(&split); + + match split.len() { + 0 => { Err(Box::new(Error::new(ErrorKind::InvalidInput, "NO_ARGS"))) } + 1 => Ok( Input { command: split[0].to_string(), args }), + 2.. => { + command = split[0].to_string(); + split.remove(0); + let mut str_args: Vec = vec![]; + for e in split { + str_args.push(e.to_string()); + } + args = Some(str_args); + Ok(Input { command, args }) + }, + _ => { panic!("This should never happen") } + } + + + } +} + +pub async fn get_input(config: Cfg) -> Result<(), Box> { + let mut user_input = String::new(); + stdin() + .read_line(&mut user_input) + .expect("ERROR"); + + dbg!(&user_input); + + let input = Input::from(user_input.trim().to_string())?; + + match input.command.as_str() { + "add" => { + if input.args == None { return Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_FEW_ARGUMENTS"))) }; + if input.args.as_ref().unwrap().len() != 1 { return Err(Box::new(Error::new(ErrorKind::InvalidInput, "TOO_MANY_ARGUMENTS"))) }; + add(config, input.args.unwrap()[0].to_string()).await?; + Ok(()) + }, + _ => Err(Box::new(Error::new(ErrorKind::InvalidInput, "UNKNOWN_COMMAND"))), + } +} 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 @@ -pub mod update; pub mod apis; +pub mod config; +pub mod commands; +pub mod input; +pub mod db; pub use apis::*; +pub use commands::*; + +pub enum Modloader { + Fabric, + Forge +} 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 @@ -use modlist::modrinth::projects; +use modlist::{config::Cfg, input::get_input}; #[tokio::main] async fn main() { - //projects(vec!["kYuIpRLv", "89Wsn8GD"]); - println!("{:?}", projects(vec!["kYuIpRLv", "89Wsn8GD"]).await); + let config = Cfg::init("config.ini"); + //TODO Error Handling + get_input(config).await.unwrap(); } 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 @@ -pub fn update_mods() { - -} - -fn get_version(link: String) { - - -} -- cgit v1.2.3