1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

今更Slack Actionを解説(2025版:備忘録)

Last updated at Posted at 2026-01-27

今更ながらSlack Actionを使ってみました。
良かった点やWebとの概念的違いについてのまとめになります。

Slack側の設定

ここではSlack側の設定になります。

Slack APIにアクセスする

image.png

Create New Appを選択します。

image.png

今回はFrom scratchで1から作成します。

image.png

  • App Nameは日本語可能で適当でOK
  • Pick a workspace to develop your app inはインサートしたいWorkspaceを選択します

API設定

今回は以下の情報をメモしておきます。

  • Basic Information > App CredentialsからSigning Secret(SHOWボタンで表示されます)

OAuth & Permissionsの設定

Scopesの設定でBOT Token Scopesでスコープを付与(今回はchat:writeを設定します)
スコープの設定を実施するとWorkspaceにインストールができるので、Install Appから選択します。

インストールが完了するとOAuth & Permissions > OAuth TokensからBOT Tokenを取得します(xoxbから始まるトークンです)

このSigning SecretとBOT Tokenはアプリ内で使用しますが決して外部に漏らしてはいけないので、その点だけ注意しましょう!(環境変数 & gitignoreで管理しましょう)

Slack Action独自の設定

Slack ActionはAPI設定とは別に独自の設定が必要になります。

サイドメニューからInteractivity & Shortcutsを選択し、InteractivityをONにします。

  • Request URLは後程設定します。デプロイで作成されたURLを入力する必要があります

サーバー側の設定

SlackのアクションはあくまでUIを提供するのに特化してるため、具体的な処理はサーバー側に任せます。先ほど紹介したRequet URLで処理を行います。

今回はNext.jsで作成しています。

app.ts
import { App, ExpressReceiver } from "@slack/bolt";


export const receiver = new ExpressReceiver({
  signingSecret: process.env.SLACK_SIGNING_SECRET ?? '',
  processBeforeResponse: true,
  endpoints: '/api/slack',
});

export const createInstance = () => {
  const app = new App({
    signingSecret: process.env.SLACK_SIGNING_SECRET, // 先ほどメモったSigning secret
    token: process.env.SLACK_BOT_TOKEN, // 先ほどメモったBot Token
    receiver: receiver,
  });
  return app; 
}

今回はendpointをhttps://[domain]/api/slackに設定しています。Request URLも同様に設定する必要がありますので、そこだけ注意が必要です。
そうではないとサーバー側に届いてるのにSlackのUI上でリクエストが応答されない現象が発生します
(ここで頭を抱えました。。。💦)

/api/slack/index.ts
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse,
) {
  const method = req.method?.toLowerCase();

  if (method !== 'post') {
    return badRequest(res);
  }

  // app.tsで定義したreceiverを参照します。
  return await receiver.app.handle(req, res);
}

Next側のAPI Routeはこのような形
認証周りとかはインスタンスを作る際に実施してくれるので、POSTのチェックだけでOKです。
(このコードだとGETだと400、POSTだと401がこのコードでは返却されます)

このルートハンドラの前に定義するコードを解説します。

/api/slack/index.ts
import type { NextApiRequest, NextApiResponse } from "next";
import { workOnTime, overTime, showInitMessage, showOverTimeModal } from "@/lib/slack/router";

// Next.jsのパーサーを設定(これをしないと受取れません)
export const config = {
  api: {
    bodyParser: false,
  },
};

// Slack Appのインスタンスを作成
const app = createInstance();


// Slackのアクションを定義(後述します)
app.action(SLACK_ACTION_ID.SOME_ACTION, async ({payload, client, ack}) => {
  await ack();
  
  const value = JSON.parse(payload?.value ?? '') as ShowSlackArgs;

  await client.chat.update({
    // ...省略
  })
});

// 先ほど紹介したハンドラ
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse,
) {
  const method = req.method?.toLowerCase();

  if (method !== 'post') {
    return badRequest(res);
  }

  return await receiver.app.handle(req, res);
}

receiver.app.handleで定義したものをapp.actionで拾うような形です。

app.actionの第一引数はUIを作る際に定義したaction_id、第二引数はコールバックです。
Slackは3秒以内での応答が必須になるので、まずはack()を非同期で必ず実行しましょう。

また、Slackなどに応答を返却したいなどがあればclientviewオブジェクトで所定の操作をするというのが基本的な流れです。

client.chat

  • メッセージを送信します
  • 更新をしたい(メッセージを書き換えたい)場合はupdateを使用しますが、メッセージIDであるtsを指定する必要があります
  • tspostMessageをしたタイミングで生成されるので、値を保持したいケースはこの戻り値をupdateで更新する必要があります(非常に面倒!)
  // 該当のWSのチャンネルにメッセージを送信
  const result = await client.chat.postMessage({
    blocks: blocks, // blocksを生成
    channel: CHANNEL_ID.GENERAL,
  });

  // 同様の内容だが、tsを付与してUpdate
  await client.chat.update({
    blocks: blocks,
    channel: CHANNEL_ID.GENERAL,
    ts: result.ts ?? '',
  })

UI作成について

Slackに送信するBlockの作成についてです、上記のコードのblocksに該当するパラメータですね。
JSON形式(JavaScript(以下JS)のobject形式)で作成が可能なのですが、面倒なのでツールを使用しましょう!

image.png

こんな感じでサンプルが表示されるので、Sectionとactionsを使用してコンポーネントを配置していきます。ある程度作成して、細かい所を都度修正する形で進めましょう。

{
  "blocks": [
    {
      "type": "actions",
      "elements": [
        {
          "type": "button",
          "text": {
            "type": "plain_text",
            "text": "Click Me",
            "emoji": true
          },
          "value": "click_me_123",
          "action_id": "actionId-0" // action_idはサーバー側に合わせる
        }
      ]
    }
  ]
}

作成されたものをコードに貼り付けて、動的なパラメータに対応できるようにしましょう。

おわりに

今回はモーダルについては触れませんでしたが、これも実際のところ簡単です。

はまりやすいポイントとしては

  • JS的なDOM挙動は出来ない
    • なのでJS的な挙動はactionやリクエスト数が増える
  • エンドポイントの指定の仕方に注意
  • ackを最初に呼ぶ
    • 応答ルールが厳しい

良かった点としてはSlack上で操作ができるのは良いですよね。
フロント部分を直感的に作成できるので、興味がある人はURLのBlock Kitだけでも遊ぶと良いと思います。

こんなかんじです。
また機会があればモーダル表示についても記載しようと思います(備忘録のため)


オブジェクティブグループではXの投稿も平日毎日行っています!
IT 関連の小ネタや便利技から、日常のアニメ・ゲーム布教なども幅広く投稿してるので、
ご興味のある方は是非フォロー・いいねをお願いします。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?