@sushibtw/youtubei
Version:
Simple package to get information from youtube such as videos, playlists, channels, video information & comments, related videos, up next video, and more!
120 lines (119 loc) • 6.19 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const _1 = require(".");
const common_1 = require("../common");
const constants_1 = require("../constants");
/** Represents a Video */
class BaseVideo extends _1.Base {
/** @hidden */
constructor(video = {}) {
super();
Object.assign(this, video);
}
/**
* Load this instance with raw data from Youtube
*
* @hidden
*/
load(data) {
var _a, _b, _c, _d;
const videoInfo = BaseVideo.parseRawData(data);
// Basic information
this.id = videoInfo.videoDetails.videoId;
this.title = videoInfo.videoDetails.title;
this.uploadDate = videoInfo.dateText.simpleText;
this.viewCount = +videoInfo.videoDetails.viewCount || null;
this.isLiveContent = videoInfo.videoDetails.isLiveContent;
this.thumbnails = new _1.Thumbnails().load(videoInfo.videoDetails.thumbnail.thumbnails);
// Channel
const { title, thumbnail } = videoInfo.owner.videoOwnerRenderer;
this.channel = new _1.Channel({
client: this.client,
id: title.runs[0].navigationEndpoint.browseEndpoint.browseId,
name: title.runs[0].text,
thumbnails: new _1.Thumbnails().load(thumbnail.thumbnails),
});
// Like Count and Dislike Count
const topLevelButtons = videoInfo.videoActions.menuRenderer.topLevelButtons;
this.likeCount = common_1.stripToInt(BaseVideo.parseButtonRenderer(topLevelButtons[0]));
this.dislikeCount = common_1.stripToInt(BaseVideo.parseButtonRenderer(topLevelButtons[1]));
// Tags and description
this.tags =
((_b = (_a = videoInfo.superTitleLink) === null || _a === void 0 ? void 0 : _a.runs) === null || _b === void 0 ? void 0 : _b.map((r) => r.text.trim()).filter((t) => t)) || [];
this.description =
((_c = videoInfo.description) === null || _c === void 0 ? void 0 : _c.runs.map((d) => d.text).join("")) || "";
// Up Next and related videos
this.related = [];
const secondaryContents = data[3].response.contents.twoColumnWatchNextResults.secondaryResults.secondaryResults
.results;
if (secondaryContents) {
const upNext = ((_d = secondaryContents.find((s) => "compactAutoplayRenderer" in s)) === null || _d === void 0 ? void 0 : _d.compactAutoplayRenderer.contents[0]) || null;
this.upNext = upNext ? BaseVideo.parseCompactRenderer(upNext, this.client) : upNext;
this.related.push(...BaseVideo.parseRelated(secondaryContents, this.client));
// Related continuation
this._relatedContinuation = common_1.getContinuationFromContents(secondaryContents);
}
else {
this.upNext = null;
this.related = [];
}
return this;
}
/** Load next related videos / playlists */
nextRelated(count = 1) {
return __awaiter(this, void 0, void 0, function* () {
const newRelated = [];
for (let i = 0; i < count || count == 0; i++) {
if (this._relatedContinuation === undefined)
break;
const response = yield this.client.http.post(`${constants_1.I_END_POINT}/next`, {
data: { continuation: this._relatedContinuation },
});
const secondaryContents = response.data.onResponseReceivedEndpoints[0].appendContinuationItemsAction
.continuationItems;
this.related.push(...BaseVideo.parseRelated(secondaryContents, this.client));
this._relatedContinuation = common_1.getContinuationFromContents(secondaryContents);
}
this.related.push(...newRelated);
return newRelated;
});
}
/** @hidden */
static parseRawData(data) {
const contents = data[3].response.contents.twoColumnWatchNextResults.results.results.contents;
const primaryInfo = contents.find((c) => "videoPrimaryInfoRenderer" in c)
.videoPrimaryInfoRenderer;
const secondaryInfo = contents.find((c) => "videoSecondaryInfoRenderer" in c).videoSecondaryInfoRenderer;
const videoDetails = data[2].playerResponse.videoDetails;
return Object.assign(Object.assign(Object.assign({}, secondaryInfo), primaryInfo), { videoDetails });
}
static parseRelated(secondaryContents, client) {
return secondaryContents
.map((c) => BaseVideo.parseCompactRenderer(c, client))
.filter((c) => c !== undefined);
}
static parseCompactRenderer(data, client) {
if ("compactVideoRenderer" in data) {
return new _1.VideoCompact({ client }).load(data.compactVideoRenderer);
}
else if ("compactRadioRenderer" in data) {
return new _1.PlaylistCompact({ client }).load(data.compactRadioRenderer);
}
}
static parseButtonRenderer(data) {
var _a;
const buttonRenderer = data.toggleButtonRenderer || data.buttonRenderer;
const accessibilityData = (((_a = buttonRenderer.defaultText) === null || _a === void 0 ? void 0 : _a.accessibility) || buttonRenderer.accessibilityData).accessibilityData;
return accessibilityData.label;
}
}
exports.default = BaseVideo;