跳转到主要内容
在本页上

Discord 斜杠命令

Discord 有一项名为斜杠命令的新功能。它们允许您键入 / 后跟命令名称来执行某些操作。例如,您可以键入 /giphy cats(内置命令)来获取一些猫咪 GIF。

Discord 斜杠命令的工作原理是在有人发出命令时向 URL 发出请求。您不需要您的应用程序始终运行才能使斜杠命令工作,这使得 Deno Deploy 成为构建此类命令的完美解决方案。

在这篇文章中,让我们看看如何使用 Deno Deploy 构建一个 hello world 斜杠命令。

步骤 1:在 Discord 开发者门户上创建一个应用程序 跳转到标题

  1. 前往 https://discord.com/developers/applications(如果需要,请使用您的 Discord 帐户登录)。
  2. 点击个人资料图片左侧的新建应用程序按钮。
  3. 为您的应用程序命名,然后点击创建
  4. 转到机器人部分,点击添加机器人,最后点击是的,就这样做!进行确认。

就是这样。创建了一个新应用程序,它将保存我们的斜杠命令。不要关闭此选项卡,因为在整个开发过程中我们需要来自此应用程序页面的信息。

步骤 2:在 Discord 应用中注册斜杠命令 跳转到标题

在编写代码之前,我们需要使用 curl 向 Discord 端点发送请求,以便在我们的应用中注册一个斜杠命令。

用**机器人**部分的令牌填充 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 的斜杠命令,该命令接受一个名为 name 的字符串类型参数。

步骤 3:在 Deno Deploy 上创建和部署 hello world 斜杠命令 跳转到标题

接下来,我们需要创建一个服务器,以便在 Discord 使用某人的斜杠命令发出 POST 请求时进行响应。

  1. 导航至 https://dash.deno.com/new 并点击**Playground**卡片下的**Play(运行)**。

  2. 在下一页的编辑器中,点击顶部菜单上的**设置**图标。在弹出的模态框中,选择**+ 添加变量**。

  3. 输入 DISCORD_PUBLIC_KEY 作为键。值应该是 Discord 应用程序页面**常规信息**部分中的公钥。

  4. 将以下代码复制并粘贴到编辑器中

    // 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/[email protected]/mod.ts";
    // TweetNaCl is a cryptography library that we use to verify requests
    // from Discord.
    import nacl from "https://esm.sh/[email protected]?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)),
      );
    }
    
  5. 点击**保存并部署**来部署服务器

  6. 部署文件后,请记下项目 URL。它位于编辑器的右上角,以 .deno.dev 结尾。

步骤 3:配置 Discord 应用程序以使用我们的 URL 作为交互端点 URL 跳转到标题

  1. 返回 Discord 开发者门户上的应用程序(Greeter)页面
  2. 用上面的 Deno Deploy 项目 URL 填写**交互端点 URL**字段,然后点击**保存更改**。

应用程序现在已准备就绪。让我们继续下一部分来安装它。

步骤 4:在 Discord 服务器上安装斜杠命令 跳转到标题

要使用 hello 斜杠命令,我们需要在 Discord 服务器上安装 Greeter 应用程序。以下是步骤

  1. 转到 Discord 开发者门户上 Discord 应用程序页面的**OAuth2**部分
  2. 选择 applications.commands 范围,然后点击下面的**复制**按钮。
  3. 现在在浏览器中粘贴并访问该 URL。选择您的服务器,然后点击**授权**。

打开 Discord,输入 /hello Deno Deploy 并按**Enter**键。输出将类似于以下内容。

Hello, Deno Deploy!

恭喜您完成本教程!继续构建一些很棒的 Discord 斜杠命令吧!并在 Deno Discord 服务器 的**deploy**频道与我们分享。