OK Google！ プルリク教えて！

# はじめに
この記事は [C# Advent Calendar 2018](https://qiita.com/advent-calendar/2018/c-sharp) 1日目の記事です。
前からやろうと思っていたGoogle Homeの開発をC#を使ってやってみました。

ここで作成したサンプルアプリはGitHubにあげています。
興味のある方は使ってみてください。
https://github.com/TomoProg/GoogleHomeGitHub

この記事では利用したサービスについての詳細を書いていないため、
各サービスの詳細を知りたい場合は別の記事を見ることをおすすめします。

また、各サービスのアカウントは作成してある前提で話を進めています。
参考にする場合はアカウントを作成してから参考にしてみてください。

それでは頑張っていきましょう。

# 開発環境および使用したサービスやパッケージなど
- Windows10
- Microsoft Visual Studio 2017 Community 
- Actions on Google
- Dialogflow
- Azure Functions
- octokit.net

# 全体構成
構成としてはこんな感じです。
![GIF2.gif](https://qiita-image-store.s3.amazonaws.com/0/68663/b59c9b03-27eb-0de7-9c4a-8e5929cf8c42.gif)

C#を書くのはAzure Functionsの中だけなので、ほとんどC#書かないです。笑

# STEP1 Actions on Googleでプロジェクトを作成する
まずは[ここ](https://console.actions.google.com/u/0/)にアクセスして`Actions on Google`のプロジェクトを作成します。
`Add/import project`を押すと以下のような画面が現れるので、

- プロジェクト名
- 言語
- 地域

を選択してプロジェクトを作成します。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/68663/bca5b1aa-1aba-03fd-c6eb-27376d0eee9e.png)
 
# STEP2 アプリを呼び出す言葉を決める
プロジェクトができたらまず、アプリの名前を決めましょう。
この名前でGoogle Homeに話しかけにいくので、アプリ名めっちゃ大事です！
![a1.png](https://qiita-image-store.s3.amazonaws.com/0/68663/63103756-79a8-829e-69b0-109f56203aec.png)

![a2.png](https://qiita-image-store.s3.amazonaws.com/0/68663/f70564ca-b644-17eb-813d-3731b45415cb.png)

と言いつつも「サンプルアプリ」という平坦な名前を設定しておきました。
これでGoogle Homeに「サンプルアプリにつないで」と言うとこのアプリにつなげるようになります。

# STEP3 Dialogflowのプロジェクトを作成する
次にDialogflowを設定していきます。
Dialogflowではこういう言葉が来たらこういう言葉を返すといった設定を行います。
`Actions`をから`ADD YOUR FIRST ACTION`を押し、`Custom Intent`を選択します。
![a3.png](https://qiita-image-store.s3.amazonaws.com/0/68663/d608d71e-d94c-7eff-562b-e71d875aa8f8.png)
![a4.png](https://qiita-image-store.s3.amazonaws.com/0/68663/7c4a078f-343e-6b58-6930-90acc59fcf0b.png)

そうするとDialogflowの画面が現れるため、今度はここで作業を行います。
言語とタイムゾーンを選択し、CREATEを押すとDialogflowの新しいプロジェクトが作られます。
![a5.png](https://qiita-image-store.s3.amazonaws.com/0/68663/270e7730-17e1-ee1c-12e9-dbf260f403e4.png)

# STEP4 DialogflowでIntentの作成を行う
`Intent`を作成することで応答を自由に作成することができます。
`Intent`から`CREATE INTENT`を押すと新しい`Intent`を作成することができます。
![a6.png](https://qiita-image-store.s3.amazonaws.com/0/68663/10d447fb-eb61-890c-01ef-4e955e3d5e1a.png)

ちなみに`Default Fallback Intent`には`Intent`に無い言葉を言われたときに返す言葉（「聞き取れませんでした。」「わかりません。」など）が定義されており、`Default Welcome Intent`にはアプリが起動したときに返す言葉（「こんにちは。」など）が定義されているようです。

`Intent`の作成画面では`Training phrases`に自分が話す言葉を、`Responses`にGoogle Homeのレスポンスを書きます。
今回はプルリクを教えてもらうため、「プルリク教えて」というと言葉に対して「プルリクはタイトル１、タイトル２です」という言葉を返してくれるように設定しました。
![a7.png](https://qiita-image-store.s3.amazonaws.com/0/68663/b8cd13db-604a-525e-3702-2788c3c1f55f.png)

これでIntentの作成は完了です。

# STEP5 テストしてみる
`Actions on Google`にはシミュレータが搭載されているため、その場でテストすることができます。
`Simulator`を選択し、`START TESTING`を押すとテスト環境が立ち上がります。
実際に「プルリク教えて」を言うと先程設定した言葉が返ってくるはずです。
![a10.png](https://qiita-image-store.s3.amazonaws.com/0/68663/cc48aea3-25ca-7006-1816-d7259cc245ac.png)

これで「プルリク教えて」という言葉を受け取るGoogle Homeのアプリが完成しました。

# STEP6 Azure Functionsの開発を行う
このままだと永遠に「プルリクはタイトル１、タイトル２です」しか言えないので、
実際にプルリクをGitHubから取ってくるプログラムを作成していきます。

まずは`Visual Studio`で`Azure Functions`のアプリケーションを作成します。
`新しいプロジェクト`→`Azure Functions`を選択し、トリガーにはHTTPを選択します。
新しいプロジェクトに`Azure Functions`にない場合は、
Visual StudioのインストーラーからAzure関連の開発環境を追加してください。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/68663/30d4e199-205a-20f3-240d-a5f62d0381b0.png)
![2.png](https://qiita-image-store.s3.amazonaws.com/0/68663/0cc1b2cc-9008-3b26-618b-aeea5ea6e807.png)

`octokit.net`もインストールしていきます。
`octokit.net`はGitHubのAPIをC#から簡単に使用できるようにするパッケージです。
これはNugetパッケージで公開されているため、パッケージ管理からすぐにインストール可能です。
![3.png](https://qiita-image-store.s3.amazonaws.com/0/68663/a1102a83-b941-b2ff-e588-9703af22eb94.png)

処理の流れですが、以下のような流れで構成しました。

**1. 渡ってくるJsonを解析する**
**2. 解析内容からIntent名を取り出し、プルリクを確認するIntentかどうか確かめる**
**3. GitHubからプルリクを取得する**
**4. 取得したプルリクのタイトルをSSML形式で整形し、HTTP 200で応答を返す**

以下プルリクの情報が入ったクラスを取得し、SSML形式に変換している部分です。
breakタグを使うと指定した時間分読み上げを止めてくれるようです。
あと、やっぱりLinqって素晴らしいですね。

``` cs
IReadOnlyList<PullRequest> prs = await Client.PullRequest.GetAllForRepository(Account, Repository);
return string.Join("<break time=\"500ms\"/>", prs.Select(pr => $"<p>{pr.Title}</p>"));
```

というわけで、プログラムも完成したので、Azureに実際にデプロイします。
デプロイは超簡単で、発行ボタンを押すだけです。
![a12.png](https://qiita-image-store.s3.amazonaws.com/0/68663/e1547115-b082-fbe7-2def-d71c874b0119.png)
![a13.png](https://qiita-image-store.s3.amazonaws.com/0/68663/182cd156-6ab0-0fd4-b727-66324e22c737.png)

# STEP7 IntentにWebHookを設定する
このままだとまだプログラムを置いただけなので起動しません。
`Intent`に`Webhook`の設定を行うことで起動させられるようになります。
まずはWebhookのURLをAzure上で確認し、コピーしておきます。
![a16.png](https://qiita-image-store.s3.amazonaws.com/0/68663/55919a8e-47d4-c462-e432-6bb6f97cbae5.png)

次に`Intent`の`Webhook`を有効にします。
ついでに定型文はもう不要のため、消してしまいます。
![a14.png](https://qiita-image-store.s3.amazonaws.com/0/68663/a574275b-167c-1758-3626-c908d3d413b5.png)

最後にFulfillmentのWebhookを有効にし、先ほどコピーしたURLを貼り付けます。
![a15.png](https://qiita-image-store.s3.amazonaws.com/0/68663/ab166b30-9510-f274-364d-f7ff39369e67.png)

以上で準備完了です！

# 実際に動かしてみた
プルリクの状態はこんな感じ。
![a17.png](https://qiita-image-store.s3.amazonaws.com/0/68663/97984b73-1bac-4055-ff55-7b3c5d8bd84c.png)

さてどうなるのか・・・
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Google Homeからプルリク教えてもらった！<br>OK Google! プルリク教えて！ <a href="https://t.co/4hkde8Mskc">https://t.co/4hkde8Mskc</a> <a href="https://twitter.com/YouTube?ref_src=twsrc%5Etfw">@YouTube</a>さんから</p>&mdash; TomoProg (@tomoprog_xxx) <a href="https://twitter.com/tomoprog_xxx/status/1068856013355331584?ref_src=twsrc%5Etfw">2018年12月1日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

a３つはなかなかおもしろかった。笑

# まとめ
かなり大雑把にまとめましたが、とにかく動くものができてよかったです。
C#のアドベントカレンダーながらほとんどC#が出てこないことになってしまいましたが、
C#でこんなこともできるんだということが伝わればいいかなと思います。

それではまた。
TomoProg


# 参考サイト
・Google Home 買ったので、マッチョな男の人に喋らせました。(C#, Azure Functions)
https://github.com/chomado/GoogleHomeHack

・Google アシスタントアプリを開発する時に Fulfillment の先を C# で開発する方法（スマートスピーカーを遊びたおす会での LT 内容）
https://blog.okazuki.jp/entry/2018/06/28/141410

・Dialogflow入門
https://qiita.com/kenz_firespeed/items/0979ceb05e4e3299f313

・Octokit.NETによるGitHubへのアクセス
https://opcdiary.net/?p=27625

・Google Homeアプリ開発と申請方法～Actions on GoogleとDialogflowの使い方
http://www.kagua.biz/tool/jisaku/action-on-google-dialogflow.html