prosolis dd97a00332 Branching zones G8e: Underforge pre-boss gauntlet (late triple fork)
T3 zone, fifth authored graph. Shape: five-node linear preamble
(sealed_gate → forge_descent → cooling_river → magma_chamber elite)
followed by a single 3-way antechamber fork before the boss.

Bends the plan §G8 "two forks for T2+" guideline to a single late
fork-with-three-options because the gauntlet shape is the design
intent — Kharak Dûn is a one-way descent. Triple-option antechamber
(direct / DEX-checked catwalks / Perception-found forge_vault secret)
preserves agency at the commitment moment.

Map renders as a long horizontal stem with a 3-leaf fan at the right
edge — visually distinct from any earlier zone.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 16:56:07 -07:00
2026-03-08 18:25:18 -07:00

GogoBee

Matrix community bot with E2EE, 50 plugins, passive tracking, scheduled posts, and optional LLM features.

Written in Go using mautrix-go for encryption and modernc.org/sqlite for storage.


Table of Contents


Features

  • E2EE that actually works - mautrix-go with goolm (pure Go). Crypto state lives in SQLite so device keys survive restarts. Cross-signing bootstraps on first run — the bot self-verifies its own device.
  • No CGo, no system deps - builds to a single static binary. Cross-compile to whatever you want.
  • 50 plugins with dependency injection and ordered registration
  • Games & economy - Euro virtual currency, Hangman (collaborative, threaded, tiered scoring, multilingual clue mode via DreamDict, difficulty tier display), Blackjack (1-4 players, auto-play timeout), UNO (solo vs bot or 24 player multiplayer via DMs, with optional No Mercy mode), Texas Hold'em (2-9 players, CFR-trained NPC bot, DM-based gameplay with Ollama coaching tips, 1-hour idle auto-close with 45-min warning), Wordle (daily cooperative, DreamDict-powered, 5-20 letter words, guess persistence across restarts, midnight expiry announcements, video game themed bonus words with category hints, dupe prevention across last 500 puzzles, earnings tracked in stats), Adventure 2.0 (D&D-layered RPG: 7 races, 5 classes with 3 subclasses each through L15, real spell slots and forward-simulating combat engine, 10 hand-tuned dungeon zones across 5 tiers, multi-day expeditions with supply burn / threat clock / day cycle / multi-region travel / extract-and-resume / per-zone temporal events, harvest nodes per room, TwinBee as a mood-driven DM with ten zone-specific narration pools, all on top of the existing economy/housing/pets/Misty/Arina/blacksmith/hospital/rivals systems), Arena (5-tier combat gauntlet with 20 unique monsters, streak-based payouts, death lockout, leaderboard), Co-op Dungeons (27 day party runs with funding tiers, TwinBee-narrated floor events with voting, spectator parimutuel betting, basket/mimic gift system, weighted-roll item distribution including masterworks at T4T5), all with channel restriction
  • Moderation system (optional) - deterministic detection only, no LLM. Word list with leetspeak variation matching, text/image flood, repeated messages, mention flooding, link rate limiting, invite flooding, join/leave cycling. Three-strike ladder (warn → mute → ban). Admin room notifications, DMs over public callouts.
  • Passive tracking - XP, stats, streaks, achievements, markov corpus, keyword alerts, all running silently
  • Scheduled posts via robfig/cron - Palavra do Dia (Portuguese WOTD with en/fr translations and etymology), holidays, game releases, birthdays, anime/movie releases, concert digests, esteemed members
  • LLM integration (optional) - Ollama-powered sentiment analysis, roast profiles, room vibes, tarot readings, conversation summaries
  • Markdown rendering - auto-detects **bold**, _italic_, and `code` in messages and sends proper HTML to Matrix clients
  • Encrypted quote wall - AES-256-GCM encrypted quotes at rest, reply-to-save, search, leaderboard
  • Space groups - automatic room grouping via membership overlap. Leaderboards, stats, and trivia scores span all rooms in a group. No Matrix Spaces API needed — the bot infers community boundaries from shared members.
  • SQLite everything - one file, no external database needed

Requirements

  • Go 1.22+
  • A Matrix homeserver account for the bot

Optional:


Installation

From Source

git clone https://github.com/prosolis/gogobee.git
cd gogobee
cp .env.example .env   # edit with your settings
go build -tags goolm -o gogobee .
./gogobee

Docker

docker build -t gogobee .
docker run --env-file .env -v ./data:/app/data gogobee

Docker Compose

docker compose up -d

Configuration

Everything is configured through environment variables or a .env file.

Required

Variable Description
HOMESERVER_URL Matrix homeserver URL, e.g. https://matrix.org
BOT_USER_ID Bot's Matrix user ID, e.g. @gogobee:matrix.org
BOT_PASSWORD Bot's Matrix password

Core (optional)

Variable Default Description
DATA_DIR ./data Where the database and device files live
BOT_DISPLAY_NAME GogoBee Display name
LOG_LEVEL info debug, info, warn, or error
ADMIN_USERS Comma-separated admin user IDs
BROADCAST_ROOMS Comma-separated room IDs for scheduled posts

API Keys (optional)

Variable Service Used By
RAWG_API_KEY RAWG !game, !retro, !releases
DREAMDICT_URL DreamDict (self-hosted) !translate, !wotd, !antonym, !pronounce, !etymology, !difficulty, !rhyme, !define (antonyms), Hangman (multilingual clues + difficulty tier), Wordle (word selection + guess validation + definitions)
CALENDARIFIC_API_KEY Calendarific Holiday posts
OPENWEATHER_API_KEY OpenWeather !weather
FINNHUB_API_KEY Finnhub !stock
BANDSINTOWN_API_KEY Bandsintown !concerts
TMDB_API_KEY TMDB !movie, !tv, !upcoming
SERPAPI_KEY SerpAPI Esteemed member image fetching

Services (optional)

Variable Description
OLLAMA_HOST Ollama server URL, e.g. http://localhost:11434
OLLAMA_MODEL Model name, e.g. llama3.2
DREAMDICT_URL DreamDict instance for !translate, !wotd, dictionary commands, Hangman clues, Wordle words (e.g. http://127.0.0.1:7777)
LLM_SAMPLE_RATE Fraction of messages to classify (0.01.0, default 0.15)

Encryption

Variable Description
QUOTE_ENCRYPTION_KEY Base64-encoded 32-byte AES-256 key for encrypted quote storage and Markov corpus. Generate with openssl rand -base64 32. If unset, !quote and !markov are disabled.

Miniflux RSS (optional)

Variable Default Description
MINIFLUX_URL Miniflux instance URL, e.g. https://rss.example.com
MINIFLUX_API_KEY Miniflux API key (Settings → API Keys)
MINIFLUX_POLL_INTERVAL 15 Minutes between polls
MINIFLUX_DEFAULT_ROOM BROADCAST_ROOMS Default room for posts
MINIFLUX_MAX_PER_POLL 5 Max entries per feed per poll cycle

Feature Flags

Variable Description
FEATURE_URL_PREVIEW Set to anything to enable automatic URL previews
FEATURE_SHADE Set to anything to enable the shade plugin (stub)
FEATURE_TRIVIA Set to false to disable trivia (default: enabled)
FEATURE_ESTEEMED Set to anything to enable satirical esteemed member posts
ESTEEMED_ROOM Room ID for esteemed member posts (separate from broadcast rooms)
FEATURE_MODERATION Set to true to enable the moderation system (disabled by default)
FEATURE_MARKET Set to true to enable the market overview plugin
MARKET_BROADCAST_SUMMARY Set to true to auto-post daily market summary to broadcast rooms
DISABLE_WOTD_POST Set to true to suppress daily WOTD auto-post (the !wotd command and passive WOTD usage tracking still work)

Games & Economy

Variable Default Description
GAMES_ROOM Room ID where game commands work (trivia, hangman, blackjack, holdem, wordle, flip)
EURO_COOLDOWN_SECONDS 30 Cooldown between passive euro earning per user
EURO_DEBT_REMINDER true Weekly DM reminder if player is in debt
EURO_STARTING_CAP 2500 Max starting balance seeded from corpus
HANGMAN_MAX_WRONG_GUESSES 6 Lives before game over
HANGMAN_SOLUTION_BONUS_MULTIPLIER 2 Bonus multiplier for early solution
HANGMAN_PHRASE_FILE Path to newline-delimited phrase file
BLACKJACK_TIMEOUT_SECONDS 60 Auto-play timeout per turn
BLACKJACK_AUTOPLAY_THRESHOLD 15 Stand at or above, hit below
BLACKJACK_MIN_BET 1 Minimum bet in euros
BLACKJACK_MAX_BET 500 Maximum bet per hand
BLACKJACK_DEBT_LIMIT 1000 Maximum debt before betting disabled
UNO_MIN_BET 10 Minimum wager in euros (solo)
UNO_POT_TAUNT_THRESHOLD 500 Pot size at which GogoBee starts taunting
UNO_MULTI_MIN_BET 25 Minimum ante for multiplayer UNO
UNO_MULTI_MAX_BET 500 Maximum ante for multiplayer UNO
UNO_MULTI_LOBBY_TIMEOUT 300 Lobby expiry in seconds
UNO_MULTI_TURN_TIMEOUT 30 Auto-play timeout in seconds
UNO_MULTI_MAX_AUTOPLAY 3 Consecutive auto-plays before forfeit
HOLDEM_SMALL_BLIND 10 Small blind amount
HOLDEM_BIG_BLIND 20 Big blind amount
HOLDEM_MIN_BUYIN 200 Minimum balance to join
HOLDEM_MAX_BUYIN 2000 Maximum stack at buy-in
HOLDEM_TIMEOUT_SECONDS 90 Action timeout per turn
HOLDEM_NPC_NAME TwinBee NPC bot display name
HOLDEM_NPC_HOUSE_BALANCE 10000 NPC starting bankroll
HOLDEM_CFR_POLICY data/policy.gob Path to CFR policy file
WORDLE_DEFAULT_LENGTH 5 Default word length (5-20)
ADVENTURE_MORNING_HOUR 8 Hour (UTC) to send morning DMs with daily choices
ADVENTURE_SUMMARY_HOUR 20 Hour (UTC) to post daily summary to games room

Moderation

All moderation settings are optional. The system is disabled unless FEATURE_MODERATION=true.

Variable Default Description
MOD_WORDLIST Path to newline-delimited prohibited word list
MOD_WORDLIST_VARIATIONS true Check leetspeak/spaced variants
MOD_STRIKE_EXPIRY_DAYS 30 Days before strikes expire
MOD_MUTE_DURATION_MINUTES 60 Temp mute duration on strike 2
MOD_MAX_STRIKES 3 Strikes before permanent ban
MOD_FLOOD_MESSAGE_COUNT 5 Messages in window = flood
MOD_FLOOD_MESSAGE_WINDOW_SECONDS 10 Text flood window
MOD_FLOOD_IMAGE_COUNT 3 Images/files in window = flood
MOD_FLOOD_IMAGE_WINDOW_SECONDS 30 Image flood window
MOD_MAX_MESSAGE_LENGTH 2000 Max chars per message (0 = disabled)
MOD_REPEAT_COUNT 3 Repeated messages before strike
MOD_REPEAT_WINDOW_SECONDS 60 Repeat detection window
MOD_REPEAT_SIMILARITY_THRESHOLD 0.85 How similar counts as "same" (0.01.0)
MOD_MENTION_MAX 5 Max unique @mentions per message
MOD_MENTION_FLOOD_COUNT 3 Mention-heavy messages in window
MOD_MENTION_FLOOD_WINDOW_SECONDS 30 Mention flood window
MOD_LINK_RATE_NEW_MEMBER 3 Max links per window (new members only)
MOD_LINK_RATE_WINDOW_SECONDS 60 Link rate window
MOD_INVITE_MAX_PER_HOUR 5 Max room invites per user per hour
MOD_JOIN_LEAVE_COUNT 3 Join/leave cycles before flag
MOD_JOIN_LEAVE_WINDOW_MINUTES 10 Join/leave window
MOD_NEW_MEMBER_DAYS 14 Days before a member is no longer "new"
MOD_NEW_MEMBER_FLOOD_MULTIPLIER 0.5 Multiply flood thresholds for new members
MOD_ADMIN_ROOM Dedicated room for mod notifications
MOD_DM_ON_ACTION true DM users when action is taken

Space Groups

Variable Default Description
SPACE_GROUP_THRESHOLD 50 Percentage of the smaller room's members that must overlap to group rooms together (1100)
HOLIDAY_COUNTRIES US Comma-separated ISO country codes for Calendarific holiday posts

Missing Members

Variable Default Description
MISSING_THRESHOLD_DAYS 14 Days of inactivity before considered missing
MISSING_MAX_DAYS 90 Days after which they're considered gone, not missing
MISSING_MIN_MESSAGES 10 Minimum lifetime messages to be eligible
MISSING_EXCLUDE_USERS Comma-separated user IDs to never list as missing

Rate Limits

Variable Default Description
RATELIMIT_WEATHER 5 Daily weather lookups per user
RATELIMIT_CONCERTS 10 Daily concert searches per user

Running the Bot

# dev
go run -tags goolm .

# prod
go build -tags goolm -o gogobee .
./gogobee

The -tags goolm flag selects the pure-Go crypto implementation. No C compiler or libolm needed.

First Run

  1. Start the bot. It logs in, creates a device, bootstraps cross-signing, and self-verifies automatically.
  2. That's it. E2EE works across restarts from here on out.

Commands

XP & Leveling

Command Description
!rank Your level, XP, and progress
!leaderboard Top 10 by XP

Reputation

Command Description
!rep [@user] Reputation count
!repboard Top 10 by rep

Rep is earned when someone thanks you. The bot detects this automatically.

Stats & Personality

Command Description
!stats [@user] Message statistics (includes Wordle and UNO earnings)
!superstatsexplusalpha [@user] Comprehensive profile: economy, games W/L, adventure levels, achievements, and more
!rankings [category] Rankings by words, links, questions, or emojis
!personality Your community archetype

Streaks

Command Description
!streak Current and longest streak
!firstboard Top first-posters-of-the-day

Trivia

Command Description
!trivia [category] [difficulty] Start a question
!trivia scores Room leaderboard
!trivia categories List categories
!trivia fastest Fastest answers
!trivia stop End current question

Economy

Command Description
!balance Check your euro balance
!baltop Euro leaderboard
!baltransfer @user €amount Send euros to another player

Games (games channel only)

Command Description
!flip Coin flip
!games List available games
!hangman start [easy|medium|hard|extreme] Start a Hangman game (optional difficulty)
!hangman <lang> [--clue <lang>] Start a multilingual game (en/fr/pt-PT) with optional clue
!hangman [letter] Guess a letter
!hangman [phrase] Attempt full solution
!hangman submit [phrase] Submit a phrase to the pool
!hangman skip Skip game (admin only)
!hangboard Hangman leaderboard

Blackjack (games channel only)

Command Description
!blackjack €amount Start/join a Blackjack table (1-4 players)
!hit Take a card
!stand End your turn
!blackjack leave Leave before game starts
!bjboard Blackjack leaderboard
!twinbeeboard GogoBee's victory record against players

UNO (games channel only)

UNO can be played solo (vs GogoBee) or multiplayer (1-4 players + bots). All gameplay happens in DMs. The games channel is used for lobby management and public announcements.

Command Description
!uno €amount Start a solo game vs GogoBee
!uno nomercy €amount Start a solo No Mercy game
!uno nomercy 7-0 €amount Solo No Mercy with 7-0 rule
!uno start €amount Create a multiplayer lobby
!uno start nomercy €amount Multiplayer No Mercy lobby
!uno start nomercy 7-0 €amount Multiplayer No Mercy with 7-0 rule
!uno join Join an open lobby
!uno addbot Add a bot opponent to the lobby (max 2, funded from community pot)
!uno removebot Remove the last added bot from the lobby
!uno go Start the game (host only, 2+ participants required)
!uno leave Leave the lobby (refunds ante)
!uno cancel Cancel the lobby (host/admin, refunds all)

DM commands during gameplay: reply with a card number to play, draw to draw, uno to call UNO (required when you have 2 cards), quit to forfeit. During draw stacking, type accept to absorb the stack.

Classic Mode

Standard 108-card UNO deck. Draw one card per turn (pass if unplayable). Wild Draw Four can be challenged — if the challenger catches a bluff, the player draws 4 instead.

GogoBee has a personality system during solo play: she reads a book while playing, and puts it down when the game gets serious (opponent has few cards). Commentary changes based on book state.

No Mercy Mode

Based on UNO Show 'Em No Mercy (2023, Mattel). Bigger 168-card deck, meaner rules.

New cards:

Card Type Effect
Skip Everyone Colored Skips all other players — you go again
Discard All Colored Play it and discard every other card of that color from your hand
Draw Four Colored Like Wild Draw Four but matches by color (not wild)
Wild Reverse Draw Four Wild Reverse direction + draw 4 + pick a color
Wild Draw Six Wild Draw 6 + pick a color
Wild Draw Ten Wild Draw 10 + pick a color
Wild Color Roulette Wild Pick a color — next player flips cards from the deck until that color appears, keeping all flipped cards

Rule changes:

  • Draw stacking — when hit with a draw card, play a draw card of equal or higher value to pass the penalty to the next player. The stack keeps growing until someone can't (or won't) stack back. That player draws the entire total.
  • Draw until playable — no more drawing one and passing. You keep drawing until you find a playable card.
  • Mercy rule — reach 25 cards in your hand and you're eliminated.

7-0 Rule (optional, No Mercy only)

Enabled by adding 7-0 to the command. When active:

  • Play a 7 — swap hands with another player of your choice (in multiplayer, you pick the target)
  • Play a 0 — all players pass their hand to the next player in play direction

Sudden Death

When a 2-player game (including bot matchups) exceeds 80 turns, a 20-turn countdown begins. At turn 100, both hands are scored by UNO card point values — lowest total wins. Tiebreaker: fewer cards, then advantage to the non-active player.

Multiplayer Bots

The default bot (GogoBee) is always present in multiplayer games. Up to 2 additional bots (WinBee, GwinBee) can be added via !uno addbot while the lobby is open. Addbot bots ante from the community pot, increasing the total pot. A single human can start a game if bots fill the remaining slots.

Texas Hold'em (games channel only)

No-limit Texas Hold'em poker for 2-9 players. Buy-in is debited from your euro balance when you sit down; your remaining stack is cashed out when you leave. Private cards and coaching tips are delivered via DM — the room only sees start/end announcements.

An optional AI opponent (NPC) uses a CFR-trained poker solver. Add one with !holdem addbot.

Command Description
!holdem join Sit down at the table
!holdem leave Leave the table (cashes out stack, shows refund)
!holdem start Start dealing (2+ players)
!holdem play Shortcut: join + start in one command
!holdem addbot Add a CFR-trained AI opponent
!holdem fold Fold your hand
!holdem check Check (no bet to call)
!holdem call Call the current bet
!holdem raise <amount> Raise to a total of amount
!holdem allin Go all-in
!holdem status Current table state (sent via DM)
!holdem help Show in-game help

DM commands: !holdem tips on/off — toggle coaching tips (equity + pot odds analysis, powered by Ollama with rules-based fallback).

Idle timeout: Tables with no hands dealt close after 1 hour. A warning is posted at 45 minutes.

NPC Bot

The NPC opponent uses Counterfactual Regret Minimization (CFR), specifically the External Sampling variant of Monte Carlo CFR. Instead of hardcoding poker strategy, the bot learns one through millions of rounds of self-play. On each iteration, it plays both seats of a heads-up hand, tracks how much it "regrets" not having taken each alternative action, and gradually shifts its strategy toward the actions it regrets not taking. Over time, the strategy converges toward a Nash equilibrium — a point where no single change in play can improve its expected winnings against a perfect opponent. The trained policy ships as a single .gob file loaded at startup, and the bot plays a mixed strategy: it doesn't always make the same play in the same spot, but randomizes according to its trained probability distribution, which makes it harder to exploit.

The interesting engineering is in the abstraction layer. Real poker has roughly 10^17 possible game states — far too many for a tabular approach. We collapse this space down to around 23,000 information sets by bucketing hand strength into 12 equity tiers (computed via Monte Carlo rollout against random opponent hands), classifying boards as dry, wet, or paired based on flush/straight draw density and board pairing, tracking stack-to-pot ratio across 5 buckets, and encoding the last 6 actions as a compressed history string. All of this gets packed into a single uint64 key — no string formatting, no allocations on the hot path. Preflop hands use a lookup table of the 169 strategically distinct hold'em starting hands, which eliminates Monte Carlo during the most frequently visited part of the game tree. Training runs at about 5 million iterations across all CPU cores with shared regret tables, periodic checkpointing, and regret pruning after a 500K warmup to skip deeply negative branches. The result is a bot that plays a solid, unpredictable game — not world-class, but strong enough to make the table interesting.

Training the NPC

A standalone training CLI is provided under cmd/holdem-train/. It requires the training build tag:

# Build the training CLI
go build -tags training -o holdem-train ./cmd/holdem-train/

# Train with 8 workers (defaults to all CPU cores if --workers is omitted)
./holdem-train --iterations 5000000 --workers 8 --output data/policy.gob

# Resume from a checkpoint
./holdem-train --iterations 5000000 --workers 8 --resume data/policy.gob.checkpoint --output data/policy.gob

# Validate the trained policy (10K hands vs random baseline)
./holdem-train --validate --output data/policy.gob
Flag Default Description
--iterations 5000000 Number of training iterations
--workers runtime.NumCPU() Parallel workers
--output data/policy.gob Output policy file
--resume Resume from checkpoint
--validate false Run validation instead of training
--checkpoint-every 500000 Checkpoint interval
--seed 42 Random seed

Progress is logged with overall completion percentage and ETA. Checkpoints are saved every 30 seconds during parallel training.

Wordle (games channel only)

Daily cooperative Wordle — one puzzle per day, the community works together with a shared 6-guess limit. Word selection powered by DreamDict with a bundled word list as fallback. A new puzzle auto-posts at midnight UTC. Word length is configurable (5-20 letters). Guesses persist across bot restarts. When a puzzle expires at midnight, the bot reveals the answer and announces it to the room. The puzzle pool includes video game themed words (loaded from data/wordle_games.txt) — when one is selected, a category hint is shown. Duplicate prevention ensures the same word won't appear within the last 500 puzzles.

Command Description
!wordle <word> Submit a guess for today's puzzle
!wordle grid Re-post the current puzzle grid
!wordle stats All-time leaderboard with community streak
!wordle new Start a new puzzle (admin)
!wordle new <5-20> New puzzle with specific word length (admin)
!wordle skip Reveal answer and end puzzle (admin)
!wordle help Show commands

Economy rewards are tracked per player — !wordle stats shows total earnings.

Adventure (DM-based RPG)

A layered RPG. Adventure 2.0 grafts a full D&D-style character system on top of the existing adventure economy, then builds two endgame loops on top of that: single-session dungeon zones and multi-day expeditions. The legacy systems — housing/Thom Krooke, pets, Misty/Arina, blacksmith, hospital, rivals, Robbie, arena, co-op dungeons — all keep working unchanged. Players who don't opt into 2.0 keep the legacy adventure shape; players who run !setup get the full D&D layer on top.

Characters auto-create on first interaction. Most gameplay happens in DMs — the morning prompt routes to zones/expeditions for the active flow plus in-town services (shop, blacksmith, rest, hospital, Thom Krooke) for the rest.

Adventure 2.0 — D&D Layer

!setup once. Pick a race + class. Your existing combat_level becomes your D&D level, treasures become attunements, equipment slots carry forward 1:1. Every fight, harvest, arena run, and co-op dungeon is then resolved through D&D mechanics — STR/DEX/CON/INT/WIS/CHA, HP, AC, ability checks, saving throws, all the rest.

Races (7) — at race choice, fixed stat mods + a passive:

Race Mods (S/D/C/I/W/Ch) Passive
Human 0/0/0/0/0/0 Versatile (floating +1 not yet wired)
Elf 0/+2/-1/+1/+1/0 Darkvision; immune to sleep effects
Dwarf +1/-1/+2/0/+1/-1 Poison resistance; bonus vs. underground
Halfling 0/+2/0/0/+1/0 Lucky: once per combat, reroll a nat 1
Orc +3/-1/+2/-1/-1/-1 Rage: once per combat, +50% damage for one turn
Tiefling 0/+1/0/+1/0/+2 Fire resistance; bonus on CHA checks
Half-Elf 0/+1/0/+1/0/+2 Two bonus skill proficiencies

Classes (5): Fighter (d10 HP, STR/CON), Rogue (d8, DEX/INT), Mage (d6, INT/WIS), Cleric (d8, WIS/CHA), Ranger (d8, DEX/WIS).

Subclasses unlock at L3 via !subclass. Each class has 3 archetypes with mechanical features at L5/L7/L10/L15:

Class Subclasses
Fighter Champion, Battle Master, Berserker
Rogue Thief, Assassin, Arcane Trickster
Mage Evocation, Abjuration, Necromancy, Arcane Trickster
Cleric Life, War, Trickery
Ranger Hunter, Beast Master, Gloom Stalker

Spells. Mages, Clerics, and Rangers cast for real. Spell slots tracked, combat consumes them. Mages have a spellbook cap that grows with level — pick what to learn at level-up via !learn.

Combat engine. Forward-simulating turn-by-turn — d20 vs AC for every attack, hit/crit/miss/fumble narration with surfaced roll values ((🎲 14 vs AC 13)), monster abilities, status effects, class resources, consumables. Outcomes stream over 23 second pacing for suspense, with a roll summary appended.

Dungeon zones (!zone) — 10 hand-tuned zones, 5 tiers, level bands L1L20:

Tier Zones
T1 Goblin Warrens, Crypt of Valdris
T2 Forest of Shadows, Sunken Temple
T3 Haunted Manor, Underforge
T4 Underdark Outpost, Feywild Crossing
T5 Dragon's Lair, Abyss Portal

Each run is procedurally laid out (entry → exploration → trap → elite → boss with exploration filler). TwinBee narrates as a mood-driven DM (0100 mood, shifts on crits/deaths/taunts/zone completion). !zone enter, !zone advance to resolve the current room, !zone status, !zone map (ASCII layout E──?──T──★──☠), !zone lore, !zone taunt / !zone compliment to poke or flatter your DM.

Multi-day expeditions (!expedition) — the long form:

  • Outfitting: buy supply packs at start (standard/deluxe), cost scales with zone tier
  • Real-time day cycle: 06:00 morning briefing, 21:00 evening recap (configurable)
  • Supply burn: rations tick down each day; harsh zones burn faster; running out triggers forced extraction
  • Threat Clock (0100): every action is noticed. Crossing bands shifts monster density, patrol odds, night events: Quiet → Stirring → Alert → Hostile → Siege
  • Patrol encounters at Alert+ — fights interrupt traversal
  • Night phase / wandering monsters — checked at the recap
  • Siege Mode (threat 80+): fortified camp branches, special warnings
  • Camp: !camp rough (free, no protection) vs !camp standard (consumes supplies, grants overnight rest)
  • Milestones: First Night, Deep Dive, Long Haul, Survivalist, etc.
  • Expedition log (!expedition log) — every event recorded

Multi-region zones. T4+ zones have multiple connected regions. !region shows where you are, where you can travel, and visited set. Inter-region travel consumes supplies and ticks threat. Base camp is a persistent waypoint per expedition. !map renders the full multi-region map.

Per-zone temporal events (signature time-based effects on every T2+ zone):

  • Sunken Temple — tidal cycle floods/recedes rooms
  • Haunted Manor — nightly reset; cleared rooms come back
  • Underforge — heat accumulation; gear damage rises
  • Feywild Crossing — time distortion; days pass at non-uniform rates
  • Dragon's Lair — awareness pulses warn the dragon directly
  • Abyss Portal — destabilization stack threatens forced collapse

Extract & resume. !extract bails safely from an expedition. Loot/XP/coins kept, expedition flips to extracting status, !resume within 7 days picks up from base camp.

Harvest. !forage / !mine / !fish / !scavenge / !essence / !commune work in cleared rooms during expeditions, and (Phase R) in single-session !zone enter runs too — per-room nodes seeded from the zone resource pool, finite charges, class-specific yield bonuses (Ranger forage/fish, Fighter mine), !resources to see what's gatherable. Zone-condition events (tidal block, heat block, manor cursed trinket drops) layer on during expeditions.

Boss combat. Every zone's boss is in the bestiary with its own stat block and phase-two narration crossing 50% HP. Win drops the per-zone loot table; T5 always drops a masterwork.

HP scale. D&D HP is the source of truth (your sheet says, e.g., 33 max). The combat engine internally uses a legacy HP scale (calibrated for the old combat_level-based curves, ~123 max for a high-level player), but combat outcomes are translated back to D&D scale before display: HP 33→26 / 33 is what you see, never the engine's internal numbers.

Holidays. On recognized holidays (~20/year, religious + cultural calendars), runs start with TwinBee mood +5, expedition outfitting includes a free standard pack, and harvest yields +1 per attempt. Hospital surcharge still applies on holiday deaths.

Player commands cheat sheet:

Command What it does
!setup Opt into D&D — pick race + class, inherits your existing progress
!sheet Full character sheet
!learn Mages — pick a spell at level-up
!subclass Inspect / select subclass at L3
!rest short / !rest long Recover HP between fights (1h / 24h cooldowns)
!check <skill> [dc] Roll a skill check
!zone / !zone list Zones available at your level
!zone enter <id> Start a single-session run
!zone advance Resolve current room
!zone status / !zone map / !zone lore Run inspection
!zone abandon End run, no rewards
!zone taunt / !zone compliment Poke the DM
!expedition list Zones available at your level
!expedition start <zone> [Ns] [Md] Outfit and begin
!expedition status / !expedition log Daily briefing + history
!expedition abandon End expedition (no rewards)
!camp rough / !camp standard Make camp
!region Multi-region inspection + travel
!map Full multi-region map
!forage / !mine / !scavenge / !fish / !essence / !commune Work the room
!resources Inventory of harvested materials
!threat Current threat clock
!extract Bail safely from an expedition
!resume Pick up an extracted expedition
!respec Wipe character (paid; cooldown gated)

Compatibility. Adv 2.0 is fully additive — every pre-2.0 column on adventure_characters, adventure_equipment, adventure_inventory, adventure_treasures, arena_stats, etc. is preserved with original semantics. Migrations are column-adds with defaults only. Players who haven't run !setup keep the legacy adventure shape. combat_level becomes the D&D level; treasures become attunements; equipment slots carry forward unchanged.

Legacy adventure surface (still active)

The pre-2.0 town economy and supporting systems still work alongside the D&D layer.

Command Description
!adventure / !adv Open today's menu (sent via DM) — now points at !expedition and town services
!adventure status Character sheet (legacy view; !sheet is the D&D-layer view)
!adventure shop Browse equipment for sale (sent via DM)
!adventure buy <item> Buy equipment by name or tier shorthand (3 sword, t4 boots)
!adventure sell <item> Sell an inventory item (credits euro balance)
!adventure sell all Sell entire inventory (consumables protected)
!adventure equip Equip masterwork gear from inventory
!adventure inventory List current inventory
!adventure leaderboard Top adventurers
!adventure revive @user Revive a dead player (admin)
!adventure summary Force daily summary post (admin)
!adventure boost Double XP/money for all adventurers for a day (admin)
!adventure babysit [week|month|status|cancel] Hire TwinBee to harvest on your behalf (trains your weakest gathering skill)
!adventure blacksmith Show repair quotes for damaged gear
!adventure repair [all|<slot>] Repair one slot or all damaged gear at the blacksmith
!adventure rivals Show the rival pool and any open challenges
!thom [shop|buy|pay|payoff|autopay|petbuy] Thom Krooke — housing, mortgage, and pet adoption broker
!hospital Check in to St. Guildmore's Memorial Hospital for same-day revival (costs €25k × combat level)

Skill tracks

Four skills are tracked separately from D&D level: Combat (legacy), Mining, Foraging, Fishing. They gain XP from harvesting in zones, arena fights, encounters, and (legacy) babysitter actions. Skill levels gate masterwork drops, fishing-zone proficiency bonuses, and crafting recipe unlocks.

Mechanics

  • Equipment — 5 slots (weapon, armor, helmet, boots, tool) with tiered upgrades from the shop. Equipment degrades on bad outcomes and breaks at 0 condition.
  • Masterwork gear — rare skill-specific equipment drops from gathering activities (mining, fishing, foraging). 15 items across 5 tiers with decreasing drop rates (5% T1 down to 0.5% T5). Location-gated — drops only at matching tier. Auto-equips if better than current gear; otherwise goes to inventory for manual equipping via !adventure equip. Masterwork items provide a +5% skill bonus when the item's source skill matches the current activity. Character sheet marks masterwork items with a star.
  • Treasures — rare collectibles (up to 3) that provide passive bonuses (XP multipliers, death chance reduction, loot quality). Prompted to discard when at cap.
  • Streaks — consecutive days of activity grant escalating bonuses (XP, loot quality, death chance reduction). Resting resets your streak. Dead players' streaks are frozen — you won't lose your streak to involuntary downtime.
  • Grudge — dying at a location marks it as your grudge. Returning there grants +10% success and +25% XP. Clears on success.
  • Death — locked out for 6 hours. Natural respawn happens automatically when the timer expires. Use !hospital for immediate revival at a cost. Death's Reprieve (surviving a lethal roll) sets all equipment to 1 condition instead of destroying it. Dead players' streaks are preserved with a grace period — if you die and can't act on revival day, your streak won't reset.
  • Holidays — on recognized holidays (~20/year across religious and cultural calendars), runs start with TwinBee mood +5, expedition outfitting includes a free standard pack, and harvest yields +1 per attempt. Hebrew and Islamic calendar support for floating holidays.
  • TwinBee — narrates as a mood-driven DM during zone runs and expeditions (see Adv 2.0 above). The legacy daily activity loop is retired in favor of zones/expeditions; the babysitter (below) is the surviving "TwinBee runs an action for you" surface.
  • Hospital — St. Guildmore's Memorial Hospital offers same-day revival for dead players. The bill is comically inflated (€125k × combat level) but guild insurance covers 80%, leaving €25k × combat level. Players who can't afford it are discharged back to the natural respawn queue. Nurse Joy provides the bedside manner.
  • Robbie the Friendly Bandit — an automated NPC who visits at a random hour each day (8:0021:00 UTC). Robbie takes sub-tier gear from your inventory (shop gear below your equipped tier, masterwork gear you've outgrown), leaves €50 per item as a "handling fee," and donates everything to the community pot. If he takes masterwork gear and you don't already have one, he drops a "Get Out of Medical Debt Free" card. No player command — Robbie comes to you.
  • Mid-day events — random events can trigger between actions, delivering bonus loot, buffs, or narrative encounters.
  • Chat level perks — active chat participation boosts your adventurer. +5% XP per 10 chat levels (capped at +25% at level 50+), plus +0.5% rare drop chance per 10 levels.

Crafting

Auto-crafting kicks in at Foraging Lv.10. Before each combat action, the system scans your inventory for matching ingredients and assembles the highest-tier recipe you qualify for. 12 recipes spanning T1T5, gated at Foraging 10/15/20/25/30. Per-recipe success rate is 50% at the unlock level, +3% per 5 levels above (capped 95%). Failed crafts destroy the ingredients — you tried.

Per attempt:

  • Successful crafts grant Foraging XP (T1: +12, T2: +25, T3: +40, T4: +60, T5: +90) and bump a lifetime CraftsSucceeded counter shown on !adventure status.
  • Failed crafts grant a token Foraging XP (1/4 of success).

Max auto-crafts per combat scales with level: 1 at Foraging 10, 2 at 20, 3 at 30+.

!adventure recipes lists every recipe unlocked at your current Foraging level with ingredients and per-recipe success rate, plus a teaser for the next unlock threshold.

Consumable protection: crafted/dropped consumables (Type consumable) are excluded from !adventure sell all and Robbie the Friendly Bandit's pickup filter. Selling consumables requires explicit !adventure sell <name> — no accidental mass-sells, no surprise donations to the community pot.

Blacksmith & Repair

Equipment accumulates damage on bad outcomes and breaks at 0 condition. The blacksmith repairs gear for a per-point fee that scales with tier (base rates T0→T5: €1, €2, €5, €12, €30, €80; masterwork and arena gear use the next tier up). The cost has a mild convexity (baseRate × damage × (1 + damage/200)), so repairing earlier is slightly cheaper per point than letting gear sit at low condition — but not punitively so. !adventure blacksmith previews quotes; !adventure repair all or !adventure repair <slot> commits.

Babysitting Service

Busy days? Hire TwinBee to harvest on your behalf. Daily cost is €100 + combatLevel × €20. TwinBee trains your weakest gathering skill (mining/fishing/foraging) each day, so the service doubles as catch-up for neglected tracks. Subscribe by the week or month, or check/cancel anytime: !adventure babysit week|month|status|cancel.

Rival Duels

At combat level 5 and above you're entered into the rival pool. Every 34 days a random eligible player is matched as your rival and challenges you to a rock-paper-scissors duel via DM. You have 24 hours to accept and play. Stake is (combatLevel / 5) × €1,000, winner-take-all. Use !adventure rivals to see the pool and open challenges.

Housing & Mortgage (Thom Krooke)

Thom Krooke is the guild's housing broker. Four tiers are available:

Tier Name Price
1 Base €75,000
2 Livable €150,000
3 Comfortable €300,000
4 Established €600,000

Buy outright or finance with a mortgage. Rates track the real-world US 5/1 ARM via the FRED API (MORTGAGE5US series; requires FRED_API_KEY, defaults to 6.5% if unset). Autopay pulls from your euro balance each day. Commands: !thom shop, !thom buy <tier>, !thom pay <amount>, !thom payoff, !thom autopay on|off, !thom petbuy.

Pets

Once you reach the Livable tier (HouseTier ≥ 2) a stray pet may show up at your door — 15% daily chance. When a pet arrives you'll get a DM prompt to chase it away or feed it to adopt. Each pet interaction grants +1.5 XP to a random skill. At pet Level 10, Thom unlocks pet armor for purchase (!thom petbuy <tier>).

Guest NPCs — Misty & Arina

Two rotating guest adventurers can be hired to join you on encounters:

  • Misty — €100 hire fee, 7-day cooldown.
  • Arina — €5,000 hire fee, 7-day cooldown.

After hiring, there's a 7.5% chance per action over the next 7 days that your NPC shows up mid-adventure and applies a buff to the outcome.

Arena (!arena)

A multi-tier combat gauntlet independent of the daily adventure action. Fight through 5 tiers of 4 rounds each — 20 unique named monsters with escalating lethality. Earnings accumulate across rounds but are forfeited on death. After clearing a tier, choose to descend deeper (keep earnings at risk) or cash out. Death locks you out of both arena and adventure for 6 hours. Each fight produces a turn-based combat log (Dragon Quest style) with fabricated HP pools and action narration — the outcome is determined by the roll, the log is assembled backward from the result. Arena losses award +60 participation XP.

Command Description
!arena Show the arena tier menu
!arena tier <1-5> Select a tier (shows confirmation with R1 opponent)
!arena fight Confirm entry / fight current round
!arena cancel Back out of tier selection
!arena descend Descend to next tier after clearing (earnings carry over, still at risk)
!arena cashout Take your earnings and leave
!arena stats Your personal arena stats
!arena status Current run state
!arena leaderboard Top arena players
!arena help Arena help text

Mechanics:

  • Death chance — based on monster lethality, combat level, equipment tier, and battle skill. Clamped between 1% and 98%.
  • Rewards — tier base payout * round number + battle skill * tier multiplier. Higher tiers and later rounds pay more.
  • Auto-cashout — 10 minutes to decide after clearing a tier. GogoBee cashes out on your behalf if you're slow.
  • Tier entry confirmation!arena tier N previews the first opponent; !arena fight commits.

Co-op Dungeons (!coop)

Multi-day party runs separate from solo. 24 players, 27 days depending on tier, scaled rewards, and a public game-room thread the whole community watches. The combat action is consumed once at lock; subsequent days only ask for a daily funding decision (harvest activities continue normally).

Tier Days Difficulty Reward Pool Optimal Funding
1 2 Moderate €22,500 Minimal/Standard
2 3 Hard €40,000 Standard
3 4 Very Hard €72,500 Standard
4 5 Brutal €120,000 Standard or Aggressive
5 7 Murderous €600,000 Aggressive (must commit)
Command Description
!coop list Show open invites
!coop start <1-5> Open an invite (24h window, pinned in the games room)
!coop join [<id>] Join an open invite (defaults to most recent)
!coop fund <tier> Set today's funding (none / minimal / standard / aggressive / all_in)
!coop vote <A|B|C> Vote on the day's TwinBee-narrated floor event
!coop bet <amount> <success|failure> Spectator parimutuel bet (10% rake)
!coop gift <run_id> <basket|mimic> Send a gift (1 harvest action)
!coop giftvote <id> <open|leave> Party votes whether to open a received gift
!coop status Your current run state
!coop stats Community-wide aggregates: outcomes, gold flow, betting, gifts, helpfulness
!coop cancel Leader cancels an open invite before lock
!coop admgift <run_id> <basket|mimic> [sender] Drop a gift into an active run, bypassing party-member and harvest-action checks (admin only — debug/testing)
!coop help Co-op command list

Funding tiers add to the per-floor success modifier: None 10%, Minimal +0%, Standard +8%, Aggressive +18%, All-In +30%. None is free; Minimal €500/day; Standard €1,500; Aggressive €4,000; All-In €10,000. Funding is non-refundable. Inactive players auto-play None.

Floor events. TwinBee narrates 1 of 4 categories per floor (Obstacle / Opportunity / Crisis / Encounter), tier-weighted. Each event has 23 options; majority vote wins, ties go to the leader, leader has the casting tiebreak. TwinBee always recommends an option — he is wrong roughly half the time. The party's vote modifier (15 to +12 per floor depending on the option) stacks on the funding modifier. The 95% per-floor success cap means once you're saturated, more funding is wasted.

Party strength factors. Each member contributes a small per-floor modifier based on their combat level relative to the tier minimum (clamped ±8) plus a pet bonus (max +2.5 at pet level 10). A maxed veteran party at T5 can succeed at Standard funding where a fresh party would need Aggressive.

Newbie liability. Players below a tier's minimum combat level are flagged in the party post and capped at +8% funding modifier regardless of how much they pay. The party chose to let them in. Their reward share is unchanged — the cost is borne by the funding economy, not the post-run split.

Spectator betting. Parimutuel pool, 10% rake. Bets can be placed or increased any time during the run; positions are locked in (success or failure can't be switched). Party members can bet on their own run — sandbagging while heavily bet against is exploitative and visible. Odds line shows estimated success% based on party levels, pets, neutral funding assumption, and a hidden TwinBee Helpfulness Rating (rolling last 30 floor events: how often his recommendation was right). Helpfulness shifts the line ±20% but is never shown directly — players notice the line moves after events resolve.

Gifts. Anyone not in the run can spend one harvest action to send a Care Basket or a Mimic. The party never sees which type. Vote open or leave. Each gift's voting window is 6 hours; voting closes when it elapses, the stack is tallied, and every sender gets a DM with the result. The modifier sits on the run until the next floor resolution merges it in. Gifts "fire" throughout the day rather than piling up at the daily tick. Magnitudes are equalized across all four outcomes — both "always open" and "always leave" yield EV=0 with σ=6, so neither is risk-averse-dominant. The choice is purely about reading sender intent.

Stacking. Multiple gifts of the same type sent on the same day stack into a single game-room post — one vote covers the whole stack, modifier scales with size (5 baskets opened = +30%, 5 baskets exploded = 30%). The first-in sets the deadline; subsequent additions inherit it without extending the timer. When a stack hits size 2, TwinBee notes "this gift looks REALLY special" once and then quietly bumps the count on further additions. The end-of-run gift log groups by stack with all senders attributed.

Open Leave
Care Basket +6% (boost) 6% (basket explodes)
Mimic 6% (mimic does what mimics do) +6% (sad mimic helps anyway)

Multiple gifts stack additively — coordinated senders can swing odds significantly. The full gift log is public at end of run.

Loot. On success, gold pool splits evenly (5% community tax). 26 items drop from the corresponding solo dungeon loot table (count scales with tier). Each item goes to a member via weighted roll — your share of total funding is your odds. T5 always drops a masterwork; T4 has a 25% chance. Masterworks go to inventory (not auto-equipped) so winners with better gear can sell or trade.

Wipes. No reward. Funding is gone. No combat-action refund (the tick already gave you a fresh one at midnight). Bet pool pays out to the failure side. The dungeon does not editorialize.

Pinning. Invite posts are pinned in the games room when opened, unpinned when the run locks or cancels. Bot needs power level for state events.

Reminders

Command Description
!remindme <time> <message> Set a reminder (natural language)
!reminders Your pending reminders
!unremind <id> Cancel a reminder

Presence

Command Description
!away [message] Set away status
!afk [message] Same as away
!back Clear away/afk
!whois @user Profile card

Fun

Command Description
!roll [NdM+X] Dice (default 1d6)
!8ball <question> Magic 8-ball
!coin Coin flip
!time [city|@user] World clock (cities or user's timezone)
!hltb <game> How Long To Beat
!twinbee Twinbee series lore
!poll <q> | <a> | <b>... Reaction poll
!weather <location> Weather (needs API key)
!dadjoke Dad joke
!randomwiki Random Wikipedia article

Tools

Command Description
!calc <expression> Calculator, understands "5 plus 3"
!qr <text> Generate QR code

Finance

Command Description
!stock <ticker> Stock quote (Finnhub)
!stockwatch add|list|remove Stock watchlist
!fx rate [EUR|JPY|CAD] Live USD exchange rate + quick signal
!fx rate EUR/USD Cross-pair rate from first currency's perspective
!fx report [EUR|JPY|CAD] Full analysis (averages, 52w range, buy score)
!fx report EUR/JPY Cross-pair full analysis with computed history
!fx setalert <currency> <rate> DM alert when rate hits threshold
!fx alerts List your active alerts
!fx delalert <currency> <rate> Remove an alert
!howsthemarket Daily market snapshot with Ollama commentary (7 global indices)
!marketstatus Exchange open/closed status (NYSE, LSE, Euronext, TSE)
!marketreport week|month|year Historical trend report with Ollama narrative
!marketreport vix VIX fear/greed trajectory
!marketreport compare <index> <days> Single index over N days

Entertainment

Command Description
!game <query> / !retro <query> Game lookup (RAWG)
!releases [month|search <q>] Game releases
!releasewatch add|list|remove Release watchlist
!concerts <artist> Concert search
!concerts watch|watching|unwatch Concert watchlist
!anime <title> Anime search (MAL)
!anime watch|watching|unwatch|season|upcoming Anime features
!movie <title> / !tv <title> Movie/TV search (TMDB)
!movie watch|watching|unwatch Movie watchlist
!upcoming movies Upcoming movies

Lookup & Reference

Command Description
!wiki <topic> Wikipedia summary
!define <word> [lang] Dictionary definition — searches all languages via DreamDict by default, or specify one (en/fr/pt-PT/zh). Includes antonyms when available. Falls back to free dictionary API for English if DreamDict is unavailable.
!urban <term> Urban Dictionary
!translate <word> [lang] Cross-language word lookup (en/fr/pt-PT, auto-detects source)
!antonym <word> [lang] Antonyms for a word (en/fr/pt-PT/zh)
!pronounce <word> [lang] Pronunciation data — IPA, CMU phonemes (en), Pinyin (zh)
!etymology <word> [lang] Word origin and history from Wiktionary
!difficulty <word> [lang] Difficulty score (Easy/Medium/Hard/Brutal) with frequency info
!rhyme <word> Rhyming words via CMU phoneme matching (English only, --all for full list)

Personal

Command Description
!settz <timezone> Set timezone (IANA)
!mytz Your timezone and current time
!timezone list Common timezones
!np [track] Now playing
!backlog add|list|random|done Personal backlog
!watch <keyword> DM alerts for a keyword
!watching List keyword watches
!unwatch <keyword> Remove watch

Countdowns

Command Description
!countdown add "<label>" <YYYY-MM-DD> Public countdown
!countdown private "<label>" <YYYY-MM-DD> Private countdown
!countdown mine Your countdowns
!countdown remove <id> Remove one
!countdown [id] List all or show one

Birthdays

Command Description
!birthday set <MM-DD[-YYYY]> Set birthday
!birthday remove Remove birthday
!birthday show Show yours
!birthdays Upcoming (next 30 days)
!horoscope Daily horoscope (requires birthday to be set)

Community

Command Description
!quote Random quote (or reply to a message to save it)
!quote @user Random quote from a specific user
!quote search <text> Search quotes
!quote "text" -- @user Manually save a quote attributed to a user
!quote delete <id> Delete a quote (admin only)
!quoteboard Top 5 most-quoted members
!missing List members who haven't posted recently
!missing post [@user] Generate a milk carton poster for the longest-absent (or specified) member
!haveyouseenthem @user Generate a milk carton missing poster for a user

Markov

Command Description
!markov [@user] Generate a sentence in the style of a user (or yourself)
!markov me Alias for generating from your own corpus
!markov @user1 @user2 Mashup — interleave both users' corpora
!impersonate @user Alias for !markov @user
!ghostwrite @user <prompt> Seed the Markov chain with a starting phrase
!markov stats [@user] Corpus size, unique words, top 5 words, earliest date
!markov forget Delete your own Markov corpus (DM confirmation)
!markov forget @user Admin-only: clear another user's corpus
!markov leaderboard Top 10 by corpus size

Emojiboard

Command Description
!emojiboard Top 10 most-used reaction emojis in this room
!emojiboard @user Top emojis given by a specific user
!emojiboard received [@user] Top emojis received by a user
!emojiboard givers <emoji> Top 5 users who used a specific emoji most
!emojiboard week Same as !emojiboard but last 7 days only

LLM (requires Ollama)

Command Description
!howami [@user] Roast profile
!vibe Room energy check
!tldr Summarize recent chat
!sentiment [@user] Sentiment breakdown (10 categories)
!potty [@user] Profanity count
!pottyboard Profanity leaderboard
!insults [@user] Insult stats
!insultboard Insult leaderboard
!tarot [@user] Draw a tarot card + LLM reading
!tarotspread [@user] Three-card spread (Past/Present/Future)

Moderation (admin only, requires FEATURE_MODERATION=true)

Command Description
!mod warn @user [reason] Issue a manual warning (counts as a strike)
!mod mute @user [duration] Manual mute (does not consume a strike)
!mod unmute @user Remove mute
!mod ban @user [reason] Permanent ban
!mod strikes @user Show active strikes
!mod forgive @user Clear all active strikes
!mod history @user Full moderation history
!mod reload Reload word list from disk
!mod status Show current moderation config
!mod test @user Simulate next violation without taking action

RSS / Miniflux (requires MINIFLUX_URL)

Command Description
!rss feeds List all feeds from Miniflux with IDs and categories
!rss subscribe <feed_id> [#room] Route a feed to this room (admin only)
!rss unsubscribe <feed_id> Stop routing a feed (admin only)
!rss subscriptions List active subscriptions for this room
!rss latest <feed_id> Manually fetch and post the latest entry
!rss pause <feed_id> Pause feed routing (admin only)
!rss resume <feed_id> Resume a paused feed (admin only)
!rss status Show polling status (admin only)

Other

Command Description
!achievements [@user] Unlocked achievements
!wotd Today's Palavra do Dia — Portuguese word with en/fr translations, etymology when available (use it in chat for 25 XP)
!wotd force Pick a new word for today (moderator only)
!botinfo Bot diagnostics (admin only)
!help DMs the full command list

Passive Features

All of these run in the background without any commands:

  • XP - 10 XP per message with 30s cooldown. Level-up announcements use Twinbee/Parodius themed messages.
  • Stats - tracks words, chars, links, images, questions, emojis, and time-of-day patterns
  • Streaks - consecutive days active, first poster of the day
  • Reputation - detects "thanks", "ty", "thx", etc. with 24h cooldown per pair
  • Achievements - 93 of them, checked silently on every message
  • Markov chains - collects encrypted messages for !markov generation (10k cap per user, 90-day TTL)
  • Keyword alerts - DMs you when someone says your watched keywords
  • Presence - auto-clears away/afk when you send a message
  • Room milestones - announces at 1k, 5k, 10k, 25k, 50k, 100k, 250k, 500k, 1M messages
  • Euro earning - earn €0.50€10 per message based on word count (30s cooldown). Starting balance seeded from corpus history (capped at €2,500)
  • URL previews - OG tag extraction (feature-flagged, off by default)
  • Reactions - logs all reactions for !emojiboard
  • Space groups - rooms with sufficient member overlap are automatically grouped. Leaderboards, trivia scores, and other per-room features aggregate across the group. Recomputed hourly; persisted to SQLite. Uses strict clique-based grouping (every room must meet the threshold with every other room in the group).
  • LLM classification - sentiment (10 categories), profanity, insults, WOTD usage (needs Ollama). Emoji reactions limited to fancy words (🎓), gratitude (💜), WOTD usage (📖), and insult responses
  • Message buffer - last 50 messages per room held in memory for !vibe and !tldr. Not persisted to disk; resets on restart. Uptime reported when insufficient messages are buffered.

Scheduled Posts

Uses robfig/cron. All times UTC.

Time Job What it does
06:00 Birthdays Birthday shoutouts + 100 XP + €1,000
07:00 Holidays Multi-calendar holidays (US, Asian, Jewish, Islamic)
08:00 WOTD Posts the Word of the Day (disable with DISABLE_WOTD_POST=true)
09:00 Mon Releases Weekly game releases
10:00 Anime Anime airing today
11:00 Movies Movie releases today
12:00 Sun Concerts Weekly concert digest
13:00 Wed/Sun Esteemed Satirical esteemed community member posts (feature-flagged)
Every 30s Reminders Fires pending reminders
Hourly Space groups Refreshes room membership overlap and group mappings
03:00 Maintenance Purges stale caches, old rate limits, expired logs, miniflux seen entries; runs SQLite optimize
03:30 Markov TTL Purges markov corpus entries older than 90 days
23:00 Market Daily market index pull (Yahoo Finance + Finnhub fallback, Ollama summary)
Every N min Miniflux Polls Miniflux for new feed entries (configurable, default 15m)

Achievements

93 achievements across 15 categories:

Message Milestones - first_message, 100_messages, 500_messages, 1000_messages, 5000_messages, 10000_messages

Time-Based - night_owl, early_bird, night_dweller, dawn_patrol

Content - wordsmith, link_collector, link_hoarder, shutterbug, photographer, question_master, emoji_lover, exclaimer

Social - welcome_wagon, rep_magnet, rep_star

Streaks - week_streak, two_week_streak, month_streak, quarter_streak, year_streak

Trivia - trivia_novice, trivia_master, trivia_legend

Economy - euro_first, euro_1k, euro_10k, euro_broke, euro_comeback, euro_generous

Blackjack - bj_first_win, bj_blackjack, bj_bust, bj_beat_twinbee, bj_100_hands

UNO - uno_first_win, uno_nomercy_win, uno_draw_stack, uno_comeback

Texas Hold'em - holdem_first_win, holdem_royal_flush, holdem_bluff, holdem_beat_npc, holdem_allin_win, holdem_bounty

Hangman - hangman_solve, hangman_first_guess, hangman_submitted, hangman_executioner

Wordle - wordle_solve, wordle_first_guess, wordle_streak_3, wordle_bonus, wordle_closer

Adventure - adv_first, adv_died, adv_revived, adv_streak_7, adv_streak_30, adv_max_level, adv_treasure_cap, adv_grudge_win, adv_party, adv_twinbee_gift

Arena - arena_first_blood, arena_tier1, arena_tier2, arena_tier3, arena_tier4, arena_tier5, arena_descend, arena_full_run, arena_death_t5, arena_omega, arena_cashout_big

Community - quote_saved, quote_saved_10, missing_poster, tarot_spread

WOTD - wotd_first, wotd_week, wotd_30, logophile

Special - markov_victim, birthday_set, timezone_set, profile_complete


Personality Archetypes

Assigned based on your message patterns:

Archetype What it means
Chatterbox You talk a lot
Novelist Long messages
Inquisitor Always asking questions
Linkmaster Shares lots of links
Shutterbug Lots of images
Enthusiast Exclamation marks!
Regular Solid community member

Sentiment Classification

Every message (subject to LLM_SAMPLE_RATE) is classified by Ollama into one of 10 sentiment categories. Per-user counts are tracked in the database and viewable via !sentiment. The LLM also returns a float score (-1.0 to 1.0) for each message, averaged per user to derive an overall mood shown in !sentiment output and fed into !howami roast profiles.

Selective emoji reactions are still active: 🎓 for fancy/uncommon words, 💜 for gratitude, and 📖 for WOTD usage. The bot also reacts when insulted. Sentiment and profanity emoji reactions are disabled — classification still runs and logs to the database, but the bot won't react with sentiment emojis.

Sentiment Score range Example
Positive > 0.5 "This is awesome, great work!"
Excited > 0.5 "OH MY GOD I can't wait for this!!"
Supportive > 0.5 "You've got this, don't give up"
Grateful > 0.5 "Thank you so much for helping me"
Humorous > 0.5 "lmao that's the funniest thing I've seen all day"
Curious > 0.5 "How does that work exactly?"
Neutral "I'll be back in 10 minutes"
Sarcastic < -0.5 "Oh sure, that'll definitely work"
Frustrated < -0.5 "I've been trying to fix this for three hours"
Negative < -0.5 "This is broken and nobody cares"

External APIs

All optional. The bot works fine without any of them, you just won't have those specific features.

Service Free? What for
RAWG Yes Game lookups, releases
DreamDict Self-host Translations, WOTD (etymology), Hangman (clues + difficulty), Wordle (word selection + validation), dictionary commands (antonyms, pronunciation, etymology, difficulty, rhymes)
Calendarific Yes (1k/mo) Holiday calendar
HebCal Yes, no key Jewish holidays
Aladhan Yes, no key Islamic dates
OpenWeather Yes (1k/day) Weather
Finnhub Yes Stock quotes, market index fallback
Yahoo Finance Yes, no key Market index snapshots (unofficial API)
Frankfurter Yes, no key Forex rates (ECB-sourced)
Bandsintown Yes Concert data
Jikan/MAL Yes, no key Anime data
TMDB Yes Movie/TV data
OpenTDB Yes, no key Trivia questions
Wikipedia Yes, no key Wiki summaries
Free Dictionary Yes, no key Definitions
Urban Dictionary Yes, no key Slang
icanhazdadjoke Yes, no key Dad jokes
SerpAPI Free (100/mo) Image search for esteemed members
HowLongToBeat Yes, no key Game completion times
Ollama Self-host LLM features (sentiment, tarot, vibes, roasts)
Miniflux Self-host RSS feed routing

Architecture

gogobee/
├── main.go                  # Entry point, plugin registration, cron setup
├── go.mod / go.sum
├── data/
│   ├── policy.gob           # Pre-trained CFR policy for Hold'em NPC
│   └── wordle_games.txt     # Video game themed words for Wordle bonus puzzles
├── cmd/
│   ├── holdem-train/
│   │   └── main.go          # CFR training CLI (build tag: training)
│   └── holdem-seed/
│       └── main.go          # Seed policy generator
├── internal/
│   ├── bot/
│   │   ├── client.go        # mautrix client + E2EE (cryptohelper + goolm)
│   │   └── dispatch.go      # Plugin registry, event dispatch
│   ├── crypto/
│   │   └── crypto.go        # AES-256-GCM encryption, HMAC-SHA256
│   ├── db/
│   │   └── db.go            # SQLite schema (80+ tables), migrations
│   ├── plugin/
│   │   ├── plugin.go        # Plugin interface, Base helpers, context types
│   │   ├── xp.go            # XP & leveling
│   │   ├── reputation.go    # Thanks detection
│   │   ├── stats.go         # Message stats & milestones
│   │   ├── streaks.go       # Daily streaks
│   │   ├── trivia.go        # OpenTDB trivia
│   │   ├── reminders.go     # Reminders
│   │   ├── presence.go      # Away/AFK
│   │   ├── fun.go           # Dice, 8ball, polls, weather, etc.
│   │   ├── tools.go         # Calculator, QR codes
│   │   ├── user.go          # Timezone, quotes, backlog, keyword watches
│   │   ├── welcome.go       # New user detection, !help
│   │   ├── achievements.go  # 93 achievements
│   │   ├── reactions.go     # Reaction logging, emojiboard
│   │   ├── markov.go        # Markov chains
│   │   ├── urls.go          # URL previews
│   │   ├── llm_passive.go   # Ollama sentiment/profanity
│   │   ├── wotd.go          # Word of the Day
│   │   ├── holidays.go      # Multi-calendar holidays
│   │   ├── gaming.go        # Game releases
│   │   ├── birthday.go      # Birthdays
│   │   ├── retro.go         # Game lookups (RAWG)
│   │   ├── lookup.go        # Wiki, dictionary, urban, translate
│   │   ├── dictionary.go    # DreamDict commands (antonym, pronounce, etymology, difficulty, rhyme)
│   │   ├── countdown.go     # Countdowns
│   │   ├── stocks.go        # Stocks
│   │   ├── market.go        # Market indices (Yahoo Finance + Finnhub fallback)
│   │   ├── forex*.go        # Forex rates & alerts (Frankfurter v2)
│   │   ├── concerts.go      # Concerts
│   │   ├── anime.go         # Anime
│   │   ├── movies.go        # Movies/TV
│   │   ├── miniflux.go      # Miniflux RSS feed routing
│   │   ├── botinfo.go       # Admin diagnostics
│   │   ├── howami.go        # LLM roasts
│   │   ├── vibe.go          # Room vibe, TLDR
│   │   ├── shade.go         # Stub
│   │   ├── milkcarton.go    # Missing member milk carton posters
│   │   ├── quotewall.go     # Encrypted quote wall (AES-256-GCM)
│   │   ├── tarot.go         # LLM-powered tarot readings
│   │   ├── horoscope.go     # Daily horoscopes
│   │   ├── euro.go          # Euro virtual currency
│   │   ├── flip.go          # Coin flip, !games
│   │   ├── hangman.go       # Collaborative Hangman
│   │   ├── blackjack.go     # Multiplayer Blackjack
│   │   ├── uno.go           # Solo UNO vs bot (DM-based)
│   │   ├── uno_multi.go     # Multiplayer UNO (lobby + DM turns + addbot)
│   │   ├── uno_nomercy.go   # No Mercy mode (deck, stacking, mercy rule, 7-0, bot AI)
│   │   ├── uno_test.go      # UNO tests (sudden death, scoring)
│   │   ├── holdem.go        # Texas Hold'em plugin (commands, game lifecycle, NPC)
│   │   ├── holdem_game.go   # Game state, player types, deck, position labels
│   │   ├── holdem_betting.go # Blinds, action validation, side pots
│   │   ├── holdem_eval.go   # Hand evaluation, showdown, settlement
│   │   ├── holdem_render.go # Card glyphs, table view, announcements
│   │   ├── holdem_tips.go   # Ollama coaching tips with equity analysis
│   │   ├── holdem_equity.go # Monte Carlo equity engine
│   │   ├── holdem_cfr.go    # CFR policy table, NPC action selection, training
│   │   ├── wordle.go        # Daily Wordle plugin (commands, lifecycle, scheduler)
│   │   ├── wordle_game.go   # Puzzle state, scoring algorithm, letter tracking
│   │   ├── wordle_render.go # Emoji grid, keyboard, announcements, leaderboard
│   │   ├── wordle_wordnik.go # Wordnik API (random word, validation, definitions)
│   │   ├── wordle_fallback.go # Emergency word list loader
│   │   ├── adventure.go     # Adventure plugin (commands, DM routing, activity resolution)
│   │   ├── adventure_character.go # Character types, DB CRUD, level-up, equipment
│   │   ├── adventure_activities.go # Locations, probability engine, loot, XP tables
│   │   ├── adventure_shop.go # Shop listings, buy/sell, inventory
│   │   ├── adventure_treasure.go # Treasure definitions, drop logic, bonuses
│   │   ├── adventure_twinbee.go # TwinBee NPC, reward distribution, buff gifts
│   │   ├── adventure_render.go # Character sheet, DMs, daily summary, leaderboard
│   │   ├── adventure_events.go  # Mid-day random events
│   │   ├── adventure_hospital.go  # Hospital revival system (Nurse Joy, itemized bill, nudges)
│   │   ├── adventure_robbie.go    # Robbie the Friendly Bandit (automated inventory cleaner)
│   │   ├── adventure_scheduler.go # Morning DM, evening summary, midnight reset tickers
│   │   ├── adventure_holidays.go # Holiday detection (Hebrew/Islamic calendar, fixed dates)
│   │   ├── adventure_masterwork.go # Masterwork gear (15 tiered items, drop logic, equip command)
│   │   ├── adventure_arena.go    # Arena commands, combat resolution, DB CRUD, auto-cashout
│   │   ├── adventure_arena_combat.go # Arena combat log generator (action pools, HP narration)
│   │   ├── adventure_arena_monsters.go # 5 tiers, 20 monsters, death messages
│   │   ├── adventure_arena_render.go   # Arena UI rendering (menus, stats, leaderboard)
│   │   ├── adventure_flavor_*.go # Flavor text pools (dungeon, mining, fishing, treasure, twinbee, events, hospital, robbie, closing)
│   │   ├── esteemed.go      # Satirical esteemed member posts
│   │   ├── moderation.go   # Moderation system (strikes, word list, flood detection)
│   │   └── ratelimits.go    # Rate limiting
│   └── util/
│       ├── auth.go          # Matrix login, token check
│       ├── logger.go        # slog logging
│       └── parser.go        # Message parsing, XP math, archetypes

Why Go?

E2EE - This project went through three SDK iterations: matrix-bot-sdk (no E2EE support), matrix-js-sdk (E2EE via fake-indexeddb with an in-memory crypto store that wiped device keys on every restart), and finally mautrix-go which stores crypto state in SQLite with cross-signing bootstrap. The bot self-verifies its own device on startup.

Deployment - Pure Go, no CGo. go build -tags goolm gives you a static binary with zero system dependencies. The TypeScript version needed Node.js, npm, a C compiler for better-sqlite3, and libolm.

Scheduler - Replaced a hand-rolled 60s tick loop with robfig/cron. Standard cron expressions, less code, fewer bugs.

Plugins - Go interfaces + struct embedding instead of abstract classes. Same pattern, less boilerplate.


Database

Single SQLite file at $DATA_DIR/gogobee.db. Schema auto-creates on first run. WAL mode enabled.

80+ tables covering users, XP, stats, streaks, reputation, reminders, trivia, achievements, encrypted quotes (AES-256-GCM), backlog, keyword watches, scheduler config, birthdays, horoscopes, LLM classifications, stocks, market snapshots, forex rates/alerts, concerts, anime, movies, countdowns, presence, encrypted markov corpus, reaction log, miniflux RSS subscriptions, and various caches.

Backup

# safe to run while the bot is up (WAL mode)
sqlite3 data/gogobee.db ".backup data/gogobee-backup.db"

Troubleshooting

E2EE

E2EE should just work. The bot bootstraps cross-signing and self-verifies its device on first run.

  1. After restarts, the bot reuses its saved device and crypto state. No manual steps needed.
  2. If things are really broken, delete data/device.json and data/gogobee.db to start fresh.

Bot not responding in encrypted rooms

  • Check that the bot joined the room (it auto-joins on invite)
  • Look at logs for decryption errors

API commands not working

  • Check that the relevant API key is set in .env
  • Look at logs for error messages
  • Most APIs have rate limits; the bot caches responses to stay within them

Build errors about libolm

# use the goolm tag:
go build -tags goolm -o gogobee .

License

MIT

Description
Matrix community bot with E2EE, 50 plugins, passive tracking, scheduled posts, and optional LLM features. Written in Go using mautrix-go for encryption and modernc.org/sqlite for storage.
Readme 18 MiB
Languages
Go 100%