twilight_model/guild/
integration.rs

1use super::{
2    GuildIntegrationType, IntegrationAccount, IntegrationApplication, IntegrationExpireBehavior,
3};
4use crate::{
5    id::{
6        Id,
7        marker::{GuildMarker, IntegrationMarker, RoleMarker},
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    /// Whether the integration has been enabled.
22    ///
23    /// May be provided on some non-Discord application integrations.
24    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    /// An array of [OAuth2 scopes] which the application has been authorized for.
40    ///
41    /// [OAuth2 scopes]: crate::oauth::scope
42    #[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                primary_guild: None,
115                public_flags: None,
116                system: None,
117                verified: None,
118            }),
119        };
120
121        serde_test::assert_tokens(
122            &value,
123            &[
124                Token::Struct {
125                    name: "GuildIntegration",
126                    len: 15,
127                },
128                Token::Str("account"),
129                Token::Struct {
130                    name: "IntegrationAccount",
131                    len: 2,
132                },
133                Token::Str("id"),
134                Token::Str("abcd"),
135                Token::Str("name"),
136                Token::Str("account name"),
137                Token::StructEnd,
138                Token::Str("enable_emoticons"),
139                Token::Some,
140                Token::Bool(true),
141                Token::Str("enabled"),
142                Token::Some,
143                Token::Bool(true),
144                Token::Str("expire_behavior"),
145                Token::Some,
146                Token::U8(1),
147                Token::Str("expire_grace_period"),
148                Token::Some,
149                Token::U64(3_600),
150                Token::Str("id"),
151                Token::NewtypeStruct { name: "Id" },
152                Token::Str("2"),
153                Token::Str("type"),
154                Token::Str("discord"),
155                Token::Str("name"),
156                Token::Str("integration name"),
157                Token::Str("revoked"),
158                Token::Some,
159                Token::Bool(false),
160                Token::Str("role_id"),
161                Token::Some,
162                Token::NewtypeStruct { name: "Id" },
163                Token::Str("3"),
164                Token::Str("scopes"),
165                Token::Some,
166                Token::Seq { len: Some(2) },
167                Token::Str(scope::APPLICATIONS_COMMANDS),
168                Token::Str(scope::BOT),
169                Token::SeqEnd,
170                Token::Str("subscriber_count"),
171                Token::Some,
172                Token::U64(1337),
173                Token::Str("synced_at"),
174                Token::Some,
175                Token::Str("2021-01-01T01:01:01.000000+00:00"),
176                Token::Str("syncing"),
177                Token::Some,
178                Token::Bool(false),
179                Token::Str("user"),
180                Token::Some,
181                Token::Struct {
182                    name: "User",
183                    len: 10,
184                },
185                Token::Str("accent_color"),
186                Token::None,
187                Token::Str("avatar"),
188                Token::Some,
189                Token::Str(image_hash::AVATAR_INPUT),
190                Token::Str("avatar_decoration"),
191                Token::None,
192                Token::Str("avatar_decoration_data"),
193                Token::None,
194                Token::Str("banner"),
195                Token::None,
196                Token::Str("bot"),
197                Token::Bool(true),
198                Token::Str("discriminator"),
199                Token::Str("1000"),
200                Token::Str("global_name"),
201                Token::Some,
202                Token::Str("test"),
203                Token::Str("id"),
204                Token::NewtypeStruct { name: "Id" },
205                Token::Str("4"),
206                Token::Str("username"),
207                Token::Str("user"),
208                Token::StructEnd,
209                Token::StructEnd,
210            ],
211        );
212
213        Ok(())
214    }
215
216    #[allow(clippy::too_many_lines)]
217    #[test]
218    fn guild_integration_complete() -> Result<(), TimestampParseError> {
219        let synced_at = Timestamp::from_str("2021-01-01T01:01:01+00:00")?;
220
221        let value = GuildIntegration {
222            account: IntegrationAccount {
223                id: "abcd".to_owned(),
224                name: "account name".to_owned(),
225            },
226            application: Some(IntegrationApplication {
227                bot: None,
228                description: "Friendship is Magic".to_string(),
229                icon: None,
230                id: Id::new(123),
231                name: "Twilight".to_string(),
232            }),
233            enable_emoticons: Some(true),
234            enabled: None,
235            expire_behavior: Some(IntegrationExpireBehavior::Kick),
236            expire_grace_period: Some(3_600),
237            guild_id: None,
238            id: Id::new(2),
239            kind: GuildIntegrationType::Discord,
240            name: "integration name".to_owned(),
241            revoked: Some(false),
242            role_id: Some(Id::new(3)),
243            scopes: Some(Vec::from([
244                scope::APPLICATIONS_COMMANDS.to_owned(),
245                scope::BOT.to_owned(),
246            ])),
247            subscriber_count: Some(1337),
248            synced_at: Some(synced_at),
249            syncing: Some(false),
250            user: Some(User {
251                accent_color: None,
252                avatar: Some(image_hash::AVATAR),
253                avatar_decoration: None,
254                avatar_decoration_data: None,
255                banner: None,
256                bot: true,
257                discriminator: 1000,
258                email: None,
259                flags: None,
260                global_name: Some("test".to_owned()),
261                id: Id::new(4),
262                locale: None,
263                mfa_enabled: None,
264                name: "user".to_owned(),
265                premium_type: None,
266                primary_guild: None,
267                public_flags: None,
268                system: None,
269                verified: None,
270            }),
271        };
272
273        serde_test::assert_tokens(
274            &value,
275            &[
276                Token::Struct {
277                    name: "GuildIntegration",
278                    len: 16,
279                },
280                Token::Str("account"),
281                Token::Struct {
282                    name: "IntegrationAccount",
283                    len: 2,
284                },
285                Token::Str("id"),
286                Token::Str("abcd"),
287                Token::Str("name"),
288                Token::Str("account name"),
289                Token::StructEnd,
290                Token::Str("application"),
291                Token::Some,
292                Token::Struct {
293                    name: "IntegrationApplication",
294                    len: 4,
295                },
296                Token::Str("description"),
297                Token::Str("Friendship is Magic"),
298                Token::Str("icon"),
299                Token::None,
300                Token::Str("id"),
301                Token::NewtypeStruct { name: "Id" },
302                Token::Str("123"),
303                Token::Str("name"),
304                Token::Str("Twilight"),
305                Token::StructEnd,
306                Token::Str("enable_emoticons"),
307                Token::Some,
308                Token::Bool(true),
309                Token::Str("enabled"),
310                Token::None,
311                Token::Str("expire_behavior"),
312                Token::Some,
313                Token::U8(1),
314                Token::Str("expire_grace_period"),
315                Token::Some,
316                Token::U64(3_600),
317                Token::Str("id"),
318                Token::NewtypeStruct { name: "Id" },
319                Token::Str("2"),
320                Token::Str("type"),
321                Token::Str("discord"),
322                Token::Str("name"),
323                Token::Str("integration name"),
324                Token::Str("revoked"),
325                Token::Some,
326                Token::Bool(false),
327                Token::Str("role_id"),
328                Token::Some,
329                Token::NewtypeStruct { name: "Id" },
330                Token::Str("3"),
331                Token::Str("scopes"),
332                Token::Some,
333                Token::Seq { len: Some(2) },
334                Token::Str(scope::APPLICATIONS_COMMANDS),
335                Token::Str(scope::BOT),
336                Token::SeqEnd,
337                Token::Str("subscriber_count"),
338                Token::Some,
339                Token::U64(1337),
340                Token::Str("synced_at"),
341                Token::Some,
342                Token::Str("2021-01-01T01:01:01.000000+00:00"),
343                Token::Str("syncing"),
344                Token::Some,
345                Token::Bool(false),
346                Token::Str("user"),
347                Token::Some,
348                Token::Struct {
349                    name: "User",
350                    len: 10,
351                },
352                Token::Str("accent_color"),
353                Token::None,
354                Token::Str("avatar"),
355                Token::Some,
356                Token::Str(image_hash::AVATAR_INPUT),
357                Token::Str("avatar_decoration"),
358                Token::None,
359                Token::Str("avatar_decoration_data"),
360                Token::None,
361                Token::Str("banner"),
362                Token::None,
363                Token::Str("bot"),
364                Token::Bool(true),
365                Token::Str("discriminator"),
366                Token::Str("1000"),
367                Token::Str("global_name"),
368                Token::Some,
369                Token::Str("test"),
370                Token::Str("id"),
371                Token::NewtypeStruct { name: "Id" },
372                Token::Str("4"),
373                Token::Str("username"),
374                Token::Str("user"),
375                Token::StructEnd,
376                Token::StructEnd,
377            ],
378        );
379
380        Ok(())
381    }
382}