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