Files
ShaiBot/utils/crumbSaucer.js
T
2026-08-22 22:10:41 +02:00

317 lines
7.0 KiB
JavaScript

const {
EmbedBuilder,
ActionRowBuilder,
ButtonBuilder,
ButtonStyle
} = require("discord.js");
const {
getCookieBalance,
temporaryEphemeralReply
} = require("./cookieEconomy");
/*
* ============================================================
* MAIN MENU
* ============================================================
*/
async function showCrumbSaucer(
interaction
) {
/*
* Button navigation must preserve ownership.
*/
if (
interaction.isButton()
) {
const ownerId =
getCrumbSaucerSessionOwner(
interaction
);
if (
ownerId !==
interaction.user.id
) {
return temporaryEphemeralReply(
interaction,
{
content:
"This isn't your Crumb Saucer session."
}
);
}
}
const balance =
await getCookieBalance(
interaction.user.id
);
const embed =
buildMainMenuEmbed(
interaction.user,
balance
);
if (
interaction.isButton()
) {
return interaction.update({
embeds: [
embed
],
components:
buildMainMenuButtons()
});
}
return interaction.reply({
embeds: [
embed
],
components:
buildMainMenuButtons()
});
}
/*
* ============================================================
* MAIN MENU EMBED
* ============================================================
*/
function buildMainMenuEmbed(
user,
balance
) {
return new EmbedBuilder()
.setTitle(
"🎰 The Crumb Saucer"
)
.setDescription(
[
`Welcome, ${user}!`,
"",
"Where Cookies are won, lost,",
"and occasionally confiscated by ShaiBot.",
"",
"### 🍪 Cookie Bakery",
"Collect your regular batch of Cookies.",
"",
"### 🎰 Slots",
"Spin the reels and chase the Cookie jackpot.",
"",
"### 🃏 Blackjack",
"Beat the dealer without going over 21.",
"",
"### 🎡 Roulette",
"Bet on Red, Black, Odd, Even, or Zero.",
"",
"### 🏦 Vault Heist",
"Attempt to breach ShaiBot's Cookie Vault."
].join("\n")
)
.addFields({
name:
"Your Vault",
value:
`**${balance.toLocaleString()} 🍪**`
})
.setFooter({
text:
`crumbSaucer:${user.id}`
});
}
/*
* ============================================================
* MAIN MENU BUTTONS
* ============================================================
*/
function buildMainMenuButtons() {
return [
new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId(
"crumbSaucerSlots"
)
.setLabel(
"Slots"
)
.setEmoji(
"🎰"
)
.setStyle(
ButtonStyle.Primary
),
new ButtonBuilder()
.setCustomId(
"crumbSaucerBlackjack"
)
.setLabel(
"Blackjack"
)
.setEmoji(
"🃏"
)
.setStyle(
ButtonStyle.Success
),
new ButtonBuilder()
.setCustomId(
"crumbSaucerRoulette"
)
.setLabel(
"Roulette"
)
.setEmoji(
"🎡"
)
.setStyle(
ButtonStyle.Primary
),
new ButtonBuilder()
.setCustomId(
"crumbSaucerHeist"
)
.setLabel(
"Vault Heist"
)
.setEmoji(
"🏦"
)
.setStyle(
ButtonStyle.Danger
)
),
new ActionRowBuilder()
.addComponents(
new ButtonBuilder()
.setCustomId(
"crumbSaucerCollectMenu"
)
.setLabel(
"Cookie Bakery"
)
.setEmoji(
"🍪"
)
.setStyle(
ButtonStyle.Success
),
/*
* Do NOT use global "abort" here.
*
* The dedicated handler validates
* Crumb Saucer ownership first.
*/
new ButtonBuilder()
.setCustomId(
"crumbSaucerClose"
)
.setLabel(
"Close"
)
.setEmoji(
"✖️"
)
.setStyle(
ButtonStyle.Secondary
)
)
];
}
/*
* ============================================================
* SESSION OWNER
* ============================================================
*/
function getCrumbSaucerSessionOwner(
interaction
) {
const footer =
interaction.message
?.embeds?.[0]
?.footer
?.text;
const parts =
footer?.split(":")
??
[];
switch (
parts[0]
) {
case "crumbSaucer":
case "crumbSaucerCollect":
case "crumbSaucerSlots":
case "crumbSaucerSlotsResult":
case "crumbSaucerBlackjack":
case "crumbBlackjackResult":
case "crumbRouletteMenu":
case "crumbRouletteBet":
case "crumbRouletteResult":
case "cookieHeist":
return parts[1];
/*
* Active Blackjack:
*
* crumbBlackjack:<gameId>:<userId>
*/
case "crumbBlackjack":
return parts[2];
default:
return null;
}
}
/*
* ============================================================
* EXPORTS
* ============================================================
*/
module.exports = {
showCrumbSaucer,
getCrumbSaucerSessionOwner
};