Slackでメンションしたら返答くれるbotを作る【Slack × GAS】

## 完成系のイメージ 

![スクリーンショット 2024-02-18 15.04.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/c4eb8b96-b500-661e-e978-140e7232202f.png)
（処理の流れ）
1. Slackでbotへのメンションイベントを拾う
1. GASでリクエストを受けて、返答内容を作る
1. 同じチャンネル（スレッド）に返答する

## 作成手順

### Slackアプリを設定する

#### アプリ作成
Slackアプリ作成を行う
https://api.slack.com/apps　

- 「Create New App」→「From scratch」で、
作成するアプリ名と導入先ワークスペースを入力し、アプリを作成

#### アプリ情報入力
- 「Basic Information」のページを開く
- 「Display Information」でアプリの説明やアイコンを入力

#### 権限設定
- 「OAuth & Permissions」のページを開く
- 「Scopes」に以下の権限を追加
![スクリーンショット 2024-02-18 14.58.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/e72d4edd-c85a-7a5e-c13a-f8cc1768c57a.png)

・app_mentions:read    ...メンション読み取り
・chat:write           ...チャット書き込み
・im:history           ...DM読み取り

- アプリへのDMを受け付ける場合、「App Home」ページで以下のチェックを入れる
![スクリーンショット 2024-02-18 13.57.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/135234fd-c35d-6fd5-abf3-ecb94bc5d270.png)


#### Token作成
- 「OAuth & Permissions」のページを開く
- 「OAuth Tokens for Your Workspace」 > 「Install to Workspace」を実行
- インストール後、作成されたBotUserOAuthTokenをコピーしておく
（後でGASで使用する）


### GASプロジェクトを作る
GASプロジェクトを作る。
https://script.google.com/home

- 「新しいプロジェクトを作る」からプロジェクトを作成
- コードを書く

コードサンプル
```js
//Slackアプリ管理画面でコピーしたBotUserOAuthTokenを入力する。
const slackToken = "XXXXXXX"; 

function doPost(e) {
  var params = JSON.parse(e.postData.contents);

  // Event Subscriptions のリクエストURL認証用の処理
  if (params.type === 'url_verification') {
    return ContentService.createTextOutput(params.challenge);
  }

  // botの投稿を無視する（無限ループ回避のため）
  if (params.event.bot_id) return;

  // 返答を作成
  var postData = createPostData();
  // 返答を送信
  postMessageToSlack(slackToken, postData, params.event.channel, params.event.ts);
  
  return ContentService.createTextOutput("");
}

function doGet(e) {
  // ログ「Script function not found: doGet」 を回避するために一応入れてる
}

// 送信するデータの内容を作成
function createPostData() {
  // TODO 返答内容はここでいろいろ作る
  return "はぁ？"
}

// Slackにメッセージを投稿
function postMessageToSlack(token, message, channelId, ts) {

  var payload = {
    channel: channelId,
    thread_ts: ts, // スレッドで返信する場合は必要。メンションの後に続けて投稿したい場合は不要。
    text: message,
  };
  var options = {
    method: "post",
    contentType: "application/json",
    headers: { 'Authorization': 'Bearer ' + token },
    payload: JSON.stringify(payload),
  };

  // SlackAPIにリクエストを送信
  var apiUrl = "https://slack.com/api/chat.postMessage";
  var response = UrlFetchApp.fetch(apiUrl, options);

  // レスポンスを確認しとく
  var responseData = JSON.parse(response.getContentText());
  if (!responseData.ok) {
    Logger.log("Slack API Error:", responseData.error);
    throw new Error(response);
  }
}
```

### Slack内のイベント処理を設定する
- Slackアプリ管理画面で、「Event Subscriptions」のページを開く
- 「Enable Events」をONにする
- 「Subscribe to bot events」に以下の設定を追加
![スクリーンショット 2024-02-18 13.36.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/5d28281c-bb6c-f28a-daa7-440d9b0ad6dd.png)
app_mention ...メンションに反応する設定
message.im ...DMに反応する設定。ここもDM使わないなら不要そう。

### GASプロジェクトのデプロイを実行する
作成したGASプロジェクトを開く。
- GASのデプロイを行う
    - 「デプロイ」 > 「新しいデプロイ」を選択
    - 「種類の選択」で「ウェブアプリ」を選択
    - アクセスできるユーザを「全員」に設定し、「デプロイ」を実行
    - Googleアカウントの許可設定が必要であれば許可
- デプロイできたら、作成されたウェブアプリのURLをコピーする（Slack管理画面で使用する）

### SlackアプリにGASへのリクエストURLを設定する
Slackアプリ管理画面を開く。
- 「Event Subscriptions」ページのRequest URLに、
GASのウェブアプリのURLを入力
- Veridfiedが表示されたらOK。表示されなければコード、URLやプロジェクトの設定などを見直す
- 画面右下の「Save Changes」で設定を反映する

### これで設定は完了
あとはSlackでメンションすれば返答してくれる（はず）。
ので、返答内容作成の部分を好きなようにカスタマイズしましょう。

自分は会社近くの飲食店をGoogleスプレッドシートでリスト化して、
ランダムで１件返してくれるようにしてお昼どこにいくかを決める使い方をしています。

## GASの実行ログを確認したい場合
GASプロジェクトにGCPプロジェクトの設定をすることで確認ができます。
console.logなんかで出力した結果もこちらから確認可。
![スクリーンショット 2024-02-18 14.13.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/3852335e-ca00-18da-fbb9-dcd8748c89bf.png)