docs: update docs for Teams integration
- USAGE.md: Teams Integration section (config, setup, compat matrix) - CHEATSHEET.md: Teams config snippet - API.md: TeamsBot and TeamsMessage reference - README.md: Teams in features list - ROADMAP.md: v2.1.0 milestone - TODO.md/TASKS.md: Teams items Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1301,3 +1301,102 @@ timeout = 10 # HTTP fetch timeout
|
||||
max_urls = 3 # max URLs to preview per message
|
||||
ignore_hosts = [] # additional hostnames to skip
|
||||
```
|
||||
|
||||
## Teams Integration
|
||||
|
||||
Connect derp to Microsoft Teams via outgoing webhooks. The bot runs an HTTP
|
||||
server that receives messages from Teams and replies inline. No Microsoft SDK
|
||||
required -- raw asyncio HTTP, same pattern as the webhook plugin.
|
||||
|
||||
### How It Works
|
||||
|
||||
1. **Outgoing webhook** (Teams -> bot): Teams POSTs an Activity JSON to the
|
||||
bot's HTTP endpoint when a user @mentions the bot. The bot dispatches the
|
||||
command through the shared plugin registry and returns the reply as the
|
||||
HTTP response body.
|
||||
|
||||
2. **Incoming webhook** (bot -> Teams, optional): For proactive messages
|
||||
(alerts, subscriptions), the bot POSTs to a Teams incoming webhook URL.
|
||||
|
||||
### Configuration
|
||||
|
||||
```toml
|
||||
[teams]
|
||||
enabled = true
|
||||
bot_name = "derp" # outgoing webhook display name
|
||||
bind = "127.0.0.1" # HTTP listen address
|
||||
port = 8081 # HTTP listen port
|
||||
webhook_secret = "" # HMAC-SHA256 secret from Teams
|
||||
incoming_webhook_url = "" # for proactive messages (optional)
|
||||
admins = [] # AAD object IDs (UUID format)
|
||||
operators = [] # AAD object IDs
|
||||
trusted = [] # AAD object IDs
|
||||
```
|
||||
|
||||
### Teams Setup
|
||||
|
||||
1. **Create an outgoing webhook** in a Teams channel:
|
||||
- Channel settings -> Connectors -> Outgoing Webhook
|
||||
- Set the callback URL to your bot's endpoint (e.g.
|
||||
`https://derp.example.com/api/messages`)
|
||||
- Copy the HMAC secret and set `webhook_secret` in config
|
||||
|
||||
2. **Expose the bot** via Cloudflare Tunnel or reverse proxy:
|
||||
```bash
|
||||
cloudflared tunnel --url http://127.0.0.1:8081
|
||||
```
|
||||
|
||||
3. **Configure permissions** using AAD object IDs from the Activity JSON.
|
||||
The AAD object ID is sent in `from.aadObjectId` on every message. Use
|
||||
`!whoami` to discover your ID.
|
||||
|
||||
### Permission Tiers
|
||||
|
||||
Same 4-tier model as IRC, but matches exact AAD object IDs instead of
|
||||
fnmatch hostmask patterns:
|
||||
|
||||
```toml
|
||||
[teams]
|
||||
admins = ["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"]
|
||||
operators = ["yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"]
|
||||
trusted = ["zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz"]
|
||||
```
|
||||
|
||||
### Plugin Compatibility
|
||||
|
||||
~90% of plugins work on Teams without modification -- any plugin that uses
|
||||
only `bot.send()`, `bot.reply()`, `bot.state`, `message.text`, `.nick`,
|
||||
and `.target`.
|
||||
|
||||
| Feature | IRC | Teams |
|
||||
|---------|-----|-------|
|
||||
| `bot.reply()` | Sends PRIVMSG | Appends to HTTP response |
|
||||
| `bot.send()` | Sends PRIVMSG | POSTs to incoming webhook |
|
||||
| `bot.action()` | CTCP ACTION | Italic text via incoming webhook |
|
||||
| `bot.long_reply()` | Paste overflow | Paste overflow (same logic) |
|
||||
| `bot.state` | Per-server SQLite | Per-server SQLite |
|
||||
| `bot.join/part/kick/mode` | IRC commands | No-op (logged at debug) |
|
||||
| Event handlers (JOIN, etc.) | Fired on IRC events | Not triggered |
|
||||
| Hostmask ACL | fnmatch patterns | Exact AAD object IDs |
|
||||
| Passive monitoring | All channel messages | @mention only |
|
||||
|
||||
### HMAC Verification
|
||||
|
||||
Teams outgoing webhooks sign requests with HMAC-SHA256. The secret is
|
||||
base64-encoded when you create the webhook. The `Authorization` header
|
||||
format is `HMAC <base64(hmac-sha256(b64decode(secret), body))>`.
|
||||
|
||||
If `webhook_secret` is empty, no authentication is performed (useful for
|
||||
development but not recommended for production).
|
||||
|
||||
### Endpoint
|
||||
|
||||
Single endpoint: `POST /api/messages`
|
||||
|
||||
The bot returns a JSON response:
|
||||
|
||||
```json
|
||||
{"type": "message", "text": "reply text here"}
|
||||
```
|
||||
|
||||
Multiple reply lines are joined with `\n`.
|
||||
|
||||
Reference in New Issue
Block a user