Spectreon is a modular Discord bot built for TPPC community servers, providing utilities, contests, and multiplayer games with strict consistency, deterministic rules, and per-guild configurability.
The bot is designed to scale across multiple servers without command collisions, spam, or ambiguity.
- Explicit commands only (
!cmd,?cmd, or/cmd) - One active game per guild
- Deterministic behavior
- Low-noise UX (silent ignores where configured)
- Per-guild command exposure control
- Automatically generated help
- Trading (
FT) and Looking-For (LF) lists (DB-backed) - TPPC ID storage & lookup
- Rarity lookups (live GitHub Pages JSON)
- Level-4 rarity stats
- Rarity comparison & history charts
- Wiki lookups (local index, Cloudflare-safe)
- FAQ system with fuzzy matching
- Promo tracking (
!promo/!setpromo) - RPG tools: leaderboards, power plant status, ID/box lookup, pokedex + stats + egg time
- Viewbox DMs with graceful failure handling when DMs are closed
- RNG tools:
roll,choose,elim,awesome - Reaction-based contests (
choosesupportswinners=<n>, default 1) - Whispers (hidden phrases + optional prizes)
- Giveaways (button-based entries, reroll/end/delete/list, summary file)
- Reading & forum list helpers
- Contest helpers reused by games where applicable
All games share a common framework:
- Reaction-join or tagged players
- Per-turn timers with skip handling
- Host-controlled lifecycle
- Deterministic resolution
Current games include:
- Exploding Voltorbs
- Exploding Electrode
- Safari Zone
- Bingo
- Blackjack
- Closest Roll Wins
- Higher or Lower
- Rock Paper Scissors
- Hangman
- Deal or No Deal
- Auction
- Mafia (lightweight, host-driven)
Only primary game commands appear in help to avoid clutter.
!help— public, truncated preview (safe under 2000 chars)/help— full interactive help menu (ephemeral)- Commands are grouped by category
- Per-guild exposure is respected automatically (wrong prefix is silent)
- Admin-only commands are hidden from non-admins
Each logical command can be exposed as:
bang→!commandq→?commandoff→ disabled
Wrong-prefix usage is silently ignored by design. This is controlled in configs/command_exposure.js.
This prevents collisions with other bots without breaking muscle memory.
Important:
A command is never exposed as both!and?at the same time.
Slash command exposure can be controlled per guild in configs/command_exposure.js.
.
├── bot.js # Discord client + lifecycle
├── commands.js # Unified command registry
├── info/helpbox.js # !help and /help UI
├── info/faq.js # FAQ + wiki commands
├── info/wiki.js # Wiki index/search
├── auth.js # Admin / privileged checks
├── db.js # MySQL persistence
├── tools/ # TPPC tools & promo system
├── trades/ # FT / LF / ID commands
├── tools/rarity.js # Rarity, comparisons, history
├── rpg/ # RPG utilities (leaderboards, power plant, pokedex, viewbox)
├── scripts/ # One-off generators and tooling
├── contests/
│ ├── contests.js # Contest module registry
│ ├── rng.js
│ ├── reaction_contests.js
│ ├── whispers.js
│ ├── giveaway.js
│ ├── helpers.js
│ └── ...
├── games/
│ ├── games.js # Game registry
│ ├── exploding_voltorbs.js
│ ├── blackjack.js
│ ├── auction.js
│ └── ...
├── verification/
│ ├── verification.js
│ ├── verifyme.js
│ └── whois.js
├── configs/
│ └── command_exposure.js
├── shared/
│ └── time_utils.js
├── shared/
│ └── pokename_utils.js
├── data/
│ ├── wiki_data.json
│ ├── pokedex_map.json
│ ├── pokemon_evolutions.json
│ └── privileged_users.json
└── .env.example
- Node.js 20.19+ (22 LTS recommended;
.nvmrcpinned to22.12.0) - Discord.js v14
- MySQL / MariaDB (required for most features)
- Discord bot permissions:
- Read Messages
- Send Messages
- Add Reactions
- Manage Messages (recommended for games)
npm install
cp .env.example .env
# fill in env values
npm startOptional Docker helpers (macOS):
npm run start:dev:docker— starts Docker Desktop, ensurestppc-mysqlis running, then runsstart:dev.npm run stop:dev:docker— stops the dev bot, stopstppc-mysql, and quits Docker Desktop.
See .env.example for the canonical list.
Common variables:
| Variable | Description |
|---|---|
DISCORD_TOKEN |
Required bot token |
ALLOWED_CHANNEL_IDS |
Optional channel allowlist |
SLASH_GUILD_ID |
Guild-only slash registration (dev) |
BOT_DEFAULT_NICKNAME |
Default guild nickname for this deployment |
BOT_NICKNAME_OVERRIDE |
Force a nickname regardless of seasonal rules |
DB_HOST / DB_USER / DB_NAME |
MySQL connection |
RARITY_JSON_URL |
Live rarity JSON source |
RARITY_REFRESH_MS |
Retry interval during refresh window |
RARITY_REFRESH_WINDOW_MINUTES |
Morning retry window length |
RARITY_DAILY_REFRESH_ET |
Daily refresh time (ET) |
The bot automatically creates required tables:
user_ids— TPPC IDsuser_texts— FT/LF lists, promos, whispersrpg_leaderboards— cached RPG leaderboardsrpg_pokedex— cached pokedex payloadscontests/contest_entries— giveaways and contest state
If DB is unavailable, some features safely degrade (e.g. promos fall back to memory).
git clone <repo>
cd <repo>
npm ci
cp .env.example .env
nano .env
npm startRecommended process manager:
pm2 start bot.js --name spectreon
pm2 save
pm2 startupregister(
"!example",
async ({ message, rest }) => {
await message.reply("Hello!");
},
"!example — says hello"
);- Help text updates automatically
- Exposure rules are enforced automatically
- Categories propagate to help UI
- Predictable behavior
- Minimal moderator overhead
- Clean UX for both casual users and power users
- Easily extensible without rewriting core systems