Monetización
Con Seyfert ahora puedes controlar las últimas características de monetización de Discord.
Esta sección mostrará la creación básica de botones premium, eventos y comandos.
Entitlements
Los entitlements en Discord representan que un usuario o servidor tiene acceso a una oferta premium en tu aplicación. Con esto puedes saber si un usuario está suscrito a tu aplicación y otorgarle los beneficios que desees.
Recibiendo Eventos
Actualmente hay 3 eventos para los entitlements:
entitlementCreate(entitlement: Entitlement)
Se emite cada vez que se crea un entitlement.
entitlementDelete(entitlement: Entitlement)
Se emite cada vez que se elimina un entitlement. Los entitlements no se eliminan cuando expiran. Esto solo se activa cuando Discord emite un reembolso o el desarrollador elimina el entitlement manualmente.
entitlementUpdate(entitlement: Entitlement)
Se emite cada vez que se actualiza un entitlement, por ejemplo, cuando se renueva la suscripción de un usuario.
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.
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}) se ha suscrito a ${entitlement: Entitlement
entitlement.skuId: string
skuId}`, }); },});
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: `Reembolso o suscripción eliminada (${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: `Suscripción (${entitlement: Entitlement
entitlement.skuId: string
skuId}) renovada por ${const subscribedUser: User
subscribedUser.globalName: string | null
globalName}`, }); },});
Botón Premium
Ahora puedes crear un Botón que redirija a cualquier artículo en tu tienda, como una suscripción, consumible, etc.
Este tipo de botón no necesita un CustomID o Label, pero sí necesita un SkuID, que puedes obtener desde el menú de tu tienda en 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)
Comandos / Interacciones
En cada Interacción también puedes obtener todos los entitlements activos, con ellos puedes detectar si el usuario tiene alguna suscripción, consumibles, etc.
Ejemplo:
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: 'Comando premium',})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 allEntitlements: Entitlement[]
allEntitlements = ctx: CommandContext<{}, never>
ctx.CommandContext<{}, never>.interaction: ChatInputCommandInteraction<boolean>
interaction.BaseInteraction<boolean, APIChatInputApplicationCommandInteraction>.entitlements: Entitlement[]
entitlements; const const isPremium: boolean
isPremium = const allEntitlements: Entitlement[]
allEntitlements.Array<Entitlement>.some(predicate: (value: Entitlement, index: number, array: Entitlement[]) => unknown, thisArg?: any): boolean
Determines whether the specified callback function returns true for any element of an array.
some(ent: Entitlement
ent => ent: Entitlement
ent.userId?: string | undefined
userId === ctx: CommandContext<{}, never>
ctx.CommandContext<{}, never>.author: User
author.DiscordBase<APIUser>.id: string
id);
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: boolean
isPremium) return ctx: CommandContext<{}, never>
ctx.CommandContext<{}, never>.editOrReply<false>(body: InteractionCreateBodyRequest | InteractionMessageUpdateBodyRequest, withResponse?: false | undefined): Promise<...>
editOrReply({ content: string
content: '¡Haz clic en este botón para suscribirte y obtener acceso al comando!', ResolverProps.components?: APIActionRowComponent<APIMessageActionRowComponent>[] | ActionRow<BuilderComponents>[] | undefined
components: [const row: ActionRow<BuilderComponents>
row] });
// Premium code }}