docs: update docs for Telegram integration

This commit is contained in:
user
2026-02-21 20:06:29 +01:00
parent 3bcba8b0a9
commit 0d92e6ed31
7 changed files with 199 additions and 4 deletions

View File

@@ -288,6 +288,75 @@ Same stable attributes and methods as `Bot`:
---
## `derp.telegram` -- Telegram Adapter
Alternative bot adapter for Telegram via long-polling (`getUpdates`).
All HTTP routed through SOCKS5 proxy. Exposes the same plugin API as
`derp.bot.Bot` so protocol-agnostic plugins work without modification.
### `TelegramMessage` dataclass
Duck-typed compatible with IRC `Message`:
| Field | Type | Description |
|-------|------|-------------|
| `raw` | `dict` | Original Telegram Update |
| `nick` | `str \| None` | Sender first_name (or username fallback) |
| `prefix` | `str \| None` | Sender user_id as string (for ACL) |
| `text` | `str \| None` | Message body (stripped of @bot suffix) |
| `target` | `str \| None` | chat_id as string |
| `is_channel` | `bool` | `True` for groups, `False` for DMs |
| `command` | `str` | Always `"PRIVMSG"` (compat shim) |
| `params` | `list[str]` | `[target, text]` |
| `tags` | `dict[str, str]` | Empty dict (no IRCv3 tags) |
### `TelegramBot`
Same stable attributes and methods as `Bot`:
| Attribute | Type | Description |
|-----------|------|-------------|
| `name` | `str` | Always `"telegram"` |
| `config` | `dict` | Merged TOML configuration |
| `nick` | `str` | Bot display name (from `getMe`) |
| `prefix` | `str` | Command prefix (from `[telegram]` or `[bot]`) |
| `state` | `StateStore` | Persistent key-value storage |
| `registry` | `PluginRegistry` | Shared command and event registry |
**Sending messages** -- same signatures, Telegram API transport:
| Method | Behaviour |
|--------|-----------|
| `send(target, text)` | `sendMessage` API call (proxied, rate-limited) |
| `reply(msg, text)` | `send(msg.target, text)` |
| `long_reply(msg, lines, *, label="")` | Paste overflow, same logic as IRC |
| `action(target, text)` | Italic Markdown text via `sendMessage` |
| `shorten_url(url)` | Same FlaskPaste integration |
**Message splitting**: messages > 4096 chars split at line boundaries.
**IRC no-ops** (debug log, no error):
`join`, `part`, `kick`, `mode`, `set_topic`
**Plugin management** -- delegates to shared registry:
`load_plugins`, `load_plugin`, `reload_plugin`, `unload_plugin`
**Permission tiers** -- same model, exact user_id string matching:
`_get_tier(msg)`, `_is_admin(msg)`
### Helper Functions
| Function | Signature | Description |
|----------|-----------|-------------|
| `_strip_bot_suffix` | `(text: str, bot_username: str) -> str` | Strip `@username` from command text |
| `_build_telegram_message` | `(update: dict, bot_username: str) -> TelegramMessage \| None` | Parse Telegram Update into message |
| `_split_message` | `(text: str, max_len: int = 4096) -> list[str]` | Split long text at line boundaries |
---
## Handler Signatures
All command and event handlers are async functions receiving `bot` and

View File

@@ -504,6 +504,23 @@ Teams endpoint: `POST /api/messages`. HMAC-SHA256 auth via `Authorization: HMAC
Replies returned as JSON in HTTP response. IRC-only commands (kick, ban, topic) are no-ops.
~90% of plugins work without modification.
## Telegram Integration
```toml
# config/derp.toml
[telegram]
enabled = true
bot_token = "123456:ABC-DEF..." # from @BotFather
poll_timeout = 30 # long-poll seconds
admins = [123456789] # Telegram user IDs
operators = []
trusted = []
```
Long-polling via `getUpdates` -- no public endpoint needed. All HTTP
through SOCKS5 proxy. Strips `@botusername` suffix in groups. Messages
split at 4096 chars. IRC-only commands are no-ops. ~90% of plugins work.
## Plugin Template
```python

View File

@@ -1400,3 +1400,77 @@ The bot returns a JSON response:
```
Multiple reply lines are joined with `\n`.
## Telegram Integration
Connect derp to Telegram via long-polling (`getUpdates`). All outbound HTTP
is routed through the SOCKS5 proxy. No public endpoint required, no Telegram
SDK dependency.
### How It Works
The bot calls `getUpdates` in a loop with a long-poll timeout (default 30s).
When a message arrives with the configured prefix, it is dispatched through
the shared plugin registry. Replies are sent immediately via `sendMessage`.
### Configuration
```toml
[telegram]
enabled = true
bot_token = "123456:ABC-DEF..." # from @BotFather
poll_timeout = 30 # long-poll timeout in seconds
admins = [123456789] # Telegram user IDs (numeric)
operators = [] # Telegram user IDs
trusted = [] # Telegram user IDs
```
### Telegram Setup
1. **Create a bot** via [@BotFather](https://t.me/BotFather):
- `/newbot` and follow the prompts
- Copy the bot token and set `bot_token` in config
2. **Add the bot** to a group or send it a DM
3. **Configure permissions** using Telegram user IDs. Use `!whoami` to
discover your numeric user ID.
### Permission Tiers
Same 4-tier model as IRC, but matches exact Telegram user IDs (numeric
strings) instead of fnmatch hostmask patterns:
```toml
[telegram]
admins = [123456789]
operators = [987654321]
trusted = [111222333]
```
### Plugin Compatibility
Same compatibility as Teams -- ~90% of plugins work without modification.
| Feature | IRC | Telegram |
|---------|-----|----------|
| `bot.reply()` | Sends PRIVMSG | `sendMessage` API call |
| `bot.send()` | Sends PRIVMSG | `sendMessage` API call |
| `bot.action()` | CTCP ACTION | Italic Markdown text |
| `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 user IDs |
| Message limit | 512 bytes (IRC) | 4096 chars (Telegram) |
### Group Commands
In groups, Telegram appends `@botusername` to commands. The bot strips
this automatically: `!help@mybot` becomes `!help`.
### Transport
All HTTP traffic (API calls, long-polling) routes through the SOCKS5
proxy at `127.0.0.1:1080` via `derp.http.urlopen`. No direct outbound
connections are made.