feat: add comprehensive AI coding instructions for Thoughtful Discord Bot
This commit is contained in:
102
.github/copilot-instructions.md
vendored
Normal file
102
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
# 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`.
|
||||
Reference in New Issue
Block a user