Redirect before calling Youtube

Add the ability to call Invidious API and use it to prevent any call to youtube servers.
Refactor some methods and move them in util.js.
This commit is contained in:
Booteille 2018-11-11 16:29:38 +01:00
parent 4ca19de083
commit c676af242a
No known key found for this signature in database
GPG Key ID: 7FC1ED300B74CD91
6 changed files with 85 additions and 17 deletions

View File

@ -12,7 +12,9 @@
"permissions": [ "permissions": [
"activeTab", "activeTab",
"storage", "storage",
"<all_urls>" "<all_urls>",
"webRequest",
"webRequestBlocking"
], ],
"background": { "background": {
"scripts": ["dist/background.js", "dist/vendors.js"] "scripts": ["dist/background.js", "dist/vendors.js"]

View File

@ -19,6 +19,39 @@ import * as browser from 'webextension-polyfill';
import { MessageKind } from './types'; import { MessageKind } from './types';
import constants from './constants'; import constants from './constants';
import Preferences from './preferences';
import InvidiousAPI from './invidious-api';
import { getPeertubeVideoURL } from './util';
/**
* Retrieve the title of the video using Invidious API.
*/
const getTitle = async (id: string) => {
let data = await InvidiousAPI.getVideo(id);
return data.title;
}
/**
* Prevent Youtube from loading if the video is found and preferences set on
* automatic redirection.
*/
const preventYoutube = async (r) => {
const prefs = await Preferences.getPreferences();
if (prefs.redirectYoutube === 'Auto') {
const query = new URLSearchParams(r.url.substring(r.url.indexOf('?') + 1));
let title = await getTitle(query.get('v'));
let video = await searchByName(title);
let url = getPeertubeVideoURL(video, prefs);
return {
redirectUrl: url
};
}
return {};
};
const buildSearchByNameURL = (instance: string, query: string): string => `https://${instance}/api/v1/search/videos?search=${encodeURIComponent(query)}`; const buildSearchByNameURL = (instance: string, query: string): string => `https://${instance}/api/v1/search/videos?search=${encodeURIComponent(query)}`;
@ -58,3 +91,9 @@ browser.runtime.onMessage.addListener(function(message, sender) {
return searchByID(message.id); return searchByID(message.id);
} }
}); });
browser.webRequest.onBeforeRequest.addListener(
preventYoutube,
{urls: ['*://*.youtube.com/watch?v=*']},
['blocking']
);

View File

@ -1,3 +1,8 @@
export default { export default {
defaultInstance: 'peertube.social' defaultInstance: 'peertube.social',
invidiousAPI: {
url: 'https://invidio.us/api/v1',
videos: 'videos',
channels: 'channels'
}
}; };

26
src/invidious-api.ts Normal file
View File

@ -0,0 +1,26 @@
import * as _ from 'lodash/fp';
import constants from './constants';
export default class InvidiousAPI {
static async _fetchAPI(action: string, params: any) {
let paramString = typeof params == 'string'
? params
: Object.keys(params).map(function(key){
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
}).join('&');
return fetch(`${constants.invidiousAPI.url}/${action}/${paramString}`)
.then(res => res.json())
.catch(e => console.error(
'An error occured while trying to fetch API used by PeerTubeify: '
+ e.message
));
}
static async getVideo(id: string) {
return this._fetchAPI(constants.invidiousAPI.videos, id);
}
static async getChannel(ucid: string) {
return this._fetchAPI(constants.invidiousAPI.channels, ucid);
}
}

View File

@ -3,3 +3,12 @@ export function htmlToElement(html: string): Element {
template.innerHTML = html.trim(); template.innerHTML = html.trim();
return template.content.firstElementChild; return template.content.firstElementChild;
} }
export function getPeertubeVideoURL(video, prefs) {
return `https://${getPeertubeHost(video.account.host, prefs)}/videos/watch/${video.uuid}`
}
export function getPeertubeHost(host, prefs)
{
return prefs.openInOriginalInstance ? host : prefs.searchInstance;
}

View File

@ -17,11 +17,10 @@
import * as _ from 'lodash/fp'; import * as _ from 'lodash/fp';
import * as browser from 'webextension-polyfill'; import * as browser from 'webextension-polyfill';
import { htmlToElement } from './util'; import { htmlToElement, getPeertubeVideoURL } from './util';
import { MessageKind, RedirectType } from './types'; import { MessageKind, RedirectType } from './types';
import Preferences from './preferences' import Preferences from './preferences'
const watchURL = (host, uuid) => `https://${host}/videos/watch/${uuid}`;
const thumbnailURL = (host, path) => `https://${host}${path}`; const thumbnailURL = (host, path) => `https://${host}${path}`;
const LINK_ID = 'peertube-link'; const LINK_ID = 'peertube-link';
@ -33,10 +32,6 @@ function searchVideo(query) {
}); });
} }
function getCorrectURL(video: any, prefs: Preferences) {
return watchURL(prefs.openInOriginalInstance ? video.account.host : prefs.searchInstance, video.uuid)
}
async function peertubeify(query: String) { async function peertubeify(query: String) {
const prefs = await Preferences.getPreferences(); const prefs = await Preferences.getPreferences();
@ -44,7 +39,7 @@ async function peertubeify(query: String) {
case RedirectType.Show: { case RedirectType.Show: {
searchVideo(query) searchVideo(query)
.then(async video => { .then(async video => {
const url = getCorrectURL(video, prefs) const url = getPeertubeVideoURL(video, prefs)
const link = videoLink(url, video); const link = videoLink(url, video);
removeVideoLink(); removeVideoLink();
@ -52,14 +47,6 @@ async function peertubeify(query: String) {
}).catch(removeVideoLink); }).catch(removeVideoLink);
break; break;
} }
case RedirectType.Auto: {
searchVideo(query)
.then(async video => {
const url = getCorrectURL(video, prefs)
location.replace(url);
});
break;
}
case RedirectType.None: { case RedirectType.None: {
break; break;
} }