つれづれなるままに日々の色々なことを綴ります

【GAS】Slackのスラッシュコマンドでユーザーを選択し、ユーザーIDを返事させる

GASを勉強しています。忘れないように学習メモを作っています。 そのままコピペして動くみたいな記事ではないのでお気をつけを。

やったこと

  • Slack上でスラッシュコマンド入力後、モーダルが開き、ユーザーを選択し送信すると選択したユーザーのユーザーIDが送信されてくる。
  • ユーザーは複数選択が可能

コード全文

const doPost = (e) => {
  const parameter = e.parameter
  try {
    if(parameter.payload) {
      const payload = JSON.parse(decodeURIComponent(parameter.payload))
      if (payload.type === "view_submission") {
      slackID(payload);
      }
    } else {
      if (SLACK_TOKEN != parameter.token) throw new Error(parameter.token);
      if (parameter.channel_id !== ALLOWED_CHANNEL_ID) {
      return ContentService.createTextOutput("このテストコマンドは指定のチャンネルでのみ作動するようになっています。すみません!") }
      // モーダルを開くようにSlackへリクエスト
      return openModal(parameter);
    }
  } catch(error) {
    return ContentService.createTextOutput(403)
  }
  return ContentService.createTextOutput();
}

const openModal = payload => {
  const modalView = generateModalView()
  const viewData = {
    token: SLACK_ACCESS_TOKEN,
    trigger_id: payload.trigger_id,
    view: JSON.stringify(modalView)
  }
  const postUrl = 'https://slack.com/api/views.open'
  const viewDataPayload = JSON.stringify(viewData)
  const options = {
    method: "post",
    contentType: "application/json",
    headers: { "Authorization": `Bearer ${SLACK_ACCESS_TOKEN}` },
    payload: viewDataPayload
  }

  UrlFetchApp.fetch(postUrl, options)
  return ContentService.createTextOutput()
}

//モーダル入力サブミットしたときの処理
function slackID(payload) {
  const selectedUsers = payload.view.state.values.lvIf8.selectusers.selected_users;

  const channel_id = 'チャンネルID';
  const token = "xoxb-HOGEHOGE";
  const message = `選択したユーザーIDをお返しします。 ${selectedUsers.join(", ")}`;
  sendMessageTochannel(token, channel_id, message);
}

function sendMessageTochannel(token, channel_id, message){
  const url = 'https://slack.com/api/chat.postMessage';
  const options = {
    'method': 'post',
    'contentType': 'application/json',
    'headers': {
      'Authorization': 'Bearer ' + token
    },
    'payload': JSON.stringify ({
      'channel': channel_id,  // 返答を送信するチャンネルのID
      'text': message,         // 送信するメッセージ内容
    })
  };

  // Slack APIへリクエストを送信
  UrlFetchApp.fetch(url, options);
}



/**
 * モーダルBlocks
 */
const generateModalView = () => {
  return {
    "type": "modal",
    "title": {
        "type": "plain_text",
        "text": "My App",
        "emoji": true
    },
    "submit": {
        "type": "plain_text",
        "text": "Submit",
        "emoji": true
    },
    "close": {
        "type": "plain_text",
        "text": "Cancel",
        "emoji": true
    },
    "blocks": [
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "ユーザーを選択してください (複数選択可能)"
            },
            "accessory": {
        "action_id": "selectusers",
                "type": "multi_users_select",
                "placeholder": {
                    "type": "plain_text",
                    "text": "Select options",
                    "emoji": true
                },
        }
      }
    ]
  }
}

事前準備

  • Slack上でスラッシュコマンドを使用するには、Interactivity & ShortcutsにデプロイしたアプリのURL登録とSlash Commandsに使用するコマンドの登録が必要です。
    • コマンドの登録の際にもRequest URLを求められますがInteractivity & Shortcutsに登録したものと同じものを使います

doPostで受け取る

  • 自分が作成したSlackアプリかつ指定のチャンネルだったときにモーダルを開く用にSlackへリクエストを投げます。

モーダルを開きます。

const openModal = payload => {
  const modalView = generateModalView()
  const viewData = {
    token: SLACK_ACCESS_TOKEN,
    trigger_id: payload.trigger_id,
    view: JSON.stringify(modalView)
  }
  const postUrl = 'https://slack.com/api/views.open'
  const viewDataPayload = JSON.stringify(viewData)
  const options = {
    method: "post",
    contentType: "application/json",
    headers: { "Authorization": `Bearer ${SLACK_ACCESS_TOKEN}` },
    payload: viewDataPayload
  }

  UrlFetchApp.fetch(postUrl, options)
  return ContentService.createTextOutput()
}
  • views.openを使用するにはtokneのほかにtrigger_idとviewが必要です。ここでは、generateModalViewで記載したViewの中身をJSON.stringifyで文字列としています。

api.slack.com

モーダルから送られてきた内容を受け取る。

  • モーダルから送られてきた中身には、type : view_submissionが含まれています。それが含まれているかを判定して、含まれていたらSlackIDという関数に受け渡しています。
  • 送られてきたjsonのselected_usersに選択したユーザーのIDが含まれているので、これを返事の中に含ませます。
const message = `選択したユーザーIDをお返しします。 ${selectedUsers.join(", ")}`;
  • この一文に地味に苦しんだ…。 (初心者)${ }を使うことで、変数の値を出力できるようになります。が、バッククオートで閉じなければならないというところになかなか気付けず、数敗。

Block Kit Builder… なんて甘美な調べ

  • モーダルのデザインはSlack側が用意してくれているBuilderを使うことで簡単に組み立てが出来ます。
  • 使いたい要素をポチポチ足していくだけ。
  • 入力欄にユーザーの候補を出すようにするためには"type"を"multi_users_select"にする必要があります。
  • 実際に触ってみたほうが多分楽しい。

app.slack.com

まとめ

楽しいです。

参考記事

zenn.dev