A Discord bot for managing game servers (Minecraft & Hytale) hosted on Crafty Controller. Start, stop, and monitor your servers directly from Discord with slash commands and live status updates.
/start_server— Start a game server with autocomplete server selection. Shows live status updates once the server is online./stop_server— Stop a game server. Prevents stopping when players are online./get_server_status— View a server's current status, players, version, and IP — auto-refreshes every minute.- Auto-shutdown — Servers with no players are automatically stopped after 30 minutes of inactivity, with a notification sent to the channel where the server was started.
- Bot activity — Cycles through online server statuses in the bot's Discord presence.
- Node.js >= 18
- A Crafty Controller instance with API access
- A Discord Application with a bot token
-
Clone the repository
git clone https://github.com/Saanicc/crafty-mc-discord-bot.git cd crafty-mc-discord-bot -
Install dependencies
npm install
-
Configure environment variables
Create a
.envfile in the project root:NODE_ENV=dev # "dev" or "prod" DISCORD_TOKEN=your_bot_token DISCORD_CLIENT_ID=your_client_id DISCORD_GUILD_ID=your_guild_id # Required in dev mode for instant command registration CRAFTY_API_DOMAIN=https://your-crafty-instance.com CRAFTY_API_KEY=your_crafty_api_key ROOT_SERVER_DOMAIN=your-server.com # Used for mapping server IPs (e.g. mc.your-server.com)
-
Configure server domains and thumbnails
Copy the template configuration file:
cp bot-config.example.json bot-config.json
Edit
bot-config.jsonto map your server ports to their specific subdomains and (optionally) thumbnail URLs. The subdomains will be prefixed to yourROOT_SERVER_DOMAIN. -
Run in development
npm run dev
This uses
tsx watchfor hot-reloading during development. Slash commands are registered per-guild for instant availability.
npm run build # Bundles with tsup → dist/index.cjs
npm start # Runs the bundlenpm run build
npm run docker-build
npm run docker-save # Exports to discord-bot.tar for transferOr run the full pipeline:
npm run build-prod # build → docker-build → docker-saveThe Docker image uses node:22-alpine and runs under a non-root user.
bot-config.example.json # Template for dynamic server config
src/
├── index.ts # Bot entry point & event handlers
├── config.ts # Environment variable validation
├── botConfig.ts # Loads and validates bot-config.json
├── deploy-commands.ts # Slash command registration
├── api/
│ └── crafty.ts # Crafty Controller API client
├── services/
│ └── serverManager.ts # Auto-shutdown & inactivity monitoring
├── interactions/
│ └── commands/
│ ├── index.ts # Command registry
│ ├── startServer.ts # /start_server command
│ ├── stopServer.ts # /stop_server command
│ └── getServerStatus.ts # /get_server_status command
└── utils/
├── constants.ts # Timing constants
├── emojis.ts # Custom Discord emoji mappings
├── types/
│ └── crafty-api.ts # Crafty API response types
├── embeds/
│ ├── serverStatusReply.ts # Server status message builder
│ └── serverInactivityReply.ts # Inactivity shutdown message
└── helpers/
├── handleInteraction.ts # Interaction router
├── buildMessageContainer.ts # Discord Components v2 message builder
├── autoCompleteChoices.ts # Server autocomplete with caching
├── serverStatusUpdater.ts # Live-updating status messages
├── serverCommandContext.ts # Tracks where commands were issued
├── waitAndUpdateStatus.ts # Shared start/stop polling flow
├── setBotActivity.ts # Bot presence updater
├── portMapper.ts # Server port → domain mapping
├── parsePlayers.ts # Player list parser (MC & Hytale)
└── utils.ts # General utilities
- discord.js v14 — Discord API library
- tsup — Bundler (outputs CJS for production)
- tsx — TypeScript runner with watch mode for development
- dotenv — Environment variable loading
This project is unlicensed — it is a personal project.