import type { RconClient } from "@/lib/services/rcon"; export type CurrencyName = "credits" | "duckets" | "diamonds" | "points"; // users_currency.type values for the non-credits currencies. const TYPE_VALUE: Record, number> = { duckets: 0, diamonds: 5, points: 101, }; export interface CurrencyDb { user: { update(args: { where: { id: number }; data: { credits: { increment: number } }; }): Promise; }; usersCurrency: { upsert(args: { where: { userId_type: { userId: number; type: number } }; update: { amount: { increment: number } }; create: { userId: number; type: number; amount: number }; }): Promise; }; } export interface SendCurrencyDeps { rcon: Pick; db: CurrencyDb; } /** * Mirrors AtomCMS's SendCurrency action: deliver via RCON, falling back to a * direct DB write when RCON delivery fails (the PHP version checks * rcon->isConnected up front; trying-then-falling-back is equivalent and more * robust). Credits live on users.credits; duckets/diamonds/points live in * users_currency keyed by (user_id, type). */ export async function sendCurrency( deps: SendCurrencyDeps, userId: number, type: CurrencyName, amount: number | null | undefined, ): Promise { if (!amount || amount <= 0) return false; if (await rconDeliver(deps.rcon, userId, type, amount)) return true; if (type === "credits") { await deps.db.user.update({ where: { id: userId }, data: { credits: { increment: amount } }, }); } else { // eslint-disable-next-line security/detect-object-injection -- type is CurrencyName union, not "credits" const t = TYPE_VALUE[type]; await deps.db.usersCurrency.upsert({ where: { userId_type: { userId, type: t } }, update: { amount: { increment: amount } }, create: { userId, type: t, amount }, }); } return true; } function rconDeliver( rcon: SendCurrencyDeps["rcon"], userId: number, type: CurrencyName, amount: number, ): Promise { switch (type) { case "credits": return rcon.giveCredits(userId, amount); case "duckets": return rcon.giveDuckets(userId, amount); case "diamonds": return rcon.giveDiamonds(userId, amount); case "points": return rcon.givePointsGotw(userId, amount); } }