mirror of
https://github.com/ahmadk953/poixpixel-discord-bot.git
synced 2025-05-10 02:33:06 +00:00
375 lines
11 KiB
TypeScript
375 lines
11 KiB
TypeScript
import {
|
|
ActionRowBuilder,
|
|
ButtonBuilder,
|
|
ButtonInteraction,
|
|
ButtonStyle,
|
|
ChatInputCommandInteraction,
|
|
EmbedBuilder,
|
|
} from 'discord.js';
|
|
|
|
import { GiveawaySession } from './types.js';
|
|
import { DEFAULT_REQUIRE_ALL, DEFAULT_WINNER_COUNT } from './constants.js';
|
|
import { getSession, saveSession } from './utils.js';
|
|
|
|
/**
|
|
* Handles the start of the giveaway builder.
|
|
* @param interaction The interaction object from the command or button click.
|
|
*/
|
|
export async function startGiveawayBuilder(
|
|
interaction: ChatInputCommandInteraction | ButtonInteraction,
|
|
): Promise<void> {
|
|
await interaction.deferReply({ flags: ['Ephemeral'] });
|
|
|
|
const session: GiveawaySession = {
|
|
step: 1,
|
|
winnerCount: DEFAULT_WINNER_COUNT,
|
|
requirements: {
|
|
requireAll: DEFAULT_REQUIRE_ALL,
|
|
},
|
|
};
|
|
|
|
await saveSession(interaction.user.id, session);
|
|
await showBuilderStep(interaction, session);
|
|
}
|
|
|
|
/**
|
|
* Handles the display of the current step in the giveaway builder.
|
|
* @param interaction The interaction object from the command or button click.
|
|
* @param session The current giveaway session.
|
|
*/
|
|
export async function showBuilderStep(
|
|
interaction: any,
|
|
session: GiveawaySession,
|
|
): Promise<void> {
|
|
if (!interaction.isCommand() && interaction.responded) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
let embed: EmbedBuilder;
|
|
const components: ActionRowBuilder<ButtonBuilder>[] = [];
|
|
|
|
switch (session.step) {
|
|
case 1:
|
|
embed = createStep1Embed(session);
|
|
components.push(createStep1Buttons(session));
|
|
break;
|
|
case 2:
|
|
embed = createStep2Embed(session);
|
|
components.push(...createStep2Buttons(session));
|
|
break;
|
|
case 3:
|
|
embed = createStep3Embed(session);
|
|
components.push(...createStep3Buttons(session));
|
|
break;
|
|
case 4:
|
|
embed = createStep4Embed(session);
|
|
components.push(...createStep4Buttons());
|
|
break;
|
|
case 5:
|
|
embed = createStep5Embed(session);
|
|
components.push(...createStep5Buttons());
|
|
break;
|
|
default:
|
|
embed = new EmbedBuilder()
|
|
.setTitle('🎉 Giveaway Creation')
|
|
.setDescription('Setting up your giveaway...')
|
|
.setColor(0x3498db);
|
|
}
|
|
|
|
if (interaction.replied || interaction.deferred) {
|
|
await interaction.editReply({ embeds: [embed], components });
|
|
} else {
|
|
await interaction.update({ embeds: [embed], components });
|
|
}
|
|
} catch (error) {
|
|
console.error('Error in showBuilderStep:', error);
|
|
if (!interaction.replied) {
|
|
try {
|
|
await interaction.reply({
|
|
content: 'There was an error updating the giveaway builder.',
|
|
flags: ['Ephemeral'],
|
|
});
|
|
} catch (replyError) {
|
|
console.error('Failed to send error reply:', replyError);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handles the next step in the giveaway builder.
|
|
* @param interaction The interaction object from the button click.
|
|
*/
|
|
export async function nextBuilderStep(
|
|
interaction: ButtonInteraction,
|
|
): Promise<void> {
|
|
const session = await getSession(interaction.user.id);
|
|
if (!session) {
|
|
await interaction.reply({
|
|
content: 'Your giveaway session has expired. Please start over.',
|
|
flags: ['Ephemeral'],
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (session.step === 1) {
|
|
if (!session.prize || !session.endTime) {
|
|
await interaction.reply({
|
|
content: 'Please set both prize and duration before continuing.',
|
|
flags: ['Ephemeral'],
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (!(session.endTime instanceof Date)) {
|
|
await interaction.reply({
|
|
content: 'Invalid duration setting. Please set the duration again.',
|
|
flags: ['Ephemeral'],
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
|
|
session.step = Math.min(session.step + 1, 5);
|
|
await saveSession(interaction.user.id, session);
|
|
await showBuilderStep(interaction, session);
|
|
}
|
|
|
|
/**
|
|
* Handles the previous step in the giveaway builder.
|
|
* @param interaction The interaction object from the button click.
|
|
*/
|
|
export async function previousBuilderStep(
|
|
interaction: ButtonInteraction,
|
|
): Promise<void> {
|
|
const session = await getSession(interaction.user.id);
|
|
if (!session) {
|
|
await interaction.reply({
|
|
content: 'Your giveaway session has expired. Please start over.',
|
|
flags: ['Ephemeral'],
|
|
});
|
|
return;
|
|
}
|
|
|
|
session.step = Math.max(session.step - 1, 1);
|
|
await saveSession(interaction.user.id, session);
|
|
await showBuilderStep(interaction, session);
|
|
}
|
|
|
|
function createStep1Embed(session: GiveawaySession): EmbedBuilder {
|
|
const endTimeValue =
|
|
session.endTime instanceof Date
|
|
? `${session.duration} (ends <t:${Math.floor(session.endTime.getTime() / 1000)}:R>)`
|
|
: 'Not set';
|
|
|
|
return new EmbedBuilder()
|
|
.setTitle(' Giveaway Creation - Step 1/5')
|
|
.setDescription('Set the basic details for your giveaway.')
|
|
.setColor(0x3498db)
|
|
.addFields([
|
|
{ name: 'Prize', value: session.prize || 'Not set', inline: true },
|
|
{ name: 'Duration', value: endTimeValue, inline: true },
|
|
{ name: 'Winners', value: session.winnerCount.toString(), inline: true },
|
|
]);
|
|
}
|
|
|
|
function createStep1Buttons(
|
|
session: GiveawaySession,
|
|
): ActionRowBuilder<ButtonBuilder> {
|
|
return new ActionRowBuilder<ButtonBuilder>().addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_set_prize')
|
|
.setLabel('Set Prize')
|
|
.setStyle(ButtonStyle.Primary),
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_set_duration')
|
|
.setLabel('Set Duration')
|
|
.setStyle(ButtonStyle.Primary),
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_set_winners')
|
|
.setLabel('Set Winners')
|
|
.setStyle(ButtonStyle.Primary),
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_next')
|
|
.setLabel('Next Step')
|
|
.setStyle(ButtonStyle.Success)
|
|
.setDisabled(!session.prize || !session.endTime),
|
|
);
|
|
}
|
|
|
|
function createStep2Embed(session: GiveawaySession): EmbedBuilder {
|
|
const requirementsList = [];
|
|
if (session.requirements?.level) {
|
|
requirementsList.push(`• Level ${session.requirements.level}+`);
|
|
}
|
|
if (session.requirements?.roleId) {
|
|
requirementsList.push(`• Role <@&${session.requirements.roleId}>`);
|
|
}
|
|
if (session.requirements?.messageCount) {
|
|
requirementsList.push(`• ${session.requirements.messageCount}+ messages`);
|
|
}
|
|
|
|
const requirementsText = requirementsList.length
|
|
? `${session.requirements.requireAll ? 'ALL requirements must be met' : 'ANY ONE requirement must be met'}\n${requirementsList.join('\n')}`
|
|
: 'No requirements set';
|
|
|
|
return new EmbedBuilder()
|
|
.setTitle('🎉 Giveaway Creation - Step 2/5')
|
|
.setDescription('Set entry requirements for your giveaway (optional).')
|
|
.setColor(0x3498db)
|
|
.addFields([
|
|
{ name: 'Prize', value: session.prize || 'Not set' },
|
|
{ name: 'Requirements', value: requirementsText },
|
|
]);
|
|
}
|
|
|
|
function createStep2Buttons(
|
|
session: GiveawaySession,
|
|
): ActionRowBuilder<ButtonBuilder>[] {
|
|
return [
|
|
new ActionRowBuilder<ButtonBuilder>().addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_set_requirements')
|
|
.setLabel('Set Requirements')
|
|
.setStyle(ButtonStyle.Primary),
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_toggle_logic')
|
|
.setLabel(
|
|
session.requirements.requireAll ? 'Require ANY' : 'Require ALL',
|
|
)
|
|
.setStyle(ButtonStyle.Secondary),
|
|
),
|
|
new ActionRowBuilder<ButtonBuilder>().addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_previous')
|
|
.setLabel('Previous Step')
|
|
.setStyle(ButtonStyle.Secondary),
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_next')
|
|
.setLabel('Next Step')
|
|
.setStyle(ButtonStyle.Success),
|
|
),
|
|
];
|
|
}
|
|
|
|
function createStep3Embed(session: GiveawaySession): EmbedBuilder {
|
|
const embed = new EmbedBuilder()
|
|
.setTitle('🎉 Giveaway Creation - Step 3/5')
|
|
.setDescription('Select Giveaway Channel (optional).')
|
|
.setColor(0x3498db)
|
|
.addFields([
|
|
{
|
|
name: 'Channel',
|
|
value: session.channelId
|
|
? `<#${session.channelId}>`
|
|
: 'Current Channel',
|
|
},
|
|
]);
|
|
|
|
return embed;
|
|
}
|
|
|
|
function createStep3Buttons(
|
|
session: GiveawaySession,
|
|
): ActionRowBuilder<ButtonBuilder>[] {
|
|
return [
|
|
new ActionRowBuilder<ButtonBuilder>().addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_set_channel')
|
|
.setLabel(session.channelId ? 'Change Channel' : 'Set Channel')
|
|
.setStyle(ButtonStyle.Primary),
|
|
),
|
|
new ActionRowBuilder<ButtonBuilder>().addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_previous')
|
|
.setLabel('Previous Step')
|
|
.setStyle(ButtonStyle.Secondary),
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_next')
|
|
.setLabel('Next Step')
|
|
.setStyle(ButtonStyle.Success),
|
|
),
|
|
];
|
|
}
|
|
|
|
function createStep4Embed(session: GiveawaySession): EmbedBuilder {
|
|
const bonusEntries = session.bonusEntries || {};
|
|
|
|
const rolesText =
|
|
bonusEntries.roles?.map((r) => `<@&${r.id}>: +${r.entries}`).join('\n') ||
|
|
'None';
|
|
const levelsText =
|
|
bonusEntries.levels
|
|
?.map((l) => `Level ${l.threshold}+: +${l.entries}`)
|
|
.join('\n') || 'None';
|
|
const messagesText =
|
|
bonusEntries.messages
|
|
?.map((m) => `${m.threshold}+ messages: +${m.entries}`)
|
|
.join('\n') || 'None';
|
|
|
|
return new EmbedBuilder()
|
|
.setTitle('🎉 Giveaway Creation - Step 4/5')
|
|
.setDescription('Configure bonus entries for your giveaway.')
|
|
.setColor(0x3498db)
|
|
.addFields([
|
|
{ name: 'Role Bonuses', value: rolesText, inline: true },
|
|
{ name: 'Level Bonuses', value: levelsText, inline: true },
|
|
{ name: 'Message Bonuses', value: messagesText, inline: true },
|
|
]);
|
|
}
|
|
|
|
function createStep4Buttons(): ActionRowBuilder<ButtonBuilder>[] {
|
|
return [
|
|
new ActionRowBuilder<ButtonBuilder>().addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_bonus_entries')
|
|
.setLabel('Set Bonus Entries')
|
|
.setStyle(ButtonStyle.Primary),
|
|
),
|
|
new ActionRowBuilder<ButtonBuilder>().addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_previous')
|
|
.setLabel('Previous Step')
|
|
.setStyle(ButtonStyle.Secondary),
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_next')
|
|
.setLabel('Next Step')
|
|
.setStyle(ButtonStyle.Success),
|
|
),
|
|
];
|
|
}
|
|
|
|
function createStep5Embed(session: GiveawaySession): EmbedBuilder {
|
|
return new EmbedBuilder()
|
|
.setTitle('🎉 Giveaway Creation - Step 5/5')
|
|
.setDescription('Finalize your giveaway settings.')
|
|
.setColor(0x3498db)
|
|
.addFields([
|
|
{
|
|
name: 'Role to Ping',
|
|
value: session.pingRoleId ? `<@&${session.pingRoleId}>` : 'None',
|
|
},
|
|
]);
|
|
}
|
|
|
|
function createStep5Buttons(): ActionRowBuilder<ButtonBuilder>[] {
|
|
return [
|
|
new ActionRowBuilder<ButtonBuilder>().addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_set_ping_role')
|
|
.setLabel('Set Ping Role')
|
|
.setStyle(ButtonStyle.Primary),
|
|
),
|
|
new ActionRowBuilder<ButtonBuilder>().addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_previous')
|
|
.setLabel('Previous Step')
|
|
.setStyle(ButtonStyle.Secondary),
|
|
new ButtonBuilder()
|
|
.setCustomId('giveaway_publish')
|
|
.setLabel('Create Giveaway')
|
|
.setStyle(ButtonStyle.Success),
|
|
),
|
|
];
|
|
}
|