UNPKG

@duell10111/youtubei.js

Version:

A JavaScript client for YouTube's private API, known as InnerTube.

130 lines 5.54 kB
import { HorizontalListContinuation, Parser } from '../../parser/index.js'; import { generateRandomString, InnertubeError, throwIfMissing } from '../../utils/Utils.js'; import NavigationEndpoint from '../../parser/classes/NavigationEndpoint.js'; import HorizontalList from '../../parser/classes/HorizontalList.js'; import Playlist from '../../parser/yttv/Playlist.js'; import Library from '../../parser/yttv/Library.js'; import SubscriptionsFeed from '../../parser/yttv/SubscriptionsFeed.js'; import PlaylistsFeed from '../../parser/yttv/PlaylistsFeed.js'; import HomeFeed from '../../parser/yttv/HomeFeed.js'; import VideoInfo from '../../parser/yttv/VideoInfo.js'; import MyYoutubeFeed from '../../parser/yttv/MyYoutubeFeed.js'; export default class TV { #session; #actions; constructor(session) { this.#session = session; this.#actions = session.actions; } async getInfo(target, options) { throwIfMissing({ target }); const payload = { videoId: target instanceof NavigationEndpoint ? target.payload?.videoId : target, playlistId: target instanceof NavigationEndpoint ? target.payload?.playlistId : undefined, playlistIndex: target instanceof NavigationEndpoint ? target.payload?.playlistIndex : undefined, params: target instanceof NavigationEndpoint ? target.payload?.params : undefined, racyCheckOk: true, contentCheckOk: true }; const watch_endpoint = new NavigationEndpoint({ watchEndpoint: payload }); const watch_next_endpoint = new NavigationEndpoint({ watchNextEndpoint: payload }); const extra_payload = { playbackContext: { contentPlaybackContext: { vis: 0, splay: false, lactMilliseconds: '-1', signatureTimestamp: this.#session.player?.sts } }, client: 'TV' }; if (options?.po_token) { extra_payload.serviceIntegrityDimensions = { poToken: options.po_token }; } else if (this.#session.po_token) { extra_payload.serviceIntegrityDimensions = { poToken: this.#session.po_token }; } const watch_response = watch_endpoint.call(this.#actions, extra_payload); const watch_next_response = await watch_next_endpoint.call(this.#actions, { client: 'TV' }); const response = await Promise.all([watch_response, watch_next_response]); const cpn = generateRandomString(16); return new VideoInfo(response, this.#actions, cpn); } async getHomeFeed() { const client = 'TV'; const home_feed = new NavigationEndpoint({ browseEndpoint: { browseId: 'default' } }); const response = await home_feed.call(this.#actions, { client }); return new HomeFeed(response, this.#actions); } async getLibrary() { const browse_endpoint = new NavigationEndpoint({ browseEndpoint: { browseId: 'FElibrary' } }); const response = await browse_endpoint.call(this.#actions, { client: 'TV' }); return new Library(response, this.#actions); } async getSubscriptionsFeed() { const browse_endpoint = new NavigationEndpoint({ browseEndpoint: { browseId: 'FEsubscriptions' } }); const response = await browse_endpoint.call(this.#actions, { client: 'TV' }); return new SubscriptionsFeed(response, this.#actions); } /** * Retrieves the user's playlists. */ async getPlaylists() { const browse_endpoint = new NavigationEndpoint({ browseEndpoint: { browseId: 'FEplaylist_aggregation' } }); const response = await browse_endpoint.call(this.#actions, { client: 'TV' }); return new PlaylistsFeed(response, this.#actions); } /** * Retrieves the user's My YouTube page. */ async getMyYoutubeFeed() { const browse_endpoint = new NavigationEndpoint({ browseEndpoint: { browseId: 'FEmy_youtube' } }); const response = await browse_endpoint.call(this.#actions, { client: 'TV' }); return new MyYoutubeFeed(response, this.#actions); } async getPlaylist(id) { throwIfMissing({ id }); if (!id.startsWith('VL')) { id = `VL${id}`; } const browse_endpoint = new NavigationEndpoint({ browseEndpoint: { browseId: id } }); const response = await browse_endpoint.call(this.#actions, { client: 'TV' }); return new Playlist(response, this.#actions); } // Utils async fetchContinuationData(item, client) { let continuation; if (item.is(HorizontalList)) { continuation = item.continuations?.[0]?.continuation; } else if (item.is(HorizontalListContinuation)) { continuation = item.continuation; } else { throw new InnertubeError(`No supported YTNode supplied. Type: ${item.type}`); } if (!continuation) { throw new InnertubeError('No continuation data available.'); } const data = await this.#actions.execute('/browse', { client: client ?? 'TV', continuation: continuation }); const parser = Parser.parseResponse(data.data); return parser.continuation_contents; } } //# sourceMappingURL=TV.js.map