# GogoBee Matrix community bot with E2EE, 43 plugins, passive tracking, scheduled posts, and optional LLM features. Written in Go using [mautrix-go](https://github.com/mautrix/go) for encryption and [modernc.org/sqlite](https://modernc.org/sqlite) for storage. --- ## Table of Contents - [Features](#features) - [Requirements](#requirements) - [Installation](#installation) - [Configuration](#configuration) - [Running the Bot](#running-the-bot) - [Commands](#commands) - [Passive Features](#passive-features) - [Scheduled Posts](#scheduled-posts) - [Achievements](#achievements) - [Personality Archetypes](#personality-archetypes) - [External APIs](#external-apis) - [Architecture](#architecture) - [Database](#database) - [Troubleshooting](#troubleshooting) --- ## 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. - **43 plugins** with dependency injection and ordered registration - **Games & economy** - Euro virtual currency, Hangman (collaborative, threaded, tiered scoring), Blackjack (1-2 players, auto-play timeout), UNO (solo vs bot or 2–4 player multiplayer via DMs), 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](https://github.com/robfig/cron) - WOTD, 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 - **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: - [Ollama](https://ollama.ai) for LLM features - API keys for various services (see [Configuration](#configuration)) --- ## Installation ### From Source ```bash 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 ```bash docker build -t gogobee . docker run --env-file .env -v ./data:/app/data gogobee ``` ### Docker Compose ```bash 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](https://rawg.io/apidocs) | `!game`, `!retro`, `!releases` | | `WORDNIK_API_KEY` | [Wordnik](https://developer.wordnik.com) | Word of the Day | | `CALENDARIFIC_API_KEY` | [Calendarific](https://calendarific.com) | Holiday posts | | `OPENWEATHER_API_KEY` | [OpenWeather](https://openweathermap.org/api) | `!weather` | | `FINNHUB_API_KEY` | [Finnhub](https://finnhub.io) | `!stock` | | `BANDSINTOWN_API_KEY` | [Bandsintown](https://artists.bandsintown.com) | `!concerts` | | `TMDB_API_KEY` | [TMDB](https://www.themoviedb.org/documentation/api) | `!movie`, `!tv`, `!upcoming` | | `SERPAPI_KEY` | [SerpAPI](https://serpapi.com) | 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` | | `LIBRETRANSLATE_URL` | LibreTranslate instance for `!translate` | | `LLM_SAMPLE_RATE` | Fraction of messages to classify (0.0–1.0, default `0.15`) | ### Encryption | Variable | Description | |----------|-------------| | `QUOTE_ENCRYPTION_KEY` | Base64-encoded 32-byte AES-256 key for encrypted quote storage. Generate with `openssl rand -base64 32`. If unset, `!quote` is disabled. | ### 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) | ### Games & Economy | Variable | Default | Description | |----------|---------|-------------| | `GAMES_ROOM` | | Room ID where game commands work (trivia, hangman, blackjack, 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 | ### 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.0–1.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 (1–100) | | `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_TRANSLATE` | `20` | Daily translation limit per user | | `RATELIMIT_CONCERTS` | `10` | Daily concert searches per user | --- ## Running the Bot ```bash # 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 | | `!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 [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 €amount` | Start/join a Blackjack table | | `!hit` | Take a card | | `!stand` | End your turn | | `!blackjack leave` | Leave before game starts | | `!bjboard` | Blackjack leaderboard | | `!uno €amount` | Start a solo UNO game vs GogoBee (played in DMs) | | `!uno start €amount` | Create a multiplayer UNO lobby | | `!uno join` | Join an open UNO lobby | | `!uno go` | Start the game (host only, 2+ players required) | | `!uno leave` | Leave the lobby (refunds ante) | | `!uno cancel` | Cancel the lobby (host/admin, refunds all) | ### Reminders | Command | Description | |---------|-------------| | `!remindme