docs: refactor documentation to remove duplication and improve clarity

- README: remove CW/Morse notes, condense multi-arch Docker detail, fix screenshot path, tighten credentials note
- FEATURES.md: replace 550-line bullet dump with a concise mode→link table
- USAGE.md: replace 140-line Webhooks section with pointer to new WEBHOOKS.md; remove duplicate Configuration and CLI Options sections
- docs/WEBHOOKS.md: new file with full webhook setup, payload format, and Discord relay guide
- HARDWARE.md: remove duplicate Quick Install / Python Environment / Running INTERCEPT sections; add Icecast setup section
- TROUBLESHOOTING.md: replace Icecast install/config block with pointer to HARDWARE.md; replace duplicate udev rules with pointer to HARDWARE.md
- SECURITY.md: update auth section to reflect admin/admin login (was "no authentication mechanism")
- UI_GUIDE.md: add contributor/developer notice at the top

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
James Smith
2026-07-01 14:43:34 +01:00
parent 0d45d5ce07
commit 48b9d9d05a
8 changed files with 237 additions and 971 deletions
+2 -183
View File
@@ -570,187 +570,6 @@ For complete documentation, see [Distributed Agents Guide](DISTRIBUTED_AGENTS.md
## Webhooks & Notifications
INTERCEPT has a built-in alert engine that fires webhooks when decoded events match configurable rules. This lets you forward pager messages (or events from any other mode) to Discord, Slack, n8n, Home Assistant, or any HTTP endpoint.
INTERCEPT has a built-in alert engine that fires webhooks on decoded events. Configure rules in the Alerts panel to forward pager messages, ADS-B alerts, WiFi events, or anything else to Discord, Slack, n8n, Home Assistant, or any HTTP endpoint.
### How it works
1. You configure **alert rules** via the Alerts UI — each rule defines which mode and event type to watch, optional match criteria, and a severity level.
2. When an incoming event matches a rule, INTERCEPT stores it in the alert log and POSTs a JSON payload to your configured webhook URL.
3. All modes are supported: pager, sensor, ADS-B, AIS, ACARS, WiFi, Bluetooth, and more.
### Enable the webhook
Set these environment variables in your `.env` file or `docker-compose.yml`:
| Variable | Default | Description |
|----------|---------|-------------|
| `ALERT_WEBHOOK_URL` | _(empty)_ | URL to POST alert payloads to |
| `ALERT_WEBHOOK_SECRET` | _(empty)_ | Optional token sent as `X-Alert-Token` header |
| `ALERT_WEBHOOK_TIMEOUT` | `5` | HTTP timeout in seconds |
**Local install (`.env`):**
```env
ALERT_WEBHOOK_URL=https://your-endpoint.example.com/intercept-alerts
ALERT_WEBHOOK_SECRET=mysecrettoken
```
**Docker (`.env` or `docker-compose.yml` environment block):**
```env
ALERT_WEBHOOK_URL=https://your-endpoint.example.com/intercept-alerts
ALERT_WEBHOOK_SECRET=mysecrettoken
```
### Create an alert rule
1. Open the **Alerts** panel in INTERCEPT
2. Click **New Rule**
3. Configure:
- **Mode**: `pager` (or any other mode, or leave blank to match all)
- **Event type**: `message` for pager decodes (or blank to match all event types)
- **Match criteria**: leave empty to forward everything, or add filters (e.g. capcode equals `1234567`, or message contains `FIRE`)
- **Severity**: `low`, `medium`, or `high`
4. Save and enable the rule
### Webhook payload format
INTERCEPT sends a POST request with `Content-Type: application/json`:
```json
{
"id": 42,
"rule_id": 1,
"mode": "pager",
"event_type": "message",
"severity": "medium",
"title": "My Pager Rule",
"message": "message | 1234567",
"created_at": "2026-04-13T10:00:00+00:00",
"payload": {
"mode": "pager",
"event_type": "message",
"event": {
"capcode": "1234567",
"message": "UNIT 4 RESPOND TO 123 MAIN ST",
"type": "POCSAG1200"
},
"rule": { "id": 1, "name": "My Pager Rule" }
}
}
```
### Sending to Discord
Discord webhooks expect a specific JSON format (`content`, `embeds`), so you need a small relay between INTERCEPT and Discord. Two options:
**Option A — No-code relay (recommended)**
Use [n8n](https://n8n.io), [Make](https://make.com), or [Pipedream](https://pipedream.com) to receive INTERCEPT's webhook and forward it to Discord with a custom message template. Point `ALERT_WEBHOOK_URL` at your workflow's ingest URL.
**Option B — Self-hosted Python relay**
Save this as `discord_relay.py` and run it alongside INTERCEPT:
```python
from flask import Flask, request
import urllib.request, json
app = Flask(__name__)
DISCORD_WEBHOOK_URL = "https://discord.com/api/webhooks/YOUR_ID/YOUR_TOKEN"
@app.post("/relay")
def relay():
data = request.get_json(force=True)
mode = data.get("mode", "unknown").upper()
title = data.get("title", "Alert")
message = data.get("message", "")
event = data.get("payload", {}).get("event", {})
# Build a readable Discord message
lines = [f"**[{mode}]** {title}", message]
if event.get("capcode"):
lines.append(f"Capcode: `{event['capcode']}`")
if event.get("type"):
lines.append(f"Protocol: {event['type']}")
payload = json.dumps({"content": "\n".join(lines)}).encode()
req = urllib.request.Request(
DISCORD_WEBHOOK_URL,
data=payload,
headers={"Content-Type": "application/json"},
method="POST",
)
urllib.request.urlopen(req, timeout=5)
return "", 204
app.run(host="0.0.0.0", port=5051)
```
Then set:
```env
ALERT_WEBHOOK_URL=http://localhost:5051/relay
```
Run the relay: `python3 discord_relay.py`
The relay formats pager decodes as Discord messages like:
```
[PAGER] My Pager Rule
message | 1234567
Capcode: `1234567`
Protocol: POCSAG1200
```
### Filtering specific capcodes
To only forward decodes from a specific capcode, set the rule's **Match criteria**:
| Field | Operator | Value |
|-------|----------|-------|
| `capcode` | equals | `1234567` |
Multiple rules can coexist — e.g. one rule for all pager traffic to a general Discord channel, and a second rule for emergency capcodes with `high` severity to a separate channel (using a second relay instance on a different port).
## Configuration
INTERCEPT can be configured via environment variables:
| Variable | Default | Description |
|----------|---------|-------------|
| `INTERCEPT_HOST` | `0.0.0.0` | Server bind address |
| `INTERCEPT_PORT` | `5050` | Server port |
| `INTERCEPT_DEBUG` | `false` | Enable debug mode |
| `INTERCEPT_LOG_LEVEL` | `WARNING` | Log level (DEBUG, INFO, WARNING, ERROR) |
| `INTERCEPT_DEFAULT_GAIN` | `40` | Default RTL-SDR gain |
Example: `INTERCEPT_PORT=8080 sudo ./start.sh`
## Command-line Options
### Production server (recommended)
```
sudo ./start.sh --help
-p, --port PORT Port to listen on (default: 5050)
-H, --host HOST Host to bind to (default: 0.0.0.0)
-d, --debug Run in debug mode (Flask dev server)
--https Enable HTTPS with self-signed certificate
--check-deps Check dependencies and exit
```
> **Note:** `sudo` is required for SDR hardware access, WiFi monitor mode, and Bluetooth low-level operations.
`start.sh` auto-detects gunicorn + gevent and runs a production WSGI server with cooperative greenlets — this handles multiple SSE streams and WebSocket connections concurrently without blocking. Falls back to the Flask dev server if gunicorn is not installed.
### Development server
```
python3 intercept.py --help
-p, --port PORT Port to run server on (default: 5050)
-H, --host HOST Host to bind to (default: 0.0.0.0)
-d, --debug Enable debug mode
--check-deps Check dependencies and exit
```
See [WEBHOOKS.md](WEBHOOKS.md) for configuration, payload format, and Discord relay setup.