BareGit
# 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.