Skip to content

Commit

Permalink
fix: fix empty related videos for some user accounts (#853)
Browse files Browse the repository at this point in the history
* fix: empty related videos when autoplay is on

* test: add test for getting related videos when autoplay is on

* test: correct the name of the test case

* test: add related-topics to refresh.js
  • Loading branch information
skick1234 committed Jan 10, 2021
1 parent 0bcf85b commit 6a9ca4f
Show file tree
Hide file tree
Showing 5 changed files with 17,665 additions and 55 deletions.
123 changes: 68 additions & 55 deletions lib/info-extras.js
Expand Up @@ -130,6 +130,66 @@ exports.getAuthor = info => {
}
};

const parseRelatedVideo = (details, rvsParams) => {
if (!details) return;
try {
let viewCount = getText(details.viewCountText);
let shortViewCount = getText(details.shortViewCountText);
let rvsDetails = rvsParams.find(elem => elem.id === details.videoId);
if (!/^\d/.test(shortViewCount)) {
shortViewCount = (rvsDetails && rvsDetails.short_view_count_text) || '';
}
viewCount = (/^\d/.test(viewCount) ? viewCount : shortViewCount).split(' ')[0];
let browseEndpoint = details.shortBylineText.runs[0].navigationEndpoint.browseEndpoint;
let channelId = browseEndpoint.browseId;
let name = getText(details.shortBylineText);
let user = (browseEndpoint.canonicalBaseUrl || '').split('/').slice(-1)[0];
let video = {
id: details.videoId,
title: getText(details.title),
published: getText(details.publishedTimeText),
author: {
id: channelId,
name,
user,
channel_url: `https://www.youtube.com/channel/${channelId}`,
user_url: `https://www.youtube.com/user/${user}`,
thumbnails: details.channelThumbnail.thumbnails.map(thumbnail => {
thumbnail.url = urllib.resolve(VIDEO_URL, thumbnail.url);
return thumbnail;
}),
verified: isVerified(details.ownerBadges),

[Symbol.toPrimitive]() {
console.warn(`\`relatedVideo.author\` will be removed in a near future release, ` +
`use \`relatedVideo.author.name\` instead.`);
return video.author.name;
},

},
short_view_count_text: shortViewCount.split(' ')[0],
view_count: viewCount.replace(/,/g, ''),
length_seconds: details.lengthText ?
Math.floor(parseTimestamp(getText(details.lengthText)) / 1000) :
rvsParams && `${rvsParams.length_seconds}`,
thumbnails: details.thumbnail.thumbnails,
richThumbnails:
details.richThumbnail ?
details.richThumbnail.movingThumbnailRenderer.movingThumbnailDetails.thumbnails : [],
isLive: !!(details.badges && details.badges.find(b => b.metadataBadgeRenderer.label === 'LIVE NOW')),
};

utils.deprecate(video, 'author_thumbnail', video.author.thumbnails[0].url,
'relatedVideo.author_thumbnail', 'relatedVideo.author.thumbnails[0].url');
utils.deprecate(video, 'ucid', video.author.id, 'relatedVideo.ucid', 'relatedVideo.author.id');
utils.deprecate(video, 'video_thumbnail', video.thumbnails[0].url,
'relatedVideo.video_thumbnail', 'relatedVideo.thumbnails[0].url');
return video;
} catch (err) {
// Skip.
}
};

/**
* Get related videos.
*
Expand All @@ -152,61 +212,14 @@ exports.getRelatedVideos = info => {
for (let result of secondaryResults || []) {
let details = result.compactVideoRenderer;
if (details) {
try {
let viewCount = getText(details.viewCountText);
let shortViewCount = getText(details.shortViewCountText);
let rvsDetails = rvsParams.find(elem => elem.id === details.videoId);
if (!/^\d/.test(shortViewCount)) {
shortViewCount = (rvsDetails && rvsDetails.short_view_count_text) || '';
}
viewCount = (/^\d/.test(viewCount) ? viewCount : shortViewCount).split(' ')[0];
let browseEndpoint = details.shortBylineText.runs[0].navigationEndpoint.browseEndpoint;
let channelId = browseEndpoint.browseId;
let name = getText(details.shortBylineText);
let user = (browseEndpoint.canonicalBaseUrl || '').split('/').slice(-1)[0];
let video = {
id: details.videoId,
title: getText(details.title),
published: getText(details.publishedTimeText),
author: {
id: channelId,
name,
user,
channel_url: `https://www.youtube.com/channel/${channelId}`,
user_url: `https://www.youtube.com/user/${user}`,
thumbnails: details.channelThumbnail.thumbnails.map(thumbnail => {
thumbnail.url = urllib.resolve(VIDEO_URL, thumbnail.url);
return thumbnail;
}),
verified: isVerified(details.ownerBadges),

[Symbol.toPrimitive]() {
console.warn(`\`relatedVideo.author\` will be removed in a near future release, ` +
`use \`relatedVideo.author.name\` instead.`);
return video.author.name;
},

},
short_view_count_text: shortViewCount.split(' ')[0],
view_count: viewCount.replace(/,/g, ''),
length_seconds: details.lengthText ?
Math.floor(parseTimestamp(getText(details.lengthText)) / 1000) :
rvsParams && `${rvsParams.length_seconds}`,
thumbnails: details.thumbnail.thumbnails,
richThumbnails:
details.richThumbnail ?
details.richThumbnail.movingThumbnailRenderer.movingThumbnailDetails.thumbnails : [],
isLive: !!(details.badges && details.badges.find(b => b.metadataBadgeRenderer.label === 'LIVE NOW')),
};

utils.deprecate(video, 'author_thumbnail', video.author.thumbnails[0].url,
'relatedVideo.author_thumbnail', 'relatedVideo.author.thumbnails[0].url');
utils.deprecate(video, 'ucid', video.author.id, 'relatedVideo.ucid', 'relatedVideo.author.id');
utils.deprecate(video, 'video_thumbnail', video.thumbnails[0].url,
'relatedVideo.video_thumbnail', 'relatedVideo.thumbnails[0].url');
videos.push(video);
} catch (err) {
// Skip.
let video = parseRelatedVideo(details, rvsParams);
if (video) videos.push(video);
} else {
let autoplay = result.compactAutoplayRenderer || result.itemSectionRenderer;
if (!autoplay || !Array.isArray(autoplay.contents)) continue;
for (let content of autoplay.contents) {
let video = parseRelatedVideo(content.compactVideoRenderer, rvsParams);
if (video) videos.push(video);
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions test/files/refresh.js
Expand Up @@ -100,6 +100,13 @@ const videos = [
id: 'z2jeHsa0UG0',
type: 'private',
},
{
id: '_HSylqgVYQI',
type: 'related-topics',
needCookie: true,
basicInfo: true,
saveInfo: true,
},
];


Expand Down Expand Up @@ -230,6 +237,8 @@ const refreshVideo = async(video, noRequests) => {
try {
let info;
let options = { requestOptions: { maxRetries: 0 } };
// Not implemented yet
if (video.needCookie) return console.log('Need cookies to refresh this.');
if (video.basicInfo) {
info = await getInfo.getBasicInfo(video.id, options);
} else {
Expand Down

0 comments on commit 6a9ca4f

Please sign in to comment.