modio/request/mods/
add_mod.rs1use std::future::IntoFuture;
2use std::path::Path;
3
4use serde_derive::Serialize;
5
6use crate::client::Client;
7use crate::error;
8use crate::request::multipart::{Form, Part};
9use crate::request::{Output, RequestBuilder, Route};
10use crate::response::ResponseFuture;
11use crate::types::id::GameId;
12use crate::types::mods::{CommunityOptions, CreditOptions, MaturityOption, Mod};
13
14pub struct AddMod<'a> {
16 http: &'a Client,
17 game_id: GameId,
18 logo: Part,
19 fields: AddModFields<'a>,
20}
21
22#[derive(Serialize)]
23struct AddModFields<'a> {
24 name: &'a str,
25 summary: &'a str,
26 #[serde(skip_serializing_if = "Option::is_none")]
27 visibility: Option<u8>,
28 #[serde(skip_serializing_if = "Option::is_none")]
29 name_id: Option<&'a str>,
30 #[serde(skip_serializing_if = "Option::is_none")]
31 description: Option<&'a str>,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 homepage_url: Option<&'a str>,
34 #[serde(skip_serializing_if = "Option::is_none")]
35 stock: Option<u32>,
36 #[serde(skip_serializing_if = "Option::is_none")]
37 maturity_option: Option<MaturityOption>,
38 #[serde(skip_serializing_if = "Option::is_none")]
39 community_options: Option<CommunityOptions>,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 credit_options: Option<CreditOptions>,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 metadata_blob: Option<&'a str>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 tags: Option<&'a [&'a str]>,
46}
47
48impl<'a> AddMod<'a> {
49 pub(crate) fn new(
50 http: &'a Client,
51 game_id: GameId,
52 name: &'a str,
53 summary: &'a str,
54 logo: impl AsRef<Path>,
55 ) -> Self {
56 let logo = Part::file(logo, "logo.png").mime(mime::IMAGE_STAR);
57
58 Self {
59 http,
60 game_id,
61 logo,
62 fields: AddModFields {
63 name,
64 summary,
65 visibility: None,
66 name_id: None,
67 description: None,
68 homepage_url: None,
69 stock: None,
70 maturity_option: None,
71 community_options: None,
72 credit_options: None,
73 metadata_blob: None,
74 tags: None,
75 },
76 }
77 }
78
79 pub const fn name_id(mut self, name_id: &'a str) -> Self {
80 self.fields.name_id = Some(name_id);
81 self
82 }
83
84 pub const fn description(mut self, description: &'a str) -> Self {
85 self.fields.description = Some(description);
86 self
87 }
88
89 pub const fn homepage_url(mut self, homepage_url: &'a str) -> Self {
90 self.fields.homepage_url = Some(homepage_url);
91 self
92 }
93
94 pub const fn stock(mut self, stock: u32) -> Self {
95 self.fields.stock = Some(stock);
96 self
97 }
98
99 pub const fn maturity_option(mut self, option: MaturityOption) -> Self {
100 self.fields.maturity_option = Some(option);
101 self
102 }
103
104 pub const fn community_options(mut self, options: CommunityOptions) -> Self {
105 self.fields.community_options = Some(options);
106 self
107 }
108
109 pub const fn credit_options(mut self, options: CreditOptions) -> Self {
110 self.fields.credit_options = Some(options);
111 self
112 }
113
114 pub const fn metadata_blob(mut self, metadata: &'a str) -> Self {
115 self.fields.metadata_blob = Some(metadata);
116 self
117 }
118
119 pub const fn tags(mut self, tags: &'a [&'a str]) -> Self {
120 self.fields.tags = Some(tags);
121 self
122 }
123
124 pub const fn visible(mut self, visible: bool) -> Self {
125 self.fields.visibility = Some(if visible { 1 } else { 0 });
126 self
127 }
128}
129
130impl IntoFuture for AddMod<'_> {
131 type Output = Output<Mod>;
132 type IntoFuture = ResponseFuture<Mod>;
133
134 fn into_future(self) -> Self::IntoFuture {
135 let route = Route::AddMod {
136 game_id: self.game_id,
137 };
138
139 let mut form = Form::new();
140
141 form = form.text("name", self.fields.name.to_owned());
142 form = form.text("summary", self.fields.summary.to_owned());
143 form = form.part("logo", self.logo);
144
145 if let Some(value) = self.fields.name_id {
146 form = form.text("name_id", value.to_owned());
147 }
148 if let Some(value) = self.fields.description {
149 form = form.text("description", value.to_owned());
150 }
151 if let Some(value) = self.fields.homepage_url {
152 form = form.text("homepage_url", value.to_owned());
153 }
154 if let Some(value) = self.fields.visibility {
155 form = form.text("visible", value.to_string());
156 }
157 if let Some(value) = self.fields.stock {
158 form = form.text("stock", value.to_string());
159 }
160 if let Some(value) = self.fields.maturity_option {
161 form = form.text("maturity_option", value.to_string());
162 }
163 if let Some(value) = self.fields.community_options {
164 form = form.text("community_options", value.to_string());
165 }
166 if let Some(value) = self.fields.credit_options {
167 form = form.text("credit_options", value.to_string());
168 }
169 if let Some(value) = self.fields.metadata_blob {
170 form = form.text("metadata_blob", value.to_owned());
171 }
172 if let Some(tags) = self.fields.tags {
173 for tag in tags {
174 form = form.text("tags[]", (*tag).to_owned());
175 }
176 }
177
178 form = match serde_json::to_vec(&self.fields) {
179 Ok(json) => form.part("input_json", Part::bytes(json.into())),
180 Err(err) => return ResponseFuture::failed(error::builder(err)),
181 };
182
183 match RequestBuilder::from_route(&route).multipart(form) {
184 Ok(req) => self.http.request(req),
185 Err(err) => ResponseFuture::failed(err),
186 }
187 }
188}