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. 1. Motivation & Goals
  2. 2. System Architecture
  3. 3. Shared Package
  4. 4. Economy & Transactions
  5. 5. Casino Game Engine
  6. 6. RTP & Fairness
  7. 7. Daily Bonus
  8. 8. VIP Rooms
  9. 9. Predictions
  10. 10. Raffles
  11. 11. Admin Dashboard
  12. 12. Background Workers
  13. 13. Testing & Quality
  14. 14. Technical Challenges

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.
Player runs slash command in Discord
Bot validates guild config + balances
MongoDB session writes User + Transaction
Embed / buttons update in channel
Manager adjusts settings or reviews logs in dashboard

3. Shared Package

Duplicating types or payout math between bot and dashboard would eventually desync. Everything that defines “what a guild is allowed to configure” lives in the published package and is imported by both apps.

  • Models: User, Transaction, GuildConfiguration, Prediction, VipRoom, BlackjackGame, AtmRequest, Raffle, and related indexes.
  • defaultCasinoSettings and readableGameNames for UI labels.
  • Zod: casinoSettingsSchema, channelsFormSchema, bonusFormSchema, vipSettingsFormSchema, managerRoleFormSchema.
  • Utilities: calculateRTP (per game), calculateBonusReward, generateBonusPreview, validateBetAmount, validatePredictionBet.
  • Constants: roulette layout (MINI_NUMBERS), lottery draw sizes, transaction type/source enums.
Publish workflow

The shared repo versions independently. Bot and admin pin the same version so schema migrations and RTP changes ship together.

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; optional betId for 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:

  1. Check registration, allowed casino channels, and per-game cooldowns.
  2. Validate bet against min/max and available cash + bonus.
  3. reserveCasinoBet with a generated betId.
  4. Run game logic (RNG, buttons, multi-step embeds).
  5. 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 * 100
Per-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.

Moderator creates prediction
Players place bets
Autolock (optional)
Moderator resolves
Payouts or refunds + transaction log
  • 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.