Case Study
Gambling BOT – Discord Casino & Admin Dashboard Ecosystem
A multi-repo virtual economy and casino platform for Discord communities: eleven configurable games, gated ATM deposits, predictions, scheduled raffles, VIP rooms, and a Next.js admin panel.
All three apps-Discord bot, admin dashboard, and shared NPM package-read the same Mongoose models, Zod schemas, and RTP math so configuration never drifts between Discord and the web.
Project overview
Three repositories (gambling-bot-discord, gambling-bot-admin, gambling-bot-shared) share MongoDB and gambling-bot-shared. The bot runs on CommandKit with background workers; the dashboard uses Next.js 16, NextAuth (Discord OAuth), and TanStack Table for guild-scoped management.
Contents
1. Motivation & Goals
The project started as a way to bring a persistent, auditable casino into Discord-deeper than one-off fun commands. The target was a single economic model that moderators can tune without redeploying the bot, while players get transparent rules, history, and fair odds.
- Per-guild virtual currency with immutable transaction logs and admin-approved deposits/withdrawals (suited to RP servers).
- Configurable casino games with computed RTP, not magic numbers.
- Engagement systems: daily bonuses, VIP rooms, predictions, and recurring raffles.
- A web dashboard for managers and server admins to inspect users, cash flow, and settings.
- One shared TypeScript package so bot and dashboard never disagree on schemas or math.
2. System Architecture
Each application deploys independently but stays aligned through gambling-bot-shared and a single MongoDB database. The Discord bot owns gameplay, workers, and Discord API side effects; the dashboard owns OAuth, forms, and read-heavy analytics.
Discord Bot
- discord.js v14 + CommandKit (slash commands, events, workers).
- Casino, ATM, VIP, predictions, raffles, and mod tooling.
- MongoDB transactions for bets, VIP purchases, and refunds.
- Vitest unit/integration tests with mongodb-memory-server.
- Structured logging via Pino.
Shared Package
- Mongoose schemas: User, Transaction, GuildConfiguration, Prediction, VipRoom, etc.
- Zod form schemas mirrored in the dashboard.
- calculateRTP, bonus streak helpers, bet validators, formatters.
- Subpath exports: root, ./server, ./schemas.
Admin Dashboard
- Next.js 16 App Router, React 19, Tailwind 4, Radix UI.
- NextAuth Discord OAuth; guild access via manager role or Administrator.
- Server actions + shared Zod schemas for settings persistence.
- TanStack Table: users, transactions (filters, PnL summaries).
- Live RTP preview while editing casino settings.
4. Economy & Transactions
Users are scoped per guild. Balances split into three buckets so bonuses, withdrawable cash, and in-flight bets stay separable.
balance- withdrawable cash (ATM withdrawals only touch this).bonusBalance- non-withdrawable funds from daily bonuses and admin grants; spent first on casino bets.lockedBalance- funds reserved while a bet is open; released on settle or refund.Transaction- append-only log: types deposit, withdraw, bet, win, refund, bonus, vip; sources command, manual, web, system, casino; optionalbetIdfor correlated rounds.
Casino bets use reserveCasinoBet /settleCasinoWinnings inside MongoDB multi-document transactions: duplicate betId is rejected, bonus balance is consumed before cash, and locked balance tracks exposure until settlement.
Gated ATM
Deposits and withdrawals are request-based. Admins approve in Discord or via dashboard actions (register, deposit, withdraw, bonus grant, reset). The bot never moves real in-game currency without human approval-important for GTA RP-style servers.
5. Casino Game Engine
Eleven game configs exist in GuildConfiguration (dice, coinflip, slots, lottery, roulette, rps, goldenJackpot, blackjack, prediction limits, raffle house cut, plinko). Playable slash games share the same pipeline:
- Check registration, allowed casino channels, and per-game cooldowns.
- Validate bet against min/max and available cash + bonus.
- reserveCasinoBet with a generated betId.
- Run game logic (RNG, buttons, multi-step embeds).
- settleCasinoWinnings and render result embeds.
Dice
Pick a side (1–6), optional multi-roll. Win when the roll matches; payout scales with guild winMultiplier. Simple 1/6 probability model feeds RTP.
Plinko
Drop 1–10 balls through an animated board; each path lands in a bin with configured multipliers. RTP uses binomial probabilities over nine bins (Galton-board style 50/50 left-right steps).
Blackjack
- Persistent BlackjackGame document; one active hand per user per guild.
- Button interactions: hit, stand, double; dealer hits to 17 with soft-17 rules.
- Background worker auto-stands stale games after one hour.
- Blackjack detection on initial deal for player and dealer.
Mini Roulette
- Custom 19-pocket wheel (0–18) via MINI_NUMBERS color map.
- Bet types: number, color, parity, range, dozen, column-multiple bets per command.
- Per-bet-type RTP returned as a map (not a single percentage).
Lottery
Players pick numbers; draws use fixed pool sizes. Payout tiers by match count; combinatorics drive RTP.
Coinflip
Heads/tails with optional multi-flip; guild winMultiplier sets RTP.
Slots
Weighted emoji reels; only triple matches pay using per-combo multipliers in settings.
RPS (PvP)
Challenge flow: matched bets, winner takes pot minus casinoCut; shared betId across both players’ transactions.
Golden Jackpot
High-variance tickets against oneInChance; large winMultiplier; optional simulation commands for moderators.
6. RTP & Fairness Controls
calculateRTP in the shared package derives effective return from guild settings and game-specific probability-not hardcoded labels. The dashboard shows live RTP (with warnings when RTP ≤ 90% or ≥ 100%) while editing casino settings.
- Dice: (1/6) × winMultiplier.
- Coinflip: 0.5 × winMultiplier.
- Slots: Σ P(3-of-a-kind per symbol) × multiplier.
- Lottery: hypergeometric match probabilities × tier multipliers.
- Roulette: separate RTP per bet type from wheel layout.
- Plinko: binomial path probabilities × bin multipliers.
- RPS: 1 − casinoCut; Golden Jackpot: winMultiplier / oneInChance.
- Blackjack: documented ~99.4% baseline; prediction/raffle RTP not auto-calculated.
Example: Plinko RTP (binomial bins)
for (let k = 0; k <= N; k++) {
const p = C(N,k) * 0.5^k * 0.5^(N-k)
rtp += p * binMultipliers[k]
}
return rtp * 100Per-guild tuning
All sensitive knobs (multipliers, weights, cuts, bet limits) live in GuildConfiguration.casinoSettings and are editable from the dashboard without restarting the bot.
7. Daily Bonus & Streaks
bonusSettings per guild controls linear or exponential streak growth, caps, reset-on-max, and weekly / monthly milestone bonuses. Rewards credit bonusBalance only-keeping farmed value inside the casino economy.
- /bonus check - 28-day preview calendar (shared generateBonusPreview).
- /bonus claim - 24h cooldown enforced in DB; streak + transaction logged.
- Dashboard: bonus form + live calendar preview when editing settings.
- Admin can grant or revoke bonus balance from the users table.
8. VIP Rooms
Players buy private channels for a duration (days/weeks). Config covers category, owner/member roles, pricing per day, creation fee, and multi-member support (maxMembers, pricePerAdditionalMember).
Purchase & extend
- /vip buy and /vip extend with atomic balance checks.
- reserveVipPurchase / finalizeVipPurchase pattern mirrors casino bets.
- VIP transactions and VipRoom documents track expiry.
Membership
- /vip add-member and remove-member with permission updates.
- Expired rooms: channel stays, write access revoked.
- vipExpiration worker runs every minute.
- Dashboard VIP settings form + VIP table (feature present; sidebar link optional).
9. Predictions
Moderators run a parimutuel-style market: create an event with up to three choices and odds, players bet in-channel, optional autolock, then resolve or cancel with full refunds.
- Dedicated prediction action/log channels in guild config.
- predictionAutolock worker (1 min) and predictionCleanup worker (daily).
- validatePredictionBet shared between bot and tests.
- Win payout: stake × odds; cancellations issue refund transactions.
10. Raffles
Scheduled ticket raffles complement the casino: moderators set ticket price, per-user max tickets, draw time, and repeat interval. Players buy tickets in the raffle channel; the pot pays out minus a configurable house cut.
- /raffle create, cancel, and ticket purchase flows with atomic DB updates.
- raffleDraw worker checks every minute for due draws.
- Weighted random winner by ticket count; single-participant edge case refunds.
- Recurring raffles reschedule after each draw.
- Separate raffle action/log channels-configured in dashboard channel settings.
11. Admin Web Dashboard
After Discord OAuth, users pick a guild where they are Administrator or hold the configured manager role. Routes live under /dashboard/g/[guildId]/[section] with permission gates (bot present, role check, Discord API rate-limit handling).
General
- Transactions - paginated table, type/source/date filters, search, cash-flow and game PnL summary panels.
- Home - guild overview placeholder for future analytics.
Manage
- Users - Discord member list with register/unregister, deposit, withdraw, bonus grant, balance reset.
- VIPs - active VIP channels table (management UI built).
Settings (admin-only sidebar group): channel bindings for ATM, casino, prediction, and raffle; manager role; VIP pricing and roles; bonus progression with calendar preview; full casino accordion per game with RTP headers and Zod-validated save.
Public casino overview
A separate /[guildId] route can render read-only casino cards (bets, multipliers, RTP breakdown) for transparency pages-useful for communities that want players to inspect house rules without dashboard access.
12. Background Workers
Long-running Discord bots cannot rely on players to finish every session. A shared runWorkerLoop scheduler starts on clientReady and runs idempotent jobs on intervals.
- VIP expiration - 1 min: revoke write access, sync permissions.
- Prediction autolock - 1 min: close betting at configured time.
- Raffle auto-draw - 1 min: pick winner, pay pot, reschedule repeats.
- Guild settings sync - 6 h: refresh cached config from MongoDB.
- Blackjack auto-stand - 1 h (delayed start): resolve abandoned hands.
- Prediction cleanup - daily: archive or remove stale documents.
13. Testing & Quality
The Discord bot repo treats correctness as part of the product: Vitest with separate unit and integration targets, ESLint + Prettier + tsc --noEmit in CI-style pnpm check.
- Unit: blackjack engine, roulette math, plinko path/render, RTP helpers, bet validation, cooldowns.
- Integration: casinoBet sessions, daily bonus claims, prediction bets, raffle DB, VIP DB, workers (autolock, raffle draw, blackjack autostand).
- mongodb-memory-server for hermetic database tests.
- Moderator simulate-* commands for dice, slots, lottery, golden jackpot, and transaction stress tests.
14. Technical Challenges
Building a Discord-first financial surface forces trade-offs that a typical web app does not hit as hard.
- Concurrency - MongoDB transactions + unique betId indexes prevent double-spend and duplicate settlement when users spam interactions.
- Dual balance - bonus-first bet consumption and locked balance keep withdrawable cash honest while still rewarding streak play.
- Interaction latency - multi-step games (blackjack, plinko animations) need clear error handling and workers for abandoned state.
- Config drift - central package + Zod schemas + guild sync worker keep bot memory and dashboard writes aligned.
- Permission model - dashboard distinguishes Discord Administrator vs configured manager role; settings UI hidden from managers who only need transactions/users.
- RP safety - gated ATM and manual transaction source document every balance change for moderator review.
Community & repos
Public Discord: discord.gg/Y2mMQN5QVE. Open-source repos: gambling-bot-discord, gambling-bot-admin, gambling-bot-shared on GitHub (krouskystepan).
Living case study for the Gambling BOT ecosystem-updated as games, dashboard sections, and shared package releases ship.