Skip to content

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.

events/entitlementCreate.ts
export default
createEvent<"entitlementCreate">(data: {
data: {
name: "entitlementCreate";
once?: boolean;
};
run: (args_0: Entitlement, args_1: UsingClient, args_2: number) => any;
}): {
...;
}

Creates an event with the specified data and run function.

@paramdata - The event data.

@returnsThe created event.

@example const myEvent = createEvent({ data: { name: 'ready', once: true }, run: (user, client, shard) => { client.logger.info(Start ${user.username} on shard #${shard}); } });

createEvent
({
data: {
name: "entitlementCreate";
once?: boolean;
}
data
: {
name: "entitlementCreate"
name
: 'entitlementCreate' },
async
run: (args_0: Entitlement, args_1: UsingClient, args_2: number) => any
run
(
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
: `${
const subscribedUser: User
subscribedUser
.
globalName: string | null
globalName
} (${
const subscribedUser: User
subscribedUser
.
DiscordBase<APIUser>.id: string
id
}) has been subscribed to ${
entitlement: Entitlement
entitlement
.
skuId: string
skuId
}`,
});
},
});

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 { ButtonStyle } from 'seyfert/lib/types';
new
new Button(data?: Partial<APIButtonComponent>): Button

Creates a new Button instance.

@paramdata - The initial data for the button.

Button
()
.
Button.setSKUId(skuId: string): Button
setSKUId
('STORE_ITEM_SKU_ID')
.
Button.setStyle(style: ButtonStyle): Button
setStyle
(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:

commands/premium.ts
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 { 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.

@paramdata - Optional data to initialize the Action Row.

@example const actionRow = new ActionRow({ components: [buttonRawJSON] });

ActionRow
()
.
ActionRow<BuilderComponents>.setComponents(component: BuilderComponents[]): ActionRow<BuilderComponents>

Sets the components of the Action Row.

@paramcomponent - The components to set.

@returnsThe updated Action Row instance.

@example actionRow.setComponents([buttonComponent1, buttonComponent2]);

setComponents
([
new
new Button(data?: Partial<APIButtonComponent>): Button

Creates a new Button instance.

@paramdata - The initial data for the button.

Button
()
.
Button.setSKUId(skuId: string): Button
setSKUId
('STORE_ITEM_SKU_ID')
.
Button.setStyle(style: ButtonStyle): Button
setStyle
(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
}
}