125 lines
3.1 KiB
JavaScript
125 lines
3.1 KiB
JavaScript
const { timer, from, zip, iif, of } = require('rxjs');
|
|
const { switchMap, concatMap } = require('rxjs/operators');
|
|
const { google } = require('googleapis');
|
|
const { chunkDocument, stripHTML, stripURLs } = require('../../utils');
|
|
|
|
const { YOUTUBE_SECRET } = process.env;
|
|
const youtube = google.youtube({ version: 'v3', auth: YOUTUBE_SECRET });
|
|
|
|
function getPlaylistItems(
|
|
{ playlistId, playlistTitle },
|
|
nextPage,
|
|
currentItems = []
|
|
) {
|
|
return zip(
|
|
timer(2000),
|
|
from(
|
|
new Promise((resolve, reject) => {
|
|
youtube.playlistItems.list(
|
|
{
|
|
part: 'snippet',
|
|
playlistId,
|
|
pageToken: nextPage ? nextPage : ''
|
|
},
|
|
(err, data) => {
|
|
if (err) {
|
|
return reject(err);
|
|
}
|
|
return resolve({ ...data.data, playlistTitle });
|
|
}
|
|
);
|
|
})
|
|
),
|
|
(a, b) => b
|
|
).pipe(
|
|
switchMap(({ nextPageToken, items, playlistTitle }) => {
|
|
const allItems = currentItems.concat(items);
|
|
return iif(
|
|
() => !!nextPageToken,
|
|
getPlaylistItems(
|
|
{ playlistId, playlistTitle },
|
|
nextPageToken,
|
|
allItems
|
|
),
|
|
of({ videos: allItems, playlistTitle })
|
|
);
|
|
})
|
|
);
|
|
}
|
|
|
|
function getPlayLists(nextPage, currentItems = []) {
|
|
return from(
|
|
new Promise((resolve, reject) => {
|
|
youtube.playlists.list(
|
|
{
|
|
auth: YOUTUBE_SECRET,
|
|
part: 'snippet',
|
|
channelId: 'UC8butISFwT-Wl7EV0hUK0BQ',
|
|
pageToken: nextPage ? nextPage : ''
|
|
},
|
|
(err, data) => {
|
|
if (err) {
|
|
return reject(err);
|
|
}
|
|
return resolve(data.data);
|
|
}
|
|
);
|
|
})
|
|
).pipe(
|
|
switchMap(({ nextPageToken, items }) => {
|
|
const allItems = items.concat(currentItems);
|
|
return iif(
|
|
() => !!nextPageToken,
|
|
getPlayLists(nextPageToken, allItems),
|
|
of(allItems)
|
|
);
|
|
})
|
|
);
|
|
}
|
|
|
|
exports.getYoutubeData = function getYoutubeData() {
|
|
return getPlayLists().pipe(
|
|
switchMap(playlists => {
|
|
return from(playlists).pipe(
|
|
concatMap(({ id, snippet: { title } }) =>
|
|
getPlaylistItems({ playlistId: id, playlistTitle: title })
|
|
)
|
|
);
|
|
}),
|
|
switchMap(({ videos, playlistTitle }) => {
|
|
const formattedVideos = videos
|
|
.map(video => {
|
|
const {
|
|
id,
|
|
snippet: {
|
|
title,
|
|
description,
|
|
resourceId: { videoId },
|
|
thumbnails
|
|
}
|
|
} = video;
|
|
return {
|
|
id,
|
|
videoId,
|
|
title: stripHTML(title),
|
|
description: stripURLs(stripHTML(description)),
|
|
thumbnails,
|
|
playlistTitle
|
|
};
|
|
})
|
|
.reduce(
|
|
(chunked, current) => [
|
|
...chunked,
|
|
...chunkDocument(
|
|
current,
|
|
['id', 'videoId', 'title', 'thumbnail', 'playlistTitle'],
|
|
'description'
|
|
)
|
|
],
|
|
[]
|
|
);
|
|
return of(formattedVideos);
|
|
})
|
|
);
|
|
};
|