YouTube Data APIを使い過去にユーザーが高評価した動画を取得する

# 【Rails】YouTube Data APIを利用、OAuth2.0の認証を使い動画を取得

Ruby version 2.5.8
Rails version 6.1.1

rails new をした前提で話を進めます。自身がこのapiを使い認証機能を使い動画をviewに出すまでかなり苦労したので残しておきます。

### 完成イメージ
・過去に自身のアカウントで高評価した動画をviewに表示できている
・viewのデザインは皆さん適当に作ってみてください。私はyoutubeのデザインをもろパクリしました。
![スクリーンショット 2021-01-20 095147.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684396/82921232-6c75-5b3f-3176-ab821286bed6.png)

# この記事には7つのステップがあります
## 1 API keyの発行
[まず、apikeyを発行します。](https://console.cloud.google.com/apis/library?hl=ja&project=primeval-array-300603&folder&organizationId)
![スクリーンショット 2021-01-25 104150.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684396/9333bbcf-2793-5a02-3a5d-57df2a69cdcb.png)
名前は何でもいいのですがアプリケーションの制限をなしにしてAPIの制限をYouTube Data API v3のみにして発行します。

*****

### 2 OAuth 2.0 クライアントIDの発行
認証情報を作成をクリック、APIキーの下にあるOAuthクライアントIDを選択し作成します。
リダイレクトURIを埋めておきます。承認を突破したあとにどのページに戻されるかです。
私は開発環境ではhttp://localhost:3000/にしておきました。

*****

### 3 gemをセット,コントローラーの設定
```gemfile
gem 'google-api-client', '0.9.20', require: 'google/apis/youtube_v3'
gem 'googleauth'
```
bundle install
コントローラーにapi,jsonを使えるように記述
コントローラーが増えても手間が増えないようにApplicationControllerに一応書いています

 ```Ruby
class ApplicationController < ActionController::Base
  require 'net/http'
  require 'uri'
  require 'json'
  CLIENT_SECRET = ENV['CLIENT_SECRET']
  @@service = Google::Apis::YoutubeV3::YouTubeService.new
  @@service.key = ENV['GOOGLE_APP_SECRET']
end
```
*****

## [ここからガイドに従い作っていく](https://developers.google.com/youtube/v3/guides/auth/server-side-web-apps#OAuth2_Refreshing_a_Token)
### 4 viewからOAuthに認証を送る
``` html
  <%# アカウント認証するとcode発行 %>
  <%= link_to "このボックスをクリックしgoogleアカウントを認証するとアプリが使えます", "https://accounts.google.com/o/oauth2/auth?client_id=あなたのクライアントID&redirect_uri=リダイレクトURI&scope=https://www.googleapis.com/auth/youtube&response_type=code", class:'side-bar-menu__bottom__oauth'%>
```

auth?の後にパラメーターをつないでいきます。scopeは今回youtubeで動くので余計なものは付けずyoutubeのみにしておきます。

*****

### 5 codeパラメーターの処理,アクセストークンの取得
そして承認を突破してくるとcodeパラメーターを返してくるのでアクセストークンと交換させて頂きます。

``` Ruby
def get_access_token
    # OAuth 2.0 の承認を突破した段階でurlのcode=~~の部分を取得
    # redirect_codeは後にアクセストークン、更新トークンと交換
    # リクエスト送信に必要なため
    response_hash = URI.decode_www_form(request.fullpath).to_h
    redirect_code = response_hash['/?code']

    # parseでuriを区切れるようになる
    uri = URI.parse('https://accounts.google.com/o/oauth2/token')
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE

    # POST リクエストを https://accounts.google.com/o/oauth2/token に送信
    headers = { 'Contant-Type' => 'application/x-www-form-urlencoded' }
    params = {
      code: "#{redirect_code}",
      client_id:
        'あなたのクライアントID',
      client_secret: "#{CLIENT_SECRET}",
      redirect_uri: '好きなリダイレクト先',
      grant_type: 'authorization_code',
    }
    req = Net::HTTP::Post.new(uri.path)
    req.set_form_data(params)
    req.initialize_http_header(headers)

    # リクエストのレスポンスからトークン取得
    response = http.request(req)
    @access_token = JSON.parse(response.body)['access_token']
    return @access_token
  end
```
コードは以下のスクリーンショットの言われたとおりにしています。
それぞれのキーをparamsハッシュにしてリクエストを送ります。
![スクリーンショット 2021-01-26 102711.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684396/fda063d8-12e9-323b-dced-8fa524dd0cc5.png)

*****

### 6 YouTube Data APIの呼び出し
[動画を取得](https://developers.google.com/youtube/v3/docs/videos/list?hl=ja%2Fs%2Fresults%2F%3Fq%3Dscopes)
様々なパラメーターが用意されています。
my_ratingなどは承認されたリクエストのみのためこのようにアクセストークンを取得し、処理する必要があるようです。

※my_rating,max_resultsは変えやすいように変数に入れていますがそのようにしなくても大丈夫です。

公式にも「アクセス トークンを Authorization: Bearer HTTP リクエスト ヘッダーの値として指定します。これは推奨される方法です。」とあるのでそうしておきます。

※また、私の場合は動画を少しでもランダムに返したかったため@items = response['items'].shuffle[0..4]となっていますがランダムで返さなくていいのならいらないですしそもそも50本もとってこなくて大丈夫です。
無課金だと1日のリクエスト量が決まっていて私も制限される日が続いて萎えましたので

```Ruby
 def youtube_data_api
    get_access_token
    if @access_token
      option = { my_rating: 'like', max_results: 50 }
      uri =
        URI.parse(
          "https://www.googleapis.com/youtube/v3/videos?part=snippet&maxResults=#{
            option[:max_results]
          }&myRating=#{option[:my_rating]}",
        )

      https = Net::HTTP.new(uri.host, uri.port)
      https.use_ssl = true
      https.verify_mode = OpenSSL::SSL::VERIFY_NONE

      headers = { 'Authorization' => "Bearer #{@access_token}" }

      # request_uriはyoutube/v3/videos?part=snippet&maxResults=#{option[:max_results]}&myRating=#{option[:my_rating]}を指す
      req = Net::HTTP::Get.new(uri.request_uri)
      req.initialize_http_header(headers)

      # エンコード→操作しやすいようにハッシュに
      response = https.request(req)
      response = response.body.force_encoding('UTF-8')
      response = JSON.parse(response)
      # ランダムに5つの動画を返す
      @items = response['items'].shuffle[0..4]
      return @items
    end
  end
```
*****

### 7 レスポンスをviewに表示
```html
<% @items.each do |i| %>
  <iframe class="youtube__screen-frame" width="889" height="500" src="https://www.youtube.com/embed/<%= i['id'] %>" frameborder="no"allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<% end %>
```

*****
参考サイト
[data api 公式(ガイド、リファレンス)](https://developers.google.com/youtube/v3/guides/auth/server-side-web-apps#OAuth2_Refreshing_a_Token)
[【Ruby on Rails】最もわかりやすいYouTube API 使い方](https://qiita.com/gyu_outputs/items/af4319258b3d67c57d24)