Skip to main content

conduit_cli/core/api/minecraftforge/
mod.rs

1pub mod models;
2
3use crate::errors::{ConduitError, ConduitResult};
4
5use self::models::ForgeMetadata;
6use quick_xml::de::from_str;
7use reqwest::Client;
8
9pub struct ForgeClient {
10    client: Client,
11}
12
13impl Default for ForgeClient {
14    fn default() -> Self {
15        Self {
16            client: Client::new(),
17        }
18    }
19}
20
21impl ForgeClient {
22    pub async fn get_metadata(&self) -> ConduitResult<ForgeMetadata> {
23        let url = "https://maven.minecraftforge.net/net/minecraftforge/forge/maven-metadata.xml";
24        let response = self.client.get(url).send().await?.text().await?;
25
26        let metadata: ForgeMetadata = from_str(&response)
27            .map_err(|e| ConduitError::Deserialize(format!("failed to parse forge xml: {e}")))?;
28
29        Ok(metadata)
30    }
31
32    pub async fn get_latest_version(&self, input_version: &str) -> ConduitResult<String> {
33        let meta = self.get_metadata().await?;
34
35        if meta
36            .versioning
37            .versions
38            .list
39            .iter()
40            .any(|v| v == input_version)
41        {
42            return Ok(input_version.to_string());
43        }
44
45        let prefix = format!("{input_version}-");
46
47        meta.versioning
48            .versions
49            .list
50            .into_iter()
51            .rev()
52            .find(|v| v.starts_with(&prefix))
53            .ok_or_else(|| {
54                ConduitError::NotFound(format!("no forge version found for {input_version}"))
55            })
56    }
57    pub fn build_bin_url(&self, version: &str, classifier: &str) -> String {
58        let base = "https://maven.minecraftforge.net/net/minecraftforge/forge";
59        format!("{base}/{version}/forge-{version}-{classifier}.jar")
60    }
61}