about summary refs log tree commit diff stats
path: root/src/assets/javascripts
diff options
context:
space:
mode:
authorSoispha <soispha@vhack.eu>2023-12-09 12:55:10 +0100
committerSoispha <soispha@vhack.eu>2023-12-09 12:55:10 +0100
commit5f2088c0bb7ea5ee1f18bc5b3ce15d707e043751 (patch)
tree0aa576cf0559dbdca25fa69f5b3a664365e6a428 /src/assets/javascripts
parentchore(manifest.json): Bump version number (diff)
parentAdded toggle for bookmarks menu in settings https://github.com/libredirect/br... (diff)
downloadlibredirect-5f2088c0bb7ea5ee1f18bc5b3ce15d707e043751.zip
chore(Merge): remote-tracking branch 'origin/master'
Diffstat (limited to 'src/assets/javascripts')
-rw-r--r--src/assets/javascripts/localise.js3
-rw-r--r--src/assets/javascripts/services.js83
-rw-r--r--src/assets/javascripts/utils.js65
3 files changed, 142 insertions, 9 deletions
diff --git a/src/assets/javascripts/localise.js b/src/assets/javascripts/localise.js
index 34ccd66b..c0936873 100644
--- a/src/assets/javascripts/localise.js
+++ b/src/assets/javascripts/localise.js
@@ -1,6 +1,9 @@
 window.browser = window.browser || window.chrome
 
 function localisePage() {
+	/**
+	 * @param {string} tag
+	 */
 	function getMessage(tag) {
 		return tag.replace(/__MSG_(\w+)__/g, (_match, v1) => {
 			return v1 ? browser.i18n.getMessage(v1) : null
diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js
index 446926c0..0aea56cc 100644
--- a/src/assets/javascripts/services.js
+++ b/src/assets/javascripts/services.js
@@ -30,6 +30,12 @@ function all(service, frontend, options, config) {
 	return instances
 }
 
+/**
+ * @param {string} service
+ * @param {URL} url
+ * @param {{}} config
+ * @param {string} frontend
+ */
 function regexArray(service, url, config, frontend) {
 	let targetList = config.services[service].targets
 	if (frontend && 'excludeTargets' in config.services[service].frontends[frontend]) {
@@ -44,15 +50,29 @@ function regexArray(service, url, config, frontend) {
 	return false
 }
 
+/**
+ * @param {URL} url
+ * @param {string} type
+ * @param {URL} initiator
+ * @param {boolean} forceRedirection
+ */
 async function redirectAsync(url, type, initiator, forceRedirection) {
 	await init()
 	return redirect(url, type, initiator, forceRedirection)
 }
 
-function redirect(url, type, initiator, forceRedirection) {
+/**
+ * @param {URL} url
+ * @param {string} type
+ * @param {URL} initiator
+ * @param {boolean} forceRedirection
+ * @returns {string | undefined}
+ */
+function redirect(url, type, initiator, forceRedirection, incognito) {
 	if (type != "main_frame" && type != "sub_frame" && type != "image") return
 	let randomInstance
 	let frontend
+	if (!forceRedirection && options.redirectOnlyInIncognito == true && !incognito) return
 	for (const service in config.services) {
 		if (!forceRedirection && !options[service].enabled) continue
 
@@ -147,6 +167,10 @@ function redirect(url, type, initiator, forceRedirection) {
 		case "freetube": {
 			return 'freetube://' + url.href
 		}
+		case "freetubePwa": {
+			return 'freetube://' + url.href
+		}
+
 		case "poketube": {
 			if (url.pathname.startsWith('/channel')) {
 				const reg = /\/channel\/(.*)\/?$/.exec(url.pathname)
@@ -375,7 +399,7 @@ function redirect(url, type, initiator, forceRedirection) {
 		}
 		case "anonymousOverflow": {
 			if (url.hostname == "stackoverflow.com") {
-				const threadID = /\/(\d+)\/?$/.exec(url.pathname)
+				const threadID = /^\/a\/(\d+)\/?/.exec(url.pathname)
 				if (threadID) return `${randomInstance}/questions/${threadID[1]}${url.search}`
 				return `${randomInstance}${url.pathname}${url.search}`
 			}
@@ -524,26 +548,39 @@ function redirect(url, type, initiator, forceRedirection) {
 			return `${randomInstance}`
 		}
 		case "tuboSoundcloud": {
-			if (url.pathname.match(/\/user[^\/]+(\/$|$)/)) {
+			if (url.pathname == '/') return `${randomInstance}?kiosk?serviceId=1`
+			if (url.pathname.match(/^\/[^\/]+(\/$|$)/)) {
 				return `${randomInstance}/channel?url=${encodeURIComponent(url.href)}`
 			}
-			if (url.pathname.match(/\/user[^\/]+\/[^\/]+/)) {
+			if (url.pathname.match(/^\/[^\/]+\/[^\/]+/)) {
 				return `${randomInstance}/stream?url=${encodeURIComponent(url.href)}`
 			}
 			return `${randomInstance}`
 		}
+		case "twineo":
 		case "safetwitch": {
 			if (url.hostname.startsWith("clips.")) {
 				return `${randomInstance}/clip${url.pathname}${url.search}`
 			}
 			return `${randomInstance}${url.pathname}${url.search}`
 		}
+		case "tekstoLibre": {
+			return `${randomInstance}/?${url.pathname.slice(1)}`;
+		}
+		case "skyview": {
+			if (url.pathname == '/') return randomInstance
+			return `${randomInstance}?url=${encodeURIComponent(url.href)}`
+		}
 		default: {
 			return `${randomInstance}${url.pathname}${url.search}`
 		}
 	}
 }
 
+/**
+ * @param {URL} url
+ * @param {*} returnFrontend
+ */
 function computeService(url, returnFrontend) {
 	return new Promise(async resolve => {
 		const config = await utils.getConfig()
@@ -568,6 +605,10 @@ function computeService(url, returnFrontend) {
 	})
 }
 
+/**
+ * @param {URL} url
+ * @param {string} customService
+ */
 function switchInstance(url, customService) {
 	return new Promise(async resolve => {
 		let options = await utils.getOptions()
@@ -577,7 +618,7 @@ function switchInstance(url, customService) {
 		if (customService) {
 			const instancesList = options[options[customService].frontend]
 			if (instancesList !== undefined) {
-				resolve(`${utils.getRandomInstance(instancesList)}${url.pathname}${url.search}`)
+				resolve(`${utils.getNextInstance(url.origin, instancesList)}${url.pathname}${url.search}`)
 			}
 		} else {
 			for (const service in config.services) {
@@ -590,7 +631,7 @@ function switchInstance(url, customService) {
 					resolve()
 					return
 				}
-				resolve(`${utils.getRandomInstance(instancesList)}${url.pathname}${url.search}`)
+				resolve(`${utils.getNextInstance(url.origin, instancesList)}${url.pathname}${url.search}`)
 				return
 			}
 		}
@@ -598,6 +639,9 @@ function switchInstance(url, customService) {
 	})
 }
 
+/**
+ * @param {URL} url
+ */
 async function reverse(url) {
 	let options = await utils.getOptions()
 	let config = await utils.getConfig()
@@ -640,6 +684,9 @@ async function reverse(url) {
 				}
 				return
 			}
+			case "tekstowo": {
+				return `${config.services[service].url}/${url.search.slice(1)}`
+			}
 			default:
 				return
 		}
@@ -689,9 +736,12 @@ const defaultInstances = {
 	'indestructables': ['https://indestructables.private.coffee'],
 	'destructables': ['https://ds.vern.cc'],
 	'safetwitch': ['https://safetwitch.drgns.space'],
+	'twineo': ['https://twineo.exozy.me'],
 	'proxigram': ['https://proxigram.privacyfrontends.repl.co'],
 	'tuboYoutube': ['https://tubo.migalmoreno.com'],
 	'tuboSoundcloud': ['https://tubo.migalmoreno.com'],
+	'tekstoLibre': ['https://davilarek.github.io/TekstoLibre'],
+	'skyview': ['https://skyview.social'],
 }
 
 function initDefaults() {
@@ -714,9 +764,10 @@ function initDefaults() {
 				url: [],
 				regex: [],
 			}
-			options['theme'] = "detect"
-			options['popupServices'] = ["youtube", "twitter", "tiktok", "imgur", "reddit", "quora", "translate", "maps"]
-			options['fetchInstances'] = 'github'
+			options.theme = "detect"
+			options.popupServices = ["youtube", "twitter", "tiktok", "imgur", "reddit", "quora", "translate", "maps"]
+			options.fetchInstances = 'github'
+			options.redirectOnlyInIncognito = false
 
 			options = { ...options, ...defaultInstances }
 
@@ -765,6 +816,13 @@ function processUpdate() {
 					delete options[frontend]
 				}
 			}
+
+			for (const frontend of options.popupServices) {
+				if (!Object.keys(config.services).includes(frontend)) {
+					const i = options.popupServices.indexOf(frontend);
+					if (i > -1) options.popupServices.splice(i, 1);
+				}
+			}
 		}
 		browser.storage.local.set({ options }, () => {
 			resolve()
@@ -772,6 +830,10 @@ function processUpdate() {
 	})
 }
 
+/**
+ * @param {URL} url
+ * @param {boolean} test
+ */
 async function copyRaw(url, test) {
 	const newUrl = await reverse(url)
 	if (newUrl) {
@@ -792,6 +854,9 @@ async function copyRaw(url, test) {
 	}
 }
 
+/**
+ * @param {URL} url
+ */
 function isException(url) {
 	if (!options.exceptions) return false
 	let exceptions = options.exceptions
diff --git a/src/assets/javascripts/utils.js b/src/assets/javascripts/utils.js
index e85b1115..fe08e576 100644
--- a/src/assets/javascripts/utils.js
+++ b/src/assets/javascripts/utils.js
@@ -1,18 +1,68 @@
 window.browser = window.browser || window.chrome
 
+/**
+ * @param {Array.<T>} instances 
+ * @returns {T}
+ */
 function getRandomInstance(instances) {
 	return instances[~~(instances.length * Math.random())]
 }
 
+/**
+ * @param {string} currentInstanceUrl
+ * @param {Array.<T>} instances
+ * @returns {T}
+ */
+function getNextInstance(currentInstanceUrl, instances) {
+	const currentInstanceIndex = instances.indexOf(currentInstanceUrl);
+
+	if (currentInstanceIndex === -1){
+		return getRandomInstance(instances);
+	}
+
+	const nextInstanceIndex = (currentInstanceIndex + 1) % instances.length;
+
+	return instances[nextInstanceIndex];
+}
+
+/**
+ * @param {string} str
+ */
 function camelCase(str) {
 	return str.charAt(0).toUpperCase() + str.slice(1)
 }
 
+/**
+ * @param {URL} url
+ */
 function protocolHost(url) {
 	if (url.username && url.password) return `${url.protocol}//${url.username}:${url.password}@${url.host}`
+	if (url.pathname == "/TekstoLibre/" && url.host.endsWith("github.io")) // workaround
+		return `${url.protocol}//${url.host}${url.pathname.slice(0, -1)}`
 	return `${url.protocol}//${url.host}`
 }
 
+/**
+ * @typedef FrontendInfo
+ * @prop {boolean} instanceList
+ * @prop {string} name
+ * @prop {string} url
+ */
+
+/**
+ * @typedef {Object} Service
+ * @prop {Object.<string, FrontendInfo>} frontends
+ * @prop {Object} options
+ */
+
+/**
+ * @typedef {Object} Config
+ * @prop {Object.<string, Service>} services
+ */
+
+/**
+ * @returns {Promise<Config>}
+ */
 function getConfig() {
 	return new Promise(resolve => {
 		fetch("/config.json")
@@ -24,6 +74,14 @@ function getConfig() {
 	})
 }
 
+/**
+ * @typedef {Object} Option
+ * @prop {string} frontend
+ */
+
+/**
+ * @returns {Promise<Object.<string, Option | string[]>>}
+ */
 function getOptions() {
 	return new Promise(resolve =>
 		browser.storage.local.get("options", r => {
@@ -106,6 +164,9 @@ function getList(options) {
 	})
 }
 
+/**
+ * @param {string} href
+ */
 function pingOnce(href) {
 	return new Promise(async resolve => {
 		let started
@@ -130,6 +191,9 @@ function pingOnce(href) {
 	})
 }
 
+/**
+ * @param {string} href
+ */
 function ping(href) {
 	return new Promise(async resolve => {
 		let average = 0
@@ -150,6 +214,7 @@ function ping(href) {
 
 export default {
 	getRandomInstance,
+	getNextInstance,
 	protocolHost,
 	getList,
 	getBlacklist,