@np-dev/youtubei-js
Version:
A wrapper around YouTube's private API. Supports YouTube, YouTube Music, YouTube Kids and YouTube Studio (WIP).
239 lines • 11.1 kB
JavaScript
var _a, _Session_api_version, _Session_key, _Session_context, _Session_account_index, _Session_player, _Session_retrieveSessionData, _Session_generateSessionData;
import { __awaiter, __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
import * as Constants from '../utils/Constants.js';
import EventEmitterLike from '../utils/EventEmitterLike.js';
import Actions from './Actions.js';
import Player from './Player.js';
import * as Proto from '../proto/index.js';
import HTTPClient from '../utils/HTTPClient.js';
import { generateRandomString, getRandomUserAgent, InnertubeError, Platform, SessionError } from '../utils/Utils.js';
import OAuth from './OAuth.js';
export var ClientType;
(function (ClientType) {
ClientType["WEB"] = "WEB";
ClientType["KIDS"] = "WEB_KIDS";
ClientType["MUSIC"] = "WEB_REMIX";
ClientType["IOS"] = "iOS";
ClientType["ANDROID"] = "ANDROID";
ClientType["ANDROID_MUSIC"] = "ANDROID_MUSIC";
ClientType["ANDROID_CREATOR"] = "ANDROID_CREATOR";
ClientType["TV_EMBEDDED"] = "TVHTML5_SIMPLY_EMBEDDED_PLAYER";
})(ClientType || (ClientType = {}));
/**
* Represents an InnerTube session. This holds all the data needed to make requests to YouTube.
*/
class Session extends EventEmitterLike {
constructor(context, api_key, api_version, account_index, player, cookie, fetch, cache) {
super();
_Session_api_version.set(this, void 0);
_Session_key.set(this, void 0);
_Session_context.set(this, void 0);
_Session_account_index.set(this, void 0);
_Session_player.set(this, void 0);
__classPrivateFieldSet(this, _Session_context, context, "f");
__classPrivateFieldSet(this, _Session_account_index, account_index, "f");
__classPrivateFieldSet(this, _Session_key, api_key, "f");
__classPrivateFieldSet(this, _Session_api_version, api_version, "f");
__classPrivateFieldSet(this, _Session_player, player, "f");
this.http = new HTTPClient(this, cookie, fetch);
this.actions = new Actions(this);
this.oauth = new OAuth(this);
this.logged_in = !!cookie;
this.cache = cache;
}
on(type, listener) {
super.on(type, listener);
}
once(type, listener) {
super.once(type, listener);
}
static create(options = {}) {
return __awaiter(this, void 0, void 0, function* () {
const { context, api_key, api_version, account_index } = yield Session.getSessionData(options.lang, options.location, options.account_index, options.visitor_data, options.enable_safety_mode, options.generate_session_locally, options.device_category, options.client_type, options.timezone, options.fetch, options.on_behalf_of_user);
return new Session(context, api_key, api_version, account_index, options.retrieve_player === false ? undefined : yield Player.create(options.cache, options.fetch), options.cookie, options.fetch, options.cache);
});
}
static getSessionData(lang = '', location = '', account_index = 0, visitor_data = '', enable_safety_mode = false, generate_session_locally = false, device_category = 'desktop', client_name = ClientType.WEB, tz = Intl.DateTimeFormat().resolvedOptions().timeZone, fetch = Platform.shim.fetch, on_behalf_of_user) {
return __awaiter(this, void 0, void 0, function* () {
let session_data;
const session_args = { lang, location, time_zone: tz, device_category, client_name, enable_safety_mode, visitor_data, on_behalf_of_user };
if (generate_session_locally) {
session_data = __classPrivateFieldGet(this, _a, "m", _Session_generateSessionData).call(this, session_args);
}
else {
try {
// This can fail if the data changes or the request is blocked for some reason.
session_data = yield __classPrivateFieldGet(this, _a, "m", _Session_retrieveSessionData).call(this, session_args, fetch);
}
catch (err) {
session_data = __classPrivateFieldGet(this, _a, "m", _Session_generateSessionData).call(this, session_args);
}
}
return Object.assign(Object.assign({}, session_data), { account_index });
});
}
signIn(credentials) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
const error_handler = (err) => reject(err);
this.once('auth', (data) => {
this.off('auth-error', error_handler);
if (data.status === 'SUCCESS') {
this.logged_in = true;
resolve();
}
reject(data);
});
this.once('auth-error', error_handler);
try {
yield this.oauth.init(credentials);
if (this.oauth.validateCredentials()) {
yield this.oauth.refreshIfRequired();
this.logged_in = true;
resolve();
}
}
catch (err) {
reject(err);
}
}));
});
}
/**
* Signs out of the current account and revokes the credentials.
*/
signOut() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.logged_in)
throw new InnertubeError('You must be signed in to perform this operation.');
const response = yield this.oauth.revokeCredentials();
this.logged_in = false;
return response;
});
}
/**
* InnerTube API key.
*/
get key() {
return __classPrivateFieldGet(this, _Session_key, "f");
}
/**
* InnerTube API version.
*/
get api_version() {
return __classPrivateFieldGet(this, _Session_api_version, "f");
}
get client_version() {
return __classPrivateFieldGet(this, _Session_context, "f").client.clientVersion;
}
get client_name() {
return __classPrivateFieldGet(this, _Session_context, "f").client.clientName;
}
get account_index() {
return __classPrivateFieldGet(this, _Session_account_index, "f");
}
get context() {
return __classPrivateFieldGet(this, _Session_context, "f");
}
get player() {
return __classPrivateFieldGet(this, _Session_player, "f");
}
get lang() {
return __classPrivateFieldGet(this, _Session_context, "f").client.hl;
}
}
_a = Session, _Session_api_version = new WeakMap(), _Session_key = new WeakMap(), _Session_context = new WeakMap(), _Session_account_index = new WeakMap(), _Session_player = new WeakMap(), _Session_retrieveSessionData = function _Session_retrieveSessionData(options, fetch = Platform.shim.fetch) {
return __awaiter(this, void 0, void 0, function* () {
const url = new URL('/sw.js_data', Constants.URLS.YT_BASE);
let visitor_id = generateRandomString(11);
if (options.visitor_data) {
const decoded_visitor_data = Proto.decodeVisitorData(options.visitor_data);
visitor_id = decoded_visitor_data.id;
}
const res = yield fetch(url, {
headers: {
'accept-language': options.lang || 'en-US',
'user-agent': getRandomUserAgent('desktop'),
'accept': '*/*',
'referer': 'https://www.youtube.com/sw.js',
'cookie': `PREF=tz=${options.time_zone.replace('/', '.')};VISITOR_INFO1_LIVE=${visitor_id};`
}
});
if (!res.ok)
throw new SessionError(`Failed to retrieve session data: ${res.status}`);
const text = yield res.text();
const data = JSON.parse(text.replace(/^\)\]\}'/, ''));
const ytcfg = data[0][2];
const api_version = `v${ytcfg[0][0][6]}`;
const [[device_info], api_key] = ytcfg;
const context = {
client: {
hl: device_info[0],
gl: options.location || device_info[2],
remoteHost: device_info[3],
screenDensityFloat: 1,
screenHeightPoints: 1080,
screenPixelDensity: 1,
screenWidthPoints: 1920,
visitorData: device_info[13],
clientName: options.client_name,
clientVersion: device_info[16],
osName: device_info[17],
osVersion: device_info[18],
platform: options.device_category.toUpperCase(),
clientFormFactor: 'UNKNOWN_FORM_FACTOR',
userInterfaceTheme: 'USER_INTERFACE_THEME_LIGHT',
timeZone: device_info[79] || options.time_zone,
browserName: device_info[86],
browserVersion: device_info[87],
originalUrl: Constants.URLS.YT_BASE,
deviceMake: device_info[11],
deviceModel: device_info[12],
utcOffsetMinutes: -new Date().getTimezoneOffset()
},
user: {
enableSafetyMode: options.enable_safety_mode,
lockedSafetyMode: false,
onBehalfOfUser: options.on_behalf_of_user
}
};
return { context, api_key, api_version };
});
}, _Session_generateSessionData = function _Session_generateSessionData(options) {
let visitor_id = generateRandomString(11);
if (options.visitor_data) {
const decoded_visitor_data = Proto.decodeVisitorData(options.visitor_data);
visitor_id = decoded_visitor_data.id;
}
const context = {
client: {
hl: options.lang || 'en',
gl: options.location || 'US',
screenDensityFloat: 1,
screenHeightPoints: 1080,
screenPixelDensity: 1,
screenWidthPoints: 1920,
visitorData: Proto.encodeVisitorData(visitor_id, Math.floor(Date.now() / 1000)),
clientName: options.client_name,
clientVersion: Constants.CLIENTS.WEB.VERSION,
osName: 'Windows',
osVersion: '10.0',
platform: options.device_category.toUpperCase(),
clientFormFactor: 'UNKNOWN_FORM_FACTOR',
userInterfaceTheme: 'USER_INTERFACE_THEME_LIGHT',
timeZone: options.time_zone,
originalUrl: Constants.URLS.YT_BASE,
deviceMake: '',
deviceModel: '',
utcOffsetMinutes: -new Date().getTimezoneOffset()
},
user: {
enableSafetyMode: options.enable_safety_mode,
lockedSafetyMode: false,
onBehalfOfUser: options.on_behalf_of_user
}
};
return { context, api_key: Constants.CLIENTS.WEB.API_KEY, api_version: Constants.CLIENTS.WEB.API_VERSION };
};
export default Session;
//# sourceMappingURL=Session.js.map