[*Slack*] Google App Scriptを使って経費申請を行うSlackアプリを作る方法

# はじめに
こんな感じのSlackアプリを作る方法です。
経費申請をActionから行う必要は全く無いので、記事用のいい例が思いつかなかっただけです。（経費申請なら`Interactive messages`を使ったほうが自然そう）
![1xbnr-el9fk.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/3f6c000f-5759-a1a1-9916-74007d2252bb.gif)
今回は`Google App Script`で処理自体は書いていきます。

# 作成方法
## 処理を書くファイルの作成
今回は`Google App Script`を使用するので、`Google Drive`から`Google App Script`を選択してスクリプトファイルを作成する。
![01_gas.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/069133c1-526f-ca6d-39ab-fca4ed233181.png)

一旦このまま何もせずに`ウェブアプリケーションとして導入...`をクリックする。
![02_gas.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/b7bd6571-1bb5-dee7-1c9e-15d70495e211.png)

`アプリケーションにアクセスできるユーザー`を`全員（匿名ユーザーを含む）`にして`導入`をクリックする。
![03_gas.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/f6c64482-080e-9d5b-9866-9acf4a57499f.png)

`現在のウェブアプリケーションのURL`はどこかにコピーしておく。
![04_gas.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/477e4380-25a9-be4d-11f8-1a9db9c51d61.png)

## Slack App側の設定
### アプリの作成
[slack api](https://api.slack.com/)にアクセスし、
右上の`Your Apps`をクリックし、`Create New App`をクリックする。
作成するアプリの情報を入力して`Create App`をクリックする。

* `App Name`・・・アプリの名前
* `Development Slack Workspace`・・・アプリを使用するワークスペース
![05_create_app.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/3c05e94e-5741-78c4-171a-f474cb2bf943.png)

### Incoming Webhooksの設定
メッセージをSlackに投稿するための設定。

左側のメニューから`Incoming Webhooks`をクリックし、`Activate Incoming Webhooks`を`On`に変更する。

下の方の`Webhook URLs for Your Workspace`の`Add New Webhook to Workspace`をクリックする。
![06_create_webhook.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/2617bbed-5d0e-0653-de5c-d20ec39b7108.png)

メッセージの投稿先のチャンネルを選択し、`許可する`をクリックする。
![07_permission.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/fd748817-bdcf-3d0a-0d8b-f4b08d0a626b.png)

こんな感じに`Webhook URL`が追加される。
![08_webhook_url.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/a2aa7c71-a7d4-5e1d-45eb-2b01ceb9adb8.png)

投稿先のチャンネルを選択し、`許可する`をクリックする。

### Interactive Componentsの設定
今回はメッセージのメニューから申請画面を立ち上げるのでその設定を行う。

左側のメニューから`Interactive Components`をクリックし、`Interactivity `を`On`に変更する。
`Request URL`には`Google App Script`をウェブアプリケーションとして公開したときのURLを入力する。
![09_interactivity.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/72708136-bcc8-1239-7009-c68d30f7a720.png)

`Actions `のところから`Create New Action`をクリックし、以下を入力して登録する。

* `Action Name`・・・メニューに出てくるアクション名
* `Short Description`・・・短いアクションの説明
* `Callback ID`・・・このアクションが行われた際のペイロードに含まれるコールバックID
![10_add_action.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/0080bc64-87f2-d715-23e0-a91f84e7cbcb.png)

以下のようにアクションの登録が完了する。
![11_done_action.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/12cc8130-d784-9d2a-e713-e8c0fe88a974.png)

### Bot Userの設定
今回のアプリで使用するボットを作成する。

左側のメニューから`Bot Users`をクリックし、以下を入力して登録する。

* `Display Name`・・・表示名
* `Default username`・・・ユーザー名
![13_add_bot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/42340e40-7977-0094-7ee2-cd22deb0c076.png)

### OAuth & Permissionsの設定
どのAPIの使用を許可するかなどの設定。

以下のように設定する。
![14_scope.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/c718e213-8936-ac6f-5305-b6bb8200e4c9.png)

### アプリの再インストール
以下のようなメッセージが上に出ていると思うので、`click here`をクリックしてワークスペースにアプリを再インストールする。
![スクリーンショット 2019-05-25 9.52.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/82882bb1-eb27-16b7-e798-30a55d0f105f.png)
![15_reinstall.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/3da6e57c-42fb-0584-9348-e226803c51ca.png)

## 処理の作成
`Google App Script`を編集して、具体的な処理を作成する。

```js
/**
* Slackからのリクエストを受ける処理
*/
function doPost(e) {
  var params = e.parameter;
  var data = params.payload;
  var json = JSON.parse(decodeURIComponent(data));
  var type = json.type;
  var trigger_id = json.trigger_id;
  var response = {};
  
  if (type === 'message_action') {
    // メッセージアクションがあった場合の処理
    var url = 'https://slack.com/api/dialog.open';

    // トークン
    var token = 'xoxp-xxxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxx';

    var payload = {
      "token": token,
      "trigger_id": trigger_id,
      "dialog": JSON.stringify({
        "callback_id": "dialog",
        "title": "経費申請",
        "submit_label": "申請",
        "notify_on_cancel": true,
        "state": "Limo",
        "elements": [
          {
            "type": "text",
            "label": "申請者名",
            "name": "name",
          },
          {
            "type": "text",
            "label": "金額",
            "name": "amount",
            "subtype": "number"
          }
        ]
      })
    };
    
    var headers = {
      "Authorization": "Bearer " + token
    };
    
    var options = {
      "method" : "post",
      "headers": headers,
      "payload" : payload
    };
    
    UrlFetchApp.fetch(url, options);
    return ContentService.createTextOutput();
    
  } else if (type === 'dialog_submission') {
    // ダイアログでサブミットボタンを押したときの処理
    var url = '[Incoming Webhooksで作成したWebhook URL]';
    
    var payload = {
      "attachments": [{
            "color": "#36a64f",
            "pretext": "以下で経費の申請がありました。",
            "fields": [
              {
                "title": "申請者名",
                "value": json.submission.name,
                "short": false
              },
              {
                "title": "金額",
                "value": json.submission.amount,
                "short": false
              }
            ]
        }
      ]
    };  
    
    var options = {
      "method" : "post",
      "contentType" : "application/json",
      "payload" : JSON.stringify(payload)
    };
    
    response = UrlFetchApp.fetch(url, options);
    return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
  }
}

```

スクリプトに出てくるトークンは`OAuth & Permissions`の`OAuth Access Token`に記載されているものを指定。
![16_token.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/0541556f-7205-2456-bde2-9cc3cbf4528f.png)

再度、新しいバージョンのウェブアプリケーションとして公開し直さないといけないため、`プロジェクトのバージョン`を`New`にして登録する。
![17_gas.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/9a005aa6-46e5-380f-a6f8-e514e825719d.png)

承認が必要と出るので承認を行う。
![18_gas.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/3a8d459b-62f3-615b-d1e1-50b24d19552a.png)

## アプリの画像などを設定する
アプリのアイコン画像などを設定する。

`slack api`の左側のメニューから`Basic Information`をクリックし、`Display Information`でアプリ名やアプリ画像を設定する。
![19_info.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/5b982201-ff28-42c9-01f7-c8b2bd98a17f.png)

## 動作確認
メッセージの「・・・」をクリックする。
![20_message.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/472ebf45-abaa-8349-1912-2ac05d7d6b26.png)

`経費申請`をクリックする。
![21_action.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/c9b8c76a-b89d-2b8e-5893-89ee46624492.png)

するとダイアログが表示されるので、情報を入力して、`申請`をクリックする。
![23_dialog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/217205e6-d4b4-060a-b12a-bbc372f91b1b.png)

投稿先として設定したチャンネルに入力した情報が投稿される。
![24_message.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48912/0247c7da-a672-0276-d9e0-60be62151faa.png)

# おわりに
ダイアログがなかなか表示できなくてAuthorizationヘッダーつけないといけないことに気づくまで時間がかかった。

今回は単に申請内容をSlack上に投稿する形にしましたが、実際はGASからスプレッドシートに書き込んだり、その他のサービスを経由してどっかに登録したり・・・をすれば良いと思います。

# 参考
* [Slack メッセージ・アクション API を使ってディスカバラブルなアプリを作ろう](https://qiita.com/girlie_mac/items/21fedcc6ce07aa44a670)
* [Defining and handling message actions](https://api.slack.com/actions)
* [dialog.open](https://api.slack.com/methods/dialog.open)
* [Interacting with users through dialogs](https://api.slack.com/dialogs#text_elements)
* [Making messages interactive](https://api.slack.com/interactive-messages)