Skip to main content

twilight_http/request/channel/
update_channel_permission.rs

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