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 #[serde(skip_serializing_if = "Option::is_none")]
31 pub source_channel: Option<WebhookChannel>,
32 #[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 #[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}