UNPKG

@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
"use strict"; 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;