# Interactive Spaces — Discord Bot

Discord bot that bridges Figurate AI conversations and room events into Discord.

## Features

- **Text chat**: Send messages in a Discord channel, get AI character responses via Figurate
- **Voice chat**: Bot joins a voice channel, listens for speech, responds with AI character voice
- **Room events**: HTTP endpoint receives events from the projection system and posts them as Discord embeds
- **Slash commands**: `/join`, `/leave`, `/character`, `/set-character`

## Setup

1. Create a Discord bot at [discord.com/developers](https://discord.com/developers/applications)
   - Enable **Message Content Intent** under Bot settings
   - Add bot to your server with permissions: Send Messages, Connect, Speak, Use Slash Commands

2. Get a Figurate API key from [Flowstate](https://flowstate.app)

3. Configure environment:
   ```
   cp .env.example .env
   ```
   Fill in your tokens and IDs in `.env`

4. Install dependencies:
   ```
   npm install
   ```

5. Start the bot:
   ```
   npm start
   ```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `DISCORD_BOT_TOKEN` | Your Discord bot token |
| `FIGURATE_API_KEY` | Figurate API key (starts with `fg_`) |
| `FIGURATE_SERVER_URL` | Figurate server URL |
| `FIGURATE_CHARACTER_ID` | Default character ID (optional, auto-selects first) |
| `DISCORD_CHANNEL_ID` | Channel to listen for messages (optional, listens to all if empty) |
| `EVENT_PORT` | Port for the room event HTTP server (default: 3001) |

## Room Event API

POST events to `http://localhost:3001/event`:

```json
{
  "title": "Person Detected",
  "description": "A person approached the table",
  "color": 3066993,
  "fields": [
    { "name": "Gesture", "value": "Open palm" },
    { "name": "Time", "value": "2:30 PM" }
  ]
}
```

## Voice Chat

1. Join a voice channel in Discord
2. Use `/join` to bring the bot into your channel
3. Speak — the bot detects ~1.5s of silence as end of utterance
4. Bot sends your speech to Figurate and plays back the AI response
5. Use `/leave` when done
