YouTubeのプレイリストから動画を付け替える


プレイリストAにある動画をプレイリストBに付け替えます。

過去にそれぞれ書いてた処理をまとめた感じです。

## 検索 -> 編集 -> 元のリストから削除の3ステップが必要そう

- 1. プレイリストAから対象動画Cを検索
- 2. プレイリストBに対象動画Cを紐付け
- 3. プレイリストAから対象動画Cを削除

の処理が必要になりそうでした。

### 1. プレイリストAから対象動画Cを検索

`youtube.playlistItems.list`を使います。

```js
const res = await youtube.playlistItems.list({
    part: 'snippet',
    maxResults: 50, // 一度に取得する最大動画数
    playlistId: oldPlayListId
});
```

### 2. プレイリストBに対象動画Cを紐付け

`youtube.playlistItems.insert`を使います。

```js
    const playListAdd = async (playListId, videoId) => {
        try {
            const params = {
                part: 'id,snippet,contentDetails',
                requestBody: {
                  snippet: {
                    playlistId: playListId,
                    // position: 0,
                    resourceId: {
                      videoId: videoId,
                      kind: 'youtube#video',
                    },
                  },
                }
            }
            const res = await youtube.playlistItems.insert(params);
            return res.data;
        } catch (error) {
            throw new Error(error);
        }
    }
```

### 3. プレイリストAから対象動画Cを削除

`youtube.playlistItems.delete`を使います。

```js
await youtube.playlistItems.delete({
    id: oldPlayListItem.id
});
```


## コード全て

```js
'use strict';

const fs = require('fs');
const {google} = require('googleapis');

const googleAuth = () => {
    const CREDENTIALS_PATH = 'client_secret.json';
    const TOKEN_PATH = 'token.json';
    const credentials = JSON.parse(fs.readFileSync(CREDENTIALS_PATH, 'utf8'));
    const token = JSON.parse(fs.readFileSync(TOKEN_PATH, 'utf8'));

    const {client_secret, client_id, redirect_uris} = credentials.installed;
    const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
    oAuth2Client.setCredentials(token);

    return oAuth2Client;
};

(async () => {
    const auth = googleAuth();
    const youtube = google.youtube({version: 'v3', auth});

    const oldPlayListId = `XXXXXXXXXXXXX`; //プレイリストA
    const newPlayListId = `YYYYYYYYYYYYY`; //プレイリストB
    const videoId = `ZZZZZZZZZ`; //対象動画C

    //プレイリストに動画を追加
    const playListAdd = async (playListId, videoId) => {
        try {
            const params = {
                part: 'id,snippet,contentDetails',
                requestBody: {
                  snippet: {
                    playlistId: playListId,
                    // position: 0,
                    resourceId: {
                      videoId: videoId,
                      kind: 'youtube#video',
                    },
                  },
                }
            }
            const res = await youtube.playlistItems.insert(params);
            return res.data;
        } catch (error) {
            throw new Error(error);
        }
    }

    // console.log(youtube.channels)
    try {
        console.log(`--start`)
        //プレイリストAを検索
        const res = await youtube.playlistItems.list({
            part: 'snippet',
            maxResults: 50, // 一度に取得する最大動画数
            playlistId: oldPlayListId
        });

        //プレイリストAから対象動画Cを検索
        const oldPlayListItem = res.data.items.find(i => i.snippet.resourceId.videoId === videoId);
        if (!oldPlayListItem) {
            throw new Error('指定された動画はプレイリストに存在しません');
        }

        console.log(`検索結果: ${oldPlayListItem.snippet.title}`);

        //プレイリストBに対象動画Cを追加
        const newPlayListRes = await playListAdd(newPlayListId, oldPlayListItem.snippet.resourceId.videoId);
        console.log(newPlayListRes);
        console.log('プレイリストBに対象動画Cを追加');

        // プレイリストAから動画を削除
        await youtube.playlistItems.delete({
            id: oldPlayListItem.id
        });
        console.log('プレイリストAから対象動画Cを削除');

        console.log('--付け替え処理完了');
    } catch (error) {
        console.log('The API returned an error: ' + error);
    }
})();

```

## 結果

良い感じの付け替え挙動ができました。