GithubのissueをSlackに通知する方法1(Heroku + botkit)

初めての投稿につき、やさしい心で見て頂けると嬉しいです。
自分のメモ用を再編集したもので、不備が多いかと思いますが、誰かの役に立てば幸甚です。
 ~~細かい部分は覚えていない~~ 初期設定など情報が多々ある部分は、所々省略しています。

# やりたいこと
* Githubのissueを横断的にSlackで見たい
 * ID、タイトル、author、URL、reactionの数(投票などをするため)
* せっかくなので、RESTAPIではなくGraphQLを使ってみたい

# 2018/6/28 追記
* AzureFunctions+Webhook版もやってみました。
* [GithubのissueをSlackに通知する方法2(AzureFunctions+WebHook)] (https://qiita.com/kazutxt/items/b067261c10c001424a88)

# イメージ
![shg.png](https://qiita-image-store.s3.amazonaws.com/0/259228/5c9901f5-9219-c8db-bd13-4a14b210850d.png)

# 動作環境
* MacOS 10.13.5
* botkit ^0.6.14
* git-graphql-client 1.0.0
* heroku 無料プラン
* Slack 無料プラン
* Github 無料プラン

# STEP1 herokuにアカウントを作る
* herokuはPaaSで、アプリケーションをデプロイするだけでプラットフォームより下のレイヤーの設備はすべて準備してくれるサービスです。
* 今回は、無料枠 && node.js && workerを利用します。
* アカウントの作成や資材のアップロードは様々な先人の方がノウハウを残しているので省略します。
 * 手抜きでごめんなさい。先人方の記事を参考にされるとよいと思います。
 * https://qiita.com/Arashi/items/b2f2e01259238235e187
 * https://webbibouroku.com/Blog/Article/heroku-getting-started

# STEP2 Slackからbot用のtokenを払いだす
* 日本語化している場合は、slackをカスタマイズ ⇒　App管理　⇒ カスタムインテグレーション　⇒ Botsからいけます
* 細かい手順は、こちらも様々な先人の方がノウハウを残しているので省略します。
 * 手抜きでごめんなさい。先人方の記事を参考にされるとよいと思います。(2回目)
 * https://qiita.com/NagaokaKenichi/items/e0715b6bdde8459a705c

# STEP3 GithubのPersonalAccessTokenを払いだす
* 細かい手順は、こちらも様々な先人の方がノウハウを残しているので省略します。
 * 手抜きでごめんなさい。先人方の記事を参考にされるとよいと思います。(3回目)
 * https://qiita.com/kz800/items/497ec70bff3e555dacd0
* 公開しているプロジェクトであれば、なにも権限がなくて大丈夫です

# STEP4 GraphQLのクエリを作成する
* 公式APIドキュメント：https://developer.github.com/v4/
* 動作を確認するエクスプローラ：https://developer.github.com/v4/explorer/

作成したリクエスト

* owner,name,labelsは自分の条件に合わせて使ってください
 * 今回は、ステータスがOpenで特定のラベルが付いたissueを集めました
 * 条件の追加をする場合は、()内を公式APIドキュメントをみてカスタマイズしてください

```
{
  repository(owner: "xxx", name: "yyy") {
    issues(last: 100, states: OPEN, labels: "zzz") {
      edges {
        node {
          number
          title
          url
          author {
            login
          }
          reactions(last: 100) {
            nodes {
              content
            }
          }
        }
      }
    }
  }
}
```

応答イメージ

```
{
  "data": {
    "repository": {
      "issues": {
        "edges": [
          {
            "node": {
              "number": 1,
              "title": "タイトル",
              "url": "https://github.com/XXX/YYY/issues/1",
              "author": {
                "login": "user"
              },
              "reactions": {
                "nodes": [
                  {
                    "content": "THUMBS_UP"
                  }
                ]
              }
            }
          }
        ]
      }
    }
  }
}
```

# STEP5 package.jsonを書く
最低限の名前とバージョン、依存関係としてrequest,botkit,github-graphql-clientを書く

```
{
 "name": "topic-bot",
 "version": "1.0.0" ,
 "dependencies": {
 "botkit": "^0.6.14",
 "github-graphql-client": "1.0.0"
 }
}
```

* botkit
 * https://github.com/howdyai/botkit
* girhub-graphql-client
 * https://www.npmjs.com/package/github-graphql-client

# STEP6 プログラム本体を記述する

```
// Botの準備
if (!process.env.token) {
	process.exit(1);
}
var Botkit = require('botkit');
var os = require('os');
var request = require('request');
var controller = Botkit.slackbot({ debug: false, });
var myquery = {上記のクエリ}
var mytoken = {取得したGithubのtoken};
var bot = controller.spawn({ token: {取得したSlackのtoken} }).startRTM((err, bot, payload) => {
 // topic-listに反応するイベント
	controller.hears(['topic-list'], 'direct_message,direct_mention,mention', function (bot, message) {
	var issues = [];
	var client = require('github-graphql-client');
  // githubに問い合わせ
	var request = client({
	token : mytoken,
	query : myquery
	},function(err,res){
	if(err){
	console.log("error");
	console.log(err);
	} else {
	// 成功した場合
	var resData = res.data.repository.issues.edges;

	for(i = 0; i < resData.length; i ++){
	　　var issue　= {};
	issue.number = resData[i].node.number;
	issue.title = resData[i].node.title;
	issue.url = resData[i].node.url;
	　　issue.author = resData[i].node.author.login;
	　　issue.reaction = resData[i].node.reactions.nodes.length;
	　　issues.push(issue);
	}
	// チャットに返信
	var result = ""
	for (i = 0; i < issues.length; i++) {
	var resultLine = "#" + issues[i].number + ":" + issues[i].title + " :studio_microphone: " + issues[i].author + " :+1:" + issues[i].reaction + "pt\n"　+ "detail: " + issues[i].url + "\n\n";
	result += resultLine;
	}
	bot.reply(message,result);
	}
	})
	});
});
```
* tokenなどはherokuの環境変数にいれ、読み込む方がより良いと思います。
* reactionsはtotalCountを使ってもOK
 * 今回は、個別の合計や特定の要素は不要で、全体数がほしいのでこのようにしています。

## 上手くいかなかったこと
* github-graphql-clientを使わず、requestだけでリクエストを投げていたのですが、エスケープなどいくら頑張ってもjsonparseエラーにな、うまくいきませんでした。


# STEP7 Herokuにあげて動作確認
* herokuのgitリポジトリにプッシュして、起動する
* Slack側でBotが在室中になったのを確認して、実際に呼ぶ

![botrep.png](https://qiita-image-store.s3.amazonaws.com/0/259228/69af8f25-cd52-38cd-8df4-f23ac948513b.png)

* NGなら、どこかでこけているので、ログを確認する


# ちょっと困ること
* herokuを使いっぱなしにすると、他のことに使えない(無料枠をこれだけで占有してしまう)
 * 方法2でAzureFunctionsとWebHookを使って同じことをする機能を紹介する予定です。
 * [GithubのissueをSlackに通知する方法2(AzureFunctions+WebHook)] (https://qiita.com/kazutxt/items/b067261c10c001424a88)