✞
SIASapphire - Imagine a framework
Created by on 2/22/2025 in #sapphire-support
I have use @/ as Root
No description
10 replies
SIASapphire - Imagine a framework
Created by on 2/19/2025 in #sapphire-support
Button Interaction Pass Data
Hello im traying to make a coinflip game which is simple, but I need to pass some data to the button handler and I'm not sure how to do it, and I even need to send and embed to an other channel and interact with 3 differents button which modify the embeds in different ways, if someone can answer all of that I will be happy where some code if something is wrong let me know.
export class GameCoinFlipButton extends InteractionHandler {
public constructor(ctx: InteractionHandler.LoaderContext, options: InteractionHandler.Options) {
super(ctx, {
...options,
interactionHandlerType: InteractionHandlerTypes.Button
});
}

public override parse(interaction: ButtonInteraction) {
if (interaction.customId !== 'confirm') return this.none();

return this.some();
}

public async run(interaction: ButtonInteraction) {
// edit current the message
const newEmbed = successEmbed(`${knowIcon} Coin Flip Confirmed`, `The coin flip has been created. Please wait for someone to join.`);
await interaction.update({ embeds: [newEmbed], components: [] });

// create a new message
const embed = createEmbed(`${knowIcon} Coin Flip Created`, `${gemsIcon} **Gems Amount:** ...\n`);
}
}
export class GameCoinFlipButton extends InteractionHandler {
public constructor(ctx: InteractionHandler.LoaderContext, options: InteractionHandler.Options) {
super(ctx, {
...options,
interactionHandlerType: InteractionHandlerTypes.Button
});
}

public override parse(interaction: ButtonInteraction) {
if (interaction.customId !== 'confirm') return this.none();

return this.some();
}

public async run(interaction: ButtonInteraction) {
// edit current the message
const newEmbed = successEmbed(`${knowIcon} Coin Flip Confirmed`, `The coin flip has been created. Please wait for someone to join.`);
await interaction.update({ embeds: [newEmbed], components: [] });

// create a new message
const embed = createEmbed(`${knowIcon} Coin Flip Created`, `${gemsIcon} **Gems Amount:** ...\n`);
}
}
@ApplyOptions<Command.Options>({
description: 'The upgrader game',
preconditions: ['RoomsOnly', 'HasRegistered']
})
export class GameCoinFlip extends Command {
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) => {
builder
.setName(this.name)
.setDescription(this.description)
.addStringOption((option) =>
option.setName('choice').setDescription('The choice to flip').setRequired(true).addChoices(
{
name: 'Head',
value: 'head'
},
{
name: 'Tails',
value: 'tails'
}
)
)
.addStringOption((option) => option.setName('amount').setDescription('The amount to flip').setRequired(true));
});
}
public override async chatInputRun(interaction: ChatInputCommandInteraction, _context: ChatInputCommand.RunContext) {
try {
await this.sendInfo(interaction);
} catch (error) {
console.error('Error in chatInputRun:', error);
await interaction.reply({ content: 'An error occurred while processing your request.', ephemeral: true });
}
}

private async sendInfo(interaction: ChatInputCommandInteraction) {
const choice = interaction.options.getString('choice');
const amountOption = interaction.options.getString('amount');

if (!amountOption || !choice) {
return await interaction.reply({ content: 'Amount and choice are required options.', ephemeral: true });
}

const amount = suffixToAmount(amountOption);

const user = await prisma.userStakes.findUnique({ where: { userId: Number(interaction.user.id) } });
if (!user || !checkIfUserHasBalance(user.userId, amount, interaction)) {
return await interaction.reply({ content: 'insufficient balance.', ephemeral: true });
}

const embed = createEmbed(
`${knowIcon} Coin Flip Confirmation`,
`${gemsIcon} **Gems Amount:** ${amountToSuffix(amount)}\n` + `${diceIcon} **Side:** ${choice}\n`
);
const confirmButton = new ButtonBuilder().setCustomId('confirm').setLabel('Confirm').setStyle(ButtonStyle.Secondary);

const row = new ActionRowBuilder<ButtonBuilder>().addComponents(confirmButton);

return await interaction.reply({ embeds: [embed], components: [row] });
}
}
@ApplyOptions<Command.Options>({
description: 'The upgrader game',
preconditions: ['RoomsOnly', 'HasRegistered']
})
export class GameCoinFlip extends Command {
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) => {
builder
.setName(this.name)
.setDescription(this.description)
.addStringOption((option) =>
option.setName('choice').setDescription('The choice to flip').setRequired(true).addChoices(
{
name: 'Head',
value: 'head'
},
{
name: 'Tails',
value: 'tails'
}
)
)
.addStringOption((option) => option.setName('amount').setDescription('The amount to flip').setRequired(true));
});
}
public override async chatInputRun(interaction: ChatInputCommandInteraction, _context: ChatInputCommand.RunContext) {
try {
await this.sendInfo(interaction);
} catch (error) {
console.error('Error in chatInputRun:', error);
await interaction.reply({ content: 'An error occurred while processing your request.', ephemeral: true });
}
}

private async sendInfo(interaction: ChatInputCommandInteraction) {
const choice = interaction.options.getString('choice');
const amountOption = interaction.options.getString('amount');

if (!amountOption || !choice) {
return await interaction.reply({ content: 'Amount and choice are required options.', ephemeral: true });
}

const amount = suffixToAmount(amountOption);

const user = await prisma.userStakes.findUnique({ where: { userId: Number(interaction.user.id) } });
if (!user || !checkIfUserHasBalance(user.userId, amount, interaction)) {
return await interaction.reply({ content: 'insufficient balance.', ephemeral: true });
}

const embed = createEmbed(
`${knowIcon} Coin Flip Confirmation`,
`${gemsIcon} **Gems Amount:** ${amountToSuffix(amount)}\n` + `${diceIcon} **Side:** ${choice}\n`
);
const confirmButton = new ButtonBuilder().setCustomId('confirm').setLabel('Confirm').setStyle(ButtonStyle.Secondary);

const row = new ActionRowBuilder<ButtonBuilder>().addComponents(confirmButton);

return await interaction.reply({ embeds: [embed], components: [row] });
}
}
13 replies
SIASapphire - Imagine a framework
Created by on 2/18/2025 in #sapphire-support
How to organize commands?
Hello, Im new to TS and Discord.JS, but I have knowloadge on programming, but this framework is new to me, I need to make different commands, I have create 3 folders, user, admin, games, every dir has it owns games and class (not made all but im there), and this is a simple class Im not sure if this what Im doing is correct, but for organizing it should be. this is the code I have made if there is a better way of doing this lmk:
import { ApplyOptions } from '@sapphire/decorators';
import { ChatInputCommand, Command } from '@sapphire/framework';
import { ChatInputCommandInteraction, EmbedBuilder } from 'discord.js';
import { createEmbed } from '../../lib/utils';

@ApplyOptions<Command.Options>({
description: 'Show user balance'
})
export class UserBalance extends Command {
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) => {
builder
.setName(this.name)
.setDescription(this.description)
.addUserOption((option) => option.setName('user').setDescription('The user to check').setRequired(false));
});
}

public override async chatInputRun(interaction: ChatInputCommandInteraction, _context: ChatInputCommand.RunContext) {
return this.sendInfo(interaction);
}

private async sendInfo(interaction: Command.ChatInputCommandInteraction) {
const user = interaction.options.getUser('user') ?? interaction.user;
const embed: EmbedBuilder = createEmbed('Balance', `balance of ${user.username}`);
await interaction.reply({ embeds: [embed] });
}
}
import { ApplyOptions } from '@sapphire/decorators';
import { ChatInputCommand, Command } from '@sapphire/framework';
import { ChatInputCommandInteraction, EmbedBuilder } from 'discord.js';
import { createEmbed } from '../../lib/utils';

@ApplyOptions<Command.Options>({
description: 'Show user balance'
})
export class UserBalance extends Command {
public override registerApplicationCommands(registry: Command.Registry) {
registry.registerChatInputCommand((builder) => {
builder
.setName(this.name)
.setDescription(this.description)
.addUserOption((option) => option.setName('user').setDescription('The user to check').setRequired(false));
});
}

public override async chatInputRun(interaction: ChatInputCommandInteraction, _context: ChatInputCommand.RunContext) {
return this.sendInfo(interaction);
}

private async sendInfo(interaction: Command.ChatInputCommandInteraction) {
const user = interaction.options.getUser('user') ?? interaction.user;
const embed: EmbedBuilder = createEmbed('Balance', `balance of ${user.username}`);
await interaction.reply({ embeds: [embed] });
}
}
12 replies
SIASapphire - Imagine a framework
Created by on 2/18/2025 in #sapphire-support
Help me to setup this sapphire typescript
Hello im new to ts and discord.js, I have made some bot in discord.py, but I wanna level up and using typescript and sapphire, but I have no idea how to, please someone?
8 replies
Buttons Interactions
Hello fellows, I have some questions. I'm a developer with experience with jda-ktx and JDA, I'm not great with shappire, I'm trying to learn it because it is really fast to boot up and does all of the things in milliseconds compared to the java one. My question is, I have many embeds with buttons, they should modify the embed for the user that created the embed, but I have no idea how cold I do that. Does anyone know how I can fix this?
72 replies