【入門】Google Apps Scriptチュートリアル1/2（デモ動画付き・①doGet()とdoPost()でHellow World!）

# 0.表題の背景

業務でGoogle Apps Scriptを使っているので、なんか自分で作りたい
→**サーバーレス**なBOTを作りたい。
→→**無料**がいい。

ということで、Google Apps ScriptでSlack BOTを作ることにチャレンジしました。

その結果、Google Apps Scriptのお作法は言わずもがなとして、HTTPやらAPIと色々触ることが出来ました。

そこでApps Scriptの基本的な書き方からBOTの作成手順を忘れないうちに、デモ動画や画像を適宜交えながらご紹介します。


**本記事では、以下のことを取り上げます。**
**[1.最終的に出来上がるSlack BOTの機能](#1最終的に出来上がるslack-botの機能)**
 1-1.デモ
 1-2.要件をざっくりと
 1-3.構成図はこんなかんじ

[**2.使用するサービス、技術、フレームワークなど**](#2使用するサービス技術フレームワークなど)
 2-1.使っているもの
 2-2.特筆するべき使っていないもの

[**3.作成手順**](#3作成手順)
 3-1.doGet()とdoPost()でHellow World!

**Appendix**
[ワークスペースの作成](#ワークスペースの作成)
[Appの作成](#appの作成)
[BOTの作成](#botの作成)
[BOTをチャンネルに追加](#botをチャンネルに追加)
[Scriptエディターを新規で作成する2つの方法](#scriptエディターを新規で作成する2つの方法)
[スクリプトをウェブアプリケーションとして登録し、Slash Commandsを登録](#スクリプトをウェブアプリケーションとして登録しslash-commandsを登録)



**次回は後編として以下の内容を取り上げます。**
 3-2.doGet()とdoPost()でオウム返しBOTを作る
 3-3.curlでSlack APIを叩き、チャンネル情報を取得
 3-4.スプレッドシートにチャンネル情報を入力
 3-5.スプレッドシートからチャンネル情報を取得し、responseを生成
 3-6.完成

**Appendix**
userにメンションを飛ばす方法(2019/04/30現在)



#1.最終的に出来上がるSlack BOTの機能
##1-1.デモ
![navigate.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/d93d2bd5-45ca-c594-dd17-a30746b328a0.gif)

##1-2.要件をざっくりと
・**/navigate**とslackの任意のチャンネルの投稿画面で打ったら、ワークスペースに登録されている**パブリックチャンネルと各チャンネルの参加者数**がコマンドを叩いた者だけに表示されること

・表示される**パブリックチャンネルと各チャンネルの参加者数**は事前に**Slack API**を使ってスプレッドシートに書き出しておくこと

##1-3.構成図はこんなかんじ↓
①コード.gs(GithubではchannelList.js)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/76a81886-48ca-06b4-c90b-9b762ebf9b7d.png)
ソースコード：[channelList.js](https://github.com/gkzz/gas-handson/blob/devel-generateResponse/channelList.js)

②getChannels.gs(GithubではgetChannels.js)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/d161a5cd-1c0c-1722-a3b4-1c5a5c8bbaf8.png)
ソースコード：[getChannels.js](https://github.com/gkzz/gas-handson/blob/master/getChannels.js)



#2.使用するサービス、技術、フレームワークなど
##2-1.使っているもの
- Google Apps Script
 - doGet()とdoPost()
- Slack API
 - conversations.list Method
- Incoming Webhook URL
- Slash Commands

##2-2.特筆するべき使っていないもの
**Outgoing Webhook URL**はslackでは推奨されていない機能なので、使っていません。
代替サービスとしてSlash Commandsを採用しています。
両者の相違点は、コマンドを叩いたユーザーに対してのみ、Slash Commandsで登録したコマンドを叩いた後に表示される出力結果が表示されるという点です。


#3.作成手順
##3-1.doGet()とdoPost()でHellow World!
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/5a2f34e2-9e41-97d5-5c95-89f67c498ae7.png)

###3-1-1.AppのVerification Tokenを取得

以下のURLから今回使いたいAppを選択するか、新たに作成してください。
新たに作成する場合、APPを作成する様子を撮ったデモ動画と手順をAppendixで取り上げているのでご参照ください。
[https://api.slack.com/apps](https://api.slack.com/apps)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/3d55652e-6c98-acbe-64bc-f3f308f2b153.png)


- 参考：Appendix
 - [ワークスペースの作成](#ワークスペースの作成)
 - [Appの作成](#appの作成)
 - [BOTの作成](#botの作成)
 - [BOTをチャンネルに追加](#botをチャンネルに追加)


Appのページの下部にある**Verification Token**をコピーしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/fc7a8bdd-963d-1404-cfb6-dc8b53189e51.png)




###3-1-2.とりあえずコピペ！

コードをコピペ、、、の前にコードをコピペする場所となるApps Scriptのエディターを開く必要があり、エディターの開き方は2種類あるのでそこから。

エディターは任意の場所から右クリックで**Google Apps Script**を選択するか、スプレッドシートを開いた後、上タブの**Tools**から**Script Editor**を選択して開きましょう。

・任意の場所から右クリックで**Google Apps Script**を選択する（直接Google Apps Scriptを開く）
![openScriptEditor.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/a95f4aee-6ea0-e7bd-cf33-51dbb59c2484.gif)

・スプレッドシートを開いた後、上タブの**Tools**から**Script Editor**を選択して開く
![openScriptEditorWithSs.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/5192d988-f55c-8baf-e6d2-ce804361f443.gif)


※エディターの開き方によってスプレッドシートを開く方法が異なるので、興味がある方はAppendixをどうぞ。

- 参考：Appendix
 - [Scriptエディターを新規で作成する2つの方法](#scriptエディターを新規で作成する2つの方法)

Apps Scriptのエディターを開いたら、以下のコードをコピペしてください。

```
function doGet(e){
    doPost(e);
}

function doPost(e) {
    //先ほど取得したVerification Tokenをココに貼る
    const VERIFICATION_TOKEN = "<YOUR_APP_VERIFICATION_TOKEN>";
    var paramToken = e.parameter.token;
    if (paramToken != VERIFICATION_TOKEN) {
        throw new Error('Invalid token');
    }
    //お好きな言葉をどうぞ♪
    var response = {
        text: "Hellow World!"
        //text: "just published" 
    };
    return ContentService.createTextOutput(
        JSON.stringify(response)
    )
    .setMimeType(
        ContentService.MimeType.JSON
    );
}
```

さあ、いよいよ、今回一番の山場がやってきました(笑)。
がんばりましょう！

###3-1-3.ウェブアプリケーションとして登録/Deploy as web app
Scriptエディター上の**Publish(公開)**、続いて**Deploy As Web App(ウェブアプリケーションとして導入)**をそれぞれクリックしてください。
クリックした後、Project version(プロジェクトバージョン)を**New(新規)**として、Who has access to the app(アプリケーションにアクセスできるユーザー)は**Anyone, even anonymous(全員（匿名ユーザを含む）)**と設定しましょう。
![publish.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/ade82495-75c5-d887-b9b7-8c06370a4ae4.gif)


####Q. なぜ**Anyone, even anonymous(全員（匿名ユーザーを含む）)**？####
A. slackでコマンドが叩かれたときに、Googleアカウントを持っていないSlackがアプリケーションにアクセスすることになるためです。つまり、ここでの**anonymous(匿名ユーザー)とは、Googleアカウントを持たないユーザー**となります。

※Scriptを書き換えたら都度上のデプロイをやらないといけません汗。
※なお、Scciptを変えた後、上のデプロイをしても後述するslack側での設定は不要です。何故ならCurrent web app URLは変わらないためです。

※上の動画(GIF)では登録後、**Current web app URL**をコピーしていますが、みなさんもコピーしておいてください。
次にご説明するslack側での**slash comamnds**の設定でURLを貼る必要があります。


**もうだめだ、、。ワケわからん、、、。**
もし、このあたりでつまずいたら、以下のAppendixを参考に再度チャレンジしてください！

- 参考：Appendix
 - [スクリプトをウェブアプリケーションとして登録し、Slash Commandsを登録](#スクリプトをウェブアプリケーションとして登録しslash-commandsを登録)

###3-1-4.Slash Commands
以下のURLから先ほど取得したVerification TokenのAppをクリック。
[https://api.slack.com/apps](https://api.slack.com/apps)
クリック後、下の画像の青線で囲んだ、**Add features and functionality**をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/64e8fc5d-1cb0-3729-ee3d-1e8a53c88ea7.png)

同様に下の画像の青線で囲んだ、**Slash Commands**をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/2bddb735-b227-833d-98de-1769fda7e187.png)

下の画像の青線で囲んだ、**Create New Command**をクリック。
※既存のSlash Commandsの設定を変更する場合は**鉛筆マーク**をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/e32fa3d6-6fc1-597f-13cc-203ec953ae1b.png)

下の画像の青線で囲んだ、**Request URL**の右隣の枠内に先ほどの**Current web app URL**を貼り付けてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/5618dc90-39c8-5131-15c2-0f8527247071.png)

他はみなさんの好きなように入力していただいてOKですが、ご参考までに私の設定画面を共有します。
**※コマンドの冒頭(一文字目、一番左)には"/"が必要**なので、お忘れなく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/186fdafc-61fc-a28a-3ff0-dfadbcfbe4dd.png)



###3-1-5.さあ、slackの投稿画面で叩いてみよう！
```
#"/" + <slash commandsで登録した文字列> 
/navigate
```
を叩いたら

```
#<変数responseに格納した値>
Hello World
//just published
```

が表示されたらOK！

Congrats!!

おめでとうございます！！！
そしておつかれさまでした！


次回はresponseの中身を書き換えていくので、次回もお楽しみに♪


#Appendix

##ワークスペースの作成
以下のURLをクリックして、デモ動画を参考に作ってみてください。
[https://slack.com](https://slack.com)
参考：デモ動画
![addWorkspace.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/237c4dd5-0b84-4c89-5482-fe13345abee7.gif)


##Appの作成

以下のURLをクリックしてデモ動画を参考に作ってみてください。

https://<YOURWORKSPACE>.slack.com/apps

![addApps.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/6fe954cc-6a46-6ab8-8373-b90ce701cbfa.gif)


※この画像で青く塗りつぶされている部分は、先ほど作ったワークスペースごとに異なります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/2cecd8d7-79b5-a7d8-7a7a-234555aa36b9.png)

直接以下のURLを叩いてもAppの追加ページに行けますが、　僕はワークスペースのページをブックマークしているので、https://<YOURWORKSPACE>.slack.com/messages のmessagesを消してappsを入力しています。
https://api.slack.com/

##BOTの作成
Appを作成したら、続けて下記のデモ動画を参考にBOTも作ってみてください。
![addBOT.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/d0cdf30e-c2f7-3ca9-1720-28e8b62c9cea.gif)

##BOTをチャンネルに追加
ワークスペースの画面に戻って、APPをお好きなチャンネルに追加してください。
![registerBOTAsMember.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/070a149e-23f6-e4df-5b1b-d166e9211cbc.gif)

##Scriptエディターを新規で作成する2つの方法
Googleドライブから直接Scriptエディターを新規で開いた場合（スプレッドシートと紐づけることなく）、スプレッドシートのセルの値やシートの名前などスプレッドシートを操作するには、**どのスプレッドシートを操作するか**指定する必要があります。
下の画像は、操作する対象のスプレッドシートを指定することなく、スプレッドシートの一番左のシート名をLoggerメソッドで表示させようとしたところ、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/323df1ff-1a9b-cee7-45bb-a7cc4b7b4dd6.png)

>TypeError: Cannot call method "getSheets" of null. (line 3, file "Code")

とnullとエラーを吐かれてしまいました汗。
Scriptエディターをスプレッドシートに紐づけることなく、新規で作成したうえで、スプレッドシートを操作する場合、スクリプトのシートオブジェクト（the active Spreadsheet object, 本スクリプトではss）を取得する部分を以下のように改修してください。

```
function myFunction() {
  //スプレッドシートとScirptエディターが紐づいている場合に利用
  //var ss = SpreadsheetApp.getActiveSpreadsheet();

  //SpreadSheetのIDはSpreadSheetのURLの"/d/"と"/edit"との間に連なる文字列
  //https://docs.google.com/spreadsheets/d/<YOUR_SPREADSHEET_ID>/edit#gid=0
  var ss = SpreadsheetApp.openById("<YOUR_SPREADSHEET_ID>");
  var sheet = ss.getSheets()[0];
  Logger.log(sheet.getSheetName());
}
```

>getActiveSpreadsheet()
>Returns the currently active spreadsheet, or null if there is none.
[...]

>```
>// The code below logs the URL for the active spreadsheet.
>Logger.log(SpreadsheetApp.getActiveSpreadsheet().getUrl());
>```

出所：[Class SpreadsheetApp | Apps Script | Google Developers](https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app#getActiveSheet())

##スクリプトをウェブアプリケーションとして登録し、Slash Commandsを登録
![registerSlashCommands.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/28cced72-470d-f13b-dbaa-45f7f0806023.gif)

>Scriptエディター上の**Publish(公開)**、続いて**Deploy As Web App(ウェブアプリケーションとして導入)**をそれぞれクリックしてください。
クリックした後、Project version(プロジェクトバージョン)を**New(新規)**として、Who has access to the app(アプリケーションにアクセスできるユーザー)は**Anyone, even anonymous(全員（匿名ユーザを含む）)**と設定しましょう。

[本記事 ###3-1-3.ウェブアプリケーションとして登録/Deploy as web app](###3-1-3.ウェブアプリケーションとして登録/Deploy as web app) より

##Q. xoxbのtokenがない、、、。
A. **Add BOT UserからBOTを追加**しましょう。追加するとpermissionのページにBOT用のtokenが表示されると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/c692b843-3342-85bf-3984-32e755ec2670.png)

##Q. BOTとAPPの違いは？
A. **APPにユーザーと会話をする機能を追加したものがBOT**と認識しています。ご参考までにslackのドキュメントから僕が参考にした箇所を引用します。

>A bot is a type of Slack App designed to interact with users via conversation.

>A bot is the same as a regular app: it can access the same range of APIs and do all of the magical things that a Slack App can do.

出所：[Enabling interactions with bots | Slack](https://api.slack.com/bot-users)


####xoxpトークンとxoxbトークンではこのようにスコープの設定範囲
xoxpとxoxbとではスコープの設定範囲が異なります。
xoxbトークンでconversations.listを使う際には、botのみscopeに追加すればよいのです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/e20a45d4-be20-6434-0c04-e82efce4c4cc.png)

####soopeの設定範囲
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341653/5f814cb2-5054-28c2-3181-617ddeee6088.png)


**ソースコード**
[channelList.js](https://github.com/gkzz/gas-handson/blob/devel-generateResponse/channelList.js)
[getChannels.js](https://github.com/gkzz/gas-handson/blob/master/getChannels.js)

**参考**
下記の記事は、今回の実装をするうえでdoGet(), doPost(), Slash Commandsの概要を知るうえで参考にしました。
[Slash CommandsとGASでSlackのオリジナルコマンドをつくる](https://qiita.com/chikuwa111/items/7a1a349b82318a5861cc)

**後編**
[【入門】Google Apps Scriptチュートリアル2/2（デモ動画付き・②コマンドを叩いてチャンネル情報を表示させる）]
(https://qiita.com/gkzz/items/e63f8d86b6c253a5cd26)

**番外編**
[【入門】Google Apps Scriptチュートリアル1/2（デモ動画付き・①doGet()とdoPost()でHellow World!）](https://qiita.com/gkzz/items/2003f46612a4fd3a3b7f)


P.S. Twitterもやってるのでフォローお願いします！
[@gkzvoice](https://twitter.com/gkzvoice)