1use super::{
2 GuildIntegrationType, IntegrationAccount, IntegrationApplication, IntegrationExpireBehavior,
3};
4use crate::{
5 id::{
6 marker::{GuildMarker, IntegrationMarker, RoleMarker},
7 Id,
8 },
9 user::User,
10 util::Timestamp,
11};
12use serde::{Deserialize, Serialize};
13
14#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
15pub struct GuildIntegration {
16 pub account: IntegrationAccount,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pub application: Option<IntegrationApplication>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub enable_emoticons: Option<bool>,
21 pub enabled: Option<bool>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub expire_behavior: Option<IntegrationExpireBehavior>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub expire_grace_period: Option<u64>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub guild_id: Option<Id<GuildMarker>>,
31 pub id: Id<IntegrationMarker>,
32 #[serde(rename = "type")]
33 pub kind: GuildIntegrationType,
34 pub name: String,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub revoked: Option<bool>,
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub role_id: Option<Id<RoleMarker>>,
39 #[serde(skip_serializing_if = "Option::is_none")]
43 pub scopes: Option<Vec<String>>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub subscriber_count: Option<u64>,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub synced_at: Option<Timestamp>,
48 #[serde(skip_serializing_if = "Option::is_none")]
49 pub syncing: Option<bool>,
50 #[serde(skip_serializing_if = "Option::is_none")]
51 pub user: Option<User>,
52}
53
54#[cfg(test)]
55mod tests {
56 use super::{
57 GuildIntegration, IntegrationAccount, IntegrationApplication, IntegrationExpireBehavior,
58 User,
59 };
60 use crate::{
61 guild::GuildIntegrationType,
62 id::Id,
63 oauth::scope,
64 test::image_hash,
65 util::datetime::{Timestamp, TimestampParseError},
66 };
67 use serde_test::Token;
68 use std::str::FromStr;
69
70 #[allow(clippy::too_many_lines)]
71 #[test]
72 fn guild_integration() -> Result<(), TimestampParseError> {
73 let synced_at = Timestamp::from_str("2021-01-01T01:01:01+00:00")?;
74
75 let value = GuildIntegration {
76 account: IntegrationAccount {
77 id: "abcd".to_owned(),
78 name: "account name".to_owned(),
79 },
80 application: None,
81 enable_emoticons: Some(true),
82 enabled: Some(true),
83 expire_behavior: Some(IntegrationExpireBehavior::Kick),
84 expire_grace_period: Some(3_600),
85 guild_id: None,
86 id: Id::new(2),
87 kind: GuildIntegrationType::Discord,
88 name: "integration name".to_owned(),
89 revoked: Some(false),
90 role_id: Some(Id::new(3)),
91 scopes: Some(Vec::from([
92 scope::APPLICATIONS_COMMANDS.to_owned(),
93 scope::BOT.to_owned(),
94 ])),
95 subscriber_count: Some(1337),
96 synced_at: Some(synced_at),
97 syncing: Some(false),
98 user: Some(User {
99 accent_color: None,
100 avatar: Some(image_hash::AVATAR),
101 avatar_decoration: None,
102 avatar_decoration_data: None,
103 banner: None,
104 bot: true,
105 discriminator: 1000,
106 email: None,
107 flags: None,
108 global_name: Some("test".to_owned()),
109 id: Id::new(4),
110 locale: None,
111 mfa_enabled: None,
112 name: "user".to_owned(),
113 premium_type: None,
114 public_flags: None,
115 system: None,
116 verified: None,
117 }),
118 };
119
120 serde_test::assert_tokens(
121 &value,
122 &[
123 Token::Struct {
124 name: "GuildIntegration",
125 len: 15,
126 },
127 Token::Str("account"),
128 Token::Struct {
129 name: "IntegrationAccount",
130 len: 2,
131 },
132 Token::Str("id"),
133 Token::Str("abcd"),
134 Token::Str("name"),
135 Token::Str("account name"),
136 Token::StructEnd,
137 Token::Str("enable_emoticons"),
138 Token::Some,
139 Token::Bool(true),
140 Token::Str("enabled"),
141 Token::Some,
142 Token::Bool(true),
143 Token::Str("expire_behavior"),
144 Token::Some,
145 Token::U8(1),
146 Token::Str("expire_grace_period"),
147 Token::Some,
148 Token::U64(3_600),
149 Token::Str("id"),
150 Token::NewtypeStruct { name: "Id" },
151 Token::Str("2"),
152 Token::Str("type"),
153 Token::Str("discord"),
154 Token::Str("name"),
155 Token::Str("integration name"),
156 Token::Str("revoked"),
157 Token::Some,
158 Token::Bool(false),
159 Token::Str("role_id"),
160 Token::Some,
161 Token::NewtypeStruct { name: "Id" },
162 Token::Str("3"),
163 Token::Str("scopes"),
164 Token::Some,
165 Token::Seq { len: Some(2) },
166 Token::Str(scope::APPLICATIONS_COMMANDS),
167 Token::Str(scope::BOT),
168 Token::SeqEnd,
169 Token::Str("subscriber_count"),
170 Token::Some,
171 Token::U64(1337),
172 Token::Str("synced_at"),
173 Token::Some,
174 Token::Str("2021-01-01T01:01:01.000000+00:00"),
175 Token::Str("syncing"),
176 Token::Some,
177 Token::Bool(false),
178 Token::Str("user"),
179 Token::Some,
180 Token::Struct {
181 name: "User",
182 len: 10,
183 },
184 Token::Str("accent_color"),
185 Token::None,
186 Token::Str("avatar"),
187 Token::Some,
188 Token::Str(image_hash::AVATAR_INPUT),
189 Token::Str("avatar_decoration"),
190 Token::None,
191 Token::Str("avatar_decoration_data"),
192 Token::None,
193 Token::Str("banner"),
194 Token::None,
195 Token::Str("bot"),
196 Token::Bool(true),
197 Token::Str("discriminator"),
198 Token::Str("1000"),
199 Token::Str("global_name"),
200 Token::Some,
201 Token::Str("test"),
202 Token::Str("id"),
203 Token::NewtypeStruct { name: "Id" },
204 Token::Str("4"),
205 Token::Str("username"),
206 Token::Str("user"),
207 Token::StructEnd,
208 Token::StructEnd,
209 ],
210 );
211
212 Ok(())
213 }
214
215 #[allow(clippy::too_many_lines)]
216 #[test]
217 fn guild_integration_complete() -> Result<(), TimestampParseError> {
218 let synced_at = Timestamp::from_str("2021-01-01T01:01:01+00:00")?;
219
220 let value = GuildIntegration {
221 account: IntegrationAccount {
222 id: "abcd".to_owned(),
223 name: "account name".to_owned(),
224 },
225 application: Some(IntegrationApplication {
226 bot: None,
227 description: "Friendship is Magic".to_string(),
228 icon: None,
229 id: Id::new(123),
230 name: "Twilight".to_string(),
231 }),
232 enable_emoticons: Some(true),
233 enabled: None,
234 expire_behavior: Some(IntegrationExpireBehavior::Kick),
235 expire_grace_period: Some(3_600),
236 guild_id: None,
237 id: Id::new(2),
238 kind: GuildIntegrationType::Discord,
239 name: "integration name".to_owned(),
240 revoked: Some(false),
241 role_id: Some(Id::new(3)),
242 scopes: Some(Vec::from([
243 scope::APPLICATIONS_COMMANDS.to_owned(),
244 scope::BOT.to_owned(),
245 ])),
246 subscriber_count: Some(1337),
247 synced_at: Some(synced_at),
248 syncing: Some(false),
249 user: Some(User {
250 accent_color: None,
251 avatar: Some(image_hash::AVATAR),
252 avatar_decoration: None,
253 avatar_decoration_data: None,
254 banner: None,
255 bot: true,
256 discriminator: 1000,
257 email: None,
258 flags: None,
259 global_name: Some("test".to_owned()),
260 id: Id::new(4),
261 locale: None,
262 mfa_enabled: None,
263 name: "user".to_owned(),
264 premium_type: None,
265 public_flags: None,
266 system: None,
267 verified: None,
268 }),
269 };
270
271 serde_test::assert_tokens(
272 &value,
273 &[
274 Token::Struct {
275 name: "GuildIntegration",
276 len: 16,
277 },
278 Token::Str("account"),
279 Token::Struct {
280 name: "IntegrationAccount",
281 len: 2,
282 },
283 Token::Str("id"),
284 Token::Str("abcd"),
285 Token::Str("name"),
286 Token::Str("account name"),
287 Token::StructEnd,
288 Token::Str("application"),
289 Token::Some,
290 Token::Struct {
291 name: "IntegrationApplication",
292 len: 4,
293 },
294 Token::Str("description"),
295 Token::Str("Friendship is Magic"),
296 Token::Str("icon"),
297 Token::None,
298 Token::Str("id"),
299 Token::NewtypeStruct { name: "Id" },
300 Token::Str("123"),
301 Token::Str("name"),
302 Token::Str("Twilight"),
303 Token::StructEnd,
304 Token::Str("enable_emoticons"),
305 Token::Some,
306 Token::Bool(true),
307 Token::Str("enabled"),
308 Token::None,
309 Token::Str("expire_behavior"),
310 Token::Some,
311 Token::U8(1),
312 Token::Str("expire_grace_period"),
313 Token::Some,
314 Token::U64(3_600),
315 Token::Str("id"),
316 Token::NewtypeStruct { name: "Id" },
317 Token::Str("2"),
318 Token::Str("type"),
319 Token::Str("discord"),
320 Token::Str("name"),
321 Token::Str("integration name"),
322 Token::Str("revoked"),
323 Token::Some,
324 Token::Bool(false),
325 Token::Str("role_id"),
326 Token::Some,
327 Token::NewtypeStruct { name: "Id" },
328 Token::Str("3"),
329 Token::Str("scopes"),
330 Token::Some,
331 Token::Seq { len: Some(2) },
332 Token::Str(scope::APPLICATIONS_COMMANDS),
333 Token::Str(scope::BOT),
334 Token::SeqEnd,
335 Token::Str("subscriber_count"),
336 Token::Some,
337 Token::U64(1337),
338 Token::Str("synced_at"),
339 Token::Some,
340 Token::Str("2021-01-01T01:01:01.000000+00:00"),
341 Token::Str("syncing"),
342 Token::Some,
343 Token::Bool(false),
344 Token::Str("user"),
345 Token::Some,
346 Token::Struct {
347 name: "User",
348 len: 10,
349 },
350 Token::Str("accent_color"),
351 Token::None,
352 Token::Str("avatar"),
353 Token::Some,
354 Token::Str(image_hash::AVATAR_INPUT),
355 Token::Str("avatar_decoration"),
356 Token::None,
357 Token::Str("avatar_decoration_data"),
358 Token::None,
359 Token::Str("banner"),
360 Token::None,
361 Token::Str("bot"),
362 Token::Bool(true),
363 Token::Str("discriminator"),
364 Token::Str("1000"),
365 Token::Str("global_name"),
366 Token::Some,
367 Token::Str("test"),
368 Token::Str("id"),
369 Token::NewtypeStruct { name: "Id" },
370 Token::Str("4"),
371 Token::Str("username"),
372 Token::Str("user"),
373 Token::StructEnd,
374 Token::StructEnd,
375 ],
376 );
377
378 Ok(())
379 }
380}