Youtube Data APIを使用して、Youtube Liveのコメントを取得する

# はじめに
これはC# Advent Calendar 2018の20日目の記事です。  
C#の基本文法を学び終えた後にやってみたことをアウトプットしようと思い記事を書いていきます。
この記事ではYoutube Data Api v3を使用し、C#でYoutube Liveのコメントの取得を行いたいと思います。

# 前提知識
- C#の基本文法を理解していること。

# 実行環境
- .Net Framework4.6.1
- Visual Studio 2017
- Windows10
- Google.Apis.Youtube.v3 v1.36.1.1226

# 準備
今回のプログラムではYoutube Data Apiを使用するので、Apiキーの有効化を行っていきます。  
## Apiキーの有効化
1. プロジェクトの作成  
まず、Google Cloud Consoleにアクセスし、プロジェクトの作成を行います。  
https://console.developers.google.com/?hl=ja  
プロジェクトの作成は画面左上を選択します。
![a1.JPG](https://qiita-image-store.s3.amazonaws.com/0/310693/1850795c-f5c0-1e02-97ab-86aa624e8518.jpeg)

すると以下のような画面になるため、新しいプロジェクトを選択します。
![a2.JPG](https://qiita-image-store.s3.amazonaws.com/0/310693/4a00a627-51cd-b58f-b23c-34e11039469d.jpeg)

ここでプロジェクト名を~~適当に~~入力し、作成を選択します。
![a3.JPG](https://qiita-image-store.s3.amazonaws.com/0/310693/2375e2d1-686d-910f-4ed1-63ff3590e165.jpeg)
2. プロジェクトの選択  
プロジェクトを作成すると再びこの画面に戻るため、先ほど作成したプロジェクトを選択します。

![a4.JPG](https://qiita-image-store.s3.amazonaws.com/0/310693/6178b714-01e5-7dca-2c8d-db85a13c70f2.jpeg)

左上のプロジェクト名が先ほど選択した名前に変更されていることを確認したら、次は左のメニューから「ライブラリ」を選択します。
![a5.JPG](https://qiita-image-store.s3.amazonaws.com/0/310693/1a22ebc3-9d82-2be8-7b41-9541214e758b.jpeg)

ライブラリから「Youtube Data API v3」を探し、選択します。
![a6.JPG](https://qiita-image-store.s3.amazonaws.com/0/310693/84db6699-6b48-2b62-3419-1a0efeeb9648.jpeg)
3. APIキーの有効化  
有効を選択します。
![a7.JPG](https://qiita-image-store.s3.amazonaws.com/0/310693/cf01a5e4-46b0-311c-50df-835c90fe5169.jpeg)
APIを使用するには認証情報を作成する必要があるため、「認証情報を作成」を選択します。
![a8.JPG](https://qiita-image-store.s3.amazonaws.com/0/310693/22acbb0a-2caa-7a01-66d3-9892b1dcf1fd.jpeg)
ここでAPIをどのような条件で使用するかを選択します。  
今回は「その他のUI」「一般公開データ」を選択します。
![a10.JPG](https://qiita-image-store.s3.amazonaws.com/0/310693/5c86cc02-fc35-1ad1-81a2-fc3761748911.jpeg)
必要な認証情報を選択すると、APIキーが発行されるのでメモしておきましょう。後程のプログラムで使用します。
 ![a11.JPG](https://qiita-image-store.s3.amazonaws.com/0/310693/d6cd7a73-d92d-0c27-ad97-719956d75510.jpeg)


これにて、Apiキーの有効化は終了です。  

## ライブラリーの追加
C#でYoutube Data Apiを使用するにはGoogle.Apis.Youtube.v3が必要なので、NuGetパッケージマネージャーから追加しましょう。  
1. NuGetパッケージマネージャーを起動します。  
2. 参照タブで、Google.Apis.Youtube.v3を検索します。  
![a12.JPG](https://qiita-image-store.s3.amazonaws.com/0/310693/f24ac781-45d4-90a7-c9ae-3c939ff18565.jpeg)
3. Google.Apis.Youtube.v3をインストールします。  
変更のプレビューが表示された場合は、Okを選択します。  


以上で準備は終了です。

# コメントの取得
Youtube Data APIを使用する準備ができたため、Youtube Liveのチャットを取得します。  

以下がコメント取得のプログラムです。~~例外処理がされていなかったり、非同期処理の命名規則に従っていませんが、見て見ぬふりをしてください。~~  

```C#:program.cs
using System;
using System.Threading.Tasks;
using Google.Apis.Services;
using Google.Apis.YouTube.v3;

static async Task Main(string[] args)
{
    var youtubeService = new YouTubeService(new BaseClientService.Initializer()
    {
        ApiKey = "APIキーを入力"
    });


    string liveChatId = GetliveChatID("動画IDを入力", youtubeService);

    await GetLiveChatMessage(liveChatId, youtubeService, null);

}
```


```C#:GetLiveChatID
static public string GetliveChatID(string videoId, YouTubeService youtubeService)
{
    //引数で取得したい情報を指定
    var videosList = youtubeService.Videos.List("LiveStreamingDetails");
    videosList.Id = videoId;
    //動画情報の取得
    var videoListResponse = videosList.Execute();
    //LiveChatIDを返す
    foreach (var videoID in videoListResponse.Items)
    {
        return videoID.LiveStreamingDetails.ActiveLiveChatId;
    }
    //動画情報取得できない場合はnullを返す
    return null;
}
```

```C#:GetLiveCHatMessage
static public async Task GetLiveChatMessage(string liveChatId,YouTubeService youtubeService,string nextPageToken)
{
    var liveChatRequest = youtubeService.LiveChatMessages.List(liveChatId, "snippet,authorDetails");
    liveChatRequest.PageToken = nextPageToken;
    
    var liveChatResponse = await liveChatRequest.ExecuteAsync();
    foreach (var liveChat in liveChatResponse.Items)
    {
        try { 
            Console.WriteLine($"{liveChat.Snippet.DisplayMessage},{liveChat.AuthorDetails.DisplayName}");
        }
        catch { }

    }
    await Task.Delay((int)liveChatResponse.PollingIntervalMillis);


    await GetLiveChatMessage(liveChatId, youtubeService, liveChatResponse.NextPageToken);
}
```
### mainメソッド
main文の上から見ていきましょう。  

```C#
var youtubeService = new YouTubeService(new BaseClientService.Initializer()
{
    ApiKey = "APIキーを入力"
});
```
ここでYoutubeDataAPIのリクエストを行うインスタンスを生成します。
今回は公開データを取得するため、APIキーを使用します。  

```C# 
string liveChatId = GetliveChatID("動画IDを入力", youtubeService);
```
自作メソッドを呼び出しています。
Youtube Liveのチャットを取得するにはLiveChatIDが必要です。
しかし、Youtubeの動画ページのURLにはVideoIDしか書いていないため、VideoIDからLiveChatIDを取得する処理が必要になります。  
https://www.youtube.com/watch?v=ここがVideoID です  
GetLiveChatIDメソッドでは、VideoIDからLiveChatIDを取得しています。

### GetLiveChatIDメソッド

```C# 
var videosList = youtubeService.Videos.List("LiveStreamingDetails");
```
ここで、何の情報を取得するか指定します。    


```C#
videosList.Id = videoId;
var videoListResponse = videosList.Execute();
```

動画IDを指定し、Executeメソッドで情報を取得します。  
その後は動画情報からLiveChatIDを返します。  

### GetLiveChatMessageメソッド
LiveChatIDを取得できたので、ようやくLiveのコメントを取得することができます。  

```C#
var liveChatRequest = youtubeService.LiveChatMessages.List(liveChatId, "snippet,authorDetails");
```
コメントを取得するには、LiveChatMessages.Listメソッドを使用します。  
ここで先ほど取得したLiveChatIDを引数に入れ、どんな情報を取得するかを第2引数にいれます。
今回はコメントを取得するにはsnippet、コメント送信者を取得するにはauthorDetailsが必要なため、この二つを使用します。  

```C# 
liveChatRequest.PageToken = nextPageToken;
await liveChatRequest.ExecuteAsync();
```
コメントの取得を行います。  
YoutubeDataApiでは、毎回すべてのコメントを取得するのではなく、前回取得したコメントの続きだけを取得することができます。前回どこまで取得したかを管理する方法として、ページトークンを使用しています。  

``` C#
foreach (var liveChat in liveChatResponse.Items)
{
try { 
    Console.WriteLine($"{liveChat.Snippet.DisplayMessage},{liveChat.AuthorDetails.DisplayName}");
}
catch { }
}
```
取得したコメントを出力します。  

``` C#
await Task.Delay((int)liveChatResponse.PollingIntervalMillis);


await GetLiveChatMessage(liveChatId, youtubeService, liveChatResponse.NextPageToken);
```
再帰処理で最新のコメントを取得していきます。
しかし、YoutubeDataApiは1度リクエストしてから再度リクエストするのにある程度時間をおかないと結果が帰ってきません。
待たなくてはいけない時間はコメント取得時についてくるので、おとなしく言われた通りの時間待ちましょう。
# 参考
Youtube DataApi LiveChatMessage
https://developers.google.com/youtube/v3/live/docs/liveChatMessages?hl=ja  
Youtube Data Api videos:list
https://developers.google.com/youtube/v3/docs/videos/list?hl=ja  
Youtube Data API サンプル .Net
https://developers.google.com/youtube/v3/code_samples/dotnet?hl=ja#search_by_keyword