1use serde::{Serialize, Deserialize};
2
3use crate::{minecraft::modloader::ModLoaderType, errors::CreatorError};
4
5use super::{CurseApi, CURSE_API_URL};
6
7#[derive(Debug, Deserialize, Serialize)]
11pub struct FilesModResponse {
12 #[serde(rename = "data")]
13 pub data: DataFiles,
14}
15
16#[derive(Debug, Deserialize, Serialize)]
20pub struct DataFiles {
21 #[serde(rename = "latestFilesIndexes")]
22 pub latest_files_indexes: Vec<ModFiles>,
23}
24
25#[derive(Debug, Deserialize, Serialize)]
29pub struct ModFiles {
30 #[serde(rename = "fileId")]
31 pub file_id: isize,
32 #[serde(rename = "gameVersion")]
33 pub game_version: String,
34}
35
36#[derive(Debug, Deserialize, Serialize)]
40pub struct SearchModResponse {
41 #[serde(rename = "data")]
42 pub data: Vec<DataMods>,
43}
44
45#[derive(Debug, Deserialize, Serialize)]
49pub struct DataMods {
50 pub id: isize,
51 pub name: String,
52}
53
54#[derive(Debug, Deserialize, Serialize)]
56pub enum SearchSortField {
57 #[serde(rename = "featured")]
58 Featured,
59 #[serde(rename = "popularity")]
60 Popularity,
61 #[serde(rename = "lastupdated")]
62 LastUpdated,
63 #[serde(rename = "name")]
64 Name,
65 #[serde(rename = "author")]
66 Author,
67 #[serde(rename = "totaldownloads")]
68 TotalDownloads,
69 #[serde(rename = "category")]
70 Category,
71 #[serde(rename = "game_version")]
72 GameVersion,
73}
74
75#[derive(Debug, Deserialize, Serialize)]
79pub struct SearchMod {
80 #[serde(rename = "gameId")]
81 pub game_id: isize,
82 #[serde(rename = "gameVersion")]
83 pub game_version: Option<String>,
84 #[serde(rename = "searchFilter")]
85 pub search_filter: Option<String>,
86 #[serde(rename = "modLoaderType")]
87 pub mod_loader_type: Option<ModLoaderType>,
88 #[serde(rename = "sortField")]
89 pub sort_field: Option<SearchSortField>,
90}
91
92
93#[derive(Clone, Debug, Deserialize, Serialize)]
97pub struct CurseMod {
98 pub name: String,
99 pub mod_id: isize,
100 pub file_id: isize,
101}
102
103impl CurseApi {
104 pub async fn search_mod<T: ToString>(&self, search_query: T, mc_version: String, mod_loader: ModLoaderType)
116 -> Result<SearchModResponse, CreatorError>
117 where
118 T: Into<String>,
119 {
120 let url = format!("{}{}", CURSE_API_URL, "mods/search");
121
122 let query = SearchMod {
123 game_id: 432,
124 game_version: Some(mc_version),
125 search_filter: Some(search_query.into()),
126 mod_loader_type: Some(mod_loader),
127 sort_field: Some(SearchSortField::Name),
128 };
129
130 let response = self.http_client.get(&url).query(&query).send().await?;
131
132 Ok(response.json::<SearchModResponse>().await?)
133 }
134
135 pub async fn get_mod_file_id(
147 &self,
148 mod_id: isize,
149 mod_name: String,
150 mc_version: String
151 ) -> Result<CurseMod, Box<dyn std::error::Error>> {
152 let id = mod_id.clone();
153 let url = format!("{}{}", CURSE_API_URL, format!("mods/{}", mod_id));
154
155 let response = self.http_client.get(&url).send().await?;
156
157 let file_id: Result<FilesModResponse, reqwest::Error> =
158 response.json::<FilesModResponse>().await;
159 Ok(CurseMod {
161 name: mod_name,
162 mod_id: id,
163 file_id: file_id
164 .unwrap()
165 .data
166 .latest_files_indexes
167 .iter()
168 .find(|&x| x.game_version == mc_version).unwrap()
169 .file_id,
170 })
171 }
172
173}