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}