const { getCollections, getCookieBalance, getUnixTime } = require("./cookieEconomy"); const { trackProfileEvent } = require("./profileSystem"); const BANKRUPTCY_COLLECTION = "items_bankruptcy"; const BANKRUPTCY_GRANT = 1000; const BANKRUPTCY_COOLDOWN = 1 * 60 * 60; function getBankruptcyCollection() { return getCollections().db.collection(BANKRUPTCY_COLLECTION); } async function ensureBankruptcyIndexes() { const bankruptcy = getBankruptcyCollection(); await bankruptcy.createIndex( { userId: 1, guildId: 1 }, { unique: true } ); } async function getBankruptcyStatus(userId, guildId) { const balance = await getCookieBalance(userId); const document = await getBankruptcyCollection().findOne({ userId, guildId }); const now = getUnixTime(); const nextAvailableAt = Number(document?.nextAvailableAt ?? 0); return { balance, eligible: balance === 0 && nextAvailableAt <= now, nextAvailableAt, claims: Number(document?.claims ?? 0) }; } async function declareBankruptcy(interaction, userId = interaction.user.id) { const guildId = interaction.guildId; if (!guildId) { return { ok: false, reason: "GUILD_ONLY" }; } const { cookies } = getCollections(); const bankruptcy = getBankruptcyCollection(); const now = getUnixTime(); const previous = await bankruptcy.findOne({ userId, guildId }); const nextAvailableAt = Number(previous?.nextAvailableAt ?? 0); if (nextAvailableAt > now) { return { ok: false, reason: "COOLDOWN", nextAvailableAt }; } let claimLock; try { claimLock = await bankruptcy.findOneAndUpdate( { userId, guildId, $or: [ { nextAvailableAt: { $exists: false } }, { nextAvailableAt: { $lte: now } } ] }, { $set: { nextAvailableAt: now + BANKRUPTCY_COOLDOWN, lastClaimedAt: now }, $inc: { claims: 1 }, $setOnInsert: { userId, guildId } }, { upsert: true, returnDocument: "after" } ); } catch (error) { if (error?.code !== 11000) { throw error; } } if (!claimLock) { const status = await getBankruptcyStatus(userId, guildId); return { ok: false, reason: "COOLDOWN", nextAvailableAt: status.nextAvailableAt }; } let credit; try { credit = await cookies.updateOne( { userId, $or: [ { cookies: 0 }, { cookies: { $exists: false } } ] }, { $inc: { cookies: BANKRUPTCY_GRANT }, $setOnInsert: { userId } }, { upsert: true } ); } catch (error) { if (error?.code !== 11000) { throw error; } credit = { modifiedCount: 0, upsertedCount: 0 }; } if (credit.modifiedCount !== 1 && credit.upsertedCount !== 1) { await bankruptcy.updateOne( { userId, guildId }, { $set: { nextAvailableAt, lastClaimedAt: previous?.lastClaimedAt ?? null, claims: Number(previous?.claims ?? 0) } } ); return { ok: false, reason: "BALANCE_NOT_ZERO", balance: await getCookieBalance(userId) }; } await trackProfileEvent( interaction, userId, { type: "cookie_gain", source: "bankruptcy", amount: BANKRUPTCY_GRANT } ); return { ok: true, amount: BANKRUPTCY_GRANT, balance: BANKRUPTCY_GRANT, nextAvailableAt: now + BANKRUPTCY_COOLDOWN, claims: Number(claimLock.claims ?? 1) }; } module.exports = { BANKRUPTCY_GRANT, BANKRUPTCY_COOLDOWN, ensureBankruptcyIndexes, getBankruptcyStatus, declareBankruptcy };