Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

youtubei.js

Package Overview
Dependencies
Maintainers
1
Versions
124
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

youtubei.js - npm Package Compare versions

Comparing version 1.2.4 to 1.2.5

lib/Sig.js

16

lib/Actions.js

@@ -39,3 +39,3 @@ 'use strict';

const response = await Axios.post(`${Constants.urls.YT_BASE_URL}/youtubei/v1/${engagement_type}${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, JSON.stringify(data), Constants.innertube_request_opts({ session, id: args.video_id, data })).catch((error) => error);
const response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/${engagement_type}${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, JSON.stringify(data), Constants.INNERTUBE_REQOPTS({ session, id: args.video_id, data })).catch((error) => error);
if (response instanceof Error) return { success: false, status_code: response.response.status, message: response.message };

@@ -60,4 +60,4 @@ return {

}
const response = await Axios.post(`${Constants.urls.YT_BASE_URL}/youtubei/v1/browse${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, JSON.stringify(data), Constants.innertube_request_opts({ session })).catch((error) => error);
const response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/browse${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, JSON.stringify(data), Constants.INNERTUBE_REQOPTS({ session })).catch((error) => error);
if (response instanceof Error) return { success: false, status_code: response.response.status, message: response.message };

@@ -96,3 +96,3 @@ return {

const response = await Axios.post(`${Constants.urls.YT_BASE_URL}/youtubei/v1/notification/${action_type}${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, JSON.stringify(data), Constants.innertube_request_opts({ session })).catch((error) => error);
const response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/notification/${action_type}${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, JSON.stringify(data), Constants.INNERTUBE_REQOPTS({ session })).catch((error) => error);
if (response instanceof Error) return { success: false, status_code: response.response.status, message: response.message };

@@ -110,3 +110,3 @@ if (action_type === 'modify_channel_preference') return { success: true, status_code: response.status };

switch (action_type) {
case 'live_chat/send_message':
case 'live_chat/send_message':
data = {

@@ -134,4 +134,4 @@ context: session.context,

}
const response = await Axios.post(`${Constants.urls.YT_BASE_URL}/youtubei/v1/${action_type}${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, JSON.stringify(data), Constants.innertube_request_opts({ session, params: args.params })).catch((error) => error);
const response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/${action_type}${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, JSON.stringify(data), Constants.INNERTUBE_REQOPTS({ session, params: args.params })).catch((error) => error);
if (response instanceof Error) return { success: false, status_code: response.response.status, message: response.message };

@@ -161,3 +161,3 @@ return {

const response = await Axios.post(`${Constants.urls.YT_BASE_URL}/youtubei/v1/next${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, JSON.stringify(data), Constants.innertube_request_opts({ session })).catch((error) => error);
const response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/next${session.logged_in && session.cookie.length < 1 ? '' : `?key=${session.key}`}`, JSON.stringify(data), Constants.INNERTUBE_REQOPTS({ session })).catch((error) => error);
if (response instanceof Error) return { success: false, status_code: response.response.status, message: response.message };

@@ -164,0 +164,0 @@ return {

@@ -5,326 +5,262 @@ 'use strict';

const urls = {
YT_BASE_URL: 'https://www.youtube.com',
YT_MOBILE_URL: 'https://m.youtube.com',
YT_WATCH_PAGE: 'https://m.youtube.com/watch',
};
const oauth = {
scope: 'http://gdata.youtube.com https://www.googleapis.com/auth/youtube-paid-content',
grant_type: 'http://oauth.net/grant_type/device/1.0',
model_name: 'ytlr::'
};
const oauth_reqopts = {
headers: {
'accept': '*/*',
'origin': urls.YT_BASE_URL,
'user-agent': 'Mozilla/5.0 (ChromiumStylePlatform) Cobalt/Version',
'content-type': 'application/json',
'referer': `${urls.YT_BASE_URL}/tv`,
'accept-language': 'en-US'
}
};
const default_headers = (session) => {
return {
headers: {
'Cookie': session.cookie,
'user-agent': Utils.getRandomUserAgent('desktop').userAgent,
'Referer': 'https://www.google.com/',
'Accept': 'text/html',
'Accept-Language': 'en-US,en',
'Accept-Encoding': 'gzip',
'Upgrade-Insecure-Requests': 1
module.exports = {
URLS: {
YT_BASE_URL: 'https://www.youtube.com',
YT_MOBILE_URL: 'https://m.youtube.com',
YT_WATCH_PAGE: 'https://m.youtube.com/watch'
},
OAUTH: {
SCOPE: 'http://gdata.youtube.com https://www.googleapis.com/auth/youtube-paid-content',
GRANT_TYPE: 'http://oauth.net/grant_type/device/1.0',
MODEL_NAME: 'ytlr::',
HEADERS: {
headers: {
'accept': '*/*',
'origin': 'https://www.youtube.com',
'user-agent': 'Mozilla/5.0 (ChromiumStylePlatform) Cobalt/Version',
'content-type': 'application/json',
'referer': `https://www.youtube.com/tv`,
'accept-language': 'en-US'
}
}
};
};
const innertube_request_opts = (info) => {
info.desktop === undefined && (info.desktop = true);
let req_opts = {
params: info.params || {},
headers: {
'accept': '*/*',
'user-agent': Utils.getRandomUserAgent(info.desktop ? 'desktop' : 'mobile').userAgent,
'content-type': 'application/json',
'accept-language': 'en-US,en;q=0.9',
'x-goog-authuser': 0,
'x-goog-visitor-id': info.session.context.client.visitorData,
'x-youtube-client-name': info.desktop ? 1 : 2,
'x-youtube-client-version': info.session.context.client.clientVersion,
'x-youtube-chrome-connected': 'source=Chrome,mode=0,enable_account_consistency=true,supervised=false,consistency_enabled_by_default=false',
'x-origin': info.desktop ? urls.YT_BASE_URL : urls.YT_MOBILE_URL,
'origin': info.desktop ? urls.YT_BASE_URL : urls.YT_MOBILE_URL,
}
};
info.id && (req_opts.headers.referer = (info.desktop ? urls.YT_BASE_URL : urls.YT_MOBILE_URL) + '/watch?v=' + info.id);
if (info.session.logged_in && info.desktop) {
req_opts.headers.Cookie = info.session.cookie;
req_opts.headers.authorization = info.session.cookie.length < 1 ? `Bearer ${info.session.access_token}` : info.session.auth_apisid;
}
return req_opts;
};
const video_details_reqbody = (id, sts, context) => {
return {
playbackContext: {
contentPlaybackContext: {
'currentUrl': '/watch?v=' + id,
'vis': 0,
'splay': false,
'autoCaptionsDefaultOn': false,
'autonavState': 'STATE_OFF',
'html5Preference': 'HTML5_PREF_WANTS',
'signatureTimestamp': sts,
'referer': urls.YT_BASE_URL,
'lactMilliseconds': '-1'
},
DEFAULT_HEADERS: (session) => {
return {
headers: {
'Cookie': session.cookie,
'user-agent': Utils.getRandomUserAgent('desktop').userAgent,
'Referer': 'https://www.google.com/',
'Accept': 'text/html',
'Accept-Language': 'en-US,en',
'Accept-Encoding': 'gzip',
'Upgrade-Insecure-Requests': 1
}
},
context: context,
videoId: id
};
};
const stream_headers = (range) => {
let headers = {
};
},
STREAM_HEADERS: {
'Accept': '*/*',
'User-Agent': Utils.getRandomUserAgent('desktop').userAgent,
'Connection': 'keep-alive',
'Origin': urls.YT_BASE_URL,
'Referer': urls.YT_BASE_URL,
'Origin': 'https://www.youtube.com',
'Referer': 'https://www.youtube.com',
'DNT': '?1'
};
range && (headers.Range = range);
return headers;
};
},
INNERTUBE_REQOPTS: (info) => {
info.desktop === undefined && (info.desktop = true);
let req_opts = {
params: info.params || {},
headers: {
'accept': '*/*',
'user-agent': Utils.getRandomUserAgent(info.desktop ? 'desktop' : 'mobile').userAgent,
'content-type': 'application/json',
'accept-language': 'en-US,en;q=0.9',
'x-goog-authuser': 0,
'x-goog-visitor-id': info.session.context.client.visitorData,
'x-youtube-client-name': info.desktop ? 1 : 2,
'x-youtube-client-version': info.session.context.client.clientVersion,
'x-youtube-chrome-connected': 'source=Chrome,mode=0,enable_account_consistency=true,supervised=false,consistency_enabled_by_default=false',
'x-origin': info.desktop ? 'https://www.youtube.com' : 'https://m.youtube.com',
'origin': info.desktop ? 'https://www.youtube.com' : 'https://m.youtube.com',
}
};
const formatVideoData = (data, context, desktop) => {
let video_details = {};
let metadata = {};
info.id && (req_opts.headers.referer = (info.desktop ? 'https://www.youtube.com' : 'https://m.youtube.com') + '/watch?v=' + info.id);
if (desktop) {
metadata.embed = data.microformat.playerMicroformatRenderer.embed;
metadata.view_count = parseInt(data.videoDetails.viewCount);
metadata.average_rating = data.videoDetails.averageRating;
metadata.length_seconds = data.microformat.playerMicroformatRenderer.lengthSeconds;
metadata.channel_id = data.videoDetails.channelId;
metadata.channel_url = data.microformat.playerMicroformatRenderer.ownerProfileUrl;
metadata.external_channel_id = data.microformat.playerMicroformatRenderer.externalChannelId;
metadata.is_live_content = data.videoDetails.isLiveContent;
metadata.is_family_safe = data.microformat.playerMicroformatRenderer.isFamilySafe;
metadata.is_unlisted = data.microformat.playerMicroformatRenderer.isUnlisted;
metadata.is_private = data.videoDetails.isPrivate;
metadata.has_ypc_metadata = data.microformat.playerMicroformatRenderer.hasYpcMetadata;
metadata.category = data.microformat.playerMicroformatRenderer.category;
metadata.channel_name = data.microformat.playerMicroformatRenderer.ownerChannelName;
metadata.publish_date = data.microformat.playerMicroformatRenderer.publishDate || 'N/A';
metadata.upload_date = data.microformat.playerMicroformatRenderer.uploadDate || 'N/A';
metadata.keywords = data.videoDetails.keywords || [];
if (info.session.logged_in && info.desktop) {
req_opts.headers.Cookie = info.session.cookie;
req_opts.headers.authorization = info.session.cookie.length < 1 ? `Bearer ${info.session.access_token}` : info.session.auth_apisid;
}
video_details.title = data.videoDetails.title;
video_details.description = data.videoDetails.shortDescription;
video_details.thumbnail = data.videoDetails.thumbnail.thumbnails.slice(-1)[0];
video_details.metadata = metadata;
} else {
metadata.embed = data[2].playerResponse.microformat.playerMicroformatRenderer.embed;
metadata.likes = parseInt(data[3].response.contents.singleColumnWatchNextResults.results.results.contents[1].slimVideoMetadataSectionRenderer.contents[1].slimVideoActionBarRenderer.buttons[0].slimMetadataToggleButtonRenderer.button.toggleButtonRenderer.defaultText.accessibility.accessibilityData.label.replace(/\D/g, ''));
metadata.dislikes = parseInt(data[3].response.contents.singleColumnWatchNextResults.results.results.contents[1].slimVideoMetadataSectionRenderer.contents[1].slimVideoActionBarRenderer.buttons[1].slimMetadataToggleButtonRenderer.button.toggleButtonRenderer.defaultText.accessibility.accessibilityData.label.replace(/\D/g, ''));
metadata.view_count = parseInt(data[2].playerResponse.videoDetails.viewCount);
metadata.average_rating = data[2].playerResponse.videoDetails.averageRating;
metadata.length_seconds = data[2].playerResponse.microformat.playerMicroformatRenderer.lengthSeconds;
metadata.channel_id = data[2].playerResponse.videoDetails.channelId;
metadata.channel_url = data[2].playerResponse.microformat.playerMicroformatRenderer.ownerProfileUrl;
metadata.external_channel_id = data[2].playerResponse.microformat.playerMicroformatRenderer.externalChannelId;
metadata.is_live_content = data[2].playerResponse.videoDetails.isLiveContent;
metadata.is_family_safe = data[2].playerResponse.microformat.playerMicroformatRenderer.isFamilySafe;
metadata.is_unlisted = data[2].playerResponse.microformat.playerMicroformatRenderer.isUnlisted;
metadata.is_private = data[2].playerResponse.videoDetails.isPrivate;
metadata.has_ypc_metadata = data[2].playerResponse.microformat.playerMicroformatRenderer.hasYpcMetadata;
metadata.category = data[2].playerResponse.microformat.playerMicroformatRenderer.category;
metadata.channel_name = data[2].playerResponse.microformat.playerMicroformatRenderer.ownerChannelName;
metadata.publish_date = data[2].playerResponse.microformat.playerMicroformatRenderer.publishDate;
metadata.upload_date = data[2].playerResponse.microformat.playerMicroformatRenderer.uploadDate;
metadata.keywords = data[2].playerResponse.videoDetails.keywords;
return req_opts;
},
VIDEO_INFO_REQBODY: (id, sts, context) => {
return {
playbackContext: {
contentPlaybackContext: {
'currentUrl': '/watch?v=' + id,
'vis': 0,
'splay': false,
'autoCaptionsDefaultOn': false,
'autonavState': 'STATE_OFF',
'html5Preference': 'HTML5_PREF_WANTS',
'signatureTimestamp': sts,
'referer': 'https://www.youtube.com',
'lactMilliseconds': '-1'
}
},
context: context,
videoId: id
};
},
BASE64_DIALECT: {
NORMAL: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'.split(''),
REVERSE: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_'.split('')
},
FUNCS_REGEX: /d\.push\(e\)|d\.reverse\(\)|d\[0\]\)\[0\]\)|f=d\[0];d\[0\]|d\.length;d\.splice\(e,1\)|function\(\){for\(var|function\(d,e,f\){var h=f|function\(d\){for\(var|reverse\(\)\.forEach|unshift\(d\.pop\(\)\)|function\(d,e\){for\(var f/,
FUNCS: {
PUSH: 'd.push(e)',
REVERSE_1: 'd.reverse()',
REVERSE_2: 'function(d){for(var',
SPLICE: 'd.length;d.splice(e,1)',
SWAP0_1: 'd[0])[0])',
SWAP0_2: 'f=d[0];d[0]',
ROTATE_1: 'reverse().forEach',
ROTATE_2: 'unshift(d.pop())',
BASE64_DIA: 'function(){for(var',
TRANSLATE_1: 'function(d,e){for(var f',
TRANSLATE_2: 'function(d,e,f){var h=f'
},
// Helper functions, felt like Utils.js wasn't the right place for them:
formatNTransformData: (data) => {
return data
.replace(/function\(d,e\)/g, '"function(d,e)').replace(/function\(d\)/g, '"function(d)')
.replace(/function\(\)/, '"function()').replace(/function\(d,e,f\)/g, '"function(d,e,f)')
.replace(/,b,/g, ',"b",').replace(/,b/g, ',"b"').replace(/b,/g, '"b",').replace(/b]/g, '"b"]')
.replace(/\[b/g, '["b"').replace(/}]/g, '"]').replace(/},/g, '}",').replace(/""/g, '')
.replace(/length]\)}"/g, 'length])}');
},
formatVideoData: (data, context, is_desktop) => {
let video_details = {};
let metadata = {};
video_details.title = data[2].playerResponse.videoDetails.title;
video_details.description = data[2].playerResponse.videoDetails.shortDescription;
video_details.thumbnail = data[2].playerResponse.videoDetails.thumbnail.thumbnails.slice(-1)[0];
if (is_desktop) {
metadata.embed = data.microformat.playerMicroformatRenderer.embed;
metadata.view_count = parseInt(data.videoDetails.viewCount);
metadata.average_rating = data.videoDetails.averageRating;
metadata.length_seconds = data.microformat.playerMicroformatRenderer.lengthSeconds;
metadata.channel_id = data.videoDetails.channelId;
metadata.channel_url = data.microformat.playerMicroformatRenderer.ownerProfileUrl;
metadata.external_channel_id = data.microformat.playerMicroformatRenderer.externalChannelId;
metadata.is_live_content = data.videoDetails.isLiveContent;
metadata.is_family_safe = data.microformat.playerMicroformatRenderer.isFamilySafe;
metadata.is_unlisted = data.microformat.playerMicroformatRenderer.isUnlisted;
metadata.is_private = data.videoDetails.isPrivate;
metadata.has_ypc_metadata = data.microformat.playerMicroformatRenderer.hasYpcMetadata;
metadata.category = data.microformat.playerMicroformatRenderer.category;
metadata.channel_name = data.microformat.playerMicroformatRenderer.ownerChannelName;
metadata.publish_date = data.microformat.playerMicroformatRenderer.publishDate || 'N/A';
metadata.upload_date = data.microformat.playerMicroformatRenderer.uploadDate || 'N/A';
metadata.keywords = data.videoDetails.keywords || [];
// Functions
video_details.like = () => {};
video_details.dislike = () => {};
video_details.removeLike = () => {};
video_details.subscribe = () => {};
video_details.unsubscribe = () => {};
video_details.comment = () => {};
video_details.getComments = () => {};
video_details.setNotificationPref = () => {};
video_details.getLivechat = () => {};
video_details.title = data.videoDetails.title;
video_details.description = data.videoDetails.shortDescription;
video_details.thumbnail = data.videoDetails.thumbnail.thumbnails.slice(-1)[0];
video_details.metadata = metadata;
} else {
metadata.embed = data[2].playerResponse.microformat.playerMicroformatRenderer.embed;
metadata.likes = parseInt(data[3].response.contents.singleColumnWatchNextResults.results.results.contents[1].slimVideoMetadataSectionRenderer.contents[1].slimVideoActionBarRenderer.buttons[0].slimMetadataToggleButtonRenderer.button.toggleButtonRenderer.defaultText.accessibility.accessibilityData.label.replace(/\D/g, ''));
metadata.dislikes = parseInt(data[3].response.contents.singleColumnWatchNextResults.results.results.contents[1].slimVideoMetadataSectionRenderer.contents[1].slimVideoActionBarRenderer.buttons[1].slimMetadataToggleButtonRenderer.button.toggleButtonRenderer.defaultText.accessibility.accessibilityData.label.replace(/\D/g, ''));
metadata.view_count = parseInt(data[2].playerResponse.videoDetails.viewCount);
metadata.average_rating = data[2].playerResponse.videoDetails.averageRating;
metadata.length_seconds = data[2].playerResponse.microformat.playerMicroformatRenderer.lengthSeconds;
metadata.channel_id = data[2].playerResponse.videoDetails.channelId;
metadata.channel_url = data[2].playerResponse.microformat.playerMicroformatRenderer.ownerProfileUrl;
metadata.external_channel_id = data[2].playerResponse.microformat.playerMicroformatRenderer.externalChannelId;
metadata.is_live_content = data[2].playerResponse.videoDetails.isLiveContent;
metadata.is_family_safe = data[2].playerResponse.microformat.playerMicroformatRenderer.isFamilySafe;
metadata.is_unlisted = data[2].playerResponse.microformat.playerMicroformatRenderer.isUnlisted;
metadata.is_private = data[2].playerResponse.videoDetails.isPrivate;
metadata.has_ypc_metadata = data[2].playerResponse.microformat.playerMicroformatRenderer.hasYpcMetadata;
metadata.category = data[2].playerResponse.microformat.playerMicroformatRenderer.category;
metadata.channel_name = data[2].playerResponse.microformat.playerMicroformatRenderer.ownerChannelName;
metadata.publish_date = data[2].playerResponse.microformat.playerMicroformatRenderer.publishDate;
metadata.upload_date = data[2].playerResponse.microformat.playerMicroformatRenderer.uploadDate;
metadata.keywords = data[2].playerResponse.videoDetails.keywords;
// Additional metadata
video_details.metadata = metadata;
}
return video_details;
};
video_details.title = data[2].playerResponse.videoDetails.title;
video_details.description = data[2].playerResponse.videoDetails.shortDescription;
video_details.thumbnail = data[2].playerResponse.videoDetails.thumbnail.thumbnails.slice(-1)[0];
const base64_alphabet = {
normal: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'.split(''),
reverse: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_'.split('')
};
// Functions
video_details.like = () => {};
video_details.dislike = () => {};
video_details.removeLike = () => {};
video_details.subscribe = () => {};
video_details.unsubscribe = () => {};
video_details.comment = () => {};
video_details.getComments = () => {};
video_details.setNotificationPref = () => {};
video_details.getLivechat = () => {};
const filters = (order) => {
// It seems like all of these are just proto buffers, so I think it'll be easy to refactor
switch (order) {
case 'any,any,relevance':
return 'EgIQAQ%3D%3D';
case 'hour,any,relevance':
return 'EgIIAQ%3D%3D';
case 'day,any,relevance':
return 'EgQIAhAB';
case 'week,any,relevance':
return 'EgQIAxAB';
case 'month,any,relevance':
return 'EgQIBBAB';
case 'year,any,relevance':
return 'EgQIBRAB';
case 'any,short,relevance':
return 'EgQQARgB';
case 'hour,short,relevance':
return 'EgYIARABGAE%3D';
case 'day,short,relevance':
return 'EgYIAhABGAE%3D';
case 'week,short,relevance':
return 'EgYIAxABGAE%3D';
case 'month,short,relevance':
return 'EgYIBBABGAE%3D';
case 'year,short,relevance':
return 'EgYIBRABGAE%3D';
case 'any,long,relevance':
return 'EgQQARgC';
case 'hour,long,relevance':
return 'EgYIARABGAI%3D';
case 'day,long,relevance':
return 'EgYIAhABGAI%3D';
case 'week,long,relevance':
return 'EgYIAxABGAI%3D';
case 'month,long,relevance':
return 'EgYIBBABGAI%3D';
case 'year,long,relevance':
return 'EgYIBRABGAI%3D';
case 'any,any,age':
return 'CAISAhAB';
case 'hour,any,age':
return 'CAISBAgBEAE%3D';
case 'day,any,age':
return 'CAISBAgCEAE%3D';
case 'week,any,age':
return 'CAISBAgDEAE%3D';
case 'month,any,age':
return 'CAISBAgEEAE%3D';
case 'year,any,age':
return 'CAISBAgFEAE%3D';
case 'any,short,age':
return 'CAISBBABGAE%3D';
case 'hour,short,age':
return 'CAISBggBEAEYAQ%3D%3D';
case 'day,short,age':
return 'CAISBggCEAEYAQ%3D%3D';
case 'week,short,age':
return 'CAISBggDEAEYAQ%3D%3D';
case 'month,short,age':
return 'CAISBggEEAEYAQ%3D%3D';
case 'year,short,age':
return 'CAISBggFEAEYAQ%3D%3D';
case 'any,long,age':
return 'CAISBBABGAI%3D';
case 'hour,long,age':
return 'CAISBggBEAEYAg%3D%3D';
case 'day,long,age':
return 'CAISBggCEAEYAg%3D%3D';
case 'week,long,age':
return 'CAISBggDEAEYAg%3D%3D';
case 'month,long,age':
return 'CAISBggEEAEYAg%3D%3D';
case 'year,long,age':
return 'CAISBggFEAEYAg%3D%3D';
case 'any,any,views':
return 'CAMSAhAB';
case 'hour,any,views':
return 'CAMSBAgBEAE%3D';
case 'day,any,views':
return 'CAMSBAgCEAE%3D';
case 'week,any,views':
return 'CAMSBAgDEAE%3D';
case 'month,any,views':
return 'CAMSBAgEEAE%3D';
case 'year,any,views':
return 'CAMSBAgFEAE%3D';
case 'any,short,views':
return 'CAMSBBABGAE%3D';
case 'hour,short,views':
return 'CAMSBggBEAEYAQ%3D%3D';
case 'day,short,views':
return 'CAMSBggCEAEYAQ%3D%3D';
case 'week,short,views':
return 'CAMSBggDEAEYAQ%3D%3D';
case 'month,short,views':
return 'CAMSBggEEAEYAQ%3D%3D';
case 'year,short,views':
return 'CAMSBggFEAEYAQ%3D%3D';
case 'any,long,views':
return 'CAMSBBABGAI%3D';
case 'hour,long,views':
return 'CAMSBggBEAEYAg%3D%3D';
case 'day,long,views':
return 'CAMSBggCEAEYAg%3D%3D';
case 'week,long,views':
return 'CAMSBggDEAEYAg%3D%3D';
case 'month,long,views':
return 'CAMSBggEEAEYAg%3D%3D';
case 'year,long,views':
return 'CAMSBggFEAEYAg%3D%3D';
case 'any,any,rating':
return 'CAESAhAB';
case 'hour,any,rating':
return 'CAESBAgBEAE%3D';
case 'day,any,rating':
return 'CAESBAgCEAE%3D';
case 'week,any,rating':
return 'CAESBAgDEAE%3D';
case 'month,any,rating':
return 'CAESBAgEEAE%3D';
case 'year,any,rating':
return 'CAESBAgFEAE%3D';
case 'any,short,rating':
return 'CAESBBABGAE%3D';
case 'hour,short,rating':
return 'CAESBggBEAEYAQ%3D%3D';
case 'day,short,rating':
return 'CAESBggCEAEYAQ%3D%3D';
case 'week,short,rating':
return 'CAESBggDEAEYAQ%3D%3D';
case 'month,short,rating':
return 'CAESBggEEAEYAQ%3D%3D';
case 'year,short,rating':
return 'CAESBggFEAEYAQ%3D%3D';
case 'any,long,rating':
return 'CAESBBABGAI%3D';
case 'hour,long,rating':
return 'CAESBggBEAEYAg%3D%3D';
case 'day,long,rating':
return 'CAESBggCEAEYAg%3D%3D';
case 'week,long,rating':
return 'CAESBggDEAEYAg%3D%3D';
case 'month,long,rating':
return 'CAESBggEEAEYAg%3D%3D';
case 'year,long,rating':
return 'CAESBggFEAEYAg%3D%3D';
default:
// Additional metadata
video_details.metadata = metadata;
}
return video_details;
},
filters: (order) => {
return (({
'any,any,relevance': 'EgIQAQ%3D%3D',
'hour,any,relevance': 'EgIIAQ%3D%3D',
'day,any,relevance': 'EgQIAhAB',
'week,any,relevance': 'EgQIAxAB',
'month,any,relevance': 'EgQIBBAB',
'year,any,relevance': 'EgQIBRAB',
'any,short,relevance': 'EgQQARgB',
'hour,short,relevance': 'EgYIARABGAE%3D',
'day,short,relevance': 'EgYIAhABGAE%3D',
'week,short,relevance': 'EgYIAxABGAE%3D',
'month,short,relevance': 'EgYIBBABGAE%3D',
'year,short,relevance': 'EgYIBRABGAE%3D',
'any,long,relevance': 'EgQQARgC',
'hour,long,relevance': 'EgYIARABGAI%3D',
'day,long,relevance': 'EgYIAhABGAI%3D',
'week,long,relevance': 'EgYIAxABGAI%3D',
'month,long,relevance': 'EgYIBBABGAI%3D',
'year,long,relevance': 'EgYIBRABGAI%3D',
'any,any,age': 'CAISAhAB',
'hour,any,age': 'CAISBAgBEAE%3D',
'day,any,age': 'CAISBAgCEAE%3D',
'week,any,age': 'CAISBAgDEAE%3D',
'month,any,age': 'CAISBAgEEAE%3D',
'year,any,age': 'CAISBAgFEAE%3D',
'any,short,age': 'CAISBBABGAE%3D',
'hour,short,age': 'CAISBggBEAEYAQ%3D%3D',
'day,short,age': 'CAISBggCEAEYAQ%3D%3D',
'week,short,age': 'CAISBggDEAEYAQ%3D%3D',
'month,short,age': 'CAISBggEEAEYAQ%3D%3D',
'year,short,age': 'CAISBggFEAEYAQ%3D%3D',
'any,long,age': 'CAISBBABGAI%3D',
'hour,long,age': 'CAISBggBEAEYAg%3D%3D',
'day,long,age': 'CAISBggCEAEYAg%3D%3D',
'week,long,age': 'CAISBggDEAEYAg%3D%3D',
'month,long,age': 'CAISBggEEAEYAg%3D%3D',
'year,long,age': 'CAISBggFEAEYAg%3D%3D',
'any,any,views': 'CAMSAhAB',
'hour,any,views': 'CAMSBAgBEAE%3D',
'day,any,views': 'CAMSBAgCEAE%3D',
'week,any,views': 'CAMSBAgDEAE%3D',
'month,any,views': 'CAMSBAgEEAE%3D',
'year,any,views': 'CAMSBAgFEAE%3D',
'any,short,views': 'CAMSBBABGAE%3D',
'hour,short,views': 'CAMSBggBEAEYAQ%3D%3D',
'day,short,views': 'CAMSBggCEAEYAQ%3D%3D',
'week,short,views': 'CAMSBggDEAEYAQ%3D%3D',
'month,short,views': 'CAMSBggEEAEYAQ%3D%3D',
'year,short,views': 'CAMSBggFEAEYAQ%3D%3D',
'any,long,views': 'CAMSBBABGAI%3D',
'hour,long,views': 'CAMSBggBEAEYAg%3D%3D',
'day,long,views': 'CAMSBggCEAEYAg%3D%3D',
'week,long,views': 'CAMSBggDEAEYAg%3D%3D',
'month,long,views': 'CAMSBggEEAEYAg%3D%3D',
'year,long,views': 'CAMSBggFEAEYAg%3D%3D',
'any,any,rating': 'CAESAhAB',
'hour,any,rating': 'CAESBAgBEAE%3D',
'day,any,rating': 'CAESBAgCEAE%3D',
'week,any,rating': 'CAESBAgDEAE%3D',
'month,any,rating': 'CAESBAgEEAE%3D',
'year,any,rating': 'CAESBAgFEAE%3D',
'any,short,rating': 'CAESBBABGAE%3D',
'hour,short,rating': 'CAESBggBEAEYAQ%3D%3D',
'day,short,rating': 'CAESBggCEAEYAQ%3D%3D',
'week,short,rating': 'CAESBggDEAEYAQ%3D%3D',
'month,short,rating': 'CAESBggEEAEYAQ%3D%3D',
'year,short,rating': 'CAESBggFEAEYAQ%3D%3D',
'any,long,rating': 'CAESBBABGAI%3D',
'hour,long,rating': 'CAESBggBEAEYAg%3D%3D',
'day,long,rating': 'CAESBggCEAEYAg%3D%3D',
'week,long,rating': 'CAESBggDEAEYAg%3D%3D',
'month,long,rating': 'CAESBggEEAEYAg%3D%3D',
'year,long,rating': 'CAESBggFEAEYAg%3D%3D'
})[order] || 'EgIQAQ%3D%3D');
}
};
module.exports = { urls, oauth, oauth_reqopts, default_headers, innertube_request_opts, video_details_reqbody, stream_headers, formatVideoData, base64_alphabet, filters };
};

@@ -12,3 +12,3 @@ 'use strict';

const Constants = require('./Constants');
const SigDecipher = require('./SigDecipher');
const SigDecipher = require('./Sig');
const EventEmitter = require('events');

@@ -22,2 +22,3 @@ const TimeToSeconds = require('time-to-seconds');

this.cookie = cookie || '';
this.retry_count = 0;
return this.init();

@@ -27,5 +28,5 @@ }

async init() {
const response = await Axios.get(Constants.urls.YT_BASE_URL, Constants.default_headers(this)).catch((error) => error);
const response = await Axios.get(Constants.URLS.YT_BASE_URL, Constants.DEFAULT_HEADERS(this)).catch((error) => error);
if (response instanceof Error) throw new Error(`Could not extract Innertube data: ${response.message}`);
try {

@@ -52,5 +53,9 @@ const innertube_data = JSON.parse(`{${Utils.getStringBetweenStrings(response.data, 'ytcfg.set({', '});')}}`);

} else {
this.retry_count += 1;
if (this.retry_count >= 10) throw new Error('Could not retrieve Innertube data');
return this.init();
}
} catch (err) {
this.retry_count += 1;
if (this.retry_count >= 10) throw new Error('Could not retrieve Innertube data');
return this.init();

@@ -103,4 +108,4 @@ }

if (!query) throw new Error('No query was provided');
const response = await Axios.post(`${Constants.urls.YT_BASE_URL}/youtubei/v1/search${this.logged_in && this.cookie.length < 1 ? '' : `?key=${this.key}`}`, JSON.stringify({ context: this.context, params: Constants.filters(options.period + ',' + options.duration + ',' + options.order), query }), Constants.innertube_request_opts({ session: this })).catch((error) => error);
const response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/search${this.logged_in && this.cookie.length < 1 ? '' : `?key=${this.key}`}`, JSON.stringify({ context: this.context, params: Constants.filters(options.period + ',' + options.duration + ',' + options.order), query }), Constants.INNERTUBE_REQOPTS({ session: this })).catch((error) => error);
if (response instanceof Error) throw new Error(`Could not search on YouTube: ${response.message}`);

@@ -124,3 +129,3 @@

url: `https://youtu.be/${video.videoId}`,
channel_url: `${Constants.urls.YT_BASE_URL}${video.ownerText.runs[0].navigationEndpoint.commandMetadata.webCommandMetadata.url}`,
channel_url: `${Constants.URLS.YT_BASE_URL}${video.ownerText.runs[0].navigationEndpoint.commandMetadata.webCommandMetadata.url}`,
metadata: {

@@ -160,3 +165,3 @@ view_count: video.viewCountText && video.viewCountText.simpleText || 'N/A',

}
video_data.like = () => Actions.engage(this, 'like/like', { video_id: id });

@@ -173,6 +178,6 @@ video_data.dislike = () => Actions.engage(this, 'like/dislike', { video_id: id });

}
async getComments(video_id, token) {
let comment_section_token;
if (!token) {

@@ -183,22 +188,21 @@ const data_continuation = await Actions.getContinuation(this, { video_id });

}
const response = await Actions.getContinuation(this, { continuation_token: comment_section_token || token });
if (!response.success) throw new Error('Could not fetch comments section');
const comments_section = { comments: [] };
!token && (comments_section.comment_count = response.data.onResponseReceivedEndpoints[0].reloadContinuationItemsCommand.continuationItems && response.data.onResponseReceivedEndpoints[0].reloadContinuationItemsCommand.continuationItems[0].commentsHeaderRenderer.countText.runs[0].text || 'N/A');
let continuation_token;
!token && (continuation_token = response.data.onResponseReceivedEndpoints[1].reloadContinuationItemsCommand.continuationItems.find((item) => item.continuationItemRenderer).continuationItemRenderer.continuationEndpoint.continuationCommand.token)
|| (continuation_token = response.data.onResponseReceivedEndpoints[0].appendContinuationItemsAction.continuationItems.find((item) => item.continuationItemRenderer).continuationItemRenderer.continuationEndpoint.continuationCommand.token);
!token && (continuation_token = response.data.onResponseReceivedEndpoints[1].reloadContinuationItemsCommand.continuationItems.find((item) => item.continuationItemRenderer).continuationItemRenderer.continuationEndpoint.continuationCommand.token) ||
(continuation_token = response.data.onResponseReceivedEndpoints[0].appendContinuationItemsAction.continuationItems.find((item) => item.continuationItemRenderer).continuationItemRenderer.continuationEndpoint.continuationCommand.token);
comments_section.getContinuation = () => this.getComments(video_id, continuation_token);
let contents;
!token && (contents = response.data.onResponseReceivedEndpoints[1].reloadContinuationItemsCommand.continuationItems)
|| (contents = response.data.onResponseReceivedEndpoints[0].appendContinuationItemsAction.continuationItems);
!token && (contents = response.data.onResponseReceivedEndpoints[1].reloadContinuationItemsCommand.continuationItems) ||
(contents = response.data.onResponseReceivedEndpoints[0].appendContinuationItemsAction.continuationItems);
contents.forEach((thread) => {
if (!thread.commentThreadRenderer) return;
console.log(thread.commentThreadRenderer.comment);
const comment = {

@@ -222,22 +226,22 @@ text: thread.commentThreadRenderer.comment.commentRenderer.contentText.runs.map((t) => t.text).join(' '),

});
return comments_section;
}
async getSubscriptionsFeed() {
const response = await Actions.browse(this, 'subscriptions_feed');
if (!response.success) throw new Error('Could not fetch subscriptions feed');
const contents = response.data.contents.twoColumnBrowseResultsRenderer.tabs[0].tabRenderer.content.sectionListRenderer.contents;
const subscriptions_feed = {};
contents.forEach((section) => {
if (!section.itemSectionRenderer) return;
const section_contents = section.itemSectionRenderer.contents[0];
const section_items = section_contents.shelfRenderer.content.gridRenderer.items;
const key = section_contents.shelfRenderer.title.runs[0].text;
subscriptions_feed[key.toLowerCase().replace(/ +/g, '_')] = [];
section_items.forEach((item) => {

@@ -256,7 +260,7 @@ const content = {

};
subscriptions_feed[key.toLowerCase().replace(/ +/g, '_')].push(content);
});
});
return subscriptions_feed;

@@ -268,3 +272,3 @@ }

if (!response.success) throw new Error('Could not fetch notifications');
const contents = response.data.actions[0].openPopupAction.popup.multiPageMenuRenderer.sections[0];

@@ -296,4 +300,4 @@ if (!contents.multiPageMenuNotificationSectionRenderer) return { error: 'You don\'t have any notification.' };

let response;
!desktop && (response = await Axios.get(`${Constants.urls.YT_WATCH_PAGE}?v=${id}&t=8s&pbj=1`, Constants.innertube_request_opts({ session: this, id, desktop: false })).catch((error) => error))
|| (response = await Axios.post(`${Constants.urls.YT_BASE_URL}/youtubei/v1/player${this.logged_in && this.cookie.length < 1 ? '' : `?key=${this.key}`}`, JSON.stringify(Constants.video_details_reqbody(id, this.sts, this.context)), Constants.innertube_request_opts({ session: this, id, desktop: true })).catch((error) => error));
!desktop && (response = await Axios.get(`${Constants.URLS.YT_WATCH_PAGE}?v=${id}&t=8s&pbj=1`, Constants.INNERTUBE_REQOPTS({ session: this, id, desktop: false })).catch((error) => error)) ||
(response = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/player${this.logged_in && this.cookie.length < 1 ? '' : `?key=${this.key}`}`, JSON.stringify(Constants.VIDEO_INFO_REQBODY(id, this.sts, this.context)), Constants.INNERTUBE_REQOPTS({ session: this, id, desktop: true })).catch((error) => error));
if (response instanceof Error) throw new Error('Could not retrieve watch page info: ' + response.message);

@@ -367,6 +371,6 @@ return response.data;

let streams;
options.type != 'audio' && (streams = filtered_streams.filter((format) => format.mimeType.includes(options.format || 'mp4') && format.qualityLabel == options.quality))
|| (streams = filtered_streams.filter((format) => format.mimeType.includes(options.format || 'mp4')));
options.type != 'audio' && (streams = filtered_streams.filter((format) => format.mimeType.includes(options.format || 'mp4') && format.qualityLabel == options.quality)) ||
(streams = filtered_streams.filter((format) => format.mimeType.includes(options.format || 'mp4')));
streams == undefined || streams.length == 0 && (streams = filtered_streams.filter((format) => format.quality == 'medium'));

@@ -385,7 +389,7 @@

if (options.type == 'videoandaudio') {
if (options.type == 'videoandaudio' && !options.range) {
const response = await Axios.get(selected_format.url, {
responseType: 'stream',
cancelToken: new CancelToken(function executor(c) { cancel = c; }),
headers: Constants.stream_headers()
headers: Constants.STREAM_HEADERS
}).catch((error) => error);

@@ -419,7 +423,7 @@

const chunk_size = 1048576 * 10; // 10MB
let chunk_start = 0;
let chunk_end = chunk_size;
let chunk_start = (options.range && options.range.start || 0);
let chunk_end = (options.range && options.range.end || chunk_size);
let downloaded_size = 0;
let end = false;
let must_end = false;

@@ -429,8 +433,9 @@ stream.emit('start');

const downloadChunk = async () => {
if (chunk_end >= selected_format.contentLength) end = true;
(chunk_end >= selected_format.contentLength || options.range) && (must_end = true);
options.range && (selected_format.contentLength = options.range.end);
const response = await Axios.get(`${selected_format.url}&range=${chunk_start}-${chunk_end || ''}`, {
responseType: 'stream',
cancelToken: new CancelToken(function executor(c) { cancel = c; }),
headers: Constants.stream_headers()
headers: Constants.STREAM_HEADERS
}).catch((error) => error);

@@ -459,3 +464,3 @@

response.data.on('end', () => {
if (!end) {
if (!must_end && !options.range) {
chunk_start = chunk_end + 1;

@@ -467,3 +472,3 @@ chunk_end += chunk_size;

response.data.pipe(stream, { end });
response.data.pipe(stream, { end: must_end });
};

@@ -470,0 +475,0 @@ downloadChunk();

@@ -24,3 +24,3 @@ 'use strict';

}
enqueueActionGroup(group) {

@@ -42,3 +42,3 @@ group.forEach((action) => {

};
this.message_queue.push(message);

@@ -54,3 +54,3 @@ });

data = { context: this.session.context, continuation: this.ctoken };
const livechat = await Axios.post(`${Constants.urls.YT_BASE_URL}/youtubei/v1/live_chat/get_live_chat${this.session.logged_in && this.session.cookie.length < 1 ? '' : `?key=${this.session.key}`}`, JSON.stringify(data), Constants.innertube_request_opts({ session: this.session, data, desktop: true }));
const livechat = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/live_chat/get_live_chat${this.session.logged_in && this.session.cookie.length < 1 ? '' : `?key=${this.session.key}`}`, JSON.stringify(data), Constants.INNERTUBE_REQOPTS({ session: this.session, data, desktop: true }));
if (livechat instanceof Error) throw new Error(`Error polling livechat: ${livechat.message}`);

@@ -68,9 +68,9 @@

});
this.message_queue = [];
data = { context: this.session.context, videoId: this.video_id };
if (this.metadata_ctoken) data.continuation = this.metadata_ctoken;
const updated_metadata = await Axios.post(`${Constants.urls.YT_BASE_URL}/youtubei/v1/updated_metadata${this.session.logged_in && this.session.cookie.length < 1 ? '' : `?key=${this.session.key}`}`, JSON.stringify(data), Constants.innertube_request_opts({ session: this.session, data, desktop: true }));
const updated_metadata = await Axios.post(`${Constants.URLS.YT_BASE_URL}/youtubei/v1/updated_metadata${this.session.logged_in && this.session.cookie.length < 1 ? '' : `?key=${this.session.key}`}`, JSON.stringify(data), Constants.INNERTUBE_REQOPTS({ session: this.session, data, desktop: true }));
if (updated_metadata instanceof Error) throw new Error(`Error polling updated metadata: ${updated_metadata.message}`);

@@ -88,19 +88,19 @@ this.metadata_ctoken = updated_metadata.data.continuation.timedContinuationData.continuation;

});
this.livechat_poller = setTimeout(async () => await this.poll(), this.poll_intervals_ms);
}
async sendMessage(text) {
const message = await Actions.livechat(this.session, 'live_chat/send_message', { text, channel_id: this.channel_id, video_id: this.video_id });
if (!message.success) return message;
const deleteMessage = async () => {
const menu = await Actions.livechat(this.session, 'live_chat/get_item_context_menu', { params: { params: message.data.actions[0].addChatItemAction.item.liveChatTextMessageRenderer.contextMenuEndpoint.liveChatItemContextMenuEndpoint.params, pbj: 1 } });
if (!menu.success) return menu;
const chat_item_menu = menu.data.liveChatItemContextMenuSupportedRenderers.menuRenderer.items[0];
const cmd = await Actions.livechat(this.session, 'live_chat/moderate', { cmd_params: chat_item_menu.menuServiceItemRenderer.serviceEndpoint.moderateLiveChatEndpoint.params });
if (!cmd.success) return cmd;
return { success: true, status_code: cmd.status_code };

@@ -125,5 +125,5 @@ };

}
async blockUser(msg_params) {
/* TODO: Implement this */
/* TODO: Implement this */
throw new Error('Not implemented');

@@ -130,0 +130,0 @@ }

@@ -17,3 +17,2 @@ 'use strict';

try {
// Identifies the necessary transformation data and emulates them accordingly.
let transformations = this.getTransformationData(this.raw_code);

@@ -23,23 +22,15 @@ transformations = transformations.map((el) => {

const is_reverse_base64 = el.includes('case 65:');
if (el.includes('function(d){for(var')) {
el = (arr) => this.pushSplice(arr);
} else if (el.includes('d.push(e)')) {
el = (arr, item) => this.push(arr, item);
} else if (el.includes('d.reverse()')) {
el = (arr) => this.reverse(arr);
} else if (el.includes('d.length;d.splice(e,1)')) {
el = (arr, index) => this.spliceOnce(arr, index);
} else if (el.includes('d[0])[0])')) {
el = (arr, index) => this.spliceTwice(arr, index);
} else if (el.includes('reverse().forEach')) {
el = (arr, index) => this.spliceReverseUnshift(arr, index);
} else if (el.includes('f=d[0];d[0]')) {
el = (arr, index) => this.swapFirstItem(arr, index);
} else if (el.includes('unshift(d.pop())')) {
el = (arr, index) => this.unshiftPop(arr, index);
} else if (el.includes('switch')) {
el = (arr, e) => this.translateAB(arr, e, is_reverse_base64);
} else if (el === 'b') {
el = n_token;
}
(({ // Identifies the transformation functions and emulates them accordingly.
[Constants.FUNCS.PUSH]: () => el = (arr, i) => this.push(arr, i),
[Constants.FUNCS.SPLICE]: () => el = (arr, i) => this.splice(arr, i),
[Constants.FUNCS.SWAP0_1]: () => el = (arr, i) => this.swap0(arr, i),
[Constants.FUNCS.SWAP0_2]: () => el = (arr, i) => this.swap0(arr, i),
[Constants.FUNCS.ROTATE_1]: () => el = (arr, i) => this.rotate(arr, i),
[Constants.FUNCS.ROTATE_2]: () => el = (arr, i) => this.rotate(arr, i),
[Constants.FUNCS.REVERSE_1]: () => el = (arr) => this.reverse(arr),
[Constants.FUNCS.REVERSE_2]: () => el = (arr) => this.reverse(arr),
[Constants.FUNCS.BASE64_DIA]: () => el = () => this.getBase64Dia(is_reverse_base64),
[Constants.FUNCS.TRANSLATE_1]: () => el = (arr, token) => this.translate1(arr, token, is_reverse_base64),
[Constants.FUNCS.TRANSLATE_2]: () => el = (arr, token, base64_dic) => this.translate2(arr, token, base64_dic)
})[this.getFunc(el)] || (() => el === 'b' && (el = n_token)))();
}

@@ -56,7 +47,8 @@ return el;

transformation_calls.forEach((data) => {
const index = data.index;
const param_index = data.params.split(',').map((param) => param.match(/c\[(.*?)\]/)[1]);
transformations[index](transformations[param_index[0]], transformations[param_index[1]]);
const base64_dia = (param_index[2] && transformations[param_index[2]]());
transformations[data.index](transformations[param_index[0]], transformations[param_index[1]], base64_dia);
});
} catch (err) {
console.error('Could not transform n-token, download may be throttled:', err);
return n;

@@ -68,48 +60,43 @@ }

getFunc(el) {
return el.match(Constants.FUNCS_REGEX);
}
getTransformationData() {
// These variable names have always been the same since earlier player versions, so it should not be a problem for now.
let transformation_data = `[${Utils.getStringBetweenStrings(this.raw_code.replace(/\n/g, ''), 'c=[', '];c')}]`;
transformation_data = transformation_data
.replace(/function\(d,e\)/g, '"function(d,e)')
.replace(/function\(d\)/g, '"function(d)')
.replace(/,b,/g, ',"b",')
.replace(/,b/g, ',"b"')
.replace(/b,/g, '"b",')
.replace(/b]/g, '"b"]')
.replace(/\[b/g, '["b"')
.replace(/}]/g, '"]')
.replace(/},/g, '}",')
.replace(/""/g, '')
.replace(/length]\)}"/g, 'length])}');
return JSON.parse(transformation_data);
const data = `[${Utils.getStringBetweenStrings(this.raw_code.replace(/\n/g, ''), 'c=[', '];c')}]`;
return JSON.parse(Constants.formatNTransformData(data));
}
translateAB(arr, index, is_reverse_base64) {
let characters = is_reverse_base64 && Constants.base64_alphabet.reverse || Constants.base64_alphabet.normal;
translate1(arr, token, is_reverse_base64) {
const characters = is_reverse_base64 && Constants.BASE64_DIALECT.REVERSE || Constants.BASE64_DIALECT.NORMAL;
arr.forEach(function(char, index, loc) {
this.push(loc[index] = characters[(characters.indexOf(char) - characters.indexOf(this[index]) + 64) % characters.length]);
}, index.split(''));
}, token.split(''));
}
unshiftPop(arr, index) {
index = (index % arr.length + arr.length) % arr.length;
for (; index--;) {
arr.unshift(arr.pop());
}
translate2(arr, token, characters) {
let chars_length = characters.length;
arr.forEach(function(char, index, loc) {
this.push(loc[index] = characters[(characters.indexOf(char) - characters.indexOf(this[index]) + index + chars_length--) % characters.length]);
}, token.split(''));
}
swapFirstItem(arr, index) {
let oldValue = arr[0];
getBase64Dia(is_reverse_base64) {
const characters = is_reverse_base64 && Constants.BASE64_DIALECT.REVERSE || Constants.BASE64_DIALECT.NORMAL;
return characters;
}
swap0(arr, index) {
const old_value = arr[0];
index = (index % arr.length + arr.length) % arr.length;
arr[0] = arr[index];
arr[index] = oldValue;
arr[index] = old_value;
}
spliceReverseUnshift(arr, index) {
rotate(arr, index) {
index = (index % arr.length + arr.length) % arr.length;
arr.splice(-index).reverse().forEach((f) => arr.unshift(f));
arr.splice(-index).reverse().forEach((el) => arr.unshift(el));
}
spliceOnce(arr, index) {
splice(arr, index) {
index = (index % arr.length + arr.length) % arr.length;

@@ -119,21 +106,11 @@ arr.splice(index, 1);

spliceTwice(arr, index) {
index = (index % arr.length + arr.length) % arr.length;
arr.splice(0, 1, arr.splice(index, 1, arr[0])[0]);
reverse(arr) {
arr.reverse();
}
pushSplice(arr) {
for (let index = arr.length; index;)
arr.push(arr.splice(--index, 1)[0]);
}
push(arr, item) {
arr.push(item);
}
reverse(arr) {
arr.reverse();
}
}
module.exports = NToken;

@@ -16,12 +16,12 @@ 'use strict';

// OAuth URLs:
this.oauth_code_url = `${Constants.urls.YT_BASE_URL}/o/oauth2/device/code`;
this.oauth_token_url = `${Constants.urls.YT_BASE_URL}/o/oauth2/token`;
this.oauth_code_url = `${Constants.URLS.YT_BASE_URL}/o/oauth2/device/code`;
this.oauth_token_url = `${Constants.URLS.YT_BASE_URL}/o/oauth2/token`;
// Used to check whether an access token is valid or not.
this.guide_url = `${Constants.urls.YT_BASE_URL}/youtubei/v1/guide`;
this.guide_url = `${Constants.URLS.YT_BASE_URL}/youtubei/v1/guide`;
// These are always the same, so we shouldn't have any problems for now.
this.model_name = Constants.oauth.model_name;
this.grant_type = Constants.oauth.grant_type;
this.scope = Constants.oauth.scope;
this.model_name = Constants.OAUTH.MODEL_NAME;
this.grant_type = Constants.OAUTH.GRANT_TYPE;
this.scope = Constants.OAUTH.SCOPE;

@@ -38,2 +38,50 @@ // Script that contains important information such as client id and client secret.

async requestAuthCode() {
const identity = await this.getClientIdentity();
this.client_id = identity.id;
this.client_secret = identity.secret;
const data = {
client_id: this.client_id,
scope: this.scope,
device_id: Uuid.v4(),
model_name: this.model_name
};
const response = await Axios.post(this.oauth_code_url, JSON.stringify(data), Constants.OAUTH.HEADERS).catch((error) => error);
if (response instanceof Error)
return this.emit('auth', {
error: 'Could not get auth code.',
status: 'FAILED'
});
this.emit('auth', {
code: response.data.user_code,
status: 'AUTHORIZATION_PENDING',
expires_in: response.data.expires_in,
verification_url: response.data.verification_url
});
this.refresh_interval = response.data.interval;
// Keeps requesting at a specific rate until the authorization is granted or denied.
this.waitForAuth(response.data.device_code);
}
async getClientIdentity() {
// The first request is made to get the auth script url, hard-coding it isn't viable as it changes overtime.
const yttv_response = await Axios.get(`${Constants.URLS.YT_BASE_URL}/tv`, Constants.OAUTH.HEADERS).catch((error) => error);
if (yttv_response instanceof Error) throw new Error(`Could not extract client identify: ${yttv_response.message}`);
// Here we get the script and extract the necessary data to proceed with the auth flow.
const url_body = this.auth_script_regex.exec(yttv_response.data)[1];
const script_url = `${Constants.URLS.YT_BASE_URL}/${url_body}`;
const response = await Axios.get(script_url, Constants.DEFAULT_HEADERS).catch((error) => error);
if (response instanceof Error) throw new Error(`Could not extract client identify: ${response.message}`);
const identity_function = Utils.getStringBetweenStrings(response.data, 'YTLR_STORAGE_NAMESPACE",', 'reloadAppFlushLogsMaxTimeoutMs:');
const client_identity = identity_function.replace(/\n/g, '').match(this.identity_regex);
return client_identity.groups;
}
waitForAuth(device_code) {

@@ -48,3 +96,3 @@ const data = {

setTimeout(async () => {
const response = await Axios.post(this.oauth_token_url, JSON.stringify(data), Constants.oauth_reqopts).catch((error) => error);
const response = await Axios.post(this.oauth_token_url, JSON.stringify(data), Constants.OAUTH.HEADERS).catch((error) => error);
if (response instanceof Error)

@@ -90,50 +138,2 @@ return this.emit('auth', {

async requestAuthCode() {
const identity = await this.getClientIdentity();
this.client_id = identity.id;
this.client_secret = identity.secret;
const data = {
client_id: this.client_id,
scope: this.scope,
device_id: Uuid.v4(),
model_name: this.model_name
};
const response = await Axios.post(this.oauth_code_url, JSON.stringify(data), Constants.oauth_reqopts).catch((error) => error);
if (response instanceof Error)
return this.emit('auth', {
error: 'Could not get auth code.',
status: 'FAILED'
});
this.emit('auth', {
code: response.data.user_code,
status: 'AUTHORIZATION_PENDING',
expires_in: response.data.expires_in,
verification_url: response.data.verification_url
});
this.refresh_interval = response.data.interval;
// Keeps requesting at a specific rate until the authorization is granted or denied.
this.waitForAuth(response.data.device_code);
}
async getClientIdentity() {
// The first request is made to get the auth script url, hard-coding it isn't viable as it changes overtime.
const yttv_response = await Axios.get(`${Constants.urls.YT_BASE_URL}/tv`, Constants.oauth_reqopts).catch((error) => error);
if (yttv_response instanceof Error) throw new Error(`Could not extract client identify: ${yttv_response.message}`);
// Here we get the script and extract the necessary data to proceed with the auth flow.
const url_body = this.auth_script_regex.exec(yttv_response.data)[1];
const script_url = `${Constants.urls.YT_BASE_URL}/${url_body}`;
const response = await Axios.get(script_url, Constants.default_headers).catch((error) => error);
if (response instanceof Error) throw new Error(`Could not extract client identify: ${response.message}`);
const identity_function = Utils.getStringBetweenStrings(response.data, 'YTLR_STORAGE_NAMESPACE",', 'reloadAppFlushLogsMaxTimeoutMs:');
const client_identity = identity_function.replace(/\n/g, '').match(this.identity_regex);
return client_identity.groups;
}
async refreshAccessToken(refresh_token) {

@@ -149,3 +149,3 @@ const identity = await this.getClientIdentity();

const response = await Axios.post(this.oauth_token_url, JSON.stringify(data), Constants.oauth_reqopts).catch((error) => error);
const response = await Axios.post(this.oauth_token_url, JSON.stringify(data), Constants.OAUTH.HEADERS).catch((error) => error);
if (response instanceof Error)

@@ -167,3 +167,3 @@ return this.emit('refresh-token', {

async checkTokenValidity(access_token, session) {
let headers = Constants.innertube_request_opts({ session }).headers;
let headers = Constants.INNERTUBE_REQOPTS({ session }).headers;
headers.authorization = `Bearer ${access_token}`;

@@ -170,0 +170,0 @@

@@ -21,5 +21,5 @@ 'use strict';

} else {
const response = await Axios.get(`${Constants.urls.YT_BASE_URL}${this.session.player_url}`, { path: this.session.playerUrl, headers: { 'content-type': 'text/javascript', 'user-agent': Utils.getRandomUserAgent('desktop').userAgent } }).catch((error) => error);
const response = await Axios.get(`${Constants.URLS.YT_BASE_URL}${this.session.player_url}`, { path: this.session.playerUrl, headers: { 'content-type': 'text/javascript', 'user-agent': Utils.getRandomUserAgent('desktop').userAgent } }).catch((error) => error);
if (response instanceof Error) throw new Error('Could not download player script: ' + response.message);
try {

@@ -30,3 +30,3 @@ // Caches the current player so we don't have to download it all the time

} catch (err) {}
this.getSigDecipherCode(response.data);

@@ -33,0 +33,0 @@ this.getNEncoder(response.data);

@@ -42,3 +42,3 @@ 'use strict';

const youtube_proto = Proto(Fs.readFileSync(`${__dirname}/proto/youtube.proto`));
const buf = youtube_proto.NotificationPreferences.encode({

@@ -52,3 +52,3 @@ channel_id,

});
return encodeURIComponent(Buffer.from(buf).toString('base64'));

@@ -59,8 +59,8 @@ }

const youtube_proto = Proto(Fs.readFileSync(`${__dirname}/proto/youtube.proto`));
const buf = youtube_proto.LiveMessageParams.encode({
params: {
ids: {
channel_id,
video_id
channel_id,
video_id
}

@@ -71,3 +71,3 @@ },

});
return Buffer.from(encodeURIComponent(Buffer.from(buf).toString('base64'))).toString('base64');

@@ -74,0 +74,0 @@ }

{
"name": "youtubei.js",
"version": "1.2.4",
"version": "1.2.5",
"description": "An object-oriented library that allows you to search, get detailed info about videos, subscribe, unsubscribe, like, dislike, comment, download videos and much more!",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "node test"
},

@@ -9,0 +9,0 @@ "author": "LuanRT",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc