402 lines
8.0 KiB
JavaScript
402 lines
8.0 KiB
JavaScript
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;
|
|
const COLLECT_MIN = 1;
|
|
const COLLECT_MAX = 1000;
|
|
|
|
const COLLECT_COOLDOWN_KEY = "collect";
|
|
|
|
|
|
/*
|
|
* ============================================================
|
|
* SHARED COLLECT LOGIC
|
|
* ============================================================
|
|
*
|
|
* This is the one authoritative implementation used by:
|
|
*
|
|
* - /cookies collect
|
|
* - Crumb Saucer Cookie Bakery
|
|
*
|
|
* It does not reply/update Discord itself.
|
|
*/
|
|
|
|
async function collectCookies(
|
|
interaction,
|
|
userId = interaction.user.id
|
|
) {
|
|
const cooldown = await claimCooldown(
|
|
userId,
|
|
interaction.guildId,
|
|
COLLECT_COOLDOWN_KEY,
|
|
COLLECT_COOLDOWN
|
|
);
|
|
|
|
|
|
if (!cooldown.claimed) {
|
|
const balance = await getCookieBalance(
|
|
userId
|
|
);
|
|
|
|
return {
|
|
collected: false,
|
|
cooldown,
|
|
balance,
|
|
amount: 0
|
|
};
|
|
}
|
|
|
|
|
|
const amount =
|
|
Math.floor(
|
|
Math.random() *
|
|
(
|
|
COLLECT_MAX -
|
|
COLLECT_MIN +
|
|
1
|
|
)
|
|
) +
|
|
COLLECT_MIN;
|
|
|
|
|
|
await changeCookies(
|
|
userId,
|
|
amount
|
|
);
|
|
|
|
|
|
await trackProfileEvent(
|
|
interaction,
|
|
userId,
|
|
{
|
|
type: "cookie_gain",
|
|
amount
|
|
}
|
|
);
|
|
|
|
|
|
const balance = await getCookieBalance(
|
|
userId
|
|
);
|
|
|
|
|
|
return {
|
|
collected: true,
|
|
cooldown,
|
|
balance,
|
|
amount
|
|
};
|
|
}
|
|
|
|
|
|
/*
|
|
* ============================================================
|
|
* SHARED EMBED BUILDERS
|
|
* ============================================================
|
|
*/
|
|
|
|
function buildCollectSuccessEmbed(
|
|
userId,
|
|
result,
|
|
footerType = "crumbSaucerCollect"
|
|
) {
|
|
return new EmbedBuilder()
|
|
.setTitle(
|
|
"🍪 Fresh Batch!"
|
|
)
|
|
.setDescription(
|
|
[
|
|
`You collected **${result.amount.toLocaleString()} Cookies**! 🍪`,
|
|
"",
|
|
`Your next batch will be ready <t:${result.cooldown.next}:R>.`
|
|
].join("\n")
|
|
)
|
|
.addFields({
|
|
name: "Your Vault",
|
|
value:
|
|
`**${result.balance.toLocaleString()} 🍪**`
|
|
})
|
|
.setFooter({
|
|
text:
|
|
`${footerType}:${userId}`
|
|
});
|
|
}
|
|
|
|
|
|
function buildCollectCooldownEmbed(
|
|
userId,
|
|
result,
|
|
footerType = "crumbSaucerCollect"
|
|
) {
|
|
return new EmbedBuilder()
|
|
.setTitle(
|
|
"🍪 Cookie Bakery"
|
|
)
|
|
.setDescription(
|
|
[
|
|
"Your next batch isn't ready yet.",
|
|
"",
|
|
`Come back <t:${result.cooldown.next}:R>.`
|
|
].join("\n")
|
|
)
|
|
.addFields({
|
|
name: "Your Vault",
|
|
value:
|
|
`**${result.balance.toLocaleString()} 🍪**`
|
|
})
|
|
.setFooter({
|
|
text:
|
|
`${footerType}:${userId}`
|
|
});
|
|
}
|
|
|
|
|
|
/*
|
|
* ============================================================
|
|
* SHOW SAUCER 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()
|
|
});
|
|
}
|
|
|
|
|
|
/*
|
|
* ============================================================
|
|
* SAUCER COLLECT WRAPPER
|
|
* ============================================================
|
|
*/
|
|
|
|
async function collectCookiesFromSaucer(
|
|
interaction
|
|
) {
|
|
const ownerId =
|
|
getCollectOwner(
|
|
interaction
|
|
);
|
|
|
|
|
|
if (
|
|
ownerId !==
|
|
interaction.user.id
|
|
) {
|
|
return temporaryEphemeralReply(
|
|
interaction,
|
|
{
|
|
content:
|
|
"This isn't your Crumb Saucer session."
|
|
}
|
|
);
|
|
}
|
|
|
|
|
|
const result =
|
|
await collectCookies(
|
|
interaction,
|
|
interaction.user.id
|
|
);
|
|
|
|
|
|
const embed =
|
|
result.collected
|
|
? buildCollectSuccessEmbed(
|
|
interaction.user.id,
|
|
result
|
|
)
|
|
: buildCollectCooldownEmbed(
|
|
interaction.user.id,
|
|
result
|
|
);
|
|
|
|
|
|
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(":")
|
|
??
|
|
[];
|
|
|
|
|
|
if (
|
|
parts[0] ===
|
|
"crumbSaucer"
|
|
) {
|
|
return parts[1];
|
|
}
|
|
|
|
|
|
if (
|
|
parts[0] ===
|
|
"crumbSaucerCollect"
|
|
) {
|
|
return parts[1];
|
|
}
|
|
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
/*
|
|
* ============================================================
|
|
* EXPORTS
|
|
* ============================================================
|
|
*/
|
|
|
|
module.exports = {
|
|
collectCookies,
|
|
|
|
buildCollectSuccessEmbed,
|
|
buildCollectCooldownEmbed,
|
|
|
|
showCollectPage,
|
|
collectCookiesFromSaucer,
|
|
|
|
COLLECT_COOLDOWN,
|
|
COLLECT_MIN,
|
|
COLLECT_MAX
|
|
}; |