twilight_http/request/user/
update_current_user.rs1#[cfg(not(target_os = "wasi"))]
2use crate::response::{Response, ResponseFuture};
3use crate::{
4 client::Client,
5 error::Error,
6 request::{self, AuditLogReason, Nullable, Request, TryIntoRequest},
7 routing::Route,
8};
9use serde::Serialize;
10use std::future::IntoFuture;
11use twilight_model::user::User;
12use twilight_validate::request::{
13 ValidationError, audit_reason as validate_audit_reason, username as validate_username,
14};
15
16#[derive(Serialize)]
17struct UpdateCurrentUserFields<'a> {
18 #[serde(skip_serializing_if = "Option::is_none")]
19 avatar: Option<Nullable<&'a str>>,
20 #[serde(skip_serializing_if = "Option::is_none")]
21 banner: Option<Nullable<&'a str>>,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 username: Option<&'a str>,
24}
25
26#[must_use = "requests must be configured and executed"]
31pub struct UpdateCurrentUser<'a> {
32 fields: Result<UpdateCurrentUserFields<'a>, ValidationError>,
33 http: &'a Client,
34 reason: Result<Option<&'a str>, ValidationError>,
35}
36
37impl<'a> UpdateCurrentUser<'a> {
38 pub(crate) const fn new(http: &'a Client) -> Self {
39 Self {
40 fields: Ok(UpdateCurrentUserFields {
41 avatar: None,
42 banner: None,
43 username: None,
44 }),
45 http,
46 reason: Ok(None),
47 }
48 }
49
50 pub const fn avatar(mut self, avatar: Option<&'a str>) -> Self {
58 if let Ok(fields) = self.fields.as_mut() {
59 fields.avatar = Some(Nullable(avatar));
60 }
61
62 self
63 }
64
65 pub const fn banner(mut self, banner: Option<&'a str>) -> Self {
73 if let Ok(fields) = self.fields.as_mut() {
74 fields.banner = Some(Nullable(banner));
75 }
76
77 self
78 }
79
80 pub fn username(mut self, username: &'a str) -> Self {
91 self.fields = self.fields.and_then(|mut fields| {
92 validate_username(username)?;
93 fields.username.replace(username);
94
95 Ok(fields)
96 });
97
98 self
99 }
100}
101
102impl<'a> AuditLogReason<'a> for UpdateCurrentUser<'a> {
103 fn reason(mut self, reason: &'a str) -> Self {
104 self.reason = validate_audit_reason(reason).and(Ok(Some(reason)));
105
106 self
107 }
108}
109
110#[cfg(not(target_os = "wasi"))]
111impl IntoFuture for UpdateCurrentUser<'_> {
112 type Output = Result<Response<User>, Error>;
113
114 type IntoFuture = ResponseFuture<User>;
115
116 fn into_future(self) -> Self::IntoFuture {
117 let http = self.http;
118
119 match self.try_into_request() {
120 Ok(request) => http.request(request),
121 Err(source) => ResponseFuture::error(source),
122 }
123 }
124}
125
126impl TryIntoRequest for UpdateCurrentUser<'_> {
127 fn try_into_request(self) -> Result<Request, Error> {
128 let fields = self.fields.map_err(Error::validation)?;
129
130 let mut request = Request::builder(&Route::UpdateCurrentUser).json(&fields);
131
132 if let Some(reason) = self.reason.map_err(Error::validation)? {
133 request = request.headers(request::audit_header(reason)?);
134 }
135
136 request.build()
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use super::*;
143 use std::error::Error;
144
145 #[test]
146 fn test_clear_attachment() -> Result<(), Box<dyn Error>> {
147 let client = Client::new("token".into());
148
149 {
150 let expected = r"{}";
151 let actual = UpdateCurrentUser::new(&client).try_into_request()?;
152
153 assert_eq!(Some(expected.as_bytes()), actual.body());
154 }
155
156 {
157 let expected = r#"{"avatar":null}"#;
158 let actual = UpdateCurrentUser::new(&client)
159 .avatar(None)
160 .try_into_request()?;
161
162 assert_eq!(Some(expected.as_bytes()), actual.body());
163
164 let expected = r#"{"avatar":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI"}"#;
165 let actual = UpdateCurrentUser::new(&client).avatar(Some("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI")).try_into_request()?;
166
167 assert_eq!(Some(expected.as_bytes()), actual.body());
168 }
169
170 {
171 let expected = r#"{"username":"other side"}"#;
172 let actual = UpdateCurrentUser::new(&client)
173 .username("other side")
174 .try_into_request()?;
175
176 assert_eq!(Some(expected.as_bytes()), actual.body());
177 }
178
179 {
180 let expected = r#"{"avatar":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI","username":"other side"}"#;
181 let actual = UpdateCurrentUser::new(&client).avatar(Some("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI")).username("other side").try_into_request()?;
182
183 assert_eq!(Some(expected.as_bytes()), actual.body());
184 }
185 Ok(())
186 }
187}