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