fakegaming-bot Monorepo

June 25, 2026 ยท View on GitHub

Build Status codecov License: AGPL v3 Node.js Version ESLint Vitest Last Commit

A modular Discord bot for community management, Twitch stream notifications, YouTube video announcements, League of Legends stats, quotes, reminders, and more. Built with TypeScript and Discord.js. This project is now a monorepo containing multiple packages.

๐Ÿ“– Table of Contents


๐Ÿš€ Quick Start

# 1. Clone the repository
git clone https://github.com/Zeffuro/fakegaming-bot.git
cd fakegaming-bot

# 2. Set up environment
cp .env.example .env
cp packages/bot/.env.example packages/bot/.env
cp packages/api/.env.example packages/api/.env
cp packages/dashboard/.env.example packages/dashboard/.env
# Edit all .env files with your credentials

# 3. Start all services
docker-compose up -d

# 4. Check logs
docker-compose logs -f bot

See DEPLOYMENT.md for detailed instructions.

For Developers (Local)

# 1. Install pnpm
npm install -g pnpm

# 2. Clone and install dependencies
git clone https://github.com/Zeffuro/fakegaming-bot.git
cd fakegaming-bot
pnpm install

# 3. Set up development environment
cp packages/bot/.env.example packages/bot/.env.development
cp packages/api/.env.example packages/api/.env.development
cp packages/dashboard/.env.example packages/dashboard/.env.development
# Edit files with development credentials (use SQLite)

# 4. Build and start
pnpm build
pnpm start:bot:dev     # Start bot
pnpm start:api:dev     # Start API (separate terminal)
pnpm start:dashboard:dev # Start dashboard (separate terminal)

See CONTRIBUTING.md for detailed development setup.


Features

๐Ÿค– Discord Bot

  • Slash and context-menu commands generated from module manifests
  • Quote management system
  • Birthday tracking with automatic announcements
  • Reminder system with timezone support
  • League of Legends & TFT stats and match history
  • Utility commands (poll, roll, weather, spin)

๐Ÿ”” Notifications & Integrations

  • Twitch stream notifications (Helix polling)
  • YouTube video announcements
  • TikTok live stream alerts
  • Game patch notes (League of Legends, VALORANT, Marvel Rivals, Overwatch 2)
  • Cooldown and quiet hours support

๐Ÿ–ฅ๏ธ Web Dashboard

  • Discord OAuth authentication
  • Guild-level configuration management
  • Quote, notification, and command management
  • Real-time Discord data integration

๐Ÿ”’ Security & Infrastructure

  • JWT authentication with CSRF protection
  • Redis-backed dashboard sessions and shared guild-permission cache
  • Database-backed rate limiting
  • Comprehensive testing (80% coverage target)
  • Docker Compose deployment ready
  • PostgreSQL (production) & SQLite (development)

Monorepo Structure

This repository uses pnpm workspaces to manage multiple packages:

  • packages/api โ€” Express REST API for external integrations and bot operations

  • packages/bot โ€” The Discord bot (commands, services, integrations)

  • packages/common โ€” Shared code (database models, utilities, types)

  • packages/dashboard โ€” Dashboard for bot management (Next.js)

  • data/ โ€” Persistent data, assets, and config (used by the bot)

  • migrations/ โ€” Database migration scripts

  • scripts/ โ€” Utility scripts (e.g., codegen, migration helpers)


Documentation

๐Ÿ“š Getting Started

๐Ÿ—๏ธ Architecture & Patterns

๐Ÿ”ง Development Guides

๐Ÿ“ฆ Package Documentation

๐Ÿค Contributing


Getting Started

Package Manager:
This project requires pnpm for monorepo workspace management.
Install with: npm install -g pnpm

Prerequisites

  • Node.js (v22+ recommended)
  • pnpm (install with npm install -g pnpm or see pnpm installation)
  • (Optional) Docker & Docker Compose for containerized development/production

Installation

Install all dependencies for all packages:

pnpm install

Environment Variables

For Local Development:

  1. Copy .env.example to .env.development in each package:

    cp packages/bot/.env.example packages/bot/.env.development
    cp packages/api/.env.example packages/api/.env.development
    cp packages/dashboard/.env.example packages/dashboard/.env.development
    
  2. Edit each .env.development file with your development credentials:

    • Use SQLite for the database (no DATABASE_URL needed)
    • Use development Discord tokens/IDs
    • Use test API keys

For Production/Live Data Testing:

  1. Copy .env.example to .env in each package:

    cp packages/bot/.env.example packages/bot/.env
    cp packages/api/.env.example packages/api/.env
    cp packages/dashboard/.env.example packages/dashboard/.env
    
  2. Edit each .env file with your production credentials

For Docker Compose:

  1. Copy the root .env.example to .env in the repository root:

    cp .env.example .env
    
  2. Copy each package's .env.example to .env (production credentials)

  3. Fill in database credentials in the root .env (Docker Compose will inject DATABASE_URL automatically)

Environment File Priority:

  • Development scripts (start:dev) โ†’ Loads .env.development (via NODE_ENV=development)
  • Production scripts (start) โ†’ Loads .env (via NODE_ENV=production)
  • If environment-specific file is missing, falls back to .env

Running & Development

Running with Docker Compose (Production)

You can run the bot and its dependencies using Docker Compose with pre-built images:

docker-compose up -d
  • This will start the bot, API, dashboard, and whichever bundled infrastructure services are enabled by COMPOSE_PROFILES.
  • Uses pre-built images from Docker Hub (zeffuro/fakegaming-*:latest).
  • The root .env file controls Docker Compose variables (database credentials, Redis URL, volume paths).
  • Each service's .env file is loaded for service-specific configuration.
  • To stop and remove containers:
    docker-compose down
    

Running with Docker Compose (Local Testing)

To test Dockerized builds locally with development credentials:

docker-compose -f docker-compose.local.yml up --build -d
  • This builds images from source instead of pulling from Docker Hub.
  • Uses .env.development files for each service (development credentials).
  • No PostgreSQL (uses SQLite via shared volume).
  • Includes a Redis container by default; set REDIS_URL and start only the app services if using hosted Redis.
  • Exposes API on port 3001 and Dashboard on port 3000.
  • Perfect for testing Docker builds before deployment.
  • Access: Dashboard at http://localhost:3000, API at http://localhost:3001/api

To rebuild after code changes:

docker-compose -f docker-compose.local.yml up --build -d

To stop:

docker-compose -f docker-compose.local.yml down

Running Locally (Development Mode)

Start the bot:

pnpm start:bot:dev

Start the API:

pnpm start:api:dev

Start the dashboard:

pnpm start:dashboard:dev

These commands:

  • Set NODE_ENV=development (loads .env.development)
  • Use tsx for TypeScript execution without compilation
  • Enable hot-reload for rapid development
  • No Docker required

Running Locally (Production Mode)

First build all packages:

pnpm build

Then start services:

pnpm start:bot    # Uses .env, runs compiled dist/index.js
pnpm start:api    # Uses .env, runs compiled dist/index.js
pnpm start:dashboard  # Uses .env, runs Next.js production server

OpenAPI & Dashboard Types

The API exports an OpenAPI spec that the dashboard consumes to generate TypeScript types.

  • Export the API spec:
pnpm --filter @zeffuro/fakegaming-bot-api run export:openapi
  • Regenerate dashboard API types:
pnpm --filter @zeffuro/fakegaming-bot-dashboard run generate:api-types
pnpm --filter @zeffuro/fakegaming-bot-dashboard run typecheck

Building, Linting, and Testing

  • Build all packages:
    pnpm build
    
  • Lint all packages:
    pnpm lint
    
  • Typecheck all packages:
    pnpm typecheck
    
  • Test all packages:
    pnpm test
    
  • Test with coverage:
    pnpm test:coverage
    

Coverage thresholds per package:

  • Lines/Statements: 80%
  • Branches: 75%
  • Functions: 80%

Notes:

  • Generated or declarative wiring files may be excluded from coverage (e.g., auto-generated bot manifest, schema override registry). Core behavior is covered by unit/integration tests.

Cross-Cutting Concerns (Security, Limits, Observability)

  • CSRF: Both API (Express) and Dashboard (Next.js) enforce CSRF on mutating routes via a shared core in @zeffuro/fakegaming-common/security.
  • Auth: JWT (HS256) with required issuer/audience. Dashboard uses HttpOnly jwt and refresh_session cookies, plus a readable csrf cookie for double-submit CSRF.
  • Shared cache: API and dashboard must share Redis for dashboard refresh sessions, Discord access tokens, and guild permission cache keys used by guild-scoped API authorization.
  • Rate limiting: DB-backed sliding window in API with standard headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, and Retry-After on 429.
  • Health/Readiness: /healthz and /ready endpoints for API and Bot. Docker compose exposes bot health locally only.
  • Logging: Pino-based structured logs (getLogger in common). Dev pretty logs with LOG_PRETTY=1. API uses pino-http for request logging (reqId, status, latency) and skips /healthz noise.
  • Metrics: Minimal in-process counters and periodic summary logs in API/Bot; Prometheus can be added later.

Validation & Error Handling Standards

  • All API routes use shared Zod-based validators from @zeffuro/fakegaming-common:
    • validateParams(schema) โ€” path params (400 on invalid)
    • validateQuery(schema) โ€” query params (400 on invalid)
    • validateBody(schema | model, mode?) or validateBodyForModel(Model, 'create'|'update') โ€” request bodies (400 on invalid)
  • Auth uses JWT; protected routes return 401 when token is missing/invalid and 403 for insufficient permissions.
  • DELETE/GET-by-id endpoints consistently return 404 when resource is not found.

Database & Migrations

  • Database models are defined in packages/common (typically in packages/common/src/models/).
  • Database schema: See SCHEMA.md for a high-level overview. Live models and migrations are the source of truth.
  • Schema changes: Any change to the database schema (adding/removing fields, tables, etc.) requires a new migration script in the migrations/ directory.
  • Writing migrations:
    • Create a new migration file in migrations/ (see existing files for naming conventions, e.g., YYYYMMDD-description.ts).
    • Migrations should be written in TypeScript and follow the project's migration conventions.
    • Both up and down functions are required for rollback capability.
    • See MIGRATIONS.md for detailed migration guide with examples.
  • Running migrations:
    • Migrations run during service startup where enabled; production Compose disables bot-side migrations and lets the API own startup migrations.
    • The system uses Umzug to track which migrations have been applied.
    • See MIGRATIONS.md for manual execution and troubleshooting.

Continuous Integration (CI)

This project uses GitHub Actions for continuous integration:

  • Builds, lints, and tests all packages on every pull request and push to main.
  • Uploads coverage to Codecov for api, bot, common, and dashboard packages.
  • Ensures all code passes before merging.
  • See the CI workflow in .github/workflows/ci.yml.

Available Commands

Full generated catalog: docs/generated/commands.md.

CommandTypeDescriptionPermissions
/add-bluesky-accountSlashAdd a Bluesky account for post notificationsAdministrator
/add-quoteSlashAdd a quoteAll users
/add-steam-newsSlashAdd Steam game news notificationsAdministrator
/add-tiktok-streamSlashAdd a TikTok account for live notificationsAdministrator
/add-twitch-streamSlashAdd a Twitch stream for notificationsAdministrator
/add-youtube-channelSlashAdd a Youtube Channel for new video notificationsAdministrator
/animeSlashSearch anime, manage subscriptions, and view upcoming episodesAll users
/birthdaySlashShow your or another user's birthdayAll users
/birthdaysSlashShow upcoming birthdays in this serverAll users
/calendarSlashShow upcoming birthdays and your remindersAll users
/delete-quoteSlashDelete a quote you added or authoredAll users
/delete-reminderSlashDelete one of your pending remindersAll users
/get-patchnotesSlashGet the latest patch notes for a gameAll users
/helpSlashList all available commands and their descriptions.All users
/league-formSlashSummarize recent League of Legends form by Riot ID or linked userAll users
/league-historySlashGet recent League of Legends match history by Riot ID or linked userAll users
/league-statsSlashGet League of Legends stats by Riot ID or linked userAll users
/link-riotSlashLink your Discord account or another user to a Riot accountAll users
/manage-bluesky-accountsSlashList, test, pause, resume, or remove Bluesky post notificationsAdministrator
/manage-patchnotesSlashList, test, pause, resume, or remove patch note subscriptionsAll users
/manage-steam-newsSlashList, test, pause, resume, or remove Steam news notificationsAdministrator
/manage-tiktok-streamsSlashList, test, pause, resume, or remove TikTok live notificationsAdministrator
/manage-twitch-streamsSlashList, test, pause, resume, or remove Twitch stream notificationsAdministrator
/manage-youtube-channelsSlashList, test, pause, resume, or remove YouTube video notificationsAdministrator
/mangaSlashSearch manga, manhwa, webtoons, and light novels on AniListAll users
/notesSlashAdd, list, show, and delete your personal notesAll users
/patchnotes-historySlashShow stored patch note history for a gameAll users
/pause-reminderSlashPause one of your recurring remindersAll users
/pollSlashCreate a simple poll for users to vote onAll users
/profile-cardSlashRender a Discord profile cardAll users
/quote-cardSlashRender an approved quote as a shareable imageAll users
/quote-leaderboardSlashShow the most quoted users in this serverAll users
/quotesSlashGet all quotes for a userAll users
/random-quoteSlashGet a random quote from the serverAll users
/remindersSlashList your active and paused remindersAll users
/remove-birthdaySlashRemove your birthday or another user's birthday (admins only)All users
/resume-reminderSlashResume one of your recurring remindersAll users
/riot-linksSlashManage linked Riot accountsAll users
/rollSlashRoll dice or generate a random numberAll users
/search-quoteSlashSearch quotes by textAll users
/set-birthdaySlashSet your birthday and the channel to post inAll users
/set-reminderSlashSet a reminderAll users
/set-timezoneSlashSet your timezoneAll users
/snooze-reminderSlashSnooze one of your pending remindersAll users
/spinSlashSpin the wheel to pick someone!All users
/stream-statusSlashCheck whether a Twitch channel is liveAll users
/subscribe-patchnotesSlashSubscribe a channel to patch notes for a gameAll users
/test-notificationSlashSend a sample notification to a channelAll users
/tft-historySlashGet recent Teamfight Tactics match history by Riot ID or linked userAll users
/tft-statsSlashGet Teamfight Tactics ranked stats by Riot ID or linked userAll users
/timeSlashConvert a time into Discord timestamp formatsAll users
/twitch-latest-vodSlashShow the latest Twitch archive VOD for a channelAll users
/weatherSlashGet the current weather and a short forecast for a specified locationAll users
/youtube-latestSlashShow the latest video from a YouTube channel IDAll users
Remind Me in 1hMessage contextSet a one-hour reminder for a message from the message context menuAll users
Save as QuoteMessage contextSave a message as a quote from the message context menuAll users
Show BirthdayUser contextShow a user birthday from the user context menuAll users
Show QuotesUser contextShow quotes for a user from the user context menuAll users

Note: The command table above is auto-generated by CI. You do not need to update it manually.


Development & Contributing

See CONTRIBUTING.md for code style, how to add commands or preloaders, PR process, and more. Pull requests and issues are welcome!

See also:


Code of Conduct

Participation in this project is governed by our Code of Conduct. Please be respectful and help us keep the community welcoming.


Security Policy

If you discover a security vulnerability, please see SECURITY.md for how to report it privately.


License

This project is licensed under the GNU Affero General Public License v3.0 (AGPLv3).

  • You can use, modify, and share this project, but if you deploy it or make it public, you must also share your changes under the same license.
  • See LICENSE for the full text.

FAQ

Q: Can I use this bot on my own server?
A: Yes! This project is open source and self-hosted. Follow the Quick Start guide or see DEPLOYMENT.md for detailed deployment instructions.

Q: Is there a public instance or support server?
A: No, this bot is used privately. There is no public instance or official support server. You must self-host.

Q: What are the system requirements?
A: Minimum 2GB RAM, 2 CPU cores, 20GB storage. Works great on a 2GB VPS. See DEPLOYMENT.md for details.

Q: How do I add new commands or features?
A: See CONTRIBUTING.md for detailed guides on adding commands, features, and database changes.

Q: Where are the database models?
A: All models are in packages/common/src/models/. See SCHEMA.md for complete database schema with ER diagram.

Q: How do I report bugs or request features?
A: Use GitHub Issues. See the "Reporting Issues" section in CONTRIBUTING.md.

Q: What databases are supported?
A: PostgreSQL (production recommended) and SQLite (development). Configured via DATABASE_PROVIDER environment variable.

Q: How do I update to the latest version?
A: For Docker: docker-compose pull && docker-compose up -d. For manual: git pull && pnpm install && pnpm build. See DEPLOYMENT.md.

Q: Can I disable specific commands per server?
A: Yes! Use the dashboard at /dashboard/commands/[guildId] or configure via API. See API_GUIDE.md.

Q: Who maintains this project?
A: @Zeffuro


Invite the Bot

To invite the bot to your Discord server, use the following links (replace [client_id] with your bot's client ID):

  • With Administrator permissions:
    https://discord.com/oauth2/authorize?client_id=[client_id]&scope=bot%20applications.commands&permissions=522368

  • Without Administrator permissions:
    https://discord.com/oauth2/authorize?client_id=[client_id]&scope=bot%20applications.commands&permissions=522360


Maintained by @Zeffuro

Privacy: Discord user resolution (Dashboard Quotes)

The dashboard quotes page resolves Discord user IDs (authors/submitters) to minimal display info using the bot token:

  • Cached in Redis up to 24h under user:{id}:profile (id, username, global_name, discriminator, avatar)
  • Optional guild nickname cached up to 24h under user:{id}:nick:{guildId}
  • Only guild admins can request resolutions for IDs that already appear in that guildโ€™s quotes
  • No data is persisted in SQL; cache may be cleared safely at any time

Server env required for this feature: DISCORD_BOT_TOKEN, JWT_SECRET, JWT_AUDIENCE, and Redis configuration.