# Telegram investment bot

The Telegram bot is a second, isolated interface for fund issuance/purchase and
redemption/sale. It uses the existing MongoDB, Redis, SEJAM, Tadbir, Sepah,
payment, request, and request-history implementations.

The bot does not have a separate database. Permanent Telegram authentication is
stored on the existing `User` document with `telegramId`,
`isTelegramVerified`, and `telegramVerifiedAt`. Short-lived conversation state,
quotes, rate limits, update deduplication, and idempotency markers use the
project's existing Redis connection.

## Routes and disable switch

When `TELEGRAM_BOT_ENABLED=false`, the bot runtime is not started and
`/v1/bot/*` is not mounted.

When enabled, these isolated routes are available:

- `POST /v1/bot/webhook`: receives Telegram updates in webhook mode.
- `GET /v1/bot/health`: reports the enabled mode and development-mode status.

Authentication and investment steps are handled from verified Telegram updates
inside `src/bot`; they are intentionally not exposed as unauthenticated public
REST endpoints.

## Environment

Add the relevant values to `.env.dev` or `.env.prod`:

```dotenv
TELEGRAM_BOT_ENABLED=false
TELEGRAM_BOT_TOKEN=

# polling is convenient for local development; webhook is recommended in production
TELEGRAM_BOT_MODE=polling

# Safe default is true. When true, only TEST_BOT_NATIONAL_CODES work.
TELEGRAM_BOT_DEVELOPMENT_MODE=true
TEST_BOT_NATIONAL_CODES=0019431171,0019277792

# Existing application-wide test configuration remains separate from the bot.
TEST_MODE=true
TEST_NATIONAL_CODES=0019431171,0019277792

# Required only when TELEGRAM_BOT_MODE=webhook
TELEGRAM_BOT_PUBLIC_BASE_URL=https://api.example.com
TELEGRAM_BOT_WEBHOOK_SECRET=replace-with-a-long-random-secret

# Optional
TELEGRAM_BOT_STATE_TTL_SECONDS=900
TELEGRAM_BOT_QUOTE_TTL_SECONDS=300
```

### `telegramBotConfig` reference

| Configuration property | Environment variable             | Default                        | Description                                                                                                                       |
| ---------------------- | -------------------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`              | `TELEGRAM_BOT_ENABLED`           | `false`                        | Master switch. When disabled, the runtime is not started and `/v1/bot/*` is not mounted.                                          |
| `token`                | `TELEGRAM_BOT_TOKEN`             | Empty                          | Bot API token issued by BotFather. Required when the bot is enabled.                                                              |
| `mode`                 | `TELEGRAM_BOT_MODE`              | `webhook`                      | Accepts `polling` or `webhook`. Any value other than `polling` resolves to `webhook`.                                             |
| `webhookSecret`        | `TELEGRAM_BOT_WEBHOOK_SECRET`    | Empty                          | Secret verified against Telegram's `X-Telegram-Bot-Api-Secret-Token` header. Required in webhook mode.                            |
| `webhookPath`          | Not configurable                 | `/v1/bot/webhook`              | Isolated callback route mounted by the API.                                                                                       |
| `webhookUrl`           | `TELEGRAM_BOT_PUBLIC_BASE_URL`   | `API_PUBLIC_BASE_URL` fallback | Public base URL joined with `/v1/bot/webhook`. It must be externally reachable over HTTPS in webhook mode.                        |
| `developmentMode`      | `TELEGRAM_BOT_DEVELOPMENT_MODE`  | `true`                         | Restricts bot authentication to identifiers in `TEST_BOT_NATIONAL_CODES`. Set to `false` only for an approved production rollout. |
| `allowedNationalCodes` | `TEST_BOT_NATIONAL_CODES`        | Empty list                     | Bot-specific comma-separated identifier allow-list used only when Telegram development mode is enabled.                           |
| `stateTtlSeconds`      | `TELEGRAM_BOT_STATE_TTL_SECONDS` | `900`                          | Redis lifetime in seconds for an unfinished bot conversation. Values below 300 are raised to 300.                                 |
| `quoteTtlSeconds`      | `TELEGRAM_BOT_QUOTE_TTL_SECONDS` | `300`                          | Lifetime in seconds for a server-calculated quote. Values below 60 are raised to 60.                                              |

Startup validation fails when:

- the bot is enabled without `TELEGRAM_BOT_TOKEN`;
- webhook mode is enabled without a public base URL or webhook secret;
- development mode is enabled while `TEST_BOT_NATIONAL_CODES` is empty.

For a production rollout, set:

```dotenv
TELEGRAM_BOT_ENABLED=true
TELEGRAM_BOT_MODE=webhook
TELEGRAM_BOT_DEVELOPMENT_MODE=false
```

## Authentication

1. The user starts the bot in a private chat.
2. The bot accepts a national code or legal identifier.
3. Development mode rejects identifiers not present in
   `TEST_BOT_NATIONAL_CODES`.
4. For an existing, SEJAM-complete user, the existing SMS service sends an OTP
   to the stored mobile number.
5. For a missing or SEJAM-incomplete user, the existing SEJAM OTP/profile flow
   is used.
6. After OTP verification, the Telegram user ID is permanently bound to the
   existing user record.
7. Every later update re-loads the bound user from MongoDB. No permanent JWT is
   stored in Telegram or Redis.
8. "قطع اتصال حساب" revokes the binding.

An internal user can be connected to only one verified Telegram account, and a
Telegram account can be connected to only one internal user.

## Investment flow

Only funds configured for the existing Parsian gateway or Sepah broker gateway
are shown. Issuance/purchase supports the gateway method only.

Before confirmation the bot:

- fetches the latest fund data and NAV;
- calculates units and fees;
- checks minimum, maximum, remaining issuance capacity, and the maximum payment
  amount;
- checks SEJAM and Tadbir/Sepah registration;
- checks the current redeemable balance for redemption/sale;
- creates a short-lived server-side quote.

At final confirmation all values are fetched and calculated again. A changed
NAV, fee, capacity, or balance requires a new confirmation. The bot then calls
the existing payment helper for issuance/purchase or the existing redemption
controller for redemption/sale.

The user receives the existing Parsian/Sepah gateway URL. The "بررسی وضعیت
پرداخت" button reads the existing request and also executes the existing Sepah
payment confirmation flow when required.

## Operational notes

- Use a private chat only.
- Keep `TELEGRAM_BOT_WEBHOOK_SECRET` and the bot token outside source control.
- The Telegram webhook URL is
  `TELEGRAM_BOT_PUBLIC_BASE_URL + /v1/bot/webhook`.
- Gateway callbacks remain the existing Parsian/Sepah callbacks.
- The website continues to use its current routes with no bot dependency.
