A high-performance Discord-WoW chat bridge for Ascension private server, written in Rust.
Innkeeper is a complete rewrite of WoWChat specifically optimized for Ascension's WotLK 3.3.5a protocol with custom authentication.
- ✅ Full Ascension Support: Native support for Ascension's X25519/ChaCha20 authentication
- ✅ Bidirectional Chat: WoW ↔ Discord message relay with full Unicode support
- ✅ Guild Integration: Guild chat, officer chat, roster, MOTD, and events
- ✅ Custom Channels: Support for any WoW custom channels
- ✅ Discord Commands:
!whofor online members,!gmotdfor guild MOTD - ✅ Message Filtering: Regex-based filters for both directions
- ✅ Auto-Reconnect: Graceful handling of disconnections
- ✅ Item Links: Converts WoW item links to Ascension database URLs
- ✅ Low Resource Usage: Rust efficiency (~10-20MB RAM, minimal CPU)
- ✅ Zero Dependencies: Clientless design, no WoW client needed
- Rust 1.70+ (install from rustup.rs)
- Discord bot token (create one)
- Ascension WoW account
# Clone the repository
git clone https://github.com/windymindy/innkeeper.git
cd innkeeper
# Build release binary
cargo build --release
# The binary will be in target/release/innkeeper- Copy the example configuration:
cp innkeeper.conf.example innkeeper.conf- Edit
innkeeper.confwith your settings:
discord {
token = "YOUR_DISCORD_BOT_TOKEN"
enable_dot_commands = true
}
wow {
realmlist = "logon.project-ascension.com"
realm = "Laughing Skull"
account = "your_username"
password = "your_password"
character = "YourCharacterName"
}
chat {
channels = [
{
direction = "both"
wow {
type = Guild
}
discord {
channel = "guild-chat" # Discord channel name or ID
}
}
]
}- Get your Discord channel name:
- The channel name is the text after the # (e.g., "guild-chat" for #guild-chat)
- Channel names are case-sensitive and must match exactly
# Run directly
cargo run --release
# Or use the binary
./target/release/innkeeper
# With custom config location
INNKEEPER_CONFIG=/path/to/config.conf ./target/release/innkeeperYou can override configuration values with environment variables:
export DISCORD_TOKEN="your_token_here"
export WOW_ACCOUNT="your_username"
export WOW_PASSWORD="your_password"
export WOW_CHARACTER="YourCharacter"
./target/release/innkeeperdiscord {
# Required: Your Discord bot token
token = "YOUR_TOKEN"
# Optional: Enable . prefix commands (default: true)
enable_dot_commands = true
# Optional: Whitelist of allowed dot commands (empty = all allowed if enabled)
dot_commands_whitelist = ["help", "gm"]
# Optional: Restrict commands to specific channels (empty = all channels)
# Accepts channel names (strings) or channel IDs (integers)
enable_commands_channels = ["bot-commands"]
# Optional: Notify on failed tag/mention resolution (default: true)
enable_tag_failed_notifications = true
# Optional: Enable markdown in messages sent from WoW to Discord (default: false)
enable_markdown = false
}wow {
# Treat server's MotD as SYSTEM message (default: true)
enable_server_motd = true
# Realm list server (with optional port, default port: 3724)
realmlist = "logon.project-ascension.com"
# Realm name to connect to
realm = "Laughing Skull"
# Account credentials (or use WOW_ACCOUNT/WOW_PASSWORD env vars)
account = "your_username"
password = "your_password"
# Character to log in with (or use WOW_CHARACTER env var)
character = "YourCharacterName"
}chat {
channels = [
{
# Message direction (optional, default: "both")
# - "both" (default)
# - "wow_to_discord"
# - "discord_to_wow"
direction = "both"
# WoW channel configuration
wow = {
# Channel type: Guild, Officer, Say, Yell, Emote, System, Channel, Whisper, Whispering
type = "Guild"
# Channel name (for custom "Channel" type)
channel = "Trade"
# Format string (optional)
format = "[WoW] %user: %message"
}
# Discord channel configuration
discord = {
# Discord channel name or ID
channel = "guild-chat"
# Format string (optional)
format = "[Discord] %user: %message"
}
}
]
}Global filters apply to all channels. You can also set per-channel filters on each
wow {} or discord {} block (see the example config for details).
Filter priority order (first non-disabled filter wins):
- Discord channel filters (highest priority, applies to both directions)
- WoW channel filters (applies to WoW -> Discord only)
- Global filters (lowest priority, applies to all channels)
filters {
# Whether filtering is enabled (default: true)
enabled = true
# Regex patterns to filter (fancy-regex syntax, supports lookaheads/lookbehinds)
patterns = [
"^\\[System\\].*", # System messages
".*has earned the achievement.*", # Achievements
"https?://.*" # URLs
]
}guild {
online = {
enabled = true
format = "%user has come online"
}
offline = {
enabled = true
format = "%user has gone offline"
}
# Other events: promoted, demoted, joined, left, removed, motd, achievement
}guild-dashboard {
enabled = true
channel = "guild-dashboard" # Discord channel name or ID for online member list
}quirks {
# Make the bot character sit (default: false)
sit = false
}Available commands (type in Discord):
!who- List online guild members!gmotd- Show guild Message of the Day!help- Show help message
Dot commands (if enabled):
.help- Shows WoW help.gm on/off- Toggle GM mode (if you have permissions)- Any other WoW command
Innkeeper uses a clean, modular architecture with async message passing:
┌─────────────────────────────────────────────────────────────────┐
│ main.rs │
│ - Load config │
│ - Spawn Tokio runtime │
│ - Initialize Discord + WoW connections │
└─────────────────────────────────────────────────────────────────┘
│
┌──────────────────┼──────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Discord │ │ Bridge │ │ Protocol │
│ Bot Task │ │ (Message │ │ (WoW Tasks) │
│ │ │ Routing) │ │ │
│ - Event loop │◄─┤ - Channel maps │─►│ - Realm connect │
│ - Commands │ │ - Filtering │ │ - Game connect │
│ - Send messages │ │ - Formatting │ │ - Chat relay │
└─────────────────┘ └─────────────────┘ └─────────────────┘
- Bridge: Central message router with filtering, formatting, and channel mapping
- Protocol Layer: WotLK 3.3.5a + Ascension authentication
- Discord Bot: Serenity-based integration with slash/text commands
- Message Flow: Discord ↔ Bridge ↔ WoW with bidirectional filtering
# Run all tests
cargo test
# Run with output
cargo test -- --nocapture
# Run specific test
cargo test test_auth_flowAll tests should pass.
# Debug build (faster compile, slower runtime)
cargo build
# Release build (optimized)
cargo build --release
src/
├── main.rs # Application entry point
├── bridge/ # Message routing and orchestration
│ ├── orchestrator.rs # Bridge struct - message flow orchestration
│ ├── channels.rs # BridgeChannels, DiscordChannels, GameChannels
│ ├── state.rs # BridgeState, ChannelConfig - shared state
│ ├── filter.rs # Regex filtering
│ └── mod.rs
├── config/ # Configuration loading and validation
│ ├── mod.rs
│ ├── parser.rs # HOCON parsing
│ ├── types.rs # Config structs
│ ├── validate.rs # Configuration validation
│ └── env.rs # Environment variable handling
├── protocol/ # WoW protocol implementation
│ ├── mod.rs
│ ├── realm/ # Realm server (authentication)
│ │ ├── mod.rs
│ │ ├── connector.rs # Realm server connection
│ │ ├── handler.rs # Packet handling
│ │ └── packets.rs # Realm packet definitions
│ ├── game/ # Game server (packets, chat, guild)
│ │ ├── mod.rs
│ │ ├── connector.rs # Game server connection
│ │ ├── handler.rs # Packet handling (WotLK/Ascension)
│ │ ├── header.rs # Header encryption (WotLK/Ascension variant)
│ │ ├── packets.rs # Game packet definitions
│ │ ├── chat.rs # Chat message handling
│ │ └── guild.rs # Guild roster/events
│ └── packets/ # Packet codec and opcodes
│ ├── mod.rs
│ ├── opcodes.rs # Packet opcode constants
│ └── codec.rs # Encode/decode traits
├── game/ # Game client logic
│ ├── mod.rs
│ ├── client.rs # Game client main loop
│ └── formatter.rs # Message formatting
├── discord/ # Discord bot integration
│ ├── mod.rs
│ ├── client.rs # Discord bot setup
│ ├── handler.rs # Message event handling
│ ├── commands.rs # Slash/text commands (!who, etc)
│ ├── dashboard.rs # Guild online member dashboard
│ └── resolver.rs # Emoji, link, tag resolution
└── common/ # Shared types and utilities
├── mod.rs
├── messages.rs # Message types
├── types.rs # Shared data structures
└── resources.rs # Zone names, class names, etc.
- Check that the character name matches exactly (case-sensitive)
- Ensure the character is on the correct realm
- Verify your username and password are correct
- Check that realm host and port are correct
- Ascension may have changed their login server
- Ensure bot has proper permissions in Discord
- Check that channel IDs are correct (enable Developer Mode)
- Verify the bot token is valid
Innkeeper is designed for efficiency:
- Memory: ~10-20 MB RAM usage
- CPU: Minimal (<1% on modern hardware)
- Network: Only active traffic, no polling
- Startup: < 5 seconds to full connection
- Issues: GitHub Issues
Note: This is an unofficial tool. Use at your own risk. Automated gameplay tools may violate Ascension's Terms of Service. Innkeeper is designed as a chat bridge only and does not interact with gameplay.