twilight_http/request/guild/emoji/
update_emoji.rs

1use crate::{
2    client::Client,
3    error::Error,
4    request::{self, AuditLogReason, Request, TryIntoRequest},
5    response::{Response, ResponseFuture},
6    routing::Route,
7};
8use serde::Serialize;
9use std::future::IntoFuture;
10use twilight_model::{
11    guild::Emoji,
12    id::{
13        marker::{EmojiMarker, GuildMarker, RoleMarker},
14        Id,
15    },
16};
17use twilight_validate::request::{audit_reason as validate_audit_reason, ValidationError};
18
19#[derive(Serialize)]
20struct UpdateEmojiFields<'a> {
21    #[serde(skip_serializing_if = "Option::is_none")]
22    name: Option<&'a str>,
23    #[serde(skip_serializing_if = "Option::is_none")]
24    roles: Option<&'a [Id<RoleMarker>]>,
25}
26
27/// Update an emoji in a guild, by id.
28#[must_use = "requests must be configured and executed"]
29pub struct UpdateEmoji<'a> {
30    emoji_id: Id<EmojiMarker>,
31    fields: UpdateEmojiFields<'a>,
32    guild_id: Id<GuildMarker>,
33    http: &'a Client,
34    reason: Result<Option<&'a str>, ValidationError>,
35}
36
37impl<'a> UpdateEmoji<'a> {
38    pub(crate) const fn new(
39        http: &'a Client,
40        guild_id: Id<GuildMarker>,
41        emoji_id: Id<EmojiMarker>,
42    ) -> Self {
43        Self {
44            fields: UpdateEmojiFields {
45                name: None,
46                roles: None,
47            },
48            emoji_id,
49            guild_id,
50            http,
51            reason: Ok(None),
52        }
53    }
54
55    /// Change the name of the emoji.
56    pub const fn name(mut self, name: &'a str) -> Self {
57        self.fields.name = Some(name);
58
59        self
60    }
61
62    /// Change the roles that the emoji is whitelisted to.
63    pub const fn roles(mut self, roles: &'a [Id<RoleMarker>]) -> Self {
64        self.fields.roles = Some(roles);
65
66        self
67    }
68}
69
70impl<'a> AuditLogReason<'a> for UpdateEmoji<'a> {
71    fn reason(mut self, reason: &'a str) -> Self {
72        self.reason = validate_audit_reason(reason).and(Ok(Some(reason)));
73
74        self
75    }
76}
77
78impl IntoFuture for UpdateEmoji<'_> {
79    type Output = Result<Response<Emoji>, Error>;
80
81    type IntoFuture = ResponseFuture<Emoji>;
82
83    fn into_future(self) -> Self::IntoFuture {
84        let http = self.http;
85
86        match self.try_into_request() {
87            Ok(request) => http.request(request),
88            Err(source) => ResponseFuture::error(source),
89        }
90    }
91}
92
93impl TryIntoRequest for UpdateEmoji<'_> {
94    fn try_into_request(self) -> Result<Request, Error> {
95        let mut request = Request::builder(&Route::UpdateEmoji {
96            emoji_id: self.emoji_id.get(),
97            guild_id: self.guild_id.get(),
98        });
99
100        request = request.json(&self.fields);
101
102        if let Some(reason) = self.reason.map_err(Error::validation)? {
103            request = request.headers(request::audit_header(reason)?);
104        }
105
106        request.build()
107    }
108}