diff --git a/papermc-api/src/lib.rs b/papermc-api/src/lib.rs index dbb0cf9..d9881c8 100644 --- a/papermc-api/src/lib.rs +++ b/papermc-api/src/lib.rs @@ -1,9 +1,8 @@ use serde_json::Value; -use crate::{ - error::Error, - models::{Build, BuildCommit, BuildDownload, Java, Project, Version}, -}; +pub use error::Error; + +use crate::models::{Build, BuildCommit, BuildDownload, Java, Project, Version}; mod error; mod models; @@ -26,33 +25,7 @@ impl Client { let body_json: Value = res.body_mut().read_json()?; let projects = body_json["projects"].as_array().ok_or(Error::BadBody)?; - projects - .into_iter() - .map(|p| { - Ok(Project { - id: p["project"]["id"] - .as_str() - .map(|s| s.to_string()) - .ok_or(Error::BadBody)?, - name: p["project"]["name"] - .as_str() - .map(|s| s.to_string()) - .ok_or(Error::BadBody)?, - // Flatten map of versions into one array - versions: p["versions"] - .as_object() - .ok_or(Error::BadBody)? - .into_iter() - .map(|(_, versions)| versions.as_array().ok_or(Error::BadBody)) - // Collect into error to propagate error of any of the versions - .collect::, _>>()? - .into_iter() - .flatten() - .map(|v| v.as_str().ok_or(Error::BadBody).map(|s| s.to_string())) - .collect::>()?, - }) - }) - .collect() + projects.into_iter().map(parse_project_json).collect() } pub fn project<'a>(&'a self, project: &'a str) -> ProjectQuery<'a> { @@ -69,6 +42,16 @@ pub struct ProjectQuery<'a> { } impl<'a> ProjectQuery<'a> { + pub fn info(&self) -> Result { + let mut res = self + .agent + .get(format!("{}/projects/{}", BASE_URL, self.project)) + .call()?; + let body_json: Value = res.body_mut().read_json()?; + + parse_project_json(&body_json) + } + pub fn versions(&self) -> Result, Error> { let mut res = self .agent @@ -77,39 +60,7 @@ impl<'a> ProjectQuery<'a> { let body_json: Value = res.body_mut().read_json()?; let versions = body_json["versions"].as_array().ok_or(Error::BadBody)?; - versions - .into_iter() - .map(|v| { - Ok(Version { - id: v["version"]["id"] - .as_str() - .map(String::from) - .ok_or(Error::BadBody)?, - support_status: v["version"]["support"]["status"] - .as_str() - .ok_or(Error::BadBody)? - .parse() - .map_err(|_| Error::BadBody)?, - java: Java { - minimum_version: v["version"]["java"]["version"]["minimum"] - .as_u64() - .ok_or(Error::BadBody)?, - recommended_flags: v["version"]["java"]["flags"]["recommended"] - .as_array() - .ok_or(Error::BadBody)? - .into_iter() - .map(|v| v.as_str().map(String::from).ok_or(Error::BadBody)) - .collect::>()?, - }, - builds: v["builds"] - .as_array() - .ok_or(Error::BadBody)? - .into_iter() - .map(|v| v.as_u64().ok_or(Error::BadBody)) - .collect::>()?, - }) - }) - .collect() + versions.into_iter().map(parse_version_json).collect() } pub fn version(&self, version: &'a str) -> VersionQuery<'a> { @@ -128,17 +79,17 @@ pub struct VersionQuery<'a> { } impl<'a> VersionQuery<'a> { - pub fn latest(&self) -> Result { + pub fn info(&self) -> Result { let mut res = self .agent .get(format!( - "{}/projects/{}/versions/{}/builds/latest", + "{}/projects/{}/versions/{}", BASE_URL, self.project, self.version )) .call()?; let body_json: Value = res.body_mut().read_json()?; - parse_build_json(&body_json) + parse_version_json(&body_json) } pub fn builds(&self) -> Result, Error> { @@ -158,6 +109,79 @@ impl<'a> VersionQuery<'a> { .map(parse_build_json) .collect() } + + pub fn build(&self, build: &str) -> Result { + let mut res = self + .agent + .get(format!( + "{}/projects/{}/versions/{}/builds/{}", + BASE_URL, self.project, self.version, build + )) + .call()?; + let body_json: Value = res.body_mut().read_json()?; + + parse_build_json(&body_json) + } + + pub fn latest(&self) -> Result { + return self.build("latest"); + } +} + +fn parse_project_json(value: &Value) -> Result { + Ok(Project { + id: value["project"]["id"] + .as_str() + .map(|s| s.to_string()) + .ok_or(Error::BadBody)?, + name: value["project"]["name"] + .as_str() + .map(|s| s.to_string()) + .ok_or(Error::BadBody)?, + // Flatten map of versions into one array + versions: value["versions"] + .as_object() + .ok_or(Error::BadBody)? + .into_iter() + .map(|(_, versions)| versions.as_array().ok_or(Error::BadBody)) + // Collect into error to propagate error of any of the versions + .collect::, _>>()? + .into_iter() + .flatten() + .map(|v| v.as_str().ok_or(Error::BadBody).map(|s| s.to_string())) + .collect::>()?, + }) +} + +fn parse_version_json(value: &Value) -> Result { + Ok(Version { + id: value["version"]["id"] + .as_str() + .map(String::from) + .ok_or(Error::BadBody)?, + support_status: value["version"]["support"]["status"] + .as_str() + .ok_or(Error::BadBody)? + .parse() + .map_err(|_| Error::BadBody)?, + java: Java { + minimum_version: value["version"]["java"]["version"]["minimum"] + .as_u64() + .ok_or(Error::BadBody)?, + recommended_flags: value["version"]["java"]["flags"]["recommended"] + .as_array() + .ok_or(Error::BadBody)? + .into_iter() + .map(|v| v.as_str().map(String::from).ok_or(Error::BadBody)) + .collect::>()?, + }, + builds: value["builds"] + .as_array() + .ok_or(Error::BadBody)? + .into_iter() + .map(|v| v.as_u64().ok_or(Error::BadBody)) + .collect::>()?, + }) } fn parse_build_json(value: &Value) -> Result { diff --git a/papermc-api/src/models.rs b/papermc-api/src/models.rs index c73ecf9..c28f7e9 100644 --- a/papermc-api/src/models.rs +++ b/papermc-api/src/models.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, str::FromStr}; +use std::{collections::HashMap, fmt::Display, str::FromStr}; use chrono::{DateTime, Utc}; @@ -29,6 +29,15 @@ impl FromStr for SupportStatus { } } +impl Display for SupportStatus { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Supported => f.write_str("SUPPORTED"), + Self::Unsupported => f.write_str("UNSUPPORTED"), + } + } +} + #[derive(Debug)] pub struct Java { pub minimum_version: u64, @@ -74,6 +83,16 @@ impl FromStr for BuildChannel { } } +impl Display for BuildChannel { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Alpha => f.write_str("ALPHA"), + Self::Beta => f.write_str("BETA"), + Self::Stable => f.write_str("STABLE"), + } + } +} + #[derive(Debug)] pub struct BuildCommit { pub sha: String,