0
0
Fork 0
mirror of https://github.com/VueTubeApp/VueTube synced 2024-11-01 17:32:39 +00:00
VueTube/NUXT/plugins/youtube.js

194 lines
5.5 KiB
JavaScript
Raw Normal View History

2022-02-28 15:24:06 +00:00
//--- Modules/Imports ---//
2022-03-21 23:47:11 +00:00
import { Http } from "@capacitor-community/http";
import Innertube from "./innertube";
import constants from "./constants";
import rendererUtils from "./renderers";
import { Buffer } from "buffer";
import iconv from "iconv-lite";
2022-04-09 03:06:35 +00:00
import { Toast } from "@capacitor/toast";
2022-02-25 18:54:15 +00:00
function getEncoding(contentType) {
const re = /charset=([^()<>@,;:\"/[\]?.=\s]*)/i;
const content = re.exec(contentType);
console.log(content);
return content[1].toLowerCase();
}
const searchModule = {
2022-03-21 23:47:11 +00:00
logs: new Array(),
//--- Get YouTube's Search Auto Complete ---//
autoComplete(text, callback) {
Http.get({
url: `${constants.URLS.YT_SUGGESTIONS}/search?q=${encodeURIComponent(
text
)}&client=youtube&ds=yt`,
responseType: "arraybuffer",
2022-03-21 23:47:11 +00:00
})
.then((res) => {
const contentType = res.headers["Content-Type"];
// make a new buffer object from res.data
const buffer = Buffer.from(res.data, "base64");
// convert res.data from iso-8859-1 to utf-8
const data = iconv.decode(buffer, getEncoding(contentType));
callback(data);
2022-03-21 23:47:11 +00:00
})
.catch((err) => {
callback(err);
});
},
2022-02-25 18:54:15 +00:00
2022-03-21 23:47:11 +00:00
getReturnYoutubeDislike(id, callback) {
Http.request({
method: "GET",
url: `https://returnyoutubedislikeapi.com/votes`,
params: { videoId: id },
})
.then((res) => {
callback(res.data);
})
.catch((err) => {
callback(err);
});
},
2022-06-01 02:50:55 +00:00
getSponsorBlock(id, callback) {
Http.request({
method: "GET",
url: `https://sponsor.ajay.app/api/skipSegments`,
params: { videoID: id },
})
.then((res) => {
callback(res.data);
})
.catch((err) => {
callback(err);
});
2022-06-01 21:12:00 +00:00
},
showToast(text) {
Toast.show({ text: text });
},
2022-03-21 23:47:11 +00:00
};
2022-03-13 23:45:04 +00:00
2022-03-20 09:02:52 +00:00
//--- Recommendations ---//
let InnertubeAPI;
2022-03-20 09:02:52 +00:00
// Loads Innertube object. This will be the object used in all future Innertube API calls. getAPI Code provided by Lightfire228 (https://github.com/Lightfire228)
// These are just a way for the backend Javascript to communicate with the front end Vue scripts. Essentially a wrapper inside a wrapper
const innertubeModule = {
2022-03-21 23:47:11 +00:00
async getAPI() {
if (!InnertubeAPI) {
2022-04-09 03:06:35 +00:00
InnertubeAPI = await Innertube.createAsync(
(message, isError, shortMessage) => {
if (shortMessage) {
Toast.show({ text: shortMessage });
}
}
);
2022-03-21 23:47:11 +00:00
}
return InnertubeAPI;
},
2022-03-21 23:47:11 +00:00
async getVid(id) {
try {
return await InnertubeAPI.VidInfoAsync(id);
} catch (error) {
}
},
2022-03-23 22:15:52 +00:00
getThumbnail(id, resolution, backupThumbnail) {
if (resolution == "max") {
const url = `https://img.youtube.com/vi/${id}/maxresdefault.jpg`;
let img = new Image();
img.src = url;
img.onload = function () {
if (img.height !== 120) return url;
};
}
2022-03-23 22:15:52 +00:00
if (backupThumbnail[backupThumbnail.length - 1])
return backupThumbnail[backupThumbnail.length - 1].url;
else return `https://img.youtube.com/vi/${id}/mqdefault.jpg`;
},
2022-05-04 05:21:14 +00:00
async getChannel(url) {
try {
const response = await InnertubeAPI.getChannelAsync(url);
return response.data;
} catch (error) {
}
},
2022-03-21 23:47:11 +00:00
// It just works™
// Front page recommendation
async recommend() {
const response = await InnertubeAPI.getRecommendationsAsync();
2022-03-31 02:22:22 +00:00
2022-03-21 23:47:11 +00:00
if (!response.success)
throw new Error("An error occurred and innertube failed to respond");
const contents =
response.data.contents.singleColumnBrowseResultsRenderer.tabs[0]
.tabRenderer.content.sectionListRenderer.contents;
const final = contents.map((shelves) => {
2022-03-24 11:47:13 +00:00
const video = shelves.shelfRenderer?.content?.horizontalListRenderer;
2022-03-21 23:47:11 +00:00
if (video) return video;
2022-03-21 23:47:11 +00:00
});
const continuations =
response.data.contents.singleColumnBrowseResultsRenderer.tabs[0]
.tabRenderer.content.sectionListRenderer.continuations;
2022-03-31 02:22:22 +00:00
console.log({ continuations: continuations, contents: final });
return { continuations: continuations, contents: final };
},
async recommendContinuation(continuation, endpoint) {
2022-04-19 14:03:46 +00:00
const response = await this.getContinuation(continuation, endpoint);
const contents =
response.data.continuationContents.sectionListContinuation.contents;
2022-03-31 02:22:22 +00:00
const final = contents.map((shelves) => {
const video = shelves.shelfRenderer?.content?.horizontalListRenderer;
if (video) return video;
});
const continuations =
response.data.continuationContents.sectionListContinuation.continuations;
2022-03-31 02:22:22 +00:00
return { continuations: continuations, contents: final };
},
2022-04-19 14:03:46 +00:00
async getContinuation(continuation, endpoint, mode = "android") {
let contextAdditional = {};
if (mode.toLowerCase() == "web") {
contextAdditional = {
...contextAdditional,
...{
client: {
clientName: constants.YT_API_VALUES.CLIENT_WEB_D,
2022-04-19 14:03:46 +00:00
clientVersion: constants.YT_API_VALUES.VERSION_WEB,
},
},
};
}
return await InnertubeAPI.getContinuationsAsync(
continuation,
endpoint,
contextAdditional
);
},
async search(query) {
try {
const response = await InnertubeAPI.getSearchAsync(query);
2022-03-24 11:47:13 +00:00
return response.contents.sectionListRenderer;
} catch (err) {
}
},
async saveApiStats(query, url) {
await InnertubeAPI.apiStats(query, url);
},
2022-03-21 23:47:11 +00:00
};
2022-02-28 15:24:06 +00:00
//--- Start ---//
2022-02-25 18:39:17 +00:00
export default ({ app }, inject) => {
2022-03-21 23:47:11 +00:00
inject("youtube", { ...searchModule, ...innertubeModule });
inject("rendererUtils", rendererUtils);
2022-03-21 23:47:11 +00:00
};