103 lines
4.2 KiB
Markdown
103 lines
4.2 KiB
Markdown
# 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 router
|
|
- `storage.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:
|
|
```go
|
|
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](../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](../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-Authentication` header
|
|
- Endpoints: `/api/ideas/create`, `/api/ideas/list`, `/api/ideas/delete`
|
|
- **Discord API**: via `github.com/bwmarrin/discordgo` library
|
|
|
|
## Developer Workflows
|
|
|
|
### Running Locally
|
|
```sh
|
|
# 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](../docker-compose.yml):
|
|
- Uses `golang:1.25` image (note: uncommon version - likely should be `1.21` or `1.22`)
|
|
- Auto-pulls git changes on container start
|
|
- Requires `.env` file with `DISCORD_BOT_TOKEN`
|
|
|
|
### Adding New Commands
|
|
1. Create new file in `commands/` (e.g., `mycommand.go`)
|
|
2. Implement `newMyCommand()` returning `*Cmd`
|
|
3. Add to `getAllCommands()` in [commands/commands.go](../commands/commands.go)
|
|
4. 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 `.thought` command errors
|
|
|
|
### User Identification
|
|
Discord interactions may have `User` OR `Member.User` depending on context:
|
|
```go
|
|
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-Authentication` header (not `Authorization`)
|
|
- 401 status codes mean invalid/expired API keys
|
|
|
|
### Storage Layer
|
|
- **Never** edit `users.json` directly - always use `storage.go` functions
|
|
- Operations are mutex-protected but not transactional
|
|
- Corrupted JSON automatically resets to empty map
|
|
|
|
## Critical Gotchas
|
|
|
|
1. **Intents Required**: Bot needs `IntentsGuildMessages` (set in [bot.go](../bot.go#L40)). Message Content Intent must be enabled in Discord Developer Portal.
|
|
|
|
2. **Slash Command Updates**: Slash commands persist in Discord. To update, uncomment command cleanup code in [commands/commands.go](../commands/commands.go#L30-L33).
|
|
|
|
3. **Modal Response Type**: Setup uses `InteractionResponseModal`, not `InteractionResponseChannelMessageWithSource`.
|
|
|
|
4. **Autocomplete Filtering**: Delete command autocomplete should filter by user input but currently returns all ideas - see [commands/delete.go](../commands/delete.go#L86-L100).
|
|
|
|
5. **No Database**: All state in `users.json`. Loss of this file = all users must re-run `/setup`.
|