added bankruptcy

This commit is contained in:
DeSqBlocki
2026-08-23 00:09:13 +02:00
parent 030b4b8883
commit 9c867b1adb
12 changed files with 985 additions and 676 deletions
+188
View File
@@ -0,0 +1,188 @@
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",
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
};