YouTube の動画にコメントする in Golang

[YouTube Data API](https://developers.google.com/youtube/v3/) を使って Golang で動画にコメント（返信）します。

## Requirements
- Golang
    - github.com/joho/godotenv
    - google.golang.org/api/googleapi/transport
    - google.golang.org/api/youtube/v3
- Google OAuth Client ID
    - Google Cloud Console から作成してください
    -  `Application type` は `Other`

## 準備
### 1. ライブラリのインストール

```
$ go get github.com/joho/godotenv
$ go get google.golang.org/api/googleapi/transport
$ go get google.golang.org/api/youtube/v3
```

### 2. チャンネル作成

Google アカウントでそのまま YouTube を使用している場合は、OAuth Client ID を発行しても認証が通りません。

YouTube の設定からチャンネルを作成する必要があります。

![スクリーンショット 2019-04-27 23.24.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245792/99d5d280-a5a0-6a95-3083-818296c31261.png)
![スクリーンショット 2019-04-27 23.24.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245792/171246e3-c726-7aca-7588-ef0a48557f53.png)
![スクリーンショット 2019-04-27 23.24.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245792/9acb09a7-d4e2-978c-4ec4-31a46cf6e1bb.png)

## 手順
### 1. コードダウンロード
```
$ git clone https://github.com/Doarakko/api-challenge
$ cd api-challenge/youtube-data-api
```

### 2. `CLIENT_ID` と `CLIENT_SECRET` を入力
事前に Google Cloud Console 上で作成した認証情報を入れます。

```
$ mv .env.example .env
```
```
CLIENT_ID = ghijk.apps.googleusercontent.com
CLIENT_SECRET = lmnopqr
```

コードに直書きでも動きますが、間違えて GitHub にあげると面倒なので `.env` 使います。

### 3. `main.go` 修正
```go
func main() {
    err := godotenv.Load("./.env")
    if err != nil {
        log.Fatal("Error loading .env file")
    }
    comment("enter video id", "おもしろい！")
}
```

Video ID は動画 URL の以下の箇所です。

![](https://qiita-image-store.s3.amazonaws.com/0/245792/50ff8a6b-1323-b068-4f3d-926b25d56e5a.png)

### 4. ビルド
```
$ go build -o main
```

### 5. 実行
```
$ ./main
```
![スクリーンショット 2019-05-02 18.18.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245792/a747b66e-9859-e18b-a4a0-802a40e987c5.png)


## 解説
- `comment.go`

```go
func comment(videoID string, message string) {
    service := newYoutubeService(newOAuthClient())
    commentThread := &youtube.CommentThread{
        Snippet: &youtube.CommentThreadSnippet{
            VideoId: videoID,
            TopLevelComment: &youtube.Comment{
                Snippet: &youtube.CommentSnippet{
                    TextOriginal: message,
                },
            },
        },
    }
    call := service.CommentThreads.Insert("id,snippet", commentThread)
    _, err := call.Do()
    if err != nil {
        log.Fatalf("%v", err)
    }
    log.Printf("Comment to %v\n", videoID)
}
```
コメントする際に、コメントの構造体（`commentThread`）を渡してあげる必要があります。

入れ子になっていてわかりづらいですが、[ドキュメント](https://developers.google.com/youtube/v3/)見ながらエディタの補完機能と定義ジャンプ使うと簡単です。

## おまけ
ついでにコメントへの返信もやってみます。
コメントと返信とで使用するメソッドが異なるので注意してください。

- コメント
    - [CommentThreads: insert](https://developers.google.com/youtube/v3/docs/commentThreads/insert)
- 返信
    - [Comments: insert](https://developers.google.com/youtube/v3/docs/comments/insert)


以下ではいいねの数が 100 以上のコメントに「わろた」と返信します。

### 1. `main.go` 修正

```go
func main() {
    err := godotenv.Load("./.env")
    if err != nil {
        log.Fatal("Error loading .env file")
	}

    for _, item := range getComments("enter video id") {
        likeCnt := item.Snippet.TopLevelComment.Snippet.LikeCount

        if likeCnt >= 100 {
            commentID := item.Snippet.TopLevelComment.Id
            reply(commentID, "わろた")
            log.Printf("Reply to %v\n", item.Snippet.TopLevelComment.Snippet.TextDisplay)
        }
    }
}
```

`getComments` で引数のビデオのコメントを取得して、いいね数が 100 以上のものに対して `reply` 関数を実行しています。

返信の場合は返信対象のコメント ID を指定します。

### 2. ビルド
```
$ go build -o main
```

### 3. 実行
```
$ ./main
```
![スクリーンショット 2019-05-02 18.04.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245792/18f4e2cd-d202-ce74-7103-1b3d6e4b139c.png)
![スクリーンショット 2019-05-02 18.04.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245792/56912414-359e-52a7-7a34-4279def31ece.png)
![スクリーンショット 2019-05-02 18.20.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245792/c5668402-7294-7fd0-7f59-1f53c264f12b.png)

## Hints
OAuth Client の作成コードは[公式サンプル](https://github.com/googleapis/google-api-go-client)をそのまま使いました。

作成したトークンをローカルに保存して2回目以降はローカルを参照しています。

```go
cacheFile := tokenCacheFile(config)
token, err := tokenFromFile(cacheFile)
if err != nil {
    token = tokenFromWeb(ctx, config)
    saveToken(cacheFile, token)
} else {
    log.Printf("Using cached token %#v from %q", token, cacheFile)
}
```
他にも Golang と YouTube Data API 関連で記事を書いているので参考にしてみてください。

## おわりに
テストでコメントした際に手動で削除するのが面倒なので、対象の動画で自分のコメントを全削除する関数を書いておけばよかったです。

## Reference
- [Youtube のコメントを取得する in Golang](https://qiita.com/Doarakko/items/a6a0ef7120f4bd41b8c2)