diff --git a/package.json b/package.json
index 0251bd2d5..8d2a12e0b 100644
--- a/package.json
+++ b/package.json
@@ -66,6 +66,7 @@
"mustache": "^2.3.0",
"nedb": "^1.8.0",
"node-async-loop": "^1.2.2",
- "opml-to-json": "0.0.3"
+ "opml-to-json": "0.0.3",
+ "requests": "^0.2.2"
}
}
diff --git a/src/index.html b/src/index.html
index 15852a2bf..33971f4af 100644
--- a/src/index.html
+++ b/src/index.html
@@ -11,7 +11,7 @@
-
+
diff --git a/src/js/channels.js b/src/js/channels.js
index dd7e44048..9db836c64 100644
--- a/src/js/channels.js
+++ b/src/js/channels.js
@@ -24,14 +24,11 @@ along with FreeTube. If not, see .
/*function getChannelThumbnail(channelId, callback) {
let url = '';
- let request = gapi.client.youtube.channels.list({
+ youtubeAPI('channels', {
'id': channelId,
'part': 'snippet',
- });
-
- request.execute((response) => {
- url = response['items'][0]['snippet']['thumbnails']['high']['url'];
- callback(url);
+ }, function (data){
+ callback(data.items[0].snippet.thumbnails.high.url);
});
}*/
@@ -45,7 +42,7 @@ along with FreeTube. If not, see .
function goToChannel(channelId) {
event.stopPropagation();
clearMainContainer();
- toggleLoading();
+ startLoadingAnimation();
// Check if the user is subscribed to the channel. Display different text based on the information
@@ -62,17 +59,14 @@ function goToChannel(channelId) {
});
// Call YouTube API to grab channel information
- let request = gapi.client.youtube.channels.list({
+ youtubeAPI('channels', {
part: 'snippet, brandingSettings, statistics',
id: channelId,
- });
-
- // Perform API Execution
- request.execute((response) => {
+ }, function (data){
// Set variables of extracted information
- const brandingSettings = response['items'][0]['brandingSettings'];
- const statistics = response['items'][0]['statistics'];
- const snippet = response['items'][0]['snippet'];
+ const brandingSettings = data['items'][0]['brandingSettings'];
+ const statistics = data['items'][0]['statistics'];
+ const snippet = data['items'][0]['snippet'];
const channelName = brandingSettings['channel']['title'];
const channelBanner = brandingSettings['image']['bannerImageUrl'];
const channelImage = snippet['thumbnails']['high']['url'];
@@ -97,22 +91,19 @@ function goToChannel(channelId) {
});
// Render the template on to #main
$('#main').html(rendered);
- toggleLoading();
+ stopLoadingAnimation();
});
// Grab the channel's latest upload. API forces a max of 50.
- let request = gapi.client.youtube.search.list({
+ youtubeAPI('search', {
part: 'snippet',
channelId: channelId,
type: 'video',
maxResults: 50,
order: 'date',
- });
-
- // Execute API request
- request.execute((response) => {
+ }, function (data) {
// Display recent uploads to #main
- response['items'].forEach((video) => {
+ data['items'].forEach((video) => {
displayVideos(video);
});
});
diff --git a/src/js/events.js b/src/js/events.js
index b96b178c6..f15656208 100644
--- a/src/js/events.js
+++ b/src/js/events.js
@@ -35,13 +35,11 @@ along with FreeTube. If not, see .
let commentsTemplate = $.get('templates/comments.html');
commentsTemplate.done((template) => {
- let request = gapi.client.youtube.commentThreads.list({
+ youtubeAPI('commentThreads', {
'videoId': $('#comments').attr('data-video-id'),
'part': 'snippet,replies',
'maxResults': 100,
- });
-
- request.execute((data) => {
+ }, function (data){
let comments = [];
let items = data.items;
diff --git a/src/js/googleApi.js b/src/js/googleApi.js
deleted file mode 100644
index 7d177d869..000000000
--- a/src/js/googleApi.js
+++ /dev/null
@@ -1,18 +0,0 @@
-// File was downloaded to prevent dependency on website.
-// You can find this file at https://apis.google.com/js/api.js
-//
-// This file is not covered by GPL v3. If the owners of this file would like to have
-// this file removed from FreeTube, please contact me at FreeTubeApp@protonmail.com
-
-var gapi=window.gapi=window.gapi||{};gapi._bs=new Date().getTime();(function(){/*
- gapi.loader.OBJECT_CREATE_TEST_OVERRIDE &&*/
-var g=window,h=document,m=g.location,n=function(){},q=/\[native code\]/,u=function(a,b,c){return a[b]=a[b]||c},aa=function(a){a=a.sort();for(var b=[],c=void 0,d=0;df}f&&c.push(e)}return c},U=function(){var a=A.nonce;if(void 0!==a)return a&&a===String(a)&&a.match(S)?a:A.nonce=null;var b=u(A,"us",[]);if(!b||!b.length)return A.nonce=null;for(var c=h.getElementsByTagName(R),d=0,e=c.length;d"+R+">")}},V=function(a){var b=h.createElement(R);b.setAttribute("src",a);a=U();null!==a&&b.setAttribute("nonce",a);b.async="true";(a=h.getElementsByTagName(R)[0])?a.parentNode.insertBefore(b,a):(h.head||h.body||h.documentElement).appendChild(b)},qa=function(a,
-b){var c=b&&b._c;if(c)for(var d=0;d {
+ }, function (data) {
createVideoListContainer('Watch History:');
- response['items'].forEach((video) => {
+ data['items'].forEach((video) => {
displayVideos(video, 'history');
});
- toggleLoading();
+ stopLoadingAnimation()
});
});
}
diff --git a/src/js/init.js b/src/js/init.js
index 99a7a7696..8e5ef0e78 100644
--- a/src/js/init.js
+++ b/src/js/init.js
@@ -20,7 +20,7 @@ along with FreeTube. If not, see .
/*
* File used to initializing the application
*/
-const {app, BrowserWindow} = require('electron');
+const {app, BrowserWindow, dialog} = require('electron');
const path = require('path');
const url = require('url');
let win;
diff --git a/src/js/layout.js b/src/js/layout.js
index 7aa3058f5..cf9ed7eac 100644
--- a/src/js/layout.js
+++ b/src/js/layout.js
@@ -115,23 +115,6 @@ $(document).ready(() => {
loadSubscriptions();
});
-/**
-* Start the YouTube API.
-*
-* @return {Void}
-*/
-function start() {
- // Initializes the client with the API key and the Translate API.
- gapi.client.init({
- 'apiKey': apiKey,
- })
-
- gapi.client.load('youtube', 'v3', () => {
- let isLoad = true;
- });
-}
-
-
/**
* Toggle the ability to view the side navigation bar.
*
@@ -161,28 +144,27 @@ function clearMainContainer() {
hideConfirmFunction();
}
-/**
-* Show the loading animation before / after a function runs. Also disables / enables input
-*
-* @return {Void}
-*/
-function toggleLoading() {
+function startLoadingAnimation() {
const loading = document.getElementById('loading');
const sideNavDisabled = document.getElementById('sideNavDisabled');
const searchBar = document.getElementById('search');
const goToVideoInput = document.getElementById('jumpToInput');
- if (loading.style.display === 'none' || loading.style.display === '') {
loading.style.display = 'inherit';
sideNavDisabled.style.display = 'inherit';
searchBar.disabled = true;
goToVideoInput.disabled = true;
- } else {
+}
+function stopLoadingAnimation() {
+ const loading = document.getElementById('loading');
+ const sideNavDisabled = document.getElementById('sideNavDisabled');
+ const searchBar = document.getElementById('search');
+ const goToVideoInput = document.getElementById('jumpToInput');
+
loading.style.display = 'none';
sideNavDisabled.style.display = 'none';
searchBar.disabled = false;
goToVideoInput.disabled = false;
- }
}
/**
@@ -214,7 +196,7 @@ function createVideoListContainer(headerLabel = '') {
function showAbout(){
// Remove current information and display loading animation
clearMainContainer();
- toggleLoading();
+ startLoadingAnimation();
// Grab about.html to be used as a template
$.get('templates/about.html', (template) => {
@@ -224,7 +206,7 @@ function showAbout(){
});
// Render to #main and remove loading animation
$('#main').html(rendered);
- toggleLoading();
+ stopLoadingAnimation();
});
}
diff --git a/src/js/savedVideos.js b/src/js/savedVideos.js
index 0b491a403..85f7535dc 100644
--- a/src/js/savedVideos.js
+++ b/src/js/savedVideos.js
@@ -113,7 +113,7 @@ function videoIsSaved(videoId) {
*/
function showSavedVideos(){
clearMainContainer();
- toggleLoading();
+ startLoadingAnimation();
console.log('checking saved videos');
let videoList = '';
@@ -136,20 +136,17 @@ function showSavedVideos(){
}
// Call the YouTube API
- let request = gapi.client.youtube.videos.list({
+ youtubeAPI('videos', {
part: 'snippet',
id: videoList,
maxResults: 50,
- });
-
- // Execute the API request
- request.execute((response) => {
+ }, function (data) {
// Render the videos to the screen
createVideoListContainer('Saved Videos:');
- response['items'].forEach((video) => {
+ data['items'].forEach((video) => {
displayVideos(video, 'history');
});
- toggleLoading();
+ stopLoadingAnimation();
});
});
}
diff --git a/src/js/settings.js b/src/js/settings.js
index b818ac9e8..9ca1dc11b 100644
--- a/src/js/settings.js
+++ b/src/js/settings.js
@@ -21,6 +21,10 @@ along with FreeTube. If not, see .
* A file for functions used for settings.
*/
+// To any third party devs that fork the project, please be ethical and change the API keys.
+const apiKeyBank = ['AIzaSyDjszXMCw44W_k-pdNoOxUHFyKGtU_ejwE', 'AIzaSyA0CkT2lS1q9HHaFYGNGM4Ycjl1kmRy22s', 'AIzaSyAiKgR75e3XAznCcb1cj4NUJ5rR_y3uB8E', 'AIzaSyDPy5jq2l1Bgv3-MbpGdZd3W3ik1BMZeDc', 'AIzaSyBeQ-Jd0lyMmul-K1QMZ2S4GSlnGFdCd3M'];
+
+
/**
* Display the settings screen to the user.
*
@@ -28,14 +32,11 @@ along with FreeTube. If not, see .
*/
function showSettings() {
clearMainContainer();
- toggleLoading();
+ startLoadingAnimation();
let isChecked = '';
let key = '';
- // To any third party devs that fork the project, please be ethical and change the API keys.
- const apiKeyBank = ['AIzaSyDjszXMCw44W_k-pdNoOxUHFyKGtU_ejwE', 'AIzaSyA0CkT2lS1q9HHaFYGNGM4Ycjl1kmRy22s', 'AIzaSyAiKgR75e3XAznCcb1cj4NUJ5rR_y3uB8E', 'AIzaSyDPy5jq2l1Bgv3-MbpGdZd3W3ik1BMZeDc', 'AIzaSyBeQ-Jd0lyMmul-K1QMZ2S4GSlnGFdCd3M'];
-
/*
* Check the settings database for the user's current settings. This is so the
* settings page has the correct toggles related when it is rendered.
@@ -64,7 +65,7 @@ function showSettings() {
});
// Render template to application
$('#main').html(rendered);
- toggleLoading();
+ stopLoadingAnimation();
// Check / uncheck the switch depending on the user's settings.
if (currentTheme === 'light') {
@@ -82,9 +83,6 @@ function showSettings() {
* @return {Void}
*/
function checkDefaultSettings() {
- // To any third party devs that fork the project, please be ethical and change the API keys.
- const apiKeyBank = ['AIzaSyDjszXMCw44W_k-pdNoOxUHFyKGtU_ejwE', 'AIzaSyA0CkT2lS1q9HHaFYGNGM4Ycjl1kmRy22s', 'AIzaSyAiKgR75e3XAznCcb1cj4NUJ5rR_y3uB8E', 'AIzaSyDPy5jq2l1Bgv3-MbpGdZd3W3ik1BMZeDc', 'AIzaSyBeQ-Jd0lyMmul-K1QMZ2S4GSlnGFdCd3M'];
-
// Grab a random API Key.
apiKey = apiKeyBank[Math.floor(Math.random() * apiKeyBank.length)];
@@ -129,7 +127,6 @@ function checkDefaultSettings() {
console.log("Using API key: " + apiKey);
// Loads the JavaScript client library and invokes `start` afterwards.
- gapi.load('client', start);
});
}
diff --git a/src/js/subscriptions.js b/src/js/subscriptions.js
index cfcc589b2..78ef841a8 100644
--- a/src/js/subscriptions.js
+++ b/src/js/subscriptions.js
@@ -31,25 +31,22 @@ along with FreeTube. If not, see .
function addSubscription(channelId, useToast = true) {
console.log(channelId);
// Request YouTube API
- let request = gapi.client.youtube.channels.list({
+ youtubeAPI('channels', {
part: 'snippet',
id: channelId,
- });
-
- // Execute API request
- request.execute((response) => {
- const channelInfo = response['items'][0]['snippet'];
+ }, function (data){
+ const channelInfo = data['items'][0]['snippet'];
const channelName = channelInfo['title'];
const thumbnail = channelInfo['thumbnails']['high']['url'];
- const data = {
+ const channel = {
channelId: channelId,
channelName: channelName,
channelThumbnail: thumbnail,
};
// Refresh the list of subscriptions on the side navigation bar.
- subDb.insert(data, (err, newDoc) => {
+ subDb.insert(channel, (err, newDoc) => {
if (useToast){
showToast('Added ' + channelName + ' to subscriptions.');
displaySubs();
@@ -84,13 +81,7 @@ function loadSubscriptions() {
clearMainContainer();
const loading = document.getElementById('loading');
- /*
- * It is possible for the function to be called several times. This prevents the loading
- * from being turned off when the situation occurs.
- */
- if (loading.style.display !== 'inherit'){
- toggleLoading();
- }
+ startLoadingAnimation()
let videoList = [];
@@ -118,16 +109,14 @@ function loadSubscriptions() {
* This number can be changed if we feel necessary.
*/
try {
- let request = gapi.client.youtube.search.list({
+ youtubeAPI('search', {
part: 'snippet',
channelId: channelId,
type: 'video',
maxResults: 15,
order: 'date',
- });
-
- request.execute((response) => {
- videoList = videoList.concat(response['items']);
+ }, function (error, response, data){
+ videoList = videoList.concat(data['items']);
// Iterate through the next object in the loop.
next();
});
@@ -165,12 +154,12 @@ function loadSubscriptions() {
displayVideos(videoList[i]);
}
}
- toggleLoading();
+ stopLoadingAnimation()
});
} else {
// User has no subscriptions. Display message.
const container = document.getElementById('main');
- toggleLoading();
+ stopLoadingAnimation()
container.innerHTML = `Your Subscription list is currently empty. Start adding subscriptions
to see them here.
`;
diff --git a/src/js/videos.js b/src/js/videos.js
index 9ac84561e..5a55210de 100644
--- a/src/js/videos.js
+++ b/src/js/videos.js
@@ -39,31 +39,27 @@ function search(nextPageToken = '') {
if (nextPageToken === '') {
clearMainContainer();
- toggleLoading();
+ startLoadingAnimation();
} else {
console.log(nextPageToken);
showToast('Fetching results. Please wait...');
}
// Start API request
- let request = gapi.client.youtube.search.list({
+ youtubeAPI('search', {
q: query,
part: 'id, snippet',
type: 'video',
pageToken: nextPageToken,
maxResults: 25,
- });
-
- // Execute API Request
- request.execute((response) => {
- console.log(response);
+ }, function (data){
if (nextPageToken === '') {
createVideoListContainer('Search Results:');
- toggleLoading();
+ stopLoadingAnimation();
}
- response['items'].forEach(displayVideos);
- addNextPage(response['result']['nextPageToken']);
- });
+ data.items.forEach(displayVideos);
+ addNextPage(data.result.nextPageToken);
+ })
}
/**
@@ -162,7 +158,7 @@ function addNextPage(nextPageToken) {
*/
function playVideo(videoId) {
clearMainContainer();
- toggleLoading();
+ startLoadingAnimation();
let subscribeText = '';
let savedText = '';
@@ -187,7 +183,7 @@ function playVideo(videoId) {
});
} catch (ex) {
showToast('Video not found. ID may be invalid.');
- toggleLoading();
+ stopLoadingAnimation();
return;
}
@@ -285,15 +281,11 @@ function playVideo(videoId) {
description = autolinker.link(description);
// API Request
- let request = gapi.client.youtube.channels.list({
+ youtubeAPI('channels', {
'id': channelId,
'part': 'snippet,contentDetails,statistics'
- });
-
- // Execute request
- request.execute((response) => {
- console.log(response);
- const channelThumbnail = response['items'][0]['snippet']['thumbnails']['high']['url'];
+ }, function (data){
+ const channelThumbnail = data['items'][0]['snippet']['thumbnails']['high']['url'];
$.get('templates/player.html', (template) => {
mustache.parse(template);
@@ -321,7 +313,7 @@ function playVideo(videoId) {
embedPlayer: embedPlayer,
});
$('#main').html(rendered);
- toggleLoading();
+ stopLoadingAnimation();
showVideoRecommendations(videoId);
console.log('done');
});
@@ -343,15 +335,13 @@ function playVideo(videoId) {
* @param {string} videoId - The video ID of the video to get recommendations from.
*/
function showVideoRecommendations(videoId) {
- let request = gapi.client.youtube.search.list({
+ youtubeAPI('search', {
part: 'snippet',
type: 'video',
relatedToVideoId: videoId,
maxResults: 15,
- });
-
- request.execute((response) => {
- const recommendations = response['items'];
+ }, function (data){
+ const recommendations = data.items;
recommendations.forEach((data) => {
const snippet = data['snippet'];
const videoId = data['id']['videoId'];
@@ -454,7 +444,7 @@ function parseVideoLink() {
*/
function showMostPopular() {
clearMainContainer();
- toggleLoading();
+ startLoadingAnimation();
// Get the date of 2 days ago.
var d = new Date();
@@ -465,19 +455,16 @@ function showMostPopular() {
// These are the videos that are considered as 'most popular' and is how similar
// Applications grab these. Videos in the 'Trending' tab on YouTube will be different.
// And there is no way to grab those videos.
- let request = gapi.client.youtube.search.list({
+ youtubeAPI('search', {
part: 'snippet',
order: 'viewCount',
type: 'video',
publishedAfter: d.toISOString(),
maxResults: 50,
- });
-
- request.execute((response) => {
- console.log(response);
+ }, function (data){
createVideoListContainer('Most Popular:');
- toggleLoading();
- response['items'].forEach(displayVideos);
+ stopLoadingAnimation();
+ data['items'].forEach(displayVideos);
});
}
@@ -506,14 +493,11 @@ function copyLink(website, videoId) {
function getEmbedPlayer(videoId) {
console.log(videoId);
return new Promise((resolve, reject) => {
- let request = gapi.client.youtube.videos.list({
+ youtubeAPI('videos', {
part: 'player',
id: videoId,
- });
-
- request.execute((response) => {
- console.log(response);
- let embedHtml = response['items'][0]['player']['embedHtml'];
+ }, function (data){
+ let embedHtml = data.items[0].player.embedHtml;
embedHtml = embedHtml.replace('src="', 'src="https:');
embedHtml = embedHtml.replace('width="480px"', '');
embedHtml = embedHtml.replace('height="270px"', '');
diff --git a/src/js/youtubeApi.js b/src/js/youtubeApi.js
new file mode 100644
index 000000000..add2b4130
--- /dev/null
+++ b/src/js/youtubeApi.js
@@ -0,0 +1,17 @@
+var request = require("request");
+function youtubeAPI (path, qs, callback) {
+ qs.key = apiKey;
+ request({'url': "https://www.googleapis.com/youtube/v3/"+path, 'qs': qs, 'json': true},
+ function (error, response, body){
+ console.log([error, response, body]);
+ if (error){
+ dialog.showErrorBox('YouTube API HTTP error', JSON.stringify(error))
+ stopLoadingAnimation()
+ } else if (response.statusCode != 200){
+ dialog.showErrorBox('YouTube API error', JSON.stringify(body))
+ stopLoadingAnimation()
+ } else {
+ callback(body);
+ }
+ });
+}