mirror of
https://github.com/harivansh-afk/pi-telegram-webhook.git
synced 2026-04-15 03:00:47 +00:00
Pi extension for Telegram webhook ingress and streaming message delivery
- webhook server with secret validation, rate limiting, body guards - streaming replies via sendMessage + editMessageText throttled loop - RPC session management for persistent conversations - 15/15 tests passing |
||
|---|---|---|
| .pi | ||
| src | ||
| tests | ||
| .gitignore | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| vitest.config.ts | ||
pi-telegram-webhook
Webhook-based Telegram adapter for pi with streaming replies and persistent RPC sessions.
Features
- Webhook ingress (vs polling) — lower latency, better for production
- Security hardened:
- Constant-time secret validation (timing attack resistant)
- Fixed-window rate limiter per IP
- 1MB body size limit
- 30s read timeout
- Trusted proxy X-Forwarded-For support
- Streaming replies — throttled
editMessageTextfor live updates (default 1s, 4096 char limit) - Persistent RPC sessions —
pi --mode rpcsubprocess per sender, context preserved across messages - Generation tracking — prevents new messages from clobbering old edits
- FIFO queues — per-sender serialization, configurable concurrency
- Bot commands:
/start,/help,/new,/abort,/clear
Installation
npm install pi-telegram-webhook
Configuration
Add to .pi/settings.json:
{
"pi-telegram-webhook": {
"botToken": "your-telegram-bot-token",
"webhookUrl": "https://your-domain.com/telegram-webhook",
"webhookPort": 2470,
"webhookHost": "127.0.0.1",
"webhookPath": "/telegram-webhook",
"webhookSecret": "random-secret-token",
"allowedChatIds": ["123456789"],
"streamingThrottleMs": 1000,
"minInitialChars": 50,
"trustedProxies": ["127.0.0.1", "10.0.0.0/8"],
"maxConcurrent": 2,
"timeoutMs": 300000,
"idleTimeoutMinutes": 30,
"model": "anthropic/claude-sonnet-4",
"extensions": ["pi-channels"]
}
}
Config Reference
| Key | Type | Default | Description |
|---|---|---|---|
botToken |
string |
required | Telegram Bot API token |
webhookUrl |
string |
required | Public webhook URL (must be HTTPS in production) |
webhookSecret |
string |
required | Secret token for webhook validation |
webhookPort |
number |
2470 |
Local server port |
webhookHost |
string |
127.0.0.1 |
Local server bind address |
webhookPath |
string |
/telegram-webhook |
Webhook endpoint path |
allowedChatIds |
string[] |
undefined |
Whitelist of allowed chat IDs (optional) |
streamingThrottleMs |
number |
1000 |
Throttle interval for streaming edits |
minInitialChars |
number |
50 |
Min chars before sending first message (debounce) |
trustedProxies |
string[] |
["127.0.0.1"] |
Trusted proxy IPs/CIDRs for X-Forwarded-For |
maxConcurrent |
number |
2 |
Max concurrent prompts across all senders |
timeoutMs |
number |
300000 |
Prompt timeout (5 min) |
idleTimeoutMinutes |
number |
30 |
RPC session idle timeout |
model |
string |
undefined |
Override model for RPC sessions |
extensions |
string[] |
[] |
Additional pi extensions to load |
Deployment
Reverse Proxy (nginx)
location /telegram-webhook {
proxy_pass http://127.0.0.1:2470;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_http_version 1.1;
proxy_read_timeout 35s;
client_max_body_size 2M;
}
Systemd Service
[Unit]
Description=pi Telegram webhook
After=network.target
[Service]
Type=simple
User=youruser
WorkingDirectory=/path/to/your/project
ExecStart=/usr/bin/pi --no-tui
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
Webhook Setup
The extension automatically calls setWebhook on startup. To manually test:
curl -X POST "https://api.telegram.org/bot<YOUR_TOKEN>/setWebhook" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-domain.com/telegram-webhook",
"secret_token": "your-secret"
}'
Bot Commands
/start,/help— Show welcome message/new— Start a new conversation (clear context)/abort— Abort the current task/clear— Clear the message queue
Architecture
Telegram → HTTPS webhook → nginx → pi-telegram-webhook
├─ webhook-server (security, rate limiting)
├─ bridge (FIFO queues, concurrency)
└─ RPC sessions (streaming replies)
Flow
- Incoming webhook → secret validation → rate limit check → body parsing
- Message enqueued in per-sender FIFO queue
- Bridge spawns/reuses
pi --mode rpcsubprocess for sender - Prompt sent to RPC session, streaming deltas received
- StreamingReply sends initial message, then throttled edits
- Generation tracking prevents race conditions
Development
npm install
npm run build
npm test
Security Notes
- Secret validation uses constant-time comparison (timing attack resistant)
- Rate limiting applied before secret check (prevents brute-force)
- Body size limit prevents memory exhaustion
- Read timeout prevents slowloris attacks
- Trusted proxies must be explicitly configured for X-Forwarded-For
License
MIT