twilight_model/channel/webhook/
mod.rs

1mod channel;
2mod guild;
3mod kind;
4
5pub use self::{channel::WebhookChannel, guild::WebhookGuild, kind::WebhookType};
6
7use crate::{
8    id::{
9        Id,
10        marker::{ApplicationMarker, ChannelMarker, GuildMarker, WebhookMarker},
11    },
12    user::User,
13    util::image_hash::ImageHash,
14};
15use serde::{Deserialize, Serialize};
16
17#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
18pub struct Webhook {
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub application_id: Option<Id<ApplicationMarker>>,
21    pub avatar: Option<ImageHash>,
22    pub channel_id: Id<ChannelMarker>,
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub guild_id: Option<Id<GuildMarker>>,
25    pub id: Id<WebhookMarker>,
26    #[serde(default = "WebhookType::default", rename = "type")]
27    pub kind: WebhookType,
28    pub name: Option<String>,
29    /// Partial channel object that a webhook is following.
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub source_channel: Option<WebhookChannel>,
32    /// Partial guild object that a webhook is following.
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub source_guild: Option<WebhookGuild>,
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub token: Option<String>,
37    /// Url used for executing the webhook.
38    ///
39    /// Returned by the [`webhooks` OAuth2] flow.
40    ///
41    /// [`webhooks` OAuth2]: https://discord.com/developers/docs/topics/oauth2#webhooks
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub url: Option<String>,
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub user: Option<User>,
46}
47
48#[cfg(test)]
49mod tests {
50    use super::{User, Webhook, WebhookChannel, WebhookGuild, WebhookType};
51    use crate::{id::Id, test::image_hash};
52    use serde::{Deserialize, Serialize};
53    use serde_test::Token;
54    use static_assertions::{assert_fields, assert_impl_all};
55    use std::{fmt::Debug, hash::Hash};
56
57    assert_fields!(
58        Webhook: application_id,
59        avatar,
60        channel_id,
61        guild_id,
62        id,
63        kind,
64        name,
65        source_channel,
66        source_guild,
67        token,
68        user
69    );
70
71    assert_impl_all!(
72        Webhook: Clone,
73        Debug,
74        Deserialize<'static>,
75        Eq,
76        Hash,
77        PartialEq,
78        Serialize
79    );
80
81    #[test]
82    fn webhook() {
83        let value = Webhook {
84            application_id: Some(Id::new(4)),
85            avatar: Some(image_hash::AVATAR),
86            channel_id: Id::new(1),
87            guild_id: Some(Id::new(2)),
88            id: Id::new(3),
89            kind: WebhookType::Incoming,
90            name: Some("a webhook".to_owned()),
91            source_channel: None,
92            source_guild: None,
93            token: Some("a token".to_owned()),
94            url: None,
95            user: None,
96        };
97
98        serde_test::assert_tokens(
99            &value,
100            &[
101                Token::Struct {
102                    name: "Webhook",
103                    len: 8,
104                },
105                Token::Str("application_id"),
106                Token::Some,
107                Token::NewtypeStruct { name: "Id" },
108                Token::Str("4"),
109                Token::Str("avatar"),
110                Token::Some,
111                Token::Str(image_hash::AVATAR_INPUT),
112                Token::Str("channel_id"),
113                Token::NewtypeStruct { name: "Id" },
114                Token::Str("1"),
115                Token::Str("guild_id"),
116                Token::Some,
117                Token::NewtypeStruct { name: "Id" },
118                Token::Str("2"),
119                Token::Str("id"),
120                Token::NewtypeStruct { name: "Id" },
121                Token::Str("3"),
122                Token::Str("type"),
123                Token::U8(1),
124                Token::Str("name"),
125                Token::Some,
126                Token::Str("a webhook"),
127                Token::Str("token"),
128                Token::Some,
129                Token::Str("a token"),
130                Token::StructEnd,
131            ],
132        );
133    }
134
135    #[allow(clippy::too_many_lines)]
136    #[test]
137    fn webhook_complete() {
138        let value = Webhook {
139            application_id: Some(Id::new(4)),
140            avatar: Some(image_hash::AVATAR),
141            channel_id: Id::new(1),
142            guild_id: Some(Id::new(2)),
143            id: Id::new(3),
144            kind: WebhookType::Incoming,
145            name: Some("a webhook".to_owned()),
146            source_channel: Some(WebhookChannel {
147                id: Id::new(4),
148                name: "webhook channel".into(),
149            }),
150            source_guild: Some(WebhookGuild {
151                icon: Some(image_hash::ICON),
152                id: Id::new(5),
153                name: "webhook guild".into(),
154            }),
155            token: Some("a token".to_owned()),
156            url: Some("https://a-url".to_owned()),
157            user: Some(User {
158                accent_color: None,
159                avatar: None,
160                avatar_decoration: None,
161                avatar_decoration_data: None,
162                banner: None,
163                bot: false,
164                discriminator: 1,
165                email: None,
166                flags: None,
167                global_name: Some("test".to_owned()),
168                id: Id::new(2),
169                locale: None,
170                mfa_enabled: None,
171                name: "test".to_owned(),
172                premium_type: None,
173                primary_guild: None,
174                public_flags: None,
175                system: None,
176                verified: None,
177            }),
178        };
179
180        serde_test::assert_tokens(
181            &value,
182            &[
183                Token::Struct {
184                    name: "Webhook",
185                    len: 12,
186                },
187                Token::Str("application_id"),
188                Token::Some,
189                Token::NewtypeStruct { name: "Id" },
190                Token::Str("4"),
191                Token::Str("avatar"),
192                Token::Some,
193                Token::Str(image_hash::AVATAR_INPUT),
194                Token::Str("channel_id"),
195                Token::NewtypeStruct { name: "Id" },
196                Token::Str("1"),
197                Token::Str("guild_id"),
198                Token::Some,
199                Token::NewtypeStruct { name: "Id" },
200                Token::Str("2"),
201                Token::Str("id"),
202                Token::NewtypeStruct { name: "Id" },
203                Token::Str("3"),
204                Token::Str("type"),
205                Token::U8(1),
206                Token::Str("name"),
207                Token::Some,
208                Token::Str("a webhook"),
209                Token::Str("source_channel"),
210                Token::Some,
211                Token::Struct {
212                    name: "WebhookChannel",
213                    len: 2,
214                },
215                Token::Str("id"),
216                Token::NewtypeStruct { name: "Id" },
217                Token::Str("4"),
218                Token::Str("name"),
219                Token::Str("webhook channel"),
220                Token::StructEnd,
221                Token::Str("source_guild"),
222                Token::Some,
223                Token::Struct {
224                    name: "WebhookGuild",
225                    len: 3,
226                },
227                Token::Str("icon"),
228                Token::Some,
229                Token::Str(image_hash::ICON_INPUT),
230                Token::Str("id"),
231                Token::NewtypeStruct { name: "Id" },
232                Token::Str("5"),
233                Token::Str("name"),
234                Token::Str("webhook guild"),
235                Token::StructEnd,
236                Token::Str("token"),
237                Token::Some,
238                Token::Str("a token"),
239                Token::Str("url"),
240                Token::Some,
241                Token::Str("https://a-url"),
242                Token::Str("user"),
243                Token::Some,
244                Token::Struct {
245                    name: "User",
246                    len: 10,
247                },
248                Token::Str("accent_color"),
249                Token::None,
250                Token::Str("avatar"),
251                Token::None,
252                Token::Str("avatar_decoration"),
253                Token::None,
254                Token::Str("avatar_decoration_data"),
255                Token::None,
256                Token::Str("banner"),
257                Token::None,
258                Token::Str("bot"),
259                Token::Bool(false),
260                Token::Str("discriminator"),
261                Token::Str("0001"),
262                Token::Str("global_name"),
263                Token::Some,
264                Token::Str("test"),
265                Token::Str("id"),
266                Token::NewtypeStruct { name: "Id" },
267                Token::Str("2"),
268                Token::Str("username"),
269                Token::Str("test"),
270                Token::StructEnd,
271                Token::StructEnd,
272            ],
273        );
274    }
275}