Discord Slash 指令
Discord 有項稱為斜線指令的新功能。它們允許您輸入 /
,後面接指令名稱,以執行一些動作。例如,您可以輸入 /giphy cats
(內建指令) 來取得一些貓咪 GIF。
Discord 斜線指令會在有人發出指令時,向 URL 發出要求。您不需要讓應用程式一直執行,斜線指令才能運作,這讓 Deno Deploy 成為建置此類指令的完美解決方案。
在這篇文章中,讓我們看看如何使用 Deno Deploy 建置一個 hello world 斜線指令。
步驟 1:在 Discord Developer Portal 上建立應用程式
- 前往 https://discord.com/developers/applications (如果需要,請使用您的 Discord 帳戶登入)。
- 按一下個人頭像左側的新增應用程式按鈕。
- 為您的應用程式命名,然後按一下建立。
- 前往機器人區段,按一下新增機器人,最後按一下是的,執行!來確認。
這樣就完成了。已建立一個新的應用程式,它將包含我們的斜線指令。請勿關閉分頁,因為我們在開發過程中需要從此應用程式頁面取得資訊。
步驟 2:使用 Discord 應用程式註冊斜線指令
在我們撰寫程式碼之前,我們需要 curl 一個 Discord 端點,以便在我們的應用程式中註冊一個 Slash Command。
使用 機器人 區段中提供的代碼填入 BOT_TOKEN
,並使用頁面 一般資訊 區段中提供的 ID 填入 CLIENT_ID
,然後在你的終端機上執行指令。
BOT_TOKEN='replace_me_with_bot_token'
CLIENT_ID='replace_me_with_client_id'
curl -X POST \
-H 'Content-Type: application/json' \
-H "Authorization: Bot $BOT_TOKEN" \
-d '{"name":"hello","description":"Greet a person","options":[{"name":"name","description":"The name of the person","type":3,"required":true}]}' \
"https://discord.com/api/v8/applications/$CLIENT_ID/commands"
這將註冊一個名為 hello
的 Slash Command,它接受一個名為 name
的字串型別參數。
步驟 3:在 Deno Deploy 上建立並部署 hello world Slash Command
接下來,我們需要建立一個伺服器,以便在 Discord 使用某人的 slash command 提出 POST 要求時回應 Discord。
-
瀏覽至 https://dash.deno.com/new,然後按一下 遊樂場 卡片下的 播放。
-
在下一頁的編輯器中,按一下頂端功能表上的 設定 圖示。在彈出的對話框中,選取 + 新增變數。
-
輸入
DISCORD_PUBLIC_KEY
作為 KEY。VALUE 應為 Discord 應用程式頁面 一般資訊 區段中提供的公開金鑰。 -
複製並貼上以下程式碼至編輯器
// Sift is a small routing library that abstracts away details like starting a
// listener on a port, and provides a simple function (serve) that has an API
// to invoke a function for a specific path.
import {
json,
serve,
validateRequest,
} from "https://deno.land/x/sift@0.6.0/mod.ts";
// TweetNaCl is a cryptography library that we use to verify requests
// from Discord.
import nacl from "https://cdn.skypack.dev/tweetnacl@v1.0.3?dts";
// For all requests to "/" endpoint, we want to invoke home() handler.
serve({
"/": home,
});
// The main logic of the Discord Slash Command is defined in this function.
async function home(request: Request) {
// validateRequest() ensures that a request is of POST method and
// has the following headers.
const { error } = await validateRequest(request, {
POST: {
headers: ["X-Signature-Ed25519", "X-Signature-Timestamp"],
},
});
if (error) {
return json({ error: error.message }, { status: error.status });
}
// verifySignature() verifies if the request is coming from Discord.
// When the request's signature is not valid, we return a 401 and this is
// important as Discord sends invalid requests to test our verification.
const { valid, body } = await verifySignature(request);
if (!valid) {
return json(
{ error: "Invalid request" },
{
status: 401,
},
);
}
const { type = 0, data = { options: [] } } = JSON.parse(body);
// Discord performs Ping interactions to test our application.
// Type 1 in a request implies a Ping interaction.
if (type === 1) {
return json({
type: 1, // Type 1 in a response is a Pong interaction response type.
});
}
// Type 2 in a request is an ApplicationCommand interaction.
// It implies that a user has issued a command.
if (type === 2) {
const { value } = data.options.find((option) => option.name === "name");
return json({
// Type 4 responds with the below message retaining the user's
// input at the top.
type: 4,
data: {
content: `Hello, ${value}!`,
},
});
}
// We will return a bad request error as a valid Discord request
// shouldn't reach here.
return json({ error: "bad request" }, { status: 400 });
}
/** Verify whether the request is coming from Discord. */
async function verifySignature(
request: Request,
): Promise<{ valid: boolean; body: string }> {
const PUBLIC_KEY = Deno.env.get("DISCORD_PUBLIC_KEY")!;
// Discord sends these headers with every request.
const signature = request.headers.get("X-Signature-Ed25519")!;
const timestamp = request.headers.get("X-Signature-Timestamp")!;
const body = await request.text();
const valid = nacl.sign.detached.verify(
new TextEncoder().encode(timestamp + body),
hexToUint8Array(signature),
hexToUint8Array(PUBLIC_KEY),
);
return { valid, body };
}
/** Converts a hexadecimal string to Uint8Array. */
function hexToUint8Array(hex: string) {
return new Uint8Array(
hex.match(/.{1,2}/g)!.map((val) => parseInt(val, 16)),
);
} -
按一下 儲存並部署 以部署伺服器
-
檔案部署後,請注意專案 URL。它將位於編輯器的右上角,並以
.deno.dev
結尾。
步驟 3:設定 Discord 應用程式,以使用我們的 URL 作為互動端點 URL
- 回到 Discord Developer Portal 上的應用程式 (Greeter) 頁面
- 填入 互動終端點網址 欄位為上方 Deno Deploy 專案網址,並按一下 儲存變更。
應用程式現在已準備就緒。讓我們繼續進行下一部分來安裝它。
步驟 4:在 Discord 伺服器上安裝斜線指令
因此,要使用 hello
斜線指令,我們需要在 Discord 伺服器上安裝我們的 Greeter 應用程式。以下是步驟
- 前往 Discord 開發者入口網站上 Discord 應用程式頁面的 OAuth2 區段
- 選取
applications.commands
範圍,並按一下下方的 複製 按鈕。 - 現在貼上網址並在瀏覽器中開啟。選取您的伺服器,並按一下 授權。
開啟 Discord,輸入 /hello Deno Deploy
,並按下 Enter。輸出結果會類似於下方。
恭喜您完成本教學課程!繼續前進,建立一些很棒的 Discord 斜線指令!並在 Deno Discord 伺服器 的 deploy 頻道與我們分享。