Monetization
With Seyfert you can now control the latest Discord monetization features.
This section will show the basic creation of premium buttons, events and commands.
Entitlements
Entitlements in Discord represent that a user or guild has access to a premium offering in your application, with this you can know if a user is subscribed to your application and give him the benefits you want.
Receiving Events
Currently there are 3 events for entitlements:
entitlementCreate(entitlement: Entitlement)
Emitted whenever an entitlement is created.
entitlementDelete(entitlement: Entitlement)
Emitted whenever an entitlement is deleted. Entitlements are not deleted when they expire. This is only triggered when Discord issues a refund or deletes the entitlement manually.
entitlementUpdate(entitlement: Entitlement)
Emitted whenever an entitlement is updated - i.e. when a user’s subscription renews.
export default createEvent<"entitlementDelete">(data: { data: { name: "entitlementDelete"; once?: boolean; }; run: (args_0: Entitlement, args_1: UsingClient, args_2: number) => any;}): { ...;}
Creates an event with the specified data and run function.
createEvent({ data: { name: "entitlementDelete"; once?: boolean;}
data: { name: "entitlementDelete"
name: 'entitlementDelete' }, run: (args_0: Entitlement, args_1: UsingClient, args_2: number) => any
run(entitlement: Entitlement
entitlement, client: UsingClient
client) { client: UsingClient
client.BaseClient.messages: MessageShorter
messages.MessageShorter.write(channelId: string, { files, ...body }: MessageCreateBodyRequest): Promise<MessageStructure>
write('LOG_CHANNEL_ID', { content?: string | undefined
The message contents (up to 2000 characters)
content: `Refund or subscription deleted (${entitlement: Entitlement
entitlement.skuId: string
skuId}) [${entitlement: Entitlement
entitlement.type: EntitlementType
type}]`, }); },});
export default createEvent<"entitlementUpdate">(data: { data: { name: "entitlementUpdate"; once?: boolean; }; run: (args_0: Entitlement, args_1: UsingClient, args_2: number) => any;}): { ...;}
Creates an event with the specified data and run function.
createEvent({ data: { name: "entitlementUpdate"; once?: boolean;}
data: { name: "entitlementUpdate"
name: 'entitlementUpdate' }, run: (args_0: Entitlement, args_1: UsingClient, args_2: number) => any
run: async (entitlement: Entitlement
entitlement, client: UsingClient
client) => { if (!entitlement: Entitlement
entitlement.userId?: string | undefined
userId) return; const const subscribedUser: User
subscribedUser = await client: UsingClient
client.BaseClient.users: UsersShorter
users.UsersShorter.fetch(userId: string, force?: boolean): Promise<UserStructure>
fetch(entitlement: Entitlement
entitlement.userId?: string
userId); client: UsingClient
client.BaseClient.messages: MessageShorter
messages.MessageShorter.write(channelId: string, { files, ...body }: MessageCreateBodyRequest): Promise<MessageStructure>
write('LOG_CHANNEL_ID', { content?: string | undefined
The message contents (up to 2000 characters)
content: `Subscription (${entitlement: Entitlement
entitlement.skuId: string
skuId}) renewed by ${const subscribedUser: User
subscribedUser.globalName: string | null
globalName}`, }); },});
Premium Button
Now you can create a Button that redirects to any item in your store, such as a subscription, consumable, etc.
This type of button does not need a CustomID or Label, but it does need a SkuID, which you can get from your store menu at https://discord.com/developers/applications/{APP_ID}/skus
import { class Button
Represents a button component.
Button } from 'seyfert';import { enum ButtonStyle
ButtonStyle } from 'seyfert/lib/types';
new new Button(data?: Partial<APIButtonComponent>): Button
Creates a new Button instance.
Button().Button.setSKUId(skuId: string): Button
setSKUId('STORE_ITEM_SKU_ID').Button.setStyle(style: ButtonStyle): Button
setStyle(enum ButtonStyle
ButtonStyle.function (enum member) ButtonStyle.Premium = 6
Premium)
Commands / Interactions
In each Interaction you can also get all the active entitlements, with them you can detect if the user has any subscriptions, consumables, etc.
Example:
import { function Declare(declare: CommandDeclareOptions): <T extends { new (...args: any[]): object;}>(target: T) => { new (...args: any[]): { name: string; nsfw: boolean | undefined; props: ExtraProps | undefined; contexts: InteractionContextType[]; integrationTypes: ApplicationIntegrationType[]; defaultMemberPermissions: bigint | undefined; botPermissions: bigint | undefined; description: string; type: ApplicationCommandType; guildId?: string[]; ignore?: IgnoreCommand; aliases?: string[]; handler?: EntryPointCommandHandlerType; };} & T
Declare, class Command
Command, type class CommandContext<T extends OptionsRecord = {}, M extends keyof RegisteredMiddlewares = never>interface CommandContext<T extends OptionsRecord = {}, M extends keyof RegisteredMiddlewares = never>
CommandContext, class ActionRow<T extends BuilderComponents>
Represents an Action Row component in a message.
ActionRow, class Button
Represents a button component.
Button } from 'seyfert';import { enum ButtonStyle
ButtonStyle } from 'seyfert/lib/types';
@function Declare(declare: CommandDeclareOptions): <T extends { new (...args: any[]): object;}>(target: T) => { new (...args: any[]): { name: string; nsfw: boolean | undefined; props: ExtraProps | undefined; contexts: InteractionContextType[]; integrationTypes: ApplicationIntegrationType[]; defaultMemberPermissions: bigint | undefined; botPermissions: bigint | undefined; description: string; type: ApplicationCommandType; guildId?: string[]; ignore?: IgnoreCommand; aliases?: string[]; handler?: EntryPointCommandHandlerType; };} & T
Declare({ name: string
name: 'premium', description: string
description: 'Premium command',})export class class PremiumCommand
PremiumCommand extends class Command
Command { PremiumCommand.run(ctx: CommandContext): Promise<void | WebhookMessage> | undefined
run(ctx: CommandContext<{}, never>
ctx: class CommandContext<T extends OptionsRecord = {}, M extends keyof RegisteredMiddlewares = never>interface CommandContext<T extends OptionsRecord = {}, M extends keyof RegisteredMiddlewares = never>
CommandContext) { const const isPremium: number
isPremium = ctx: CommandContext<{}, never>
ctx.CommandContext<{}, never>.interaction: ChatInputCommandInteraction<boolean>
interaction.BaseInteraction<boolean, APIChatInputApplicationCommandInteraction>.entitlements: Entitlement[]
entitlements.Array<T>.length: number
Gets or sets the length of the array. This is a number one higher than the highest index in the array.
length;
const const row: ActionRow<BuilderComponents>
row = new new ActionRow<BuilderComponents>({ components, ...data }?: Partial<APIActionRowComponent<APIActionRowComponentTypes>>): ActionRow<...>
Creates a new instance of the ActionRow class.
ActionRow() .ActionRow<BuilderComponents>.setComponents(component: BuilderComponents[]): ActionRow<BuilderComponents>
Sets the components of the Action Row.
setComponents([ new new Button(data?: Partial<APIButtonComponent>): Button
Creates a new Button instance.
Button() .Button.setSKUId(skuId: string): Button
setSKUId('STORE_ITEM_SKU_ID') .Button.setStyle(style: ButtonStyle): Button
setStyle(enum ButtonStyle
ButtonStyle.function (enum member) ButtonStyle.Premium = 6
Premium) ]);
if (!const isPremium: number
isPremium) return ctx: CommandContext<{}, never>
ctx.CommandContext<{}, never>.editOrReply<false>(body: InteractionCreateBodyRequest | InteractionMessageUpdateBodyRequest, withResponse?: false | undefined): Promise<...>
editOrReply({ content: string
content: 'Click to subscribe and get access to the command!', ResolverProps.components?: APIActionRowComponent<APIMessageActionRowComponent>[] | ActionRow<BuilderComponents>[] | undefined
components: [const row: ActionRow<BuilderComponents>
row] });
// Premium code }}