serenity/model/
monetization.rs

1#[cfg(feature = "model")]
2use crate::builder::{Builder as _, GetEntitlements};
3#[cfg(feature = "model")]
4use crate::http::CacheHttp;
5use crate::model::prelude::*;
6
7/// A premium offering that can be made available to an application's users and guilds.
8///
9/// [Discord docs](https://discord.com/developers/docs/monetization/skus#sku-object).
10#[derive(Clone, Debug, Serialize, Deserialize)]
11pub struct Sku {
12    /// The unique ID of the SKU.
13    pub id: SkuId,
14    /// The class of the SKU.
15    #[serde(rename = "type")]
16    pub kind: SkuKind,
17    /// Id of the SKU's parent application.
18    pub application_id: ApplicationId,
19    /// The customer-facing name of the premium offering.
20    pub name: String,
21    /// A system-generated URL slug based on the SKU.
22    pub slug: String,
23    /// Flags indicating the type of subscription the SKU represents.
24    pub flags: SkuFlags,
25}
26
27impl Sku {
28    /// Returns the store url for this SKU. If included in a message, will render as a rich embed.
29    /// See the [Discord docs] for details.
30    ///
31    /// [Discord docs]: https://discord.com/developers/docs/monetization/skus#linking-to-your-skus
32    #[must_use]
33    pub fn url(&self) -> String {
34        format!(
35            "https://discord.com/application-directory/{}/store/{}",
36            self.application_id, self.id
37        )
38    }
39}
40
41enum_number! {
42    /// Differentiates between SKU classes.
43    ///
44    /// [Discord docs](https://discord.com/developers/docs/monetization/skus#sku-object-sku-types).
45    #[derive(Clone, Debug, Serialize, Deserialize)]
46    #[serde(from = "u8", into = "u8")]
47    #[non_exhaustive]
48    pub enum SkuKind {
49        /// Represents a recurring subscription.
50        Subscription = 5,
51        /// A system-generated group for each SKU created of type [`SkuKind::Subscription`].
52        SubscriptionGroup = 6,
53        _ => Unknown(u8),
54    }
55}
56
57bitflags! {
58    /// Differentates between user and server subscriptions.
59    ///
60    /// [Discord docs](https://discord.com/developers/docs/monetization/skus#sku-object-sku-flags).
61    #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
62    pub struct SkuFlags: u64 {
63        /// SKU is available for purchase.
64        const AVAILABLE = 1 << 2;
65        /// Recurring SKU that can be purchased by a user and applied to a single server. Grants
66        /// access to every user in that server.
67        const GUILD_SUBSCRIPTION = 1 << 7;
68        /// Recurring SKU purchased by a user for themselves. Grants access to the purchasing user
69        /// in every server.
70        const USER_SUBSCRIPTION = 1 << 8;
71    }
72}
73
74/// Represents that a user or guild has access to a premium offering in the application.
75///
76/// [Discord docs](https://discord.com/developers/docs/monetization/entitlements#entitlement-object-entitlement-structure).
77#[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
78#[derive(Clone, Debug, Serialize, Deserialize)]
79pub struct Entitlement {
80    /// The ID of the entitlement.
81    pub id: EntitlementId,
82    /// The ID of the corresponding SKU.
83    pub sku_id: SkuId,
84    /// The ID of the parent application.
85    pub application_id: ApplicationId,
86    /// The ID of the user that is granted access to the SKU.
87    pub user_id: Option<UserId>,
88    /// The type of the entitlement.
89    #[serde(rename = "type")]
90    pub kind: EntitlementKind,
91    /// Whether the entitlement has been deleted or not. Entitlements are not deleted when they
92    /// expire.
93    pub deleted: bool,
94    /// Start date after which the entitlement is valid. Not present when using test entitlements.
95    pub starts_at: Option<Timestamp>,
96    /// End date after which the entitlement is no longer valid. Not present when using test
97    /// entitlements.
98    pub ends_at: Option<Timestamp>,
99    /// The ID of the guild that is granted access to the SKU.
100    pub guild_id: Option<GuildId>,
101}
102
103impl Entitlement {
104    /// Returns a link to the SKU corresponding to this entitlement. See [`Sku::url`] for details.
105    #[must_use]
106    pub fn sku_url(&self) -> String {
107        format!(
108            "https://discord.com/application-directory/{}/store/{}",
109            self.application_id, self.sku_id
110        )
111    }
112
113    /// Returns all entitlements for the current application, active and expired.
114    ///
115    /// # Errors
116    ///
117    /// May error due to an invalid response from discord, or network error.
118    #[cfg(feature = "model")]
119    pub async fn list(
120        cache_http: impl CacheHttp,
121        builder: GetEntitlements,
122    ) -> Result<Vec<Entitlement>> {
123        builder.execute(cache_http, ()).await
124    }
125}
126
127enum_number! {
128    /// Differentiates between Entitlement types.
129    ///
130    /// [Discord docs](https://discord.com/developers/docs/monetization/entitlements#entitlement-object-entitlement-types).
131    #[cfg_attr(feature = "typesize", derive(typesize::derive::TypeSize))]
132    #[derive(Clone, Debug, Serialize, Deserialize)]
133    #[serde(from = "u8", into = "u8")]
134    #[non_exhaustive]
135    pub enum EntitlementKind {
136        /// Entitlement was purchased as an app subscription.
137        ApplicationSubscription = 8,
138        _ => Unknown(u8),
139    }
140}
141
142pub enum EntitlementOwner {
143    Guild(GuildId),
144    User(UserId),
145}