Redirect before calling Youtube

Implements #6
This commit is contained in:
Ealhad 2018-11-12 15:56:58 +00:00
commit 3cbed317cd
6 changed files with 89 additions and 21 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

@ -17,8 +17,41 @@
import * as _ from 'lodash/fp'; import * as _ from 'lodash/fp';
import * as browser from 'webextension-polyfill'; import * as browser from 'webextension-polyfill';
import { MessageKind } from './types'; import { MessageKind, RedirectType } 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) => {
const 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 == RedirectType.Auto) {
const query = new URLSearchParams(r.url.substring(r.url.indexOf('?') + 1));
const title = await getTitle(query.get('v'));
const video = await searchByName(title);
const url = getPeertubeVideoURL(video, prefs);
return {
redirectUrl: url
};
}
throw new Error('No results.');
};
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'
}
}; };

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

@ -0,0 +1,27 @@
import * as _ from 'lodash/fp';
import constants from './constants';
export default class InvidiousAPI {
private static async fetchAPI(action: string, params: any) {
const 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

@ -1,5 +1,13 @@
export function htmlToElement(html: string): Element { export function htmlToElement(html: string): Element {
const template = document.createElement('template'); const template = document.createElement('template');
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;
} }