# Polling and Webhooks

ExGram supports two methods for receiving updates from Telegram: **Polling** and **Webhooks**.

## Polling Mode

Polling is the easiest way to get your bot running. The bot periodically calls `getUpdates` on the Telegram Bot API to retrieve new messages.

**Best for:**
- Development and testing
- Simple deployments
- Bots that don't need instant responses
- Environments where you can't expose a public URL

### Basic Polling Setup

```elixir
# In your application supervision tree
children = [
  ExGram,
  {MyBot, [method: :polling, token: "YOUR_TOKEN"]}
]
```

### Configuring `allowed_updates`

By default, Telegram sends all update types. You can filter to only the types you need:

**In supervision tree:**

```elixir
{MyBot, [
  method: {:polling, allowed_updates: ["message", "edited_message", "callback_query"]},
  token: "YOUR_TOKEN"
]}
```

**In application config:**

```elixir
config :ex_gram, :polling,
  allowed_updates: ["message", "edited_message", "callback_query"]
```

Supervision tree options override config file settings, allowing per-bot customization.

### Available Update Types

- `"message"` - New incoming messages
- `"edited_message"` - Edited messages
- `"channel_post"` - Channel posts
- `"edited_channel_post"` - Edited channel posts
- `"inline_query"` - Inline queries
- `"chosen_inline_result"` - Inline query results chosen by user
- `"callback_query"` - Callback button presses
- `"shipping_query"` - Shipping query for payments
- `"pre_checkout_query"` - Pre-checkout query for payments
- `"poll"` - Poll state updates
- `"poll_answer"` - User's poll answer

### Webhook Cleanup

By default, polling mode deletes any existing webhook. If you've never used webhooks, you can skip this:

```elixir
config :ex_gram, :polling,
  allowed_updates: ["message"],
  delete_webhook: false
```

## Webhook Mode

Webhooks provide real-time updates. Telegram sends updates to your server via HTTP POST requests.

**Best for:**
- Production deployments
- Bots requiring instant responses
- High-traffic bots
- Efficient resource usage

### Prerequisites

1. A public HTTPS URL (HTTP not supported by Telegram)
2. Valid SSL certificate (self-signed works)
3. `Plug` and `plug_cowboy` dependencies

### Setup

**1. Add dependencies:**

```elixir
def deps do
  [
    # ... other deps
    {:plug_cowboy, "~> 2.0"},
    {:plug, "~> 1.0"}
  ]
end
```

**2. Add `ExGram.Plug` to your router:**

```elixir
defmodule MyApp.Router do
  use Plug.Router

  plug ExGram.Plug
  
  # Your other routes...
end
```

The webhook endpoint will be at `/telegram/<bot_token_hash>`.

**3. Configure your bot:**

```elixir
children = [
  ExGram,
  {MyBot, [method: :webhook, token: "YOUR_TOKEN"]}
]
```

### Webhook Configuration

#### In Config File

```elixir
config :ex_gram, :webhook,
  url: "https://bot.example.com",
  allowed_updates: ["message", "callback_query"],
  certificate: "priv/cert/selfsigned.pem",
  drop_pending_updates: false,
  ip_address: "1.1.1.1",
  max_connections: 50,
  secret_token: "your_secret_here"
```

#### In Supervision Tree

```elixir
webhook_options = [
  url: "https://bot.example.com",
  allowed_updates: ["message", "callback_query"],
  secret_token: System.get_env("WEBHOOK_SECRET")
]

children = [
  ExGram,
  {MyBot, [method: {:webhook, webhook_options}, token: "YOUR_TOKEN"]}
]
```

### Webhook Options

| Option | Type | Description |
|--------|------|-------------|
| `url` | String | **Required.** Your bot's public HTTPS URL (with scheme and optional port) |
| `allowed_updates` | List of strings | Update types to receive (same as polling) |
| `certificate` | String | Path to self-signed certificate file |
| `drop_pending_updates` | Boolean | Drop updates that arrived while bot was down |
| `ip_address` | String | Fixed IP address for Telegram to use |
| `max_connections` | Integer | Max simultaneous connections (1-100, default 40) |
| `secret_token` | String | Secret token to verify requests are from Telegram |

See [Telegram setWebhook docs](https://core.telegram.org/bots/api#setwebhook) for detailed explanations.

### Using Self-Signed Certificates

For development or internal deployments:

```elixir
config :ex_gram, :webhook,
  url: "https://bot.example.com:8443",
  certificate: "priv/cert/selfsigned.pem"
```

Generate a self-signed certificate:

```bash
openssl req -newkey rsa:2048 -sha256 -nodes -keyout private.key -x509 -days 365 -out cert.pem
```

### Secret Token Verification

Add a secret token for additional security:

```elixir
config :ex_gram, :webhook,
  url: "https://bot.example.com",
  secret_token: System.get_env("WEBHOOK_SECRET_TOKEN")
```

Telegram will send this token in the `X-Telegram-Bot-Api-Secret-Token` header.

## Test Environment

Telegram provides a [Test Environment](https://core.telegram.org/bots/webapps#using-bots-in-the-test-environment) for testing your bot without affecting production.

Enable it in config:

```elixir
config :ex_gram, test_environment: true
```

**Note:** You'll need a separate bot token from the test environment's BotFather.

## Choosing Between Polling and Webhooks

| Feature | Polling | Webhooks |
|---------|---------|----------|
| Setup complexity | Simple | Moderate (requires HTTPS) |
| Real-time updates | Delayed (polling interval) | Instant |
| Server requirements | None | Public HTTPS endpoint |
| Resource usage | Constant (polling loop) | On-demand (per update) |
| Best for | Development, simple bots | Production, high-traffic |
| Network | Works behind firewall/NAT | Requires public IP |

## Multiple Bots with Different Methods

You can run different bots with different update methods:

```elixir
children = [
  ExGram,
  {MyBot.DevBot, [method: :polling, token: dev_token]},
  {MyBot.ProdBot, [method: :webhook, token: prod_token]}
]
```

See [Multiple Bots](multiple-bots.md) for more details.

## Next Steps

- [Sending Messages](sending-messages.md) - Learn the DSL for building responses
- [Multiple Bots](multiple-bots.md) - Run multiple bots in one application
- [Fly.io Deployment](flyio.md) - Deploy your webhook bot to production
