# Telegrammer Design Document
## 1. Overview
Telegrammer is a C++ based service acting as a bridge between the Telegram Bot API and other local applications. It provides a simplified HTTP API for sending messages and a webhook-style subscription mechanism for receiving messages. It utilizes `libmw` for network operations.
## 2. Architecture
The system consists of three main components:
1. **API Server (`mw::HTTPServer`)**: Handles incoming HTTP requests from local applications to send messages or subscribe to events.
2. **Telegram Client (`mw::HTTPSession`)**: Manages communication with the Telegram Bot API.
3. **Poller / Dispatcher**: Periodically fetches updates from Telegram (Long Polling) and dispatches them to registered subscriber callbacks via HTTP POST.
### Data Flow
**Sending Messages:**
`Local App` --(HTTP POST)--> `Telegrammer (Server)` --(HTTP POST)--> `Telegram API`
**Receiving Messages:**
`Telegram API` --(Long Poll Response)--> `Telegrammer (Poller)` --(Lookup)--> `Subscription Manager` --(HTTP POST)--> `Local App (Callback)`
## 3. Configuration
Configuration is handled via Command Line Arguments:
* `--token`: The API token obtained from @BotFather (required).
* `--port`: Port to listen on (default: `8080`).
* `--host`: Interface to bind to (default: `0.0.0.0`).
* `--help`: Show help message.
## 4. API Specification
### 4.1. Send Message
**Endpoint:** `POST /send`
**Content-Type:** `application/json`
**Request Body:**
```json
{
"chat_id": 123456789,
"username": "some_user",
"text": "Hello World"
}
```
* `text` (Required): The message content.
* `chat_id` (Optional): The target chat ID.
* `username` (Optional): If `chat_id` is not provided, the bot will look up the most recent `chat_id` associated with this username.
**Response:**
* `200 OK`: Message sent successfully.
* `400 Bad Request`: Missing `text`, or neither `chat_id` nor `username` provided, or username not found.
* `500 Internal Error`: Upstream Telegram error.
### 4.2. Subscribe
**Endpoint:** `POST /subscribe`
**Content-Type:** `application/json`
Registers a callback URL for a specific chat. When a message is received in that chat, Telegrammer will POST the message payload to the `callback_url`.
**Request Body:**
```json
{
"chat_id": 123456789,
"callback_url": "http://localhost:9090/webhook"
}
```
**Response:**
* `200 OK`: Subscribed successfully.
**Callback Payload:**
The callback URL will receive a POST request with `application/json` content. The body will be the JSON object of the [message](https://core.telegram.org/bots/api#message) from the Telegram [Update object](https://core.telegram.org/bots/api#update).
Example:
```json
{
"message_id": 123,
"from": {
"id": 456,
"is_bot": false,
"first_name": "John"
},
"chat": {
"id": 123456789,
"type": "private"
},
"date": 1672531200,
"text": "Hello bot"
}
```
## 5. Internal Components
### 5.1. TelegramClient Class
Wraps `mw::HTTPSession` to abstract Telegram API calls.
* `sendMessage(int64_t chat_id, string text)`
* `getUpdates(int64_t offset, int timeout)`: Uses long polling to wait for new messages.
### 5.2. SubscriptionManager Class
Thread-safe container for managing subscriptions.
* **Structure:** `std::map<int64_t, std::vector<std::string>> subscribers;` (Chat ID -> List of URLs)
* `addSubscription(chat_id, url)`
* `getSubscribers(chat_id)`
### 5.3. Polling Loop
Runs in a separate thread.
1. Calls `TelegramClient::getUpdates` with a timeout (e.g., 30s).
2. On return, updates the `offset` to `last_update_id + 1`.
3. Iterates through messages.
4. Queries `SubscriptionManager` for the `chat_id`.
5. If subscribers exist, uses a separate `mw::HTTPSession` to POST the message JSON to the registered URL.
## 6. Technologies
* **C++23**
* **libmw**: For `HTTPServer` and `HTTPSession` (Client).
* **nlohmann/json**: For JSON serialization/deserialization.
* **spdlog**: For logging.