twilight_model/oauth/
application.rs

1use super::{
2    application_integration_type::{ApplicationIntegrationMap, ApplicationIntegrationTypeConfig},
3    team::Team,
4    ApplicationFlags, InstallParams,
5};
6use crate::{
7    guild::Guild,
8    id::{
9        marker::{ApplicationMarker, GuildMarker, OauthSkuMarker},
10        Id,
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 Application {
19    /// Approximate count of guilds this app has been added to.
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub approximate_guild_count: Option<u64>,
22    /// Approximate count of users that have installed the app.
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub approximate_user_install_count: Option<u64>,
25    /// Partial user object for the bot user associated with the app.
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub bot: Option<User>,
28    /// When `false`, only the app owner can add the app to guilds
29    pub bot_public: bool,
30    /// When `true`, the app's bot will only join upon completion of the
31    /// full OAuth2 code grant flow
32    pub bot_require_code_grant: bool,
33    /// Default rich presence invite cover image.
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub cover_image: Option<ImageHash>,
36    /// Application's default custom authorization link, if enabled.
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub custom_install_url: Option<String>,
39    /// Description of the application.
40    pub description: String,
41    /// Public flags of the application.
42    pub flags: Option<ApplicationFlags>,
43    /// Partial object of the associated guild.
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub guild: Option<Guild>,
46    /// Guild associated with the app. For example, a developer support server.
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub guild_id: Option<Id<GuildMarker>>,
49    /// Icon of the application.
50    pub icon: Option<ImageHash>,
51    /// ID of the application.
52    pub id: Id<ApplicationMarker>,
53    /// Settings for the application's default in-app authorization, if enabled.
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub install_params: Option<InstallParams>,
56    #[serde(skip_serializing_if = "Option::is_none")]
57    pub integration_types_config:
58        Option<ApplicationIntegrationMap<ApplicationIntegrationTypeConfig>>,
59    /// Interactions endpoint URL for the app.
60    #[serde(skip_serializing_if = "Option::is_none")]
61    pub interactions_endpoint_url: Option<String>,
62    /// Name of the application.
63    pub name: String,
64    /// Partial user object for the owner of the app.
65    #[serde(skip_serializing_if = "Option::is_none")]
66    pub owner: Option<User>,
67    /// If this app is a game sold on Discord, this field will be the
68    /// id of the "Game SKU" that is created, if exists.
69    #[serde(skip_serializing_if = "Option::is_none")]
70    pub primary_sku_id: Option<Id<OauthSkuMarker>>,
71    /// URL of the application's privacy policy.
72    #[serde(skip_serializing_if = "Option::is_none")]
73    pub privacy_policy_url: Option<String>,
74    /// Redirect URIs for the application.
75    #[serde(skip_serializing_if = "Option::is_none")]
76    pub redirect_uris: Option<Vec<String>>,
77    /// Role connection verification URL for the app.
78    #[serde(skip_serializing_if = "Option::is_none")]
79    pub role_connections_verification_url: Option<String>,
80    #[serde(default)]
81    pub rpc_origins: Vec<String>,
82    /// If this app is a game sold on Discord, this field will be the
83    /// URL slug that links to the store page.
84    #[serde(skip_serializing_if = "Option::is_none")]
85    pub slug: Option<String>,
86    /// Tags describing the content and functionality of the application.
87    #[serde(skip_serializing_if = "Option::is_none")]
88    pub tags: Option<Vec<String>>,
89    /// If the app belongs to a team, this will be a list of the
90    /// members of that team.
91    pub team: Option<Team>,
92    /// URL of the application's terms of service.
93    #[serde(skip_serializing_if = "Option::is_none")]
94    pub terms_of_service_url: Option<String>,
95    pub verify_key: String,
96}
97
98#[cfg(test)]
99mod tests {
100    use super::{Application, ApplicationFlags, Team, User};
101    use crate::{id::Id, test::image_hash};
102    use serde::{Deserialize, Serialize};
103    use serde_test::Token;
104    use static_assertions::{assert_fields, assert_impl_all};
105    use std::{fmt::Debug, hash::Hash};
106
107    assert_fields!(
108        Application: bot_public,
109        bot_require_code_grant,
110        cover_image,
111        custom_install_url,
112        description,
113        guild_id,
114        flags,
115        icon,
116        id,
117        install_params,
118        name,
119        owner,
120        primary_sku_id,
121        privacy_policy_url,
122        rpc_origins,
123        slug,
124        tags,
125        team,
126        terms_of_service_url,
127        verify_key
128    );
129
130    assert_impl_all!(
131        Application: Clone,
132        Debug,
133        Deserialize<'static>,
134        Eq,
135        Hash,
136        PartialEq,
137        Serialize
138    );
139
140    #[allow(clippy::too_many_lines)]
141    #[test]
142    fn current_application_info() {
143        let value = Application {
144            approximate_guild_count: Some(2),
145            approximate_user_install_count: Some(5),
146            bot: None,
147            bot_public: true,
148            bot_require_code_grant: false,
149            cover_image: Some(image_hash::COVER),
150            custom_install_url: None,
151            description: "a pretty cool application".to_owned(),
152            flags: Some(ApplicationFlags::EMBEDDED),
153            guild: None,
154            guild_id: Some(Id::new(1)),
155            icon: Some(image_hash::ICON),
156            id: Id::new(2),
157            install_params: None,
158            integration_types_config: None,
159            interactions_endpoint_url: Some("https://interactions".into()),
160            name: "cool application".to_owned(),
161            owner: Some(User {
162                accent_color: None,
163                avatar: None,
164                avatar_decoration: None,
165                avatar_decoration_data: None,
166                banner: None,
167                bot: false,
168                discriminator: 1,
169                email: None,
170                flags: None,
171                global_name: Some("test".to_owned()),
172                id: Id::new(3),
173                locale: None,
174                mfa_enabled: None,
175                name: "app dev".to_owned(),
176                premium_type: None,
177                public_flags: None,
178                system: None,
179                verified: None,
180            }),
181            primary_sku_id: Some(Id::new(4)),
182            privacy_policy_url: Some("https://privacypolicy".into()),
183            redirect_uris: None,
184            role_connections_verification_url: Some("https://roleconnections".into()),
185            rpc_origins: vec!["one".to_owned()],
186            slug: Some("app slug".to_owned()),
187            tags: Some(Vec::from([
188                "ponies".to_owned(),
189                "horses".to_owned(),
190                "friendship".to_owned(),
191                "magic".to_owned(),
192            ])),
193            team: Some(Team {
194                icon: None,
195                id: Id::new(5),
196                members: Vec::new(),
197                name: "team name".into(),
198                owner_user_id: Id::new(6),
199            }),
200            terms_of_service_url: Some("https://termsofservice".into()),
201            verify_key: "key".to_owned(),
202        };
203
204        serde_test::assert_tokens(
205            &value,
206            &[
207                Token::Struct {
208                    name: "Application",
209                    len: 22,
210                },
211                Token::Str("approximate_guild_count"),
212                Token::Some,
213                Token::U64(2),
214                Token::Str("approximate_user_install_count"),
215                Token::Some,
216                Token::U64(5),
217                Token::Str("bot_public"),
218                Token::Bool(true),
219                Token::Str("bot_require_code_grant"),
220                Token::Bool(false),
221                Token::Str("cover_image"),
222                Token::Some,
223                Token::Str(image_hash::COVER_INPUT),
224                Token::Str("description"),
225                Token::Str("a pretty cool application"),
226                Token::Str("flags"),
227                Token::Some,
228                Token::U64(131_072),
229                Token::Str("guild_id"),
230                Token::Some,
231                Token::NewtypeStruct { name: "Id" },
232                Token::Str("1"),
233                Token::Str("icon"),
234                Token::Some,
235                Token::Str(image_hash::ICON_INPUT),
236                Token::Str("id"),
237                Token::NewtypeStruct { name: "Id" },
238                Token::Str("2"),
239                Token::Str("interactions_endpoint_url"),
240                Token::Some,
241                Token::Str("https://interactions"),
242                Token::Str("name"),
243                Token::Str("cool application"),
244                Token::Str("owner"),
245                Token::Some,
246                Token::Struct {
247                    name: "User",
248                    len: 10,
249                },
250                Token::Str("accent_color"),
251                Token::None,
252                Token::Str("avatar"),
253                Token::None,
254                Token::Str("avatar_decoration"),
255                Token::None,
256                Token::Str("avatar_decoration_data"),
257                Token::None,
258                Token::Str("banner"),
259                Token::None,
260                Token::Str("bot"),
261                Token::Bool(false),
262                Token::Str("discriminator"),
263                Token::Str("0001"),
264                Token::Str("global_name"),
265                Token::Some,
266                Token::Str("test"),
267                Token::Str("id"),
268                Token::NewtypeStruct { name: "Id" },
269                Token::Str("3"),
270                Token::Str("username"),
271                Token::Str("app dev"),
272                Token::StructEnd,
273                Token::Str("primary_sku_id"),
274                Token::Some,
275                Token::NewtypeStruct { name: "Id" },
276                Token::Str("4"),
277                Token::Str("privacy_policy_url"),
278                Token::Some,
279                Token::Str("https://privacypolicy"),
280                Token::Str("role_connections_verification_url"),
281                Token::Some,
282                Token::Str("https://roleconnections"),
283                Token::Str("rpc_origins"),
284                Token::Seq { len: Some(1) },
285                Token::Str("one"),
286                Token::SeqEnd,
287                Token::Str("slug"),
288                Token::Some,
289                Token::Str("app slug"),
290                Token::Str("tags"),
291                Token::Some,
292                Token::Seq { len: Some(4) },
293                Token::Str("ponies"),
294                Token::Str("horses"),
295                Token::Str("friendship"),
296                Token::Str("magic"),
297                Token::SeqEnd,
298                Token::Str("team"),
299                Token::Some,
300                Token::Struct {
301                    name: "Team",
302                    len: 5,
303                },
304                Token::Str("icon"),
305                Token::None,
306                Token::Str("id"),
307                Token::NewtypeStruct { name: "Id" },
308                Token::Str("5"),
309                Token::Str("members"),
310                Token::Seq { len: Some(0) },
311                Token::SeqEnd,
312                Token::Str("name"),
313                Token::Str("team name"),
314                Token::Str("owner_user_id"),
315                Token::NewtypeStruct { name: "Id" },
316                Token::Str("6"),
317                Token::StructEnd,
318                Token::Str("terms_of_service_url"),
319                Token::Some,
320                Token::Str("https://termsofservice"),
321                Token::Str("verify_key"),
322                Token::Str("key"),
323                Token::StructEnd,
324            ],
325        );
326    }
327}