https://github.com/en9inerd/rig
Lightweight automation runtime in Go
https://github.com/en9inerd/rig
automation bot go golang telegram
Last synced: about 2 months ago
JSON representation
Lightweight automation runtime in Go
- Host: GitHub
- URL: https://github.com/en9inerd/rig
- Owner: en9inerd
- License: mit
- Created: 2026-03-13T15:02:06.000Z (3 months ago)
- Default Branch: master
- Last Pushed: 2026-04-05T04:00:50.000Z (3 months ago)
- Last Synced: 2026-04-05T05:22:53.964Z (3 months ago)
- Topics: automation, bot, go, golang, telegram
- Language: Go
- Homepage:
- Size: 5.27 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Rig
A lightweight automation runtime in Go. Each unit of work is a **task** - a self-contained module that wires an event source to one or more actions. The runtime manages task lifecycle, shared services, and the HTTP server.
## Tasks
| Task | Type | Description |
|---|---|---|
| **Visitor Notifier** | HTTP endpoint | Receives visitor data via `POST /{token}/visitor`, geolocates the IP using a local MaxMind database, and sends a Telegram notification. Supports multiple sites, each with its own token and tag. |
| **Feed Watcher** | Ticker | Polls an Atom feed at a configurable interval and sends new posts to Telegram |
| **IP Watcher** | Ticker | Monitors the server's public IP and sends a Telegram notification on change |
Tasks are independent, each manages its own goroutine(s), state, and config. Disable any task via environment variables.
## Quick Start
```bash
cp .env.example .env
# Edit .env with your Telegram bot token, chat IDs, and MaxMind credentials
# Generate visitors.json with a random auth token (pick one)
rig --init > visitors.json # local binary
docker run --rm enginerd/rig --init > visitors.json # from Docker image
# Edit visitors.json with your site names and chat IDs
docker compose up -d
```
The `geoipupdate` sidecar downloads the GeoLite2-City database before `rig` starts. A free [MaxMind account](https://www.maxmind.com/en/geolite2/signup) is required.
## Configuration
All configuration is via environment variables.
### Global
| Variable | Description | Default |
|---|---|---|
| `RIG_HTTP_ADDR` | HTTP listen address | `:8080` |
| `RIG_TELEGRAM_BOT_TOKEN` | Telegram Bot API token | - |
| `RIG_STORE_PATH` | Path to persistent state file | `/data/rig.json` |
| `RIG_CORS_ORIGIN` | Allowed CORS origin | - |
| `RIG_TLS_CERT` | Path to TLS certificate file | - |
| `RIG_TLS_KEY` | Path to TLS private key file | - |
| `RIG_VERBOSE` | Enable debug logging | `false` |
### Visitor Notifier
| Variable | Description | Default |
|---|---|---|
| `RIG_VISITOR_ENABLED` | Enable task | `true` |
| `RIG_VISITOR_SITES_FILE` | Path to JSON file defining visitor sites | - |
| `RIG_VISITOR_GEOIP_DB` | Path to MaxMind GeoLite2-City database | `/data/geoip/GeoLite2-City.mmdb` |
| `RIG_VISITOR_DEDUP` | Drop repeat notifications for same IP+URL within the window | `false` |
| `RIG_VISITOR_DEDUP_WINDOW` | Deduplication window (when enabled) | `10m` |
The sites file is a JSON array. Generate a starter file with `rig --init`, or create one manually:
```json
[
{"name": "blog", "authToken": "TOKEN", "chatId": "CHAT_ID", "tag": "Blog"}
]
```
Each site gets its own endpoint: `POST /{authToken}/visitor`. The `tag` field is optional and defaults to the site name.
### Feed Watcher
| Variable | Description | Default |
|---|---|---|
| `RIG_FEED_ENABLED` | Enable task | `true` |
| `RIG_FEED_URL` | Atom/RSS feed URL | - |
| `RIG_FEED_INTERVAL` | Poll interval | `15m` |
| `RIG_FEED_CHAT_ID` | Telegram chat ID | - |
### IP Watcher
| Variable | Description | Default |
|---|---|---|
| `RIG_IP_ENABLED` | Enable task | `true` |
| `RIG_IP_INTERVAL` | Poll interval | `15m` |
| `RIG_IP_CHAT_ID` | Telegram chat ID | - |
### MaxMind GeoIP (geoipupdate sidecar)
| Variable | Description |
|---|---|
| `GEOIPUPDATE_ACCOUNT_ID` | MaxMind account ID |
| `GEOIPUPDATE_LICENSE_KEY` | MaxMind license key |
## Development
```bash
# Build
make build
# Run locally (loads .env)
make run
# Run with debug logging
make run-verbose
# Tests
make test
```
## Adding a Task
1. Create `internal/tasks/yourtask/yourtask.go` - implement `tasks.Task` (or `tasks.HTTPTask` for HTTP routes)
2. Create `internal/tasks/yourtask/config.go` - define `Config` struct and `LoadConfig(getenv)` that returns `(*Config, error)` (`nil` when `RIG_YOURTASK_ENABLED=false`)
3. Register in `cmd/rig/main.go`:
```go
ytcfg, err := yourtask.LoadConfig(getenv)
if err != nil {
return fmt.Errorf("yourtask config: %w", err)
}
if ytcfg != nil {
rt.Register(yourtask.New(notifier, logger, *ytcfg))
}
```
## Deployment
Docker image is multi-stage (`golang:1.26-alpine` build, `alpine:3.23` runtime) with cross-compilation support. The CI workflow builds for `linux/amd64` and `linux/arm64`.
```bash
# Build and start
docker compose up -d --build
# Logs
docker compose logs -f
# Stop
docker compose down
```
All task state is persisted in a single JSON file (`/data/rig.json` by default) in the `rig-data` volume. Writes are atomic (temp file + rename) so a crash can never corrupt state. The GeoIP database lives in the `geoip` volume, shared read-only with the `rig` container.
## License
MIT