# Telegram 互動

本頁說明 `core/telegram` 的自由文字輸入、單選與多選提示，以及各自的答案如何回到 `Reply` handler。

三個方法都接收 `(ctx, chatID int64, replyTo int, text string, ...)`，回傳 prompt 的 `*models.Message`；`text` 為空時回 `text is required`，並接受 `WithSendType` 設定 prompt 的 parse mode。`replyTo > 0` 時 prompt 以 reply 方式掛在該訊息下。

## 自由文字輸入：SendInput

```go
prompt, err := bot.SendInput(ctx, in.ChatID, in.MessageID, "What is your name?")
```

prompt 帶 `ForceReply`，使用者端會以 reply 模式開啟鍵盤。答案以一般 message update 抵達：`in.Text` 是答案，`in.Raw.Message.ReplyToMessage.ID` 等於 `prompt.ID`。函式庫不保存 input prompt 的狀態；答案與 prompt 的對應由你的 handler 處理。

## 單選：SendSelect

```go
prompt, err := bot.SendSelect(ctx, in.ChatID, in.MessageID, "Pick a color", []string{"Red", "Green", "Blue"})
```

| 步驟 | 行為 |
|---|---|
| 送出 | 每個非空項目一個 inline button，每列一個；按鈕文字與 callback data 都是該項目。至少需要一個非空項目 |
| 點擊 | 函式庫回應 callback query、清除 prompt 上的鍵盤，再以 `CallbackData` = 該項目、`MessageID` = prompt ID 呼叫 `Reply` |

Telegram 限制 callback data 為 64 bytes，較長的項目會在送出 prompt 時被 Telegram 拒絕。

## 多選：SendMultiSelect

```go
prompt, err := bot.SendMultiSelect(ctx, in.ChatID, in.MessageID, "Pick toppings", []string{"Cheese", "Ham", "Olive"})
```

| 步驟 | 行為 |
|---|---|
| 送出 | 每個非空項目一個 toggle 按鈕（`⬜ item`），最後一列為 **Done** 按鈕。項目 `__bot_multiselect_done__` 為保留字，傳入會回 error |
| 切換 | 函式庫翻轉該項目並重繪鍵盤（`✅ item`），**不**呼叫 handler。每個 prompt 每秒最多重繪一次；快速連點會合併成一次編輯 |
| Done | 函式庫清除鍵盤，並以 `CallbackPicks` = 依原順序排列的已選項目（未選時為空）、`MessageID` = prompt ID 呼叫一次 `Reply` |

多選 prompt 的狀態以 chat 與 prompt ID 為 key 存在記憶體，按下 **Done** 5 分鐘後或 `Close()` 時移除。**Done** 之後的點擊會被忽略。

## 清理 prompt

select 鍵盤會自動移除，但 prompt 文字仍保留。要移除時呼叫 `bot.Delete(ctx, chatID, prompt.ID)`，需要的話再用 `Send` reply 到原始訊息送出彙整。

## 相關頁面

- [Reply Handler](/zh/reply-handler)
- [Telegram 設定](/zh/telegram)（`Input` 欄位）
- [Discord 互動](/zh/discord-interactions)（Discord 對應功能）
