|
@@ -1,3 +1,7 @@
|
|
|
+printable = (platform) => {
|
|
|
+ return platform === "WEB";
|
|
|
+}
|
|
|
+
|
|
|
parseCodecs = (format) => {
|
|
|
const mimeType = format['mimeType']
|
|
|
if (!mimeType) {
|
|
@@ -120,7 +124,7 @@ getStringBetween = (string, needleStart, needleEnd, offsetStart = 0, offsetEnd =
|
|
|
return string.substring(x + needleStart.length + offsetEnd, y + offsetStart);
|
|
|
}
|
|
|
|
|
|
-findFunction = (jsCode, regexp) => {
|
|
|
+findFunction = (jsCode, regexp, platform) => {
|
|
|
const match = jsCode.match(regexp)
|
|
|
if (!match && match.length <= 1) {
|
|
|
return null;
|
|
@@ -142,15 +146,18 @@ findFunction = (jsCode, regexp) => {
|
|
|
}
|
|
|
}
|
|
|
result += `\n${match[0]}`;
|
|
|
- console.log(`decipherFunction result: ` + result);
|
|
|
+ if (printable(platform)) {
|
|
|
+ console.log(`decipherFunction result: ` + result);
|
|
|
+ }
|
|
|
return eval(result);
|
|
|
};
|
|
|
|
|
|
const cache = {};
|
|
|
+
|
|
|
fetchBaseJSContent = async (baseJsUrl, platform) => {
|
|
|
const cacheKey = `jsContent:${baseJsUrl}`;
|
|
|
if (cache[cacheKey]) {
|
|
|
- console.log(`from cache: ${baseJsUrl}`);
|
|
|
+ console.log(`baseContent from cache: ${baseJsUrl}`);
|
|
|
return cache[cacheKey];
|
|
|
}
|
|
|
console.log(`extract baseUrl: ${baseJsUrl}`);
|
|
@@ -163,12 +170,27 @@ fetchBaseJSContent = async (baseJsUrl, platform) => {
|
|
|
}
|
|
|
|
|
|
extractJSSignatureFunction = async (baseJsUrl, platform) => {
|
|
|
+ const cacheKey = `jsSign:${baseJsUrl}`
|
|
|
+ if (cache[cacheKey]) {
|
|
|
+ console.log(`jsSign from cache: ${baseJsUrl}`);
|
|
|
+ return cache[cacheKey];
|
|
|
+ }
|
|
|
const baseJsContent = await fetchBaseJSContent(baseJsUrl, platform);
|
|
|
- return findFunction(baseJsContent, /([a-zA-Z0-9]+)=function\([a-zA-Z0-9]+\)\{a=a\.split\(""\).*};/);
|
|
|
+ const result = findFunction(baseJsContent, /([a-zA-Z0-9]+)=function\([a-zA-Z0-9]+\)\{a=a\.split\(""\).*};/, platform);
|
|
|
+ cache[cacheKey] = result
|
|
|
+ return result
|
|
|
}
|
|
|
+
|
|
|
extractNJSFunction = async (baseJsUrl, platform) => {
|
|
|
+ const cacheKey = `jsN:${baseJsUrl}`
|
|
|
+ if (cache[cacheKey]) {
|
|
|
+ console.log(`jsN from cache: ${baseJsUrl}`);
|
|
|
+ return cache[cacheKey];
|
|
|
+ }
|
|
|
const baseJsContent = await fetchBaseJSContent(baseJsUrl, platform);
|
|
|
- return findFunction(baseJsContent, /([a-zA-Z0-9]+)=function\([a-zA-Z0-9]+\)\{var b=a\.split\(""\)[\s\S]*?};/);
|
|
|
+ const result = findFunction(baseJsContent, /([a-zA-Z0-9]+)=function\([a-zA-Z0-9]+\)\{var b=a\.split\(""\)[\s\S]*?};/, platform);
|
|
|
+ cache[cacheKey] = result
|
|
|
+ return result
|
|
|
}
|
|
|
|
|
|
signUrl = async (signatureCipher, baseJsUrl, platform) => {
|
|
@@ -182,7 +204,9 @@ signUrl = async (signatureCipher, baseJsUrl, platform) => {
|
|
|
if (!decipher) {
|
|
|
return null;
|
|
|
}
|
|
|
- console.log(`signatureCipher=${signatureCipher}, url=${url}, signature=${signature}, sp=${sp}`)
|
|
|
+ if (printable(platform)) {
|
|
|
+ console.log(`signatureCipher=${signatureCipher}, url=${url}, signature=${signature}, sp=${sp}`)
|
|
|
+ }
|
|
|
let newUrl = `${url}&${sp}=${decipher(signature)}`;
|
|
|
|
|
|
function replaceUrlParam(url, paramName, paramValue) {
|
|
@@ -231,7 +255,9 @@ detail = async (url, platform) => {
|
|
|
}
|
|
|
const ytInitialPlayerResponse = JSON.parse(match[1]);
|
|
|
const originVideoDetails = ytInitialPlayerResponse['videoDetails'];
|
|
|
- console.log(`videoDetails: ${JSON.stringify(originVideoDetails)}`);
|
|
|
+ if (printable(platform)) {
|
|
|
+ console.log(`videoDetails: ${JSON.stringify(originVideoDetails)}`);
|
|
|
+ }
|
|
|
const thumbnails = []
|
|
|
for (const item of originVideoDetails['thumbnail']['thumbnails']) {
|
|
|
thumbnails.push({
|
|
@@ -365,7 +391,9 @@ detail = async (url, platform) => {
|
|
|
let formatIds = [];
|
|
|
const formats = [];
|
|
|
for (let format of originFormats) {
|
|
|
- console.log(`current format: ${JSON.stringify(format)}`);
|
|
|
+ if (printable(platform)) {
|
|
|
+ console.log(`current format: ${JSON.stringify(format)}`);
|
|
|
+ }
|
|
|
if (format && formatIds.indexOf(format['itag']) === -1) {
|
|
|
if (!format["url"]) {
|
|
|
format["url"] = await signUrl(format["signatureCipher"], baseJsUrl, platform);
|
|
@@ -400,7 +428,9 @@ detail = async (url, platform) => {
|
|
|
const recommendInfo = [];
|
|
|
if (ytInitialDataMatch && ytInitialDataMatch.length === 2) {
|
|
|
const ytInitialData = JSON.parse(ytInitialDataMatch[1]);
|
|
|
- console.log(`ytInitialData: ${JSON.stringify(ytInitialData)}`);
|
|
|
+ if (printable(platform)) {
|
|
|
+ console.log(`ytInitialData: ${JSON.stringify(ytInitialData)}`);
|
|
|
+ }
|
|
|
for (const item of ytInitialData["contents"]?.["twoColumnWatchNextResults"]?.["secondaryResults"]?.["secondaryResults"]?.["results"] || []) {
|
|
|
if (item["compactVideoRenderer"]) {
|
|
|
const recommendVideo = item["compactVideoRenderer"];
|
|
@@ -482,7 +512,9 @@ search = async (keyword, next, platform) => {
|
|
|
const videos = [];
|
|
|
for (const item of res["onResponseReceivedCommands"][0]["appendContinuationItemsAction"]["continuationItems"][0]["itemSectionRenderer"]["contents"]) {
|
|
|
const video = item["videoRenderer"];
|
|
|
- console.log(`search result video: ${JSON.stringify(video)}`);
|
|
|
+ if (printable(platform)) {
|
|
|
+ console.log(`search result video: ${JSON.stringify(video)}`);
|
|
|
+ }
|
|
|
if (video && video["videoId"]) {
|
|
|
videos.push({
|
|
|
"type": "videoWithContextRenderer",
|
|
@@ -531,7 +563,9 @@ search = async (keyword, next, platform) => {
|
|
|
for (const item of ytInitialDataResp["contents"]?.["twoColumnSearchResultsRenderer"]?.["primaryContents"]?.["sectionListRenderer"]?.["contents"]?.[0]?.["itemSectionRenderer"]?.["contents"]) {
|
|
|
if (item["videoRenderer"]) {
|
|
|
const video = item["videoRenderer"];
|
|
|
- console.log(`search result video: ${JSON.stringify(video)}`);
|
|
|
+ if (printable(platform)) {
|
|
|
+ console.log(`search result video: ${JSON.stringify(video)}`);
|
|
|
+ }
|
|
|
if (video && video["videoId"]) {
|
|
|
videos.push({
|
|
|
"type": "videoWithContextRenderer",
|