YouTube API × GAS

# YouTube APIを使ってみる

事前に、YouTubeに動画をアップロードしてください！（3つくらい）
今回使用するYouTube APIはこちら：https://developers.google.com/youtube/v3/docs/search/list

# サービス追加

左側の「サービス」の「＋」からYouTube Data API のv3を追加してください。IDはYouTubeで大丈夫です。

![スクリーンショット 2024-09-11 17.54.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216701/dab2452d-8815-2f4e-f2b6-542c10cc8001.png)

## YouTubeボタンをスプレッドシートに追加

```youtube.js
function onOpen(){
  //メニュー配列
  const myMenu=[
    {name: "検索", functionName: "searchTest"},
    {name: "MY動画一覧更新", functionName: "searchMyVideos"},
    {name: "今日の動画を公開", functionName: "setPublicMyVideos"}
  ];
  SpreadsheetApp.getActiveSpreadsheet().addMenu("YouTube",myMenu); //メニューを追加
}
```

## 検索結果を取ってきてスプレッドシートに表示してみる

```youtube.js
function searchTest() {
  // eventType=completedはtype=videoの時に使える。
  // eventType=completedのみの指定だとエラーになる。
  // 公開されたのが2018年以降の動画
  // 日付の新しい順に、最大25件
  let i;
  const data = [];
  const results = YouTube.Search.list('id,snippet', {
    q: 'queen we will rock you',
    type: 'video',
    eventType: 'completed',
    maxResults: 25,
    order: 'date',
    publishedAfter: '2018-01-01T00:00:00Z'
  });

  for(i = 0; i < results.items.length; i++) {
    Logger.log(results.items[i]);
    const item = results.items[i];
    data.push([item.snippet.title, item.snippet.description, item.snippet.publishedAt, "http://www.youtube.com/watch?v=" + item.id.videoId]);
  }
  // スプレットシートからデータを引き出す
  SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート1").getRange(1, 1, i, 4).setValues(data);
}

```

## 自分の投稿動画を検索

```youtube.js
// 自分のvideoを検索する
// リストを取得するごとに配列（arrayId）に動画id（item.id.videoId）を保存しておいて、検索が終わったらまとめてスプレッドシートに書き出し 
function searchMyVideos() {
  let i, nextToken;
  let arrayId = [];
  while(nextToken != null) {
    const res = YouTube.Search.list('id,snippet', {
      maxResults: 50,
      forMine: true,
      order: "date",
      type: "video",
      pageToken: nextToken
    });
    for(i = 0; i < res.items.length; i++) {
      const item = res.items[i];
      arrayId.push(item.id.videoId);
    }
    nextToken = (res.nextPageToken == "") ? null :res.nextPageToken;
  }
  if (arrayId.length > 0){
    getMyVideoList(arrayId);
  }
  Browser.msgBox("動画一覧を取得しました。");
}

// videoの詳細情報を取得
function getMyVideoList(arrayId) {
  let i, nextToken;
  let arrayStatus = [];
  let count = 2; // 2行目からデータになるので。
  const id = String(arrayId);
  const sheetId = '*******************';
  const newsheet = SpreadsheetApp.openById(sheetId).getSheetByName('動画リスト');
  newsheet.getRange(1, 1).setValue('id');
  newsheet.getRange(1, 2).setValue('タイトル');
  newsheet.getRange(1, 3).setValue('作成日');
  newsheet.getRange(1, 4).setValue('公開/非公開/限定公開');
  newsheet.getRange(1, 5).setValue('動画URL');
  while(nextToken != null) {
    var playlistResponse = YouTube.Videos.list('snippet, status',{id:id});
    for(i = 0; i < playlistResponse.items.length; i++){
      var item = playlistResponse.items[i];
      arrayStatus.push(item.snippet.title + ";" + item.status.privacyStatus);
      newsheet.getRange(count, 1).setValue("" + item.id);
      newsheet.getRange(count, 2).setValue(item.snippet.title);
      newsheet.getRange(count, 3).setValue(item.snippet.publishedAt);
      newsheet.getRange(count, 4).setValue(item.status.privacyStatus);
      newsheet.getRange(count, 5).setValue("http://www.youtube.com/watch?v=" + item.id);
      count++;
    }
    nextToken = playlistResponse.nextPageToken;
  }
}

function myFunctionTest() {
  let i, nextToken;
  while(nextToken != null) {
    let res = YouTube.Playlists.list('snippet,status', {
      maxResults: 50,
      mine: true,
      pageToken: nextToken
    });
    for(i = 0; i < res.items.length; i++) {
      const item = res.items[i];
      // PlaylistResponse.itemsの型はPlaylist
      if(item.status.privacyStatus != "private") {
        Logger.log("update: " + item.snippet.title + ", " + item.status.privacyStatus );
        item.status.privacyStatus = "private";
        const updateRes = YouTube.Playlists.update(item, "snippet, status");
        Logger.log(updateRes.status.privacyStatus);
      }
    }
    nextToken = res.nextPageToken;
  }
}

```

### 解説
"snippet"を指定すると、再生リストのデータが取得されますが、公開／非公開などのstatus情報は付加されません。（GASでは、undefined）
従って、第1引数は、カンマ区切りで、"snippet,status"と指定しています。ただし、"status"だけでは、エラーになります。

YouTube.Playlists.list()は、最大50件まで、デフォルト5件なので、それ以上登録している場合は、pageTokenパラメータに
YouTube.Playlists.list()で取得したnextPageTokenを指定します。最後まで取得し終わったらnextPageTokenがnullになりますので、while文で繰り返し取得します。



##全部の動画を公開にする方法



```youtube.js

// 自分のvideoを公開する
function setPublicMyVideos() {
  var nextToken = "";
  var arrayId = [];
  while(nextToken != null) {
    var res = YouTube.Search.list('id,snippet', {
      maxResults: 50,
      forMine: true,
      order: "date",
      type: "video",
      pageToken: nextToken
    });
    
    for(var i = 0; i < res.items.length; i++) {
      var item = res.items[i];
       arrayId.push(item.id.videoId);
    }
 
    nextToken = (res.nextPageToken == "") ? null :res.nextPageToken;
  }
   
  if (arrayId.length > 0){
    updatePrivacyStatus_public(arrayId);
  }
  searchMyVideos();
  Browser.msgBox("全ての動画を公開しました。");
}
 
// VideoのprivacyStatusをpublicに変更する
function updatePrivacyStatus_public(arrayId) {
  var nextToken = "";
  var id = String(arrayId);
  while(nextToken != null) {
    var playlistResponse = YouTube.Videos.list('snippet, status',{id:id});
 
    for(var i = 0; i < playlistResponse.items.length; i++) {
      var item = playlistResponse.items[i];
 
      if(item.status.privacyStatus != "public") {
        item.status.privacyStatus = "public";
        var updateRes = YouTube.Videos.update(item, "status,snippet");
      }
 
    }
    nextToken = playlistResponse.nextPageToken;
  }
}
```

##moment.js入れよう
プロジェクトキー：MHMchiX6c1bwSqGM1PZiW_PxhMjh3Sh48
参考URL：https://tonari-it.com/gas-moment-js-moment/

#おまけ

##全部の動画を非公開にする方法

```youtube.js

// 自分のvideoを非公開にする
function setPrivateMyVideos() {
  var nextToken = "";
  var arrayId = [];
  while(nextToken != null) {
    var res = YouTube.Search.list('id,snippet',{
      maxResults: 50,
      forMine: true,
      order: "date",
      type: "video",
      pageToken: nextToken
    });
    
    for(var i = 0; i < res.items.length; i++) {
      var item = res.items[i];
       arrayId.push(item.id.videoId);
    }
 
    nextToken = (res.nextPageToken == "") ? null :res.nextPageToken;
  }
   
  if (arrayId.length > 0){
    updatePrivacyStatus_private(arrayId);
  }
  searchMyVideos();
  Browser.msgBox("全ての動画を非公開にしました。");
}
 
// VideoのprivacyStatusをprivateに変更する
function updatePrivacyStatus_private(arrayId) {
  var nextToken = "";
  var id = String(arrayId);
  while(nextToken != null) {
    var playlistResponse = YouTube.Videos.list('snippet, status',{id:id});
 
    for(var i = 0; i < playlistResponse.items.length; i++) {
      var item = playlistResponse.items[i];
      if(item.status.privacyStatus != "private") {
        item.status.privacyStatus = "private";
        var updateRes = YouTube.Videos.update(item, "status,snippet");
      }
 
    }
 
    nextToken = playlistResponse.nextPageToken;
 
  }
}
```

全体の参考URL：http://c-geru.com/as_blind_side/2015/04/gas01.html



```youtube.js
// スプレットシートからデータを引き出す
  var movieSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("動画リスト");
  var numColumn  = movieSheet.getLastColumn(); // 最後列の列番号を取得 // 5
  var numRow     = movieSheet.getLastRow()-1; // 最後行の行番号を取得
  var dataRange  = movieSheet.getRange(2, 1, numRow, numColumn);
  var moviedata  = dataRange.getValues();

```

#全部のコード

```youtube.js

function onOpen(){
  //メニュー配列
  var myMenu=[
    {name: "魔法1", functionName: "searchTest"},
    {name: "魔法2（MY動画一覧更新）", functionName: "searchMyVideos"},
    {name: "魔法3（今日の動画を公開）", functionName: "setPublicMyVideos"}
  ];
  SpreadsheetApp.getActiveSpreadsheet().addMenu("魔法のボタン",myMenu); //メニューを追加
}

function searchTest() {
  // eventType=completedはtype=videoの時に使える。
  // eventType=completedのみの指定だとエラーになる。
  // 公開されたのが2018年以降の動画
  // 日付の新しい順に、最大25件
  var results = YouTube.Search.list('id,snippet', {
    q: 'queen we will rock you',
    type: 'video',
    eventType: 'completed',
    maxResults: 25,
    order: 'date',
    publishedAfter: '2018-01-01T00:00:00Z'
  });

  var data = [];
  for(var i = 0; i < results.items.length; i++) {
    Logger.log(results.items[i]);
    var item = results.items[i];
    data.push([item.snippet.title, item.snippet.description, item.snippet.publishedAt, "http://www.youtube.com/watch?v=" + item.id.videoId]);
  }
  // スプレットシートからデータを引き出す
  SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート1").getRange(1, 1, i, 4).setValues(data);
}

// 【解説】
// "snippet"を指定すると、再生リストのデータが取得されますが、公開／非公開などのstatus情報は付加されません。（GASでは、undefined）
// 従って、第1引数は、カンマ区切りで、"snippet,status"と指定しています。ただし、"status"だけでは、エラーになります。

// YouTube.Playlists.list()は、最大50件まで、デフォルト5件なので、それ以上登録している場合は、pageTokenパラメータに
// YouTube.Playlists.list()で取得したnextPageTokenを指定します。最後まで取得し終わったらnextPageTokenがnullになりますので、while文で繰り返し取得します。

// 自分のvideoを検索する
// リストを取得するごとに配列（arrayId）に動画id（item.id.videoId）を保存しておいて、検索が終わったらまとめてスプレッドシートに書き出し 
function searchMyVideos() {
  var nextToken = "";
  var arrayId = [];
  while(nextToken != null) {
    var res = YouTube.Search.list('id,snippet', {
      maxResults: 50,
      forMine: true,
      order: "date",
      type: "video",
      pageToken: nextToken
    });

    for(var i = 0; i < res.items.length; i++) {
      var item = res.items[i];
       arrayId.push(item.id.videoId);
    }

    nextToken = (res.nextPageToken == "") ? null :res.nextPageToken;
  }

  if (arrayId.length > 0){
    getMyVideoList(arrayId); // 下の関数を呼び出している。
  }

  // Browser.msgBox("動画一覧を取得しました。");
}

// videoの詳細情報を取得
function getMyVideoList(arrayId) {
  var nextToken = "";
  var id = String(arrayId);
  var arrayStatus = [];

  var sheetId = '1c25kY7rdrk5UI0y1PWl5B8jgEjue959ZBruv7AAR-ZM';
  var spreadsheet = SpreadsheetApp.openById(sheetId);
  var newsheet = SpreadsheetApp.openById(sheetId).getSheetByName('動画リスト');
  newsheet.getRange(1, 1).setValue('id');
  newsheet.getRange(1, 2).setValue('タイトル');
  newsheet.getRange(1, 3).setValue('作成日');
  newsheet.getRange(1, 4).setValue('公開/非公開/限定公開');
  newsheet.getRange(1, 5).setValue('動画URL');

  var count = 2; // 2行目からデータになるので。

  while(nextToken != null) {
    var playlistResponse = YouTube.Videos.list('snippet, status',{id:id});

    for(var i = 0; i < playlistResponse.items.length; i++){
      var item = playlistResponse.items[i];

      arrayStatus.push(item.snippet.title + ";" + item.status.privacyStatus);

      newsheet.getRange(count, 1).setValue("" + item.id);
      newsheet.getRange(count, 2).setValue(item.snippet.title);
      newsheet.getRange(count, 3).setValue(item.snippet.publishedAt);
      newsheet.getRange(count, 4).setValue(item.status.privacyStatus);
      newsheet.getRange(count, 5).setValue("http://www.youtube.com/watch?v=" + item.id);
      count++;
    }

    nextToken = playlistResponse.nextPageToken;

  }
}

// 自分のvideoを公開する
function setPublicMyVideos() {
  var nextToken = "";
  var arrayId = [];
  while(nextToken != null) {
    var res = YouTube.Search.list('id,snippet', {
      maxResults: 50,
      forMine: true,
      order: "date",
      type: "video",
      pageToken: nextToken
    });

    for(var i = 0; i < res.items.length; i++) {
      var item = res.items[i];
       arrayId.push(item.id.videoId);
    }

    nextToken = (res.nextPageToken == "") ? null :res.nextPageToken;
  }

  if (arrayId.length > 0){
    updatePrivacyStatus_public(arrayId);
  }
  searchMyVideos();
  Browser.msgBox("全ての動画を公開しました。");
}

// VideoのprivacyStatusをpublicに変更する
function updatePrivacyStatus_public(arrayId) {
  var nowTime = Moment.moment().format('YYYY/MM/DD');
  // スプレットシートからデータを引き出す
  var movieSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("動画リスト");
  var numColumn  = movieSheet.getLastColumn(); // 最後列の列番号を取得 // 5
  var numRow     = movieSheet.getLastRow()-1; // 最後行の行番号を取得
  var dataRange  = movieSheet.getRange(2, 1, numRow, numColumn);
  var moviedata  = dataRange.getValues();
  var nextToken = "";
  var id = String(arrayId);
  while(nextToken != null) {
    var playlistResponse = YouTube.Videos.list('snippet, status',{id:id});
    for(var i = 0; i < playlistResponse.items.length; i++) {
      var item = playlistResponse.items[i];
      var timeOnSheet = Moment.moment(moviedata[i][5]).format('YYYY/MM/DD');
      
      if(nowTime == timeOnSheet){
        if(item.status.privacyStatus != "public") {
          item.status.privacyStatus = "public";
          var updateRes = YouTube.Videos.update(item, "status,snippet");
        }
      }

      
    }
    nextToken = playlistResponse.nextPageToken;
  }
}

// 自分のvideoを非公開にする
function setPrivateMyVideos() {
  var nextToken = "";
  var arrayId = [];
  while(nextToken != null) {
    var res = YouTube.Search.list('id,snippet',{
      maxResults: 50,
      forMine: true,
      order: "date",
      type: "video",
      pageToken: nextToken
    });

    for(var i = 0; i < res.items.length; i++) {
      var item = res.items[i];
       arrayId.push(item.id.videoId);
    }

    nextToken = (res.nextPageToken == "") ? null :res.nextPageToken;
  }

  if (arrayId.length > 0){
    updatePrivacyStatus_private(arrayId);
  }
  searchMyVideos();
  Browser.msgBox("全ての動画を非公開にしました。");
}

// VideoのprivacyStatusをprivateに変更する
function updatePrivacyStatus_private(arrayId) {
  var nextToken = "";
  var id = String(arrayId);
  while(nextToken != null) {
    var playlistResponse = YouTube.Videos.list('snippet, status',{id:id});

    for(var i = 0; i < playlistResponse.items.length; i++) {
      var item = playlistResponse.items[i];
      if(item.status.privacyStatus != "private") {
        item.status.privacyStatus = "private";
        var updateRes = YouTube.Videos.update(item, "status,snippet");
      }

    }

    nextToken = playlistResponse.nextPageToken;

  }
}
```