SlackのSlash Commands作成のベストプラクティスを考える

今回作るのはSlackのSlash Commandsを使った、簡単な翻訳コマンドを作ってみます
まずはSlackオリジナルコマンド作成にあたって、どういう実現方法がベストかを考えてみました
 
### 候補① Lambda
よく検索候補にも上がりますね。
なんですが、、、AWSのアカウントが必要。IAMの権限作成、ソース管理〜デプロイまで乖離する可能性が有る。などなど意外と面倒です。実際DBやS3の連携など応用効くのですが、オレオレ管理にもなりがちなので今回はパス！ ~~なんでもかんでもLambda使うなー！~~

### 候補② Firebase
無料プランは外部APIを叩けないんですよね。。。今後のオリジナルコマンド作成を考えると別のものの方が良さげ

### 候補③ Google Apps Script
ソース管理しにくいが、応用は効きそう（スプレッドシート、メール、カレンダー連携など）。claspを使えばソース管理やデプロイなど簡単になるらしい！

### Heroku
ソース管理〜デプロイしやすい。言語やDBの選択が多い。だけど、やりたいことに対して規模が大きくなりそう。Heroku独自の仕様で詰まるかもしれない


### 結論：Slackと親和性が高いGoogleのGoogle Apps Scriptを使うことにしました！

## 作成にあたっての参考サイト

ほぼこちらのサイトを参考にさせて頂きました
[Slash CommandsとGASでSlackのオリジナルコマンドをつくる](https://qiita.com/chikuwa111/items/7a1a349b82318a5861cc)

clasp公式
https://github.com/google/clasp

## 構築手順

### Macにclaspをグローバルインストール
```
sudo npm install -g @google/clasp
```

### GASプロジェクト作成
```bash

mkdir [project]
cd [project]
clasp create [project]
```

どのscriptを作成するか聞かれるのでwebappを選択

```bash
? Create which script? (Use arrow keys)
  standalone 
  docs 
  sheets 
  slides 
  forms 
❯ webapp 
  api
```

gsファイルを補完するためにnpmパッケージインストール

```
npm init -y
npm i @types/google-apps-script --save-dev
```

プロジェクトを開くとgsファイルが作成されるのでpull

```
clasp open

clasp pull
```

### Slack連携ファイル作成

今回作るコマンドは翻訳コマンド  
「/honyaku This is Pen」と入力すると「これはペンです」と返ってくるものを作ります。
ソースファイルの対象フォルダをsrcに変更しinde.jsを作成

.clasp.json

```json
{
    "scriptId": "XXXXX",
    "rootDir": "src"
}
```

src/index.js

```js
/**
 * GASプロジェクトのプロパティー（環境変数）
 */
SLACK_VERIFICATION_TOKEN = PropertiesService.getScriptProperties().getProperty("SLACK_VERIFICATION_TOKEN");

/**
 * GETリクエスト
 * 
 * @param {any} e 
 * @return {GoogleAppsScript.Content.TextOutput} text
 */
function doGet(e) {
    return ContentService.createTextOutput('slack-tool v1')
}

/**
 * POSTリクエスト
 * 
 * @param {any} e 
 * @return {GoogleAppsScript.Content.TextOutput} json
 */
function doPost(e) {
    var verificationToken = e.parameter.token
    var command = e.parameter.text

    if (verificationToken != SLACK_VERIFICATION_TOKEN) {
        throw new Error('Invalid token')
    }

    var text = ''
    switch (true) {
        case /^honyaku/.test(command):

            var args = command.split(/^honyaku /)[1]
            text = LanguageApp.translate(args, 'en', 'ja')
            break;
        default:

            text = '正しくコマンドが指定されませんでした'
            break;
    }


    var response = { text: text }

    return ContentService
        .createTextOutput(JSON.stringify(response))
        .setMimeType(ContentService.MimeType.JSON)
}
```

ソースファイルを編集後push

```bash
clasp push
```

GitHub等に秘匿情報をそのまま上げるのはセキュリティー的に宜しくないので、GASプロジェクトにプロパティー（環境変数）を追加して、それを使用しましょう。

### 外部APIとして公開

1. webappとして公開するにはスプレッドシートから直接公開する必要があるので`clasp open`
2. openしたgasファイル上で「ウェブアプリケーションとして導入」を選択。
  バージョンも最新でなければ反映されないので、Project versionを「New」、Who has access to the appを「Anyone even anonymous」で公開する。  
本当は外部APIとしてアクセス権を設定しないのは良くないのですが、簡単なコマンドなので今回は保留

## VS CodeのREST Clientで動作確認

Rest Client用ファイルを作成  
どうやらリダイレクトされているようなのでリクエスト後のLocationを受け取って、さらにそこにアクセス

.vscode/gas.rest

```
@deployKey = XXXXX

###
# @name gas_post
POST https://script.google.com/macros/s/{{deployKey}}/exec
?token=XXXXX
&text=honyaku This is Pen

###
# @name gas_post_location
GET {{gas_post.response.headers.Location}}
```

ちゃんと返ってきてる

```json
{
  "text": "これはペンです"
}
```

Slackで確認するといい感じに返ってきました！

GitHubに登録

```bash
git init
git touch .gitignore
echo ".vscode" >> .gitignore
echo ".clasp.json" >> .gitignore
echo "node_modules" >> .gitignore
git add -A
git commit -m "init commit"
git remote add origin git@github.com:[user]/[project].git
```

実際作ったコマンドのソース
https://github.com/okdyy75/slack-tool

### 感想

GAS便利になりましたね！clasp良い！
ただwebappのデプロイやプロジェクトプロパティー（環境変数）の設定がコマンドから作成できないのがちょっと使いづらいですね。今後に期待！