上一篇用 Modal 做了完整回饋流程。這篇再往前推一步:為 Slash Command 的 option 欄位加上即時搜尋,讓使用者不必死背指令名稱。
Autocomplete 是什麼?
先看一個對比。假設有個 /help command: 指令:
沒有 Autocomplete 時
command 只是一個普通文字欄位,使用者得把指令名稱完整打完,送出後 Bot 才知道他輸入了什麼。
指令少的時候沒問題,但名稱一多、一長,容易打錯,體驗就會變差。

有 Autocomplete 時
只要輸入幾個字,Discord 就會顯示 Bot 即時回傳的候選清單,使用者直接點選即可。

一句話總結:使用者還在輸入時,Bot 就先把可能的答案列出來。
什麼情況要自己做
通常是文字輸入型的 Slash Command option,才需要你自己處理 Autocomplete。
因為有些 option type,Discord 本身就有內建選擇方式,例如:
USER:直接選成員CHANNEL:直接選頻道ROLE:直接選身分組
這些類型很多時候不用你自己再寫 autocomplete。Discord 本身就會彈出對應的選擇器。

真正常見要自己處理的,是像 STRING 這種文字型欄位。Discord 不知道你想提供哪些候選值,所以要由 Bot 在 interaction.isAutocomplete() 裡自己回傳。
所以它最適合用在:
- 指令很多時的
/help - 文章、標籤、角色、商品名等搜尋
- 想避免使用者輸入錯字
註冊可 autocomplete 的指令
以 /help command 為例,把 option 的 autocomplete 設為 true。
export const COMMANDS = [
{
name: "help",
description: "查詢指令說明",
options: [
{
name: "command",
description: "要查詢的指令名稱",
type: 3, // STRING
required: true,
autocomplete: true,
},
],
},
];interactionCreate 需要兩段處理
你要同時處理:
interaction.isAutocomplete():回傳候選清單interaction.isChatInputCommand():真正執行/help
import { Client, GatewayIntentBits, EmbedBuilder } from "discord.js";
import "dotenv/config";
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
const HELP_DATA = [
{ name: "ping", description: "測試 Bot 是否在線" },
{ name: "daily", description: "每日簽到" },
{ name: "feedback", description: "提交回饋表單" },
{ name: "ask", description: "向 AI 提問" },
{ name: "reset", description: "清除目前頻道 AI 對話歷史" },
];
client.on("interactionCreate", async (interaction) => {
if (interaction.isAutocomplete()) {
if (interaction.commandName !== "help") return;
const focused = interaction.options.getFocused().toLowerCase();
const choices = HELP_DATA
.filter((item) => item.name.includes(focused))
.slice(0, 25)
.map((item) => ({ name: item.name, value: item.name }));
await interaction.respond(choices);
return;
}
if (interaction.isChatInputCommand() && interaction.commandName === "help") {
const commandName = interaction.options.getString("command", true);
const found = HELP_DATA.find((x) => x.name === commandName);
if (!found) {
await interaction.reply({ content: "找不到該指令說明。", flags: 64 });
return;
}
const embed = new EmbedBuilder()
.setColor("Aqua")
.setTitle(`/${found.name}`)
.setDescription(found.description)
.setFooter({ text: "輸入 /help 後可直接用 autocomplete 搜尋" });
await interaction.reply({ embeds: [embed], flags: 64 });
}
});常見坑
respond最多 25 筆,超過要slice(0, 25)。- Autocomplete 不支援太慢的外部查詢,先從記憶體資料做起。
- 若候選值是 ID,
name給人看、value存實際值。 isAutocomplete與isChatInputCommand是兩種不同互動,不要混在同一段邏輯。
下一篇預告
下一篇做排程任務,讓 Bot 不是只等人呼叫,而是每天固定時間自己主動做事。