DiscordにYouTubeのライブ配信を通知するBotを作ってみた

# DiscordにYouTubeのライブ配信を通知するBotを作ってみた

みなさん初めまして。@rs_sho です。Qiitaでは初投稿となります。
この記事は[ラクスアドベントカレンダー](https://qiita.com/advent-calendar/2022/rakus)の23日目の記事です。
技術的な事とは言っても思いっきり趣味寄りな内容になります。
YouTube好きでよくゲーム実況やライブ配信見てて、YouTube開かなくても任意の時間に通知が欲しい！って人や
DiscordでBot作ってみたいな～って人の参考になればと思います！
(或いは配信者で自分のDiscordサーバに配信予定通知のBotが欲しい！って人とか…！)

## なぜこのツールを選んだか

### GAS(Google App Script)
何故と言われると特に理由はありませんが、開発環境等の準備が不要な事や、自分で起動等しておかなくても
トリガを使って勝手に処理を開始してくれるのが楽だったから、というのが主な理由です。
また、YouTubeとの親和性が高くてAPIとかを簡単に使えるからです。(Google傘下なので当然ですねw)

### Discord
一番の理由はプライベートなメッセージツールとは分けたかったから、です。
プライベートで使っているツールに通知を飛ばすと鬱陶しくて通知を切ってしまって
通知するBotを作ったのに通知を切るという元も子もないことになってしまいそうなので…w
あとはBot(厳密にはWebhook)の機能が割と簡単に作れる・使えることも選定した理由の1つになります。

## 作り方

### YouTube APIの使い方
GASのプロジェクトの作り方は端折ります！まずはYouTubeからライブ配信の情報を取得する方法から説明します！
GASにはYouTube APIを簡単に使用できるようにする方法があります。
①左のリストから サービス を選択して [+]ボタンを押下する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959990/ab6042ca-5e02-1ba5-0829-d632046467db.png)

②サービスの追加モーダルが出てくるので、そこから「YouTube Data API v3」を選択
　(IDはGASのコード内で参照するライブラリ名です！デフォルトは「YouTube」になります！)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959990/98fc51a3-24cc-8427-122f-bec8eab02c40.png)

③「追加」ボタンを押したら追加完了(反映に少し時間がかかるかも)
　「YouTube」という表記が サービス の下に出れば完了です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959990/bfd59cc7-b2a9-ccad-3591-09be92dbf3d2.png)

では早速データを取得してみましょう！
```sh
const channel = "UCfmMcsMOGWbOJfdVsvM_Rdw";  //チャンネルID
// YouTubeのデータ取得設定
function getYouTubeData() {
  //YouTube Data API　リストのgetリクエスト
  var results = YouTube.Search.list('id,snippet', {
  "maxResults": 3,                   // 取得上限数
  "channelId": channel,              // チャンネルID
  "order": "date",                   // 並び替え(日付順)
  "type": "video",                   // 取得する種類(video：動画, playlist:再生リスト, channel:チャンネル)
  "eventType": "none",               // 配信のタイプ(none:投稿済み,upcoming:配信予定,live:配信中)
  });
}
```
上記の方法で取得できます！それぞれのパラメータを指定することで、取得したい動画のURLや配信の時間等が取得できます！
ちょっとややこしいのがチャンネルIDが必要で、そのIDがややこしい。(後述します)

#### maxResults
取得するデータの上限数です。例だと3件取得したら残りは取得しません。(TOP3を取得する、みたいな設定です)
SQLでいうlimitみたいなものです！0~50まで設定できます。

#### channelId
ややこしいのがこれ。
https://www.youtube.com/@rakuschannel
上記で`@rakuschannel`がチャンネルIDかと思いきやそうではないんです…。
実はYouTubeにはURLをカスタムできる機能があり、カスタムされたURLであってIDではないんです。
こういった場合はチャンネル名でGoogle検索すると見つけられるかもしれません。

カスタムされてなければ以下のように出ますので、channelの後ろの文字列がIDになります。
https://www.youtube.com/channel/UCfmMcsMOGWbOJfdVsvM_Rdw
チャンネルID： UCfmMcsMOGWbOJfdVsvM_Rdw 

#### order
取得する情報の並び替え順です。例だと日付が新しい順で取得します。
他にも評価順やタイトルのアルファベット順、再生回数の高い順などに設定できます。


#### type
取得するデータの内容を制限できます。video：動画, playlist:再生リスト, channel:チャンネル が指定できます。
取得したいデータの内容に合わせて設定します。

#### eventType
配信がどのタイプのものを取得するか設定できます。(ここが一番醍醐味かも)
- none：既に投稿されている動画の中から取得したい場合
- upcoming：これから配信予定のリマインダーが設定されている動画を取得したい場合
- live：今ライブ配信をしている動画を取得したい場合
どの内容のものを作るかでここの設定は変えてください。

もっと詳しいAPIの内容は[YouTube Data API](https://developers.google.com/youtube/v3/docs/search/list?hl=ja)のリファレンスガイドを見て下さい！

### 取得してみよう
コード書いて動作確認してみたい場合はデバッグポイントを置いてデバッグして見ましょう。
※注意※YouTubeAPIは1日に送信できるリクエスト制限があるので、やりすぎると上限行ってしまいます！
　取得レコード数でカウントされていたと思うので、maxResultsを1にするなどして対応しましょう！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959990/518d7c89-0baf-c2a2-e12b-83730492cf5e.png)

12行目にデバッグポイントを置いて上のデバッグを押すと、右のデバッガに取得してきたデータなどが表示されます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959990/c7209f95-535c-a289-c76e-891dd56e8844.png)
resultsのitemがデータ内容です。maxResultsで設定した通り3件のみの取得ですね！
1つ目のデータを見てみましょう！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959990/6a444d6b-258f-d715-e7fc-fe1b6f20c8fb.png)
(記事を書いている2022/12/17現在の)最新の動画が取得できました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959990/f71ea2ec-4fd1-0b24-88e8-736f667ae8ad.png)

### 投稿してみよう
取得したら後は投稿するだけです！まずはDiscord側の設定をしましょう！
サーバ設定 > 連携サービス > ウェブフック > 新規作成 or 任意のwebhookを選択 > ウェブフックURLをコピー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959990/261564b4-feab-0dd4-136b-b187c2112a34.png)

次はGAS側のコードです。
```sh
const WEBHOOK_URL_ARRAY = [
  "https://discord.com/api/webhooks/{webhookのURL}"
];

videoDataSet(results.items);  // 実行

function videoDataSet(items) {
  var firstPost = 0;
  for (var i=0;i<items.length;i++) {
    var item = items[i];
    const liveTitle = item.snippet.title;  // 動画タイトル
    const liveUrl = `https://www.youtube.com/watch?v=${item.id.videoId}`;  // YouTubeの動画リンク
    const payload = {
      "username": "test Bot",
      "content": `${liveTitle}\r${liveUrl}`
    };
    postDiscord(payload); // 動画の詳細投稿
  }
}
```
```sh
// Discordへの投稿
function postDiscord(payload) {
  for (var i=0;i<WEBHOOK_URL_ARRAY.length;i++) {
    var WEBHOOK_URL = WEBHOOK_URL_ARRAY[i];
    UrlFetchApp.fetch(WEBHOOK_URL, {
      "method": "post",
      "contentType": "application/json",
      "payload": JSON.stringify(payload),
    });
  }
}
```

### 実際に送ってみよう
Discordに送れるか試してみましょう！そのまま実行を押すと処理が実行され、投稿されるはずです！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959990/a7d35811-be6d-26f2-f1c2-5a7c9727cdf8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2959990/fea637e2-9d8f-bbee-6e1d-1bc49e889759.png)

ちゃんと送信されました！

### 最後に
いかがでしたでしょうか。案外色々できるんだなぁと思った反面、こういった内容の記事があまりなかったので、
仕様理解や実際に作るとなった時に結構苦労しました。(デバッグのし過ぎでリクエスト上限行ったりしたことも…)
いつも使っているBotは今回のように投稿済みの動画を取得するタイプではないですが、
設定値を変えるだけで色々できるようになるので、やってみたいって人は試して見て下さい！
こういった記事探してたけどなかなかなくてできなかったんだよなぁっていう僕と同じこと思ってた人の参考になれば幸いです。

このコードは手動で動かしていますが、トリガ設定等をすれば定期実行もできるようになります。
(X時に投稿したいなぁとか、1時間おきにライブ配信している動画のリマインドをしたいなぁみたいなこともできる)

### 参考文献
[YouTube API リファレンス](https://developers.google.com/youtube/v3/docs?hl=ja)