- scripts/learner-*.sh → scripts/dev-*.sh - docs/learner-*.md → docs/dev-*.md - tests/test-learner-env.sh → tests/test-dev-env.sh - Update all internal references 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
220 lines
5.6 KiB
Markdown
220 lines
5.6 KiB
Markdown
# Direct Slack Bot Development for Devs
|
|
|
|
Design doc for the "direct to Slack" dev path, bypassing Matrix/maubot.
|
|
|
|
## Overview
|
|
|
|
Devs write Python bots using `slack-bolt` that connect directly to Slack via Socket Mode. No Matrix, no bridge, no maubot.
|
|
|
|
```
|
|
┌─────────────────────────────────────────┐
|
|
│ VPS (ops-jrz1) │
|
|
│ │
|
|
│ alice's bot.py ──┐ │
|
|
│ bob's bot.py ────┼── Socket Mode ─────────► Slack API
|
|
│ carol's bot.py ──┘ (WebSocket) │
|
|
│ │
|
|
└─────────────────────────────────────────┘
|
|
```
|
|
|
|
## Current Setup
|
|
|
|
### Credentials
|
|
|
|
Shared Slack App tokens stored in `/etc/slack-dev.env`:
|
|
|
|
| Variable | Purpose |
|
|
|----------|---------|
|
|
| `SLACK_BOT_TOKEN` | Bot identity (xoxb-...) |
|
|
| `SLACK_APP_TOKEN` | Socket Mode connection (xapp-...) |
|
|
|
|
These come from the existing mautrix-slack bridge login (Chochacho workspace, vlad's account).
|
|
|
|
### Access Control
|
|
|
|
- File owned by `root:devs`, mode `640`
|
|
- Dev users added to `devs` group on creation
|
|
- `.bashrc` sources the env file on login
|
|
|
|
### Scripts
|
|
|
|
```
|
|
/usr/local/bin/dev-add.sh <username> '<ssh-pubkey>'
|
|
/usr/local/bin/dev-remove.sh <username> [--archive]
|
|
```
|
|
|
|
## Dev Workflow
|
|
|
|
### 1. Get Access
|
|
|
|
Send SSH pubkey to admin. Admin runs:
|
|
```bash
|
|
ssh root@ops-jrz1 'dev-add.sh alice "ssh-ed25519 AAAA..."'
|
|
```
|
|
|
|
### 2. Connect
|
|
|
|
```bash
|
|
ssh alice@<server-ip>
|
|
```
|
|
|
|
Tokens are available immediately:
|
|
```bash
|
|
echo $SLACK_BOT_TOKEN # xoxb-...
|
|
echo $SLACK_APP_TOKEN # xapp-...
|
|
```
|
|
|
|
### 3. Write a Bot
|
|
|
|
```python
|
|
# ~/bot.py
|
|
from slack_bolt import App
|
|
from slack_bolt.adapter.socket_mode import SocketModeHandler
|
|
import os
|
|
|
|
app = App(token=os.environ["SLACK_BOT_TOKEN"])
|
|
|
|
@app.message("hello")
|
|
def hello(message, say):
|
|
say(f"Hey <@{message['user']}>!")
|
|
|
|
@app.message("dice")
|
|
def dice(message, say):
|
|
import random
|
|
say(f"🎲 You rolled a {random.randint(1, 6)}!")
|
|
|
|
if __name__ == "__main__":
|
|
print("Bot starting...")
|
|
SocketModeHandler(app, os.environ["SLACK_APP_TOKEN"]).start()
|
|
```
|
|
|
|
### 4. Run It
|
|
|
|
```bash
|
|
pip install slack-bolt
|
|
python bot.py
|
|
```
|
|
|
|
Bot responds to "hello" and "dice" in Slack.
|
|
|
|
## slack-bolt Basics
|
|
|
|
### Event Handlers
|
|
|
|
```python
|
|
# Match exact text
|
|
@app.message("hello")
|
|
def handle_hello(message, say):
|
|
say("Hello!")
|
|
|
|
# Match regex
|
|
@app.message(re.compile(r"^roll (\d+)d(\d+)"))
|
|
def handle_roll(message, say, context):
|
|
# context["matches"] contains regex groups
|
|
pass
|
|
|
|
# Match any message
|
|
@app.event("message")
|
|
def handle_all(event, say):
|
|
pass
|
|
|
|
# React to app mentions (@bot)
|
|
@app.event("app_mention")
|
|
def handle_mention(event, say):
|
|
say("You mentioned me!")
|
|
```
|
|
|
|
### Slash Commands
|
|
|
|
Requires additional Slack App config (not set up yet):
|
|
```python
|
|
@app.command("/mycommand")
|
|
def handle_command(ack, respond, command):
|
|
ack() # Must acknowledge within 3 seconds
|
|
respond(f"You said: {command['text']}")
|
|
```
|
|
|
|
### Sending Messages
|
|
|
|
```python
|
|
# Reply in thread
|
|
say("Reply!", thread_ts=message["ts"])
|
|
|
|
# Send to specific channel
|
|
app.client.chat_postMessage(channel="C1234567", text="Hello")
|
|
|
|
# Rich formatting (blocks)
|
|
say(blocks=[
|
|
{"type": "section", "text": {"type": "mrkdwn", "text": "*Bold* and _italic_"}}
|
|
])
|
|
```
|
|
|
|
## Tradeoffs
|
|
|
|
### vs Maubot/Matrix Path
|
|
|
|
| Aspect | Direct Slack | Maubot/Matrix |
|
|
|--------|--------------|---------------|
|
|
| **Setup complexity** | Lower - just Python | Higher - Matrix + bridge + maubot |
|
|
| **Feedback loop** | Fast - direct to Slack | Slower - goes through bridge |
|
|
| **Mental model** | Simple - just Slack | Complex - Matrix concepts |
|
|
| **Documentation** | Excellent (Bolt is popular) | Sparse (maubot is niche) |
|
|
| **Process management** | Manual (you run it) | Managed (maubot lifecycle) |
|
|
| **Bot identity** | Shared (all bots = same user) | Per-instance configurable |
|
|
| **Crash recovery** | Manual restart | Auto-managed |
|
|
| **Production path** | Direct - same code works | Need to rewrite for Slack-only |
|
|
|
|
### Risks
|
|
|
|
1. **Shared tokens** - All devs use same bot identity
|
|
2. **Token exposure** - If leaked, affects everyone
|
|
3. **Rate limits** - Shared across all bots
|
|
4. **Process sprawl** - N devs = N processes to manage
|
|
5. **No guardrails** - Bad code can spam/crash easily
|
|
|
|
### Mitigations
|
|
|
|
- Dedicated test channel in Slack
|
|
- Supervisor/systemd for process management (not yet set up)
|
|
- Tokens in env vars, not code
|
|
- Can rotate tokens if leaked (re-login bridge)
|
|
|
|
## Future Improvements
|
|
|
|
### Process Management
|
|
|
|
Options:
|
|
1. **systemd user services** - Each dev manages their own
|
|
2. **supervisor** - Central process manager
|
|
3. **tmux/screen** - Manual but simple
|
|
4. **Container per dev** - Isolation but complex
|
|
|
|
### Starter Template
|
|
|
|
Create `~/slack-bot-template/` with:
|
|
- `bot.py` - Hello world
|
|
- `requirements.txt` - slack-bolt pinned
|
|
- `Makefile` - run, install targets
|
|
- `README.md` - Quick start
|
|
|
|
### Per-Dev Bot Identity
|
|
|
|
Create separate Slack App per dev:
|
|
- More setup friction
|
|
- Full isolation
|
|
- Each bot has own name/avatar
|
|
|
|
### Test Channel
|
|
|
|
Create `#dev-sandbox` in Slack:
|
|
- All dev bots invited
|
|
- Safe place to spam
|
|
- Doesn't pollute real channels
|
|
|
|
## References
|
|
|
|
- [Bolt for Python - Getting Started](https://slack.dev/bolt-python/tutorial/getting-started)
|
|
- [Slack API - Socket Mode](https://api.slack.com/apis/connections/socket)
|
|
- [Slack API - Events](https://api.slack.com/events)
|
|
- [slack-bolt GitHub](https://github.com/slackapi/bolt-python)
|