0
0
Fork 0
mirror of https://github.com/VueTubeApp/VueTube synced 2024-11-22 11:15:14 +00:00

feat: simple test to see if backend API works

This commit is contained in:
Alex 2022-03-16 22:07:40 +13:00
parent 0a20f33374
commit 505b69365f
4 changed files with 198 additions and 98 deletions

View file

@ -3,5 +3,16 @@
<img style="margin-top: 5em; max-width: 80%; max-height: 15em;" src="/dev.svg" />
<h1 class="grey--text">Page Under Construction</h1>
<p class="grey--text">Please read the VueTube FAQ for more information.</p>
<button @click="debug">Test Button</button>
</center>
</template>
<script>
export default {
methods: {
debug () {
console.log(this.$youtube.recommend("test", false))
}
}
}
</script>

67
NUXT/plugins/innertube.js Normal file
View file

@ -0,0 +1,67 @@
// Code specific to working with the innertube API
// https://www.youtube.com/youtubei/v1
import { Http } from '@capacitor-community/http';
import { getBetweenStrings } from './utils';
class Innertube {
constructor(ErrorCallback) {
this.ErrorCallback = ErrorCallback;
this.init();
this.retry_count = 0
}
async init() {
const html = await Http.request({ method: 'GET', url: 'https://www.youtube.com', params: { hl: "en" } }).catch((error) => error);
if (html instanceof Error) this.ErrorCallback(html.message, true);
try {
const data = JSON.parse(getBetweenStrings(html.data, 'ytcfg.set({', '});'));
if (data.INNERTUBE_CONTEXT) {
this.key = data.INNERTUBE_API_KEY;
this.context = data.INNERTUBE_CONTEXT;
}
} catch (err) {
this.ErrorCallback(err, true)
this.retry_count >= 10 ? this.init() : this.ErrorCallback("Failed to retrieve Innertube session", true);
}
};
async browse(action_type) {
let data = { context: this.context }
switch (action_type) {
case 'recommendations':
data.browseId = 'FEwhat_to_watch'
break;
case 'playlist':
data.browseId = args.browse_id
break;
default:
}
const response = await Http.request({
method: 'POST',
url: `https://www.youtube.com/youtubei/v1/browse?key=${this.key}`,
data: JSON.stringify(data)
}).catch((error) => error);
if (response instanceof Error) return { success: false, status_code: response.response.status, message: response.message };
return {
success: true,
status_code: response.status,
data: response.data
};
}
async getRecommendations() {
const response = await this.browse("recommendations")
return response.data;
}
}
export default Innertube;

9
NUXT/plugins/utils.js Normal file
View file

@ -0,0 +1,9 @@
// Collection of functions that are useful but non-specific to any particular files
function getBetweenStrings(data, start_string, end_string) {
const regex = new RegExp(`${start_string}(.*?)${end_string}`, "s");
const match = data.match(regex);
return match ? match[1] : undefined;
}
module.exports = { getBetweenStrings };

View file

@ -1,131 +1,144 @@
//--- Modules/Imports ---//
import { Http } from '@capacitor-community/http';
import Innertube from './innertube'
//--- Logger Function ---//
function logger(func, data, isError=false) {
module.logs.unshift({
name: func,
time: Date.now(),
data: data,
error: isError
})
function logger(func, data, isError = false) {
searchModule.logs.unshift({
name: func,
time: Date.now(),
data: data,
error: isError
})
}
//--- Youtube Base Parser ---//
function youtubeParse(html, callback) {
//--- Replace Encoded Characters ---///
html = html.replace(/\\x([0-9A-F]{2})/ig, (...items) => { return String.fromCharCode(parseInt(items[1], 16)); });
//--- Properly Format JSON ---//
html = html.replaceAll("\\\\\"", "");
//--- Parse JSON ---//
html = JSON.parse(html);
//--- Replace Encoded Characters ---///
html = html.replace(/\\x([0-9A-F]{2})/ig, (...items) => { return String.fromCharCode(parseInt(items[1], 16)); });
//--- Properly Format JSON ---//
html = html.replaceAll("\\\\\"", "");
//--- Parse JSON ---//
html = JSON.parse(html);
//--- Get Results ---// ( Thanks To appit-online On Github ) -> https://github.com/appit-online/youtube-search/blob/master/src/lib/search.ts
let results;
if (html && html.contents && html.contents.sectionListRenderer && html.contents.sectionListRenderer.contents
&& html.contents.sectionListRenderer.contents.length > 0
&& html.contents.sectionListRenderer.contents[0].itemSectionRenderer
&& html.contents.sectionListRenderer.contents[0].itemSectionRenderer.contents.length > 0) {
results = html.contents.sectionListRenderer.contents[0].itemSectionRenderer.contents;
logger("search", results);
callback(results);
} else {
try {
results = JSON.parse(html.split('{"itemSectionRenderer":{"contents":')[html.split('{"itemSectionRenderer":{"contents":').length - 1].split(',"continuations":[{')[0]);
logger("search", results);
callback(results);
} catch (e) {}
try {
results = JSON.parse(html.split('{"itemSectionRenderer":')[html.split('{"itemSectionRenderer":').length - 1].split('},{"continuationItemRenderer":{')[0]).contents;
logger("search", results);
callback(results);
} catch(e) {}
}
//--- Get Results ---// ( Thanks To appit-online On Github ) -> https://github.com/appit-online/youtube-search/blob/master/src/lib/search.ts
let results;
if (html && html.contents && html.contents.sectionListRenderer && html.contents.sectionListRenderer.contents &&
html.contents.sectionListRenderer.contents.length > 0 &&
html.contents.sectionListRenderer.contents[0].itemSectionRenderer &&
html.contents.sectionListRenderer.contents[0].itemSectionRenderer.contents.length > 0) {
results = html.contents.sectionListRenderer.contents[0].itemSectionRenderer.contents;
logger("search", results);
callback(results);
} else {
try {
results = JSON.parse(html.split('{"itemSectionRenderer":{"contents":')[html.split('{"itemSectionRenderer":{"contents":').length - 1].split(',"continuations":[{')[0]);
logger("search", results);
callback(results);
} catch (e) {}
try {
results = JSON.parse(html.split('{"itemSectionRenderer":')[html.split('{"itemSectionRenderer":').length - 1].split('},{"continuationItemRenderer":{')[0]).contents;
logger("search", results);
callback(results);
} catch (e) {}
}
}
//--- Search Main Function ---//
function youtubeSearch(text, callback) {
Http.request({
method: 'GET',
url: 'https://youtube.com/results',
params: { q: text, hl: "en" }
})
.then((res) => {
//--- Get HTML Only ---//
let html = res.data;
//--- Isolate The Script Containing Video Information ---//
html = html.split("var ytInitialData = '")[1].split("';</script>")[0];
Http.request({
method: 'GET',
url: 'https://youtube.com/results',
params: { q: text, hl: "en" }
})
.then((res) => {
//--- Get HTML Only ---//
let html = res.data;
//--- Isolate The Script Containing Video Information ---//
html = html.split("var ytInitialData = '")[1].split("';</script>")[0];
youtubeParse(html, (data) => {
callback(data);
})
youtubeParse(html, (data) => {
callback(data);
})
})
.catch((err) => {
logger("search", err, true);
callback(err);
});
})
.catch((err) => {
logger("search", err, true);
callback(err);
});
}
const module = {
logs: new Array(),
const searchModule = {
logs: new Array(),
//--- Get YouTube's Search Auto Complete ---//
autoComplete(text, callback) {
Http.request({
method: 'GET',
url: 'https://suggestqueries-clients6.youtube.com/complete/search',
params: { client: 'youtube', q: text }
})
.then((res) => {
logger("autoComplete", res);
callback(res.data);
})
.catch((err) => {
logger("autoComplete", err, true);
callback(err);
});
},
//--- Get YouTube's Search Auto Complete ---//
autoComplete(text, callback) {
Http.request({
method: 'GET',
url: 'https://suggestqueries-clients6.youtube.com/complete/search',
params: { client: 'youtube', q: text }
})
.then((res) => {
logger("autoComplete", res);
callback(res.data);
})
.catch((err) => {
logger("autoComplete", err, true);
callback(err);
});
},
search(text, callback) {
search(text, callback) {
let results = new Array();
youtubeSearch(text, (videos) => {
for (const i in videos) {
const video = videos[i];
let results = new Array();
youtubeSearch(text, (videos) => {
for (const i in videos) {
const video = videos[i];
if (video.compactVideoRenderer) {
//--- If Entry Is A Video ---//
results.push({
id: video.compactVideoRenderer.videoId,
title: video.compactVideoRenderer.title.runs[0].text,
runtime: video.compactVideoRenderer.lengthText.runs[0].text,
uploaded: video.compactVideoRenderer.publishedTimeText.runs[0].text,
views: video.compactVideoRenderer.viewCountText.runs[0].text,
thumbnails: video.compactVideoRenderer.thumbnail.thumbnails
})
} else {
//--- If Entry Is Not A Video ---//
//logger("search", { type: "Error Caught Successfully", error: video }, true);
}
if (video.compactVideoRenderer) {
//--- If Entry Is A Video ---//
results.push({
id: video.compactVideoRenderer.videoId,
title: video.compactVideoRenderer.title.runs[0].text,
runtime: video.compactVideoRenderer.lengthText.runs[0].text,
uploaded: video.compactVideoRenderer.publishedTimeText.runs[0].text,
views: video.compactVideoRenderer.viewCountText.runs[0].text,
thumbnails: video.compactVideoRenderer.thumbnail.thumbnails
})
} else {
//--- If Entry Is Not A Video ---//
//logger("search", { type: "Error Caught Successfully", error: video }, true);
}
}
})
callback(results);
}
})
callback(results);
},
},
getVideo(id) {
return id;
}
async recommend() {
const recommendAPI = new Innertube((message, isError) => {
logger("recommendation", message, isError)
});
return await recommendAPI.getRecommendations();
},
getVideo(id) {
return id;
}
}
//--- Recommendations --//
const recommendationModule = {
}
//--- Start ---//
export default ({ app }, inject) => {
inject('youtube', module)
inject('youtube', searchModule, recommendationModule)
}
logger("Initialize","Program Started");
logger("Initialize", "Program Started");