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        marker::{ApplicationMarker, ChannelMarker, GuildMarker, WebhookMarker},
10        Id,
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                public_flags: None,
174                system: None,
175                verified: None,
176            }),
177        };
178
179        serde_test::assert_tokens(
180            &value,
181            &[
182                Token::Struct {
183                    name: "Webhook",
184                    len: 12,
185                },
186                Token::Str("application_id"),
187                Token::Some,
188                Token::NewtypeStruct { name: "Id" },
189                Token::Str("4"),
190                Token::Str("avatar"),
191                Token::Some,
192                Token::Str(image_hash::AVATAR_INPUT),
193                Token::Str("channel_id"),
194                Token::NewtypeStruct { name: "Id" },
195                Token::Str("1"),
196                Token::Str("guild_id"),
197                Token::Some,
198                Token::NewtypeStruct { name: "Id" },
199                Token::Str("2"),
200                Token::Str("id"),
201                Token::NewtypeStruct { name: "Id" },
202                Token::Str("3"),
203                Token::Str("type"),
204                Token::U8(1),
205                Token::Str("name"),
206                Token::Some,
207                Token::Str("a webhook"),
208                Token::Str("source_channel"),
209                Token::Some,
210                Token::Struct {
211                    name: "WebhookChannel",
212                    len: 2,
213                },
214                Token::Str("id"),
215                Token::NewtypeStruct { name: "Id" },
216                Token::Str("4"),
217                Token::Str("name"),
218                Token::Str("webhook channel"),
219                Token::StructEnd,
220                Token::Str("source_guild"),
221                Token::Some,
222                Token::Struct {
223                    name: "WebhookGuild",
224                    len: 3,
225                },
226                Token::Str("icon"),
227                Token::Some,
228                Token::Str(image_hash::ICON_INPUT),
229                Token::Str("id"),
230                Token::NewtypeStruct { name: "Id" },
231                Token::Str("5"),
232                Token::Str("name"),
233                Token::Str("webhook guild"),
234                Token::StructEnd,
235                Token::Str("token"),
236                Token::Some,
237                Token::Str("a token"),
238                Token::Str("url"),
239                Token::Some,
240                Token::Str("https://a-url"),
241                Token::Str("user"),
242                Token::Some,
243                Token::Struct {
244                    name: "User",
245                    len: 10,
246                },
247                Token::Str("accent_color"),
248                Token::None,
249                Token::Str("avatar"),
250                Token::None,
251                Token::Str("avatar_decoration"),
252                Token::None,
253                Token::Str("avatar_decoration_data"),
254                Token::None,
255                Token::Str("banner"),
256                Token::None,
257                Token::Str("bot"),
258                Token::Bool(false),
259                Token::Str("discriminator"),
260                Token::Str("0001"),
261                Token::Str("global_name"),
262                Token::Some,
263                Token::Str("test"),
264                Token::Str("id"),
265                Token::NewtypeStruct { name: "Id" },
266                Token::Str("2"),
267                Token::Str("username"),
268                Token::Str("test"),
269                Token::StructEnd,
270                Token::StructEnd,
271            ],
272        );
273    }
274}