@duell10111/youtubei.js
Version:
A JavaScript client for YouTube's private API, known as InnerTube.
190 lines • 8.64 kB
JavaScript
var _TV_session, _TV_actions;
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
import { HorizontalListContinuation, Parser } from '../../parser/index.js';
import NavigationEndpoint from '../../parser/classes/NavigationEndpoint.js';
import { HomeFeed, VideoInfo, MyYoutubeFeed } from '../../parser/yttv/index.js';
import { generateRandomString, InnertubeError, throwIfMissing } from '../../utils/Utils.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';
class TV {
constructor(session) {
_TV_session.set(this, void 0);
_TV_actions.set(this, void 0);
__classPrivateFieldSet(this, _TV_session, session, "f");
__classPrivateFieldSet(this, _TV_actions, session.actions, "f");
}
async getInfo(target, client) {
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 watch_response = watch_endpoint.call(__classPrivateFieldGet(this, _TV_actions, "f"), {
playbackContext: {
contentPlaybackContext: {
vis: 0,
splay: false,
lactMilliseconds: '-1',
signatureTimestamp: __classPrivateFieldGet(this, _TV_session, "f").player?.sts
}
},
serviceIntegrityDimensions: {
poToken: __classPrivateFieldGet(this, _TV_session, "f").po_token
},
client
});
const watch_next_response = await watch_next_endpoint.call(__classPrivateFieldGet(this, _TV_actions, "f"), {
client
});
const response = await Promise.all([watch_response, watch_next_response]);
const cpn = generateRandomString(16);
return new VideoInfo(response, __classPrivateFieldGet(this, _TV_actions, "f"), cpn);
}
async getHomeFeed() {
const client = 'TV';
const home_feed = new NavigationEndpoint({ browseEndpoint: {
browseId: 'default'
} });
const response = await home_feed.call(__classPrivateFieldGet(this, _TV_actions, "f"), {
client
});
return new HomeFeed(response, __classPrivateFieldGet(this, _TV_actions, "f"));
}
async getLibrary() {
const browse_endpoint = new NavigationEndpoint({ browseEndpoint: { browseId: 'FElibrary' } });
const response = await browse_endpoint.call(__classPrivateFieldGet(this, _TV_actions, "f"), {
client: 'TV'
});
return new Library(response, __classPrivateFieldGet(this, _TV_actions, "f"));
}
async getSubscriptionsFeed() {
const browse_endpoint = new NavigationEndpoint({ browseEndpoint: { browseId: 'FEsubscriptions' } });
const response = await browse_endpoint.call(__classPrivateFieldGet(this, _TV_actions, "f"), { client: 'TV' });
return new SubscriptionsFeed(response, __classPrivateFieldGet(this, _TV_actions, "f"));
}
/**
* Retrieves the user's playlists.
*/
async getPlaylists() {
const browse_endpoint = new NavigationEndpoint({ browseEndpoint: { browseId: 'FEplaylist_aggregation' } });
const response = await browse_endpoint.call(__classPrivateFieldGet(this, _TV_actions, "f"), { client: 'TV' });
return new PlaylistsFeed(response, __classPrivateFieldGet(this, _TV_actions, "f"));
}
/**
* Retrieves the user's My YouTube page.
*/
async getMyYoutubeFeed() {
const browse_endpoint = new NavigationEndpoint({ browseEndpoint: { browseId: 'FEmy_youtube' } });
const response = await browse_endpoint.call(__classPrivateFieldGet(this, _TV_actions, "f"), { client: 'TV' });
return new MyYoutubeFeed(response, __classPrivateFieldGet(this, _TV_actions, "f"));
}
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(__classPrivateFieldGet(this, _TV_actions, "f"), {
client: 'TV'
});
return new Playlist(response, __classPrivateFieldGet(this, _TV_actions, "f"));
}
// Utils
async fetchContinuationData(item, client) {
let continuation;
if (item.is(HorizontalList)) {
continuation = item.continuations?.first()?.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 __classPrivateFieldGet(this, _TV_actions, "f").execute('/browse', {
client: client ?? 'TV',
continuation: continuation
});
const parser = Parser.parseResponse(data.data);
return parser.continuation_contents;
}
// Interactions for TV (for default OAuth login)
/**
* Adds videos to a given playlist.
* @param playlist_id - The playlist ID.
* @param video_ids - An array of video IDs to add to the playlist.
* @param client - Innertube Client to use for request
*/
async addVideos(playlist_id, video_ids, client) {
throwIfMissing({ playlist_id, video_ids });
if (!__classPrivateFieldGet(this, _TV_actions, "f").session.logged_in)
throw new InnertubeError('You must be signed in to perform this operation.');
const playlist_edit_endpoint = new NavigationEndpoint({
playlistEditEndpoint: {
playlistId: playlist_id,
actions: video_ids.map((id) => ({
action: 'ACTION_ADD_VIDEO',
addedVideoId: id
}))
}
});
const response = await playlist_edit_endpoint.call(__classPrivateFieldGet(this, _TV_actions, "f"), {
client
});
return {
playlist_id,
action_result: response.data.actions // TODO: implement actions in the parser
};
}
/**
* Adds a given playlist to the library of a user.
* @param playlist_id - The playlist ID.
*/
async addToLibrary(playlist_id) {
throwIfMissing({ playlist_id });
if (!__classPrivateFieldGet(this, _TV_actions, "f").session.logged_in)
throw new InnertubeError('You must be signed in to perform this operation.');
const like_playlist_endpoint = new NavigationEndpoint({
likeEndpoint: {
status: 'LIKE',
target: playlist_id
}
});
return await like_playlist_endpoint.call(__classPrivateFieldGet(this, _TV_actions, "f"), {
client: 'TV'
});
}
/**
* Remove a given playlist to the library of a user.
* @param playlist_id - The playlist ID.
*/
async removeFromLibrary(playlist_id) {
throwIfMissing({ playlist_id });
if (!__classPrivateFieldGet(this, _TV_actions, "f").session.logged_in)
throw new InnertubeError('You must be signed in to perform this operation.');
const remove_like_playlist_endpoint = new NavigationEndpoint({
likeEndpoint: {
status: 'INDIFFERENT',
target: playlist_id
}
});
return await remove_like_playlist_endpoint.call(__classPrivateFieldGet(this, _TV_actions, "f"), {
client: 'TV'
});
}
}
_TV_session = new WeakMap(), _TV_actions = new WeakMap();
export default TV;
//# sourceMappingURL=TV.js.map