twilight_http/request/channel/
update_channel_permission.rs

1use crate::{
2    client::Client,
3    error::Error,
4    request::{self, AuditLogReason, Request, TryIntoRequest},
5    response::{marker::EmptyBody, Response, ResponseFuture},
6    routing::Route,
7};
8use serde::Serialize;
9use std::future::IntoFuture;
10use twilight_model::{
11    guild::Permissions,
12    http::permission_overwrite::{PermissionOverwrite, PermissionOverwriteType},
13    id::{
14        marker::{ChannelMarker, GenericMarker},
15        Id,
16    },
17};
18use twilight_validate::request::{audit_reason as validate_audit_reason, ValidationError};
19
20#[derive(Serialize)]
21struct UpdateChannelPermissionFields {
22    #[serde(skip_serializing_if = "Option::is_none")]
23    allow: Option<Permissions>,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    deny: Option<Permissions>,
26    #[serde(rename = "type")]
27    kind: PermissionOverwriteType,
28}
29
30/// Update the permissions for a role or a user in a channel.
31///
32/// # Examples:
33///
34/// Create permission overrides for a role to view the channel, but not send
35/// messages:
36///
37/// ```no_run
38/// # #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> {
39/// # use twilight_http::Client;
40/// # let client = Client::new("my token".to_owned());
41/// #
42/// use twilight_model::{
43///     guild::Permissions,
44///     http::permission_overwrite::{PermissionOverwrite, PermissionOverwriteType},
45///     id::Id,
46/// };
47///
48/// let channel_id = Id::new(123);
49/// let permission_overwrite = PermissionOverwrite {
50///     allow: Some(Permissions::VIEW_CHANNEL),
51///     deny: Some(Permissions::SEND_MESSAGES),
52///     id: Id::new(432),
53///     kind: PermissionOverwriteType::Role,
54/// };
55///
56/// client
57///     .update_channel_permission(channel_id, &permission_overwrite)
58///     .await?;
59/// # Ok(()) }
60/// ```
61#[must_use = "requests must be configured and executed"]
62pub struct UpdateChannelPermission<'a> {
63    channel_id: Id<ChannelMarker>,
64    fields: UpdateChannelPermissionFields,
65    http: &'a Client,
66    reason: Result<Option<&'a str>, ValidationError>,
67    target_id: Id<GenericMarker>,
68}
69
70impl<'a> UpdateChannelPermission<'a> {
71    pub(crate) const fn new(
72        http: &'a Client,
73        channel_id: Id<ChannelMarker>,
74        permission_overwrite: &PermissionOverwrite,
75    ) -> Self {
76        Self {
77            channel_id,
78            http,
79            fields: UpdateChannelPermissionFields {
80                allow: permission_overwrite.allow,
81                deny: permission_overwrite.deny,
82                kind: permission_overwrite.kind,
83            },
84            reason: Ok(None),
85            target_id: permission_overwrite.id,
86        }
87    }
88}
89
90impl<'a> AuditLogReason<'a> for UpdateChannelPermission<'a> {
91    fn reason(mut self, reason: &'a str) -> Self {
92        self.reason = validate_audit_reason(reason).and(Ok(Some(reason)));
93
94        self
95    }
96}
97
98impl IntoFuture for UpdateChannelPermission<'_> {
99    type Output = Result<Response<EmptyBody>, Error>;
100
101    type IntoFuture = ResponseFuture<EmptyBody>;
102
103    fn into_future(self) -> Self::IntoFuture {
104        let http = self.http;
105
106        match self.try_into_request() {
107            Ok(request) => http.request(request),
108            Err(source) => ResponseFuture::error(source),
109        }
110    }
111}
112
113impl TryIntoRequest for UpdateChannelPermission<'_> {
114    fn try_into_request(self) -> Result<Request, Error> {
115        let mut request = Request::builder(&Route::UpdatePermissionOverwrite {
116            channel_id: self.channel_id.get(),
117            target_id: self.target_id.get(),
118        })
119        .json(&self.fields);
120
121        if let Some(reason) = self.reason.map_err(Error::validation)? {
122            request = request.headers(request::audit_header(reason)?);
123        }
124
125        request.build()
126    }
127}
128
129#[cfg(test)]
130mod tests {
131    use super::*;
132
133    #[test]
134    fn request() {
135        let permission_overwrite = PermissionOverwrite {
136            allow: None,
137            deny: Some(Permissions::SEND_MESSAGES),
138            id: Id::new(2),
139            kind: PermissionOverwriteType::Member,
140        };
141
142        let client = Client::new("foo".to_owned());
143        let builder = UpdateChannelPermission::new(&client, Id::new(1), &permission_overwrite);
144        let actual = builder
145            .try_into_request()
146            .expect("failed to create request");
147
148        let body = crate::json::to_vec(&UpdateChannelPermissionFields {
149            allow: None,
150            deny: Some(Permissions::SEND_MESSAGES),
151            kind: PermissionOverwriteType::Member,
152        })
153        .expect("failed to serialize payload");
154        let route = Route::UpdatePermissionOverwrite {
155            channel_id: 1,
156            target_id: 2,
157        };
158        let expected = Request::builder(&route).body(body).build().unwrap();
159
160        assert_eq!(expected.body, actual.body);
161        assert_eq!(expected.path, actual.path);
162    }
163}