【Elixir】ElixirでGoogleAPIを実行してYoutubeの動画情報を取得する

https://qiita.com/advent-calendar/2021/elixir

2021/12/10の回です。
昨日は、アルケミストになられた[pojiroさん](https://qiita.com/pojiro)の[苦節二年の時を経て職業錬金術師になれた話](https://qiita.com/pojiro/items/e4a724934feae93180b0)でした。


# はじめに
みなさん、Elixirを楽しんでいますか？私は楽しんでいます。
さて、本日はElixirを使ってGoogleAPIを実行する話をしてみます。

色々調べたのですが、国内・海外含めElixirを使ってGoogleAPIを実行するプラクティスはそんなに情報が無かったので、今回記事にしてみました。

# GoogleAPIとは
Wikipedia(英語)からの翻訳。

>Google APIは、Googleが開発したアプリケーションプログラミングインターフェースであり、Googleサービスとの通信と他のサービスへの統合を可能にします。これらの例には、検索、Gmail、翻訳、またはGoogleマップが含まれます。

つまり、GmailやGoogleマップなど、Googleのサービスが利用できるAPI、ということです。

# GoogleAPIの基礎知識
以下のサイトである程度知りました。感謝。
[これだけ押さえておけばあらゆるAPIを呼び出せる！ Google APIを使用するための基本](https://codezine.jp/article/detail/7977)

## 認証/通信方式
APIの認証/通信方式は以下の2つがあり、徐々に後者の方へ移行している模様です。
今回は後者の方式で通信を行うので、OutputはJSON書式になります。

- OAuth1でアクセス許可を得て、ATOM書式で通信
- OAuth2でアクセス許可を得て、JSON書式でhttpsを使って通信

## APIの種類
以下の3種類のAPIが存在する模様です。

- **Webサービス向けのAPI**… 最も一般的なAPI。個人が使用するWebサービスのリソースに対するアクセスを提供。
- **プラットフォーム向けのAPI**…GCPなどで使用するリソースに対するアクセスを提供。
- **Google Apps向けのAPI**…Google Appsのリソースに対するアクセスを提供。

## APIが提供する操作
GoogleAPIが提供する操作は、統一されたメソッドになっています。
リソースに対する操作は「リソース名.メソッド名」という表現で定義されています。

|メソッド|機能|
|:---|:---|
|list|一覧を取得する|
|get|IDを指定して、一件取得する|
|insert|新規作成する|
|update|上書きする|
|patch|部分的に上書きする|
|delete|指定したIDに対応するものを削除する|

## GoogleAPIを利用するのに必要なもの
今回は無料のAPIを利用します。

- Googleアカウント
- クレジットカード(有料のAPIを利用する場合。今回は不要)

# １．GoogleAPIを利用する準備

## GCPでプロジェクトを作成
最初にGCPでプロジェクトを作成します。[プロジェクトの作成と管理 ](https://cloud.google.com/resource-manager/docs/creating-managing-projects?hl=ja&visit_id=637747406766979296-4246818762&rd=1)を参照してください(割愛)。


## プロジェクトでYoutubeAPIを有効
GCPのAPIライブラリから、YoutubeのAPIを有効にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173839/70a7f730-fce6-d8fc-ed6f-f8410ce58997.png)

## Credentials jsonを取得
[認証のスタートガイド](https://cloud.google.com/docs/authentication/getting-started)の「サービス アカウントの作成」の欄を参照して、

- サービスアカウントの作成
- サービスアカウントキーを作成、jsonを取得

を行ってください。jsonファイルがダウンロードできます。

# ２．Elixirプロジェクトの作成

## 環境について
ElixirでAPIを実行するので、環境が必要です。
私は以下の環境です。

```bash
$ docker -v
Docker version 20.10.11, build dea9396
```

```bash
$ elixir -v
Erlang/OTP 24 [erts-12.1.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit]
Elixir 1.12.3 (compiled with Erlang/OTP 24)
```


## プロジェクトを作成
mixでプロジェクトを作成します。私はカレントフォルダで作成するので、2つ目の引数を「.」にしています。

```bash
$ mix new .
```

mix.exsで以下追記します。
google_api_you_tubeはYoutubeAPIを使用するためのライブラリ、gothは認証/通信するためのライブラリです。

```elixir:mix.exs
  # 中略
  defp deps do
    [
      {:google_api_you_tube, "~> 0.40.0"}, # 追記
      {:goth, "~> 1.2.0"} # 追記
    ]
  end
```

mixコマンドで、ライブラリを取得してきます。

```bash
$ mix deps.get
```

## Credentials jsonの配置と環境変数設定
プロジェクトのどこでもよいので、ダウンロードしてきたCredentials jsonを配置してください。
配置後、環境変数を設定します。Credentials jsonを配置したパスを設定してください。

```bash
$ export GOOGLE_APPLICATION_CREDENTIALS="KEY_PATH"
```

## API実行コードの実装
ソースコードを書いていきましょう。
私は今回、以下のように記載しました。これは、ある動画の情報を取得する関数です。

```elixir
  # 中略
  def get() do
    alias GoogleApi.YouTube.V3.Connection

    {:ok, token} = Goth.Token.for_scope("https://www.googleapis.com/auth/youtube.readonly")
    conn = Connection.new(token.token)  # token.token を渡す点に少し注意
    part = "snippet"
    optional_params = [id: "PpA6LfyN6Rs"]
    opts = []
    GoogleApi.YouTube.V3.Api.Videos.youtube_videos_list(conn, part, optional_params, opts)
  end
```

iexでmixもついでに実行してみましょう。

```bash
$ iex -S mix
```

コンパイル後、関数を実行してみると、以下のように情報が取得できました。

```bash
iex(1)> GoogleApiEx.get()
{:ok,
 %GoogleApi.YouTube.V3.Model.VideoListResponse{
   etag: "aPbByqwHjIjtRaRMwqYTetW_knY",
   eventId: nil,
   items: [
     %GoogleApi.YouTube.V3.Model.Video{
       ageGating: nil,
       contentDetails: nil,
       etag: "7_BmlgwCTtaTHCTnebmFeLy5NOM",
       fileDetails: nil,
       id: "PpA6LfyN6Rs",
       kind: "youtube#video",
       liveStreamingDetails: nil,
       localizations: nil,
       monetizationDetails: nil,
       player: nil,
       processingDetails: nil,
       projectDetails: nil,
       recordingDetails: nil,
       snippet: %GoogleApi.YouTube.V3.Model.VideoSnippet{
         categoryId: "28",
         channelId: "UCjFO5t0MLyQaidKGpGoRewg",
         channelTitle: "Fullstack Academy",
         defaultAudioLanguage: "en-US",
         defaultLanguage: nil,
         description: "Learn more advanced front-end and full-stack development at: https://www.fullstackacademy.com\n\nElixir is a functional programming language that has developer-friendly syntax, runs on the powerful, mature Erlang VM, and is designed with an ecosystem and toolchain that makes testing, documentation, and writing programs simpler, quicker, and more productive from the very start. In this Elixir tutorial, we show you why functional programming is a thing, why choose Elixir out of all the functional programming languages, and how you can get started with Elixir today.\n\nWatch this video to learn:\n\n- What is a functional programming language\n- The advantages of using Elixir\n- How to get started with Elixir",
         liveBroadcastContent: "none",
         localized: %GoogleApi.YouTube.V3.Model.VideoLocalization{
           description: "Learn more advanced front-end and full-stack development at: https://www.fullstackacademy.com\n\nElixir is a functional programming language that has developer-friendly syntax, runs on the powerful, mature Erlang VM, and is designed with an ecosystem and toolchain that makes testing, documentation, and writing programs simpler, quicker, and more productive from the very start. In this Elixir tutorial, we show you why functional programming is a thing, why choose Elixir out of all the functional programming languages, and how you can get started with Elixir today.\n\nWatch this video to learn:\n\n- What is a functional programming language\n- The advantages of using Elixir\n- How to get started with Elixir",
           title: "Elixir Tutorial - An Introduction to Elixir"
         },
         publishedAt: ~U[2017-10-02 14:06:01Z],
         tags: ["Elixir", "Elixir Tutorial", "Introduction to Elixir",
          "learn elixir"],
         thumbnails: %GoogleApi.YouTube.V3.Model.ThumbnailDetails{
           default: %GoogleApi.YouTube.V3.Model.Thumbnail{
             height: 90,
             url: "https://i.ytimg.com/vi/PpA6LfyN6Rs/default.jpg",
             width: 120
           },
           high: %GoogleApi.YouTube.V3.Model.Thumbnail{
             height: 360,
             url: "https://i.ytimg.com/vi/PpA6LfyN6Rs/hqdefault.jpg",
             width: 480
           },
           maxres: %GoogleApi.YouTube.V3.Model.Thumbnail{
             height: 720,
             url: "https://i.ytimg.com/vi/PpA6LfyN6Rs/maxresdefault.jpg",
             width: 1280
           },
           medium: %GoogleApi.YouTube.V3.Model.Thumbnail{
             height: 180,
             url: "https://i.ytimg.com/vi/PpA6LfyN6Rs/mqdefault.jpg",
             width: 320
           },
           standard: %GoogleApi.YouTube.V3.Model.Thumbnail{
             height: 480,
             url: "https://i.ytimg.com/vi/PpA6LfyN6Rs/sddefault.jpg",
             width: 640
           }
         },
         title: "Elixir Tutorial - An Introduction to Elixir"
       },
       statistics: nil,
       status: nil,
       suggestions: nil,
       topicDetails: nil
     }
   ],
   kind: "youtube#videoListResponse",
   nextPageToken: nil,
   pageInfo: %GoogleApi.YouTube.V3.Model.PageInfo{
     resultsPerPage: 1,
     totalResults: 1
   },
   prevPageToken: nil,
   tokenPagination: nil,
   visitorId: nil
 }}
```

# 解説?：GoogleAPIの実行コードについて
実はElixirのGoogleAPIは、[GitHubリポジトリ](https://github.com/googleapis/elixir-google-api)で公開されています。
基本はここのREADMEを見ながら「あーこんな感じかな？」で今回は動かしてみました。
今回使用したYoutubeAPIでいえば、[ソースコード](https://github.com/googleapis/elixir-google-api/blob/main/clients/you_tube/lib/google_api/you_tube/v3/api/videos.ex)を見て実装しました。
色々やってみた結果、分かったことは

- Gothからトークンを取得
- Connection aliasから接続情報を取得
- 接続情報を使ってAPI実行

といったことは共通なのかなと思いました。
また、APIのリファレンスは[YouTube Data API の概要](https://developers.google.com/youtube/v3/getting-started?hl=ja)で公開されているので、オプションパラメータもある程度把握できます。
残念なのは、やはりElixir向けの公式リファレンスが無いことです。。。。

# まとめ
いかがだったでしょうか。今回はElixirのコードでGoogleAPIを実行してYoutubeの動画情報を取得してみました。
公式リファレンスがGoogleで用意されることを祈っています。。。。

宣伝になりますが、私は以下のコミュニティで活動しています。もしご興味がある方は、JOINしていただけると助かります。

https://fukuokaex.connpass.com/

https://pelemay.connpass.com/

では、2021/12/10の回は以上です。