4.2 KiB
Thoughtful Discord Bot - AI Coding Instructions
Project Overview
A Go Discord bot that integrates with the Thoughtful API for managing ideas through Discord commands. Built with discordgo library, uses JSON for user config persistence.
Architecture
Component Structure
- bot.go: Main entry point. Handles Discord session, registers handlers, manages bot lifecycle
- commands/: Modular command system where each command is a separate file
commands.go: Command registry and interaction routerstorage.go: JSON-based user config persistence (users.json)- Individual command files:
setup.go,list.go,delete.go,logout.go
Key Design Patterns
Command Registration Pattern: Each command implements the Cmd struct:
type Cmd struct {
Command *discordgo.ApplicationCommand
Handler func(s *discordgo.Session, ic *discordgo.InteractionCreate)
AutocompleteHandler func(s *discordgo.Session, ic *discordgo.InteractionCreate) // optional
}
All commands are registered via getAllCommands() in commands/commands.go.
Dual Command Interface: The bot supports both:
- Slash commands (e.g.,
/setup,/list) via Discord's ApplicationCommand API - Legacy text commands (e.g.,
.thought Title; Description) for backward compatibility
User State Management: Per-user configs (Thoughtful instance URL + API key) stored in users.json. Thread-safe access via mutex in commands/storage.go.
Modal-Based Setup: /setup uses Discord modals (not option prompts) to collect sensitive credentials privately.
External Dependencies
- Thoughtful API: External idea management service. Requires:
- Base URL (user-provided, e.g.,
https://instance.com) - API key authentication via
API-Authenticationheader - Endpoints:
/api/ideas/create,/api/ideas/list,/api/ideas/delete
- Base URL (user-provided, e.g.,
- Discord API: via
github.com/bwmarrin/discordgolibrary
Developer Workflows
Running Locally
# Set environment variable
$env:DISCORD_BOT_TOKEN="your_token_here"
# Run directly
go run .
Docker Deployment
The bot is designed for Docker Compose deployment. See docker-compose.yml:
- Uses
golang:1.25image (note: uncommon version - likely should be1.21or1.22) - Auto-pulls git changes on container start
- Requires
.envfile withDISCORD_BOT_TOKEN
Adding New Commands
- Create new file in
commands/(e.g.,mycommand.go) - Implement
newMyCommand()returning*Cmd - Add to
getAllCommands()in commands/commands.go - Command automatically registers on bot startup
Project-Specific Conventions
Error Handling
- Use
respondError()helper for interaction failures (defined in command files) - Silent failures acceptable for autocomplete handlers
- Channel messages for
.thoughtcommand errors
User Identification
Discord interactions may have User OR Member.User depending on context:
user := ic.User
if user == nil {
user = ic.Member.User
}
Always check both when accessing user data.
API Communication
- Always trim trailing slashes from instance URLs:
url = strings.TrimSuffix(url, "/") - Use
API-Authenticationheader (notAuthorization) - 401 status codes mean invalid/expired API keys
Storage Layer
- Never edit
users.jsondirectly - always usestorage.gofunctions - Operations are mutex-protected but not transactional
- Corrupted JSON automatically resets to empty map
Critical Gotchas
-
Intents Required: Bot needs
IntentsGuildMessages(set in bot.go). Message Content Intent must be enabled in Discord Developer Portal. -
Slash Command Updates: Slash commands persist in Discord. To update, uncomment command cleanup code in commands/commands.go.
-
Modal Response Type: Setup uses
InteractionResponseModal, notInteractionResponseChannelMessageWithSource. -
Autocomplete Filtering: Delete command autocomplete should filter by user input but currently returns all ideas - see commands/delete.go.
-
No Database: All state in
users.json. Loss of this file = all users must re-run/setup.