Skip to main content

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