diff --git a/src/background.ts b/src/background.ts
index 2fc52e0..fd414b2 100644
--- a/src/background.ts
+++ b/src/background.ts
@@ -20,7 +20,8 @@ import * as browser from 'webextension-polyfill';
import { MessageKind, RedirectType } from './types';
import constants from './constants';
import Preferences from './preferences';
-import InvidiousAPI from './invidious-api';
+import * as InvidiousAPI from './invidious-api';
+import * as PeertubeAPI from './peertube-api';
import { getPeertubeVideoURL } from './util';
/**
@@ -32,10 +33,10 @@ const getTitle = async (id: string) => {
}
/**
- * Prevent Youtube from loading if the video is found and preferences set on
- * automatic redirection.
+ * Redirect Youtube without loading it if the video is found and preferences lAHhDKzReKBQKj3R
+ * set on automatic redirection.
*/
-const preventYoutube = async (r) => {
+const redirectYoutube = async (r) => {
const prefs = await Preferences.getPreferences();
if (prefs.redirectYoutube == RedirectType.Auto) {
@@ -53,13 +54,38 @@ const preventYoutube = async (r) => {
throw new Error('No results.');
};
-const buildSearchByNameURL = (instance: string, query: string): string => `https://${instance}/api/v1/search/videos?search=${encodeURIComponent(query)}`;
+/**
+ * Redirect to preferred PeerTube Instance when trying to watch a PeerTube
+ * video.
+ */
+const redirectPeertube = async (r) => {
+ const prefs = await Preferences.getPreferences();
+ const hostname = new URL(r.url).hostname;
+
+ if (prefs.openInOriginalInstance === false && prefs.searchInstance === hostname) {
+ return {}; // Don't redirect if good instance
+ }
+
+ if (prefs.redirectPeertube == RedirectType.Auto) {
+ const id = _.last(_.split('/', r.url));
+ const video: any = await PeertubeAPI.getVideo(id);
+
+ if (prefs.openInOriginalInstance && video.account.host === hostname) {
+ return {}; // Don't redirect if original instance
+ }
+
+ const url = getPeertubeVideoURL(video, prefs);
+
+ return {
+ redirectUrl: url
+ };
+ }
+
+ throw new Error('No results.');
+};
const searchByName = query => new Promise(async (resolve, reject) => {
- const instance = _.getOr(constants.defaultInstance, 'searchInstance', await browser.storage.local.get()).toString();
-
- fetch(buildSearchByNameURL(instance, query))
- .then(res => res.json())
+ PeertubeAPI.searchVideo({ search: query })
.then(function(data) {
if (data.total > 0) {
const video = data.data[0]
@@ -71,29 +97,23 @@ const searchByName = query => new Promise(async (resolve, reject) => {
});
});
-const buildSearchByIDURL = (instance: string, id: string): string => `https://${instance}/api/v1/videos/${id}`;
-
-const searchByID = id => new Promise(async (resolve, reject) => {
- const instance = _.getOr(constants.defaultInstance, 'searchInstance', await browser.storage.local.get()).toString();
-
- fetch(buildSearchByIDURL(instance, id))
- .then(res => res.json())
- .then(function(video) {
- resolve({ url: `https://${instance}/videos/watch/${id}`, video });
- })
-})
-
browser.runtime.onMessage.addListener(function(message, sender) {
switch (message.kind) {
case MessageKind.SearchByName:
return searchByName(message.query);
case MessageKind.SearchByID:
- return searchByID(message.id);
+ return PeertubeAPI.getVideo(message.id);
}
});
browser.webRequest.onBeforeRequest.addListener(
- preventYoutube,
+ redirectYoutube,
{ urls: ['*://*.youtube.com/watch?v=*'] },
['blocking']
);
+
+browser.webRequest.onBeforeRequest.addListener(
+ redirectPeertube,
+ { urls: ['*://*/videos/watch/*'] },
+ ['blocking']
+);
diff --git a/src/constants.ts b/src/constants.ts
index 7614a01..ab040e2 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -1,5 +1,8 @@
export default {
- defaultInstance: 'peertube.social',
+ peertubeAPI: {
+ defaultInstance: 'peertube.social',
+ endpoint: 'api/v1',
+ },
invidiousAPI: {
url: 'https://invidio.us/api/v1',
videos: 'videos',
diff --git a/src/invidious-api.ts b/src/invidious-api.ts
index d44863f..69f7154 100644
--- a/src/invidious-api.ts
+++ b/src/invidious-api.ts
@@ -1,27 +1,42 @@
+/* This file is part of PeerTubeify.
+ *
+ * PeerTubeify is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * PeerTubeify is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * PeerTubeify. If not, see .
+ */
+
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('&');
+async function 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);
- }
+ return fetch(`${constants.invidiousAPI.url}/${action}/${paramString}`)
+ .then(res => res.json())
+ .catch(e => console.error(
+ 'An error occured while trying to fetch Invidious API used by PeerTubeify: '
+ + e.message
+ ));
+}
+
+
+export async function getVideo(id: string) {
+ return fetchAPI(constants.invidiousAPI.videos, id);
+}
+
+export async function getChannel(ucid: string) {
+ return fetchAPI(constants.invidiousAPI.channels, ucid);
}
diff --git a/src/peertube-api.ts b/src/peertube-api.ts
new file mode 100644
index 0000000..2f353a4
--- /dev/null
+++ b/src/peertube-api.ts
@@ -0,0 +1,44 @@
+/* This file is part of PeerTubeify.
+ *
+ * PeerTubeify is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * PeerTubeify is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * PeerTubeify. If not, see .
+ */
+
+import * as _ from 'lodash/fp';
+import constants from './constants';
+import Preferences from './preferences';
+
+async function fetchAPI(path: string, query?: Object) {
+ const instance = (await Preferences.getPreferences()).searchInstance;
+
+ let url = `https://${instance}/${constants.peertubeAPI.endpoint}/${path}`;
+
+ if (query) {
+ url = url + '?' + Object.keys(query).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(query[key])).join('&');
+ }
+
+ return fetch(url)
+ .then(res => res.json())
+ .catch(e => console.error(
+ `An error occured while trying to fetch ${instance} API used by PeerTubeify: `
+ + e.message
+ ));
+}
+
+export async function getVideo(id: string) {
+ return fetchAPI('videos/' + id);
+}
+
+export async function searchVideo(query: Object) {
+ return fetchAPI('search/videos', query);
+}
diff --git a/src/peertube.ts b/src/peertube.ts
index f275fcc..76db0d9 100644
--- a/src/peertube.ts
+++ b/src/peertube.ts
@@ -17,7 +17,7 @@
import * as _ from 'lodash/fp';
import * as browser from 'webextension-polyfill';
-import { htmlToElement } from './util';
+import { htmlToElement, getPeertubeVideoURL } from './util';
import { MessageKind, RedirectType } from './types';
import Preferences from './preferences';
@@ -46,20 +46,13 @@ async function peertubeify() {
switch (prefs.redirectPeertube) {
case RedirectType.Show: {
searchVideo()
- .then(async ({ video, url }) => {
- const link = videoLink(url, video);
+ .then(async video => {
+ const link = videoLink(getPeertubeVideoURL(video, prefs), video);
removeVideoLink();
document.querySelector('body').appendChild(link);
}).catch(removeVideoLink);
break;
}
- case RedirectType.Auto: {
- searchVideo()
- .then(async ({ video, url }) => {
- location.replace(url);
- });
- break;
- }
case RedirectType.None: {
break;
}
diff --git a/src/preferences.ts b/src/preferences.ts
index fd41297..ada960a 100644
--- a/src/preferences.ts
+++ b/src/preferences.ts
@@ -28,7 +28,7 @@ export default class Preferences {
redirectPeertube: RedirectType;
constructor(localStorage) {
- this.searchInstance = _.defaultTo(constants.defaultInstance, localStorage.searchInstance as string);
+ this.searchInstance = _.defaultTo(constants.peertubeAPI.defaultInstance, localStorage.searchInstance as string);
this.openInOriginalInstance = _.defaultTo(true, localStorage.openInOriginalInstance as boolean);
this.redirectYoutube = _.defaultTo(RedirectType.Show, localStorage.redirectYoutube)
this.redirectPeertube = _.defaultTo(RedirectType.None, localStorage.redirectPeertube)
@@ -54,6 +54,6 @@ export default class Preferences {
}
set searchInstance(instance) {
- this._searchInstance = _.isEmpty(instance) ? constants.defaultInstance : stripProtocol(instance)
+ this._searchInstance = _.isEmpty(instance) ? constants.peertubeAPI.defaultInstance : stripProtocol(instance)
}
}