const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require("discord.js"); const { getCookieBalance, changeCookies, claimCooldown, temporaryEphemeralReply } = require("./cookieEconomy"); const { trackProfileEvent } = require("./profileSystem"); /* * ============================================================ * CONFIG * ============================================================ */ const COLLECT_COOLDOWN = 60 * 60; /* * IMPORTANT: * * Always use exactly the same cooldown key. */ const COLLECT_COOLDOWN_KEY = "collect"; /* * ============================================================ * SHOW COLLECT PAGE * ============================================================ */ async function showCollectPage( interaction ) { const ownerId = getCollectOwner( 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 = new EmbedBuilder() .setTitle( "🍪 Crumb Saucer Cookie Bakery" ) .setDescription( [ "Fresh Cookies are prepared regularly.", "", "Press **Collect Cookies** to claim your batch.", "", "Your collection cooldown is shared with `/cookies collect`." ].join("\n") ) .addFields({ name: "Your Vault", value: `**${balance.toLocaleString()} 🍪**` }) .setFooter({ text: `crumbSaucerCollect:${interaction.user.id}` }); return interaction.update({ embeds: [ embed ], components: buildCollectButtons() }); } /* * ============================================================ * COLLECT * ============================================================ */ async function collectCookiesFromSaucer( interaction ) { const ownerId = getCollectOwner( interaction ); if ( ownerId !== interaction.user.id ) { return temporaryEphemeralReply( interaction, { content: "This isn't your Crumb Saucer session." } ); } /* * Mongo-backed cooldown. * * Same pattern as Cookie Heist: * * userId * guildId * cooldown key * duration */ const cooldown = await claimCooldown( interaction.user.id, interaction.guildId, COLLECT_COOLDOWN_KEY, COLLECT_COOLDOWN ); /* * Already collected. */ if ( !cooldown.claimed ) { const balance = await getCookieBalance( interaction.user.id ); const embed = new EmbedBuilder() .setTitle( "🍪 Cookie Bakery" ) .setDescription( [ "Your next batch isn't ready yet.", "", `Come back .` ].join("\n") ) .addFields({ name: "Your Vault", value: `**${balance.toLocaleString()} 🍪**` }) .setFooter({ text: `crumbSaucerCollect:${interaction.user.id}` }); return interaction.update({ embeds: [ embed ], components: buildCollectButtons() }); } /* * ======================================================== * GENERATE BATCH * ======================================================== */ const amount = Math.floor( Math.random() * 1000 ) + 1; await changeCookies( interaction.user.id, amount ); /* * Profile / achievements. */ await trackProfileEvent( interaction, interaction.user.id, { type: "cookie_gain", amount } ); const balance = await getCookieBalance( interaction.user.id ); const embed = new EmbedBuilder() .setTitle( "🍪 Fresh Batch!" ) .setDescription( [ `You collected **${amount.toLocaleString()} Cookies**! 🍪`, "", `Your next batch will be ready .` ].join("\n") ) .addFields({ name: "Your Vault", value: `**${balance.toLocaleString()} 🍪**` }) .setFooter({ text: `crumbSaucerCollect:${interaction.user.id}` }); return interaction.update({ embeds: [ embed ], components: buildCollectButtons() }); } /* * ============================================================ * BUTTONS * ============================================================ */ function buildCollectButtons() { return [ new ActionRowBuilder() .addComponents( new ButtonBuilder() .setCustomId( "crumbSaucerCollect" ) .setLabel( "Collect Cookies" ) .setEmoji( "🍪" ) .setStyle( ButtonStyle.Success ), new ButtonBuilder() .setCustomId( "crumbSaucerBack" ) .setLabel( "Crumb Saucer" ) .setEmoji( "◀️" ) .setStyle( ButtonStyle.Secondary ) ) ]; } /* * ============================================================ * OWNER * ============================================================ */ function getCollectOwner( interaction ) { const footer = interaction.message ?.embeds?.[0] ?.footer ?.text; const parts = footer?.split(":") ?? []; /* * Main menu -> Cookie Bakery. */ if ( parts[0] === "crumbSaucer" ) { return parts[1]; } /* * Bakery page/result. */ if ( parts[0] === "crumbSaucerCollect" ) { return parts[1]; } return null; } /* * ============================================================ * EXPORTS * ============================================================ */ module.exports = { showCollectPage, collectCookiesFromSaucer };