From 2e5b23c83fa0a1349c5b18b06732507088fa24c9 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Sun, 10 Dec 2023 04:45:13 +0300 Subject: Added Priviblur https://github.com/libredirect/browser_extension/issues/867 --- src/assets/javascripts/services.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index d431369d..4bcc7618 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -571,6 +571,21 @@ function redirect(url, type, initiator, forceRedirection, incognito) { if (url.pathname == '/') return randomInstance return `${randomInstance}?url=${encodeURIComponent(url.href)}` } + case "priviblur": { + if (url.hostname.startsWith("blog")) + return `${randomInstance}/blog${url.pathname}${url.search}` + + if (url.hostname.startsWith("assets")) + return `${randomInstance}/assets${url.pathname}${url.search}` + + if (url.hostname.startsWith("static")) + return `${randomInstance}/static${url.pathname}${url.search}` + + const reg = /^([0-9]+)\.media\.tumblr\.com/.exec(url.hostname) + if (reg) + return `${randomInstance}/media/${reg[1]}${url.pathname}${url.search}` + return `${randomInstance}${url.pathname}${url.search}` + } default: { return `${randomInstance}${url.pathname}${url.search}` } @@ -742,6 +757,7 @@ const defaultInstances = { 'tuboSoundcloud': ['https://tubo.migalmoreno.com'], 'tekstoLibre': ['https://davilarek.github.io/TekstoLibre'], 'skyview': ['https://skyview.social'], + 'priviblur': ['https://pb.bloat.cat'], } function initDefaults() { -- cgit 1.4.1 From 4741eb2439c0484817f290eb2f1e5467ce55f7e7 Mon Sep 17 00:00:00 2001 From: syeopite Date: Sun, 10 Dec 2023 01:47:15 -0800 Subject: Add Tumblr blog redirects for Priviblur --- src/assets/javascripts/services.js | 31 ++++++++++++++++++++++++------- src/config.json | 5 +++-- 2 files changed, 27 insertions(+), 9 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 4bcc7618..603f9c23 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -572,19 +572,36 @@ function redirect(url, type, initiator, forceRedirection, incognito) { return `${randomInstance}?url=${encodeURIComponent(url.href)}` } case "priviblur": { - if (url.hostname.startsWith("blog")) - return `${randomInstance}/blog${url.pathname}${url.search}` + // www.tumblr.com + if (url.hostname === "www.tumblr.com") + return `${randomInstance}${url.pathname}${url.search}`; + // assets.tumblr.com if (url.hostname.startsWith("assets")) - return `${randomInstance}/assets${url.pathname}${url.search}` + return `${randomInstance}/tblr/assets${url.pathname}${url.search}`; + // static.tumblr.com if (url.hostname.startsWith("static")) - return `${randomInstance}/static${url.pathname}${url.search}` + return `${randomInstance}/tblr/static${url.pathname}${url.search}`; - const reg = /^([0-9]+)\.media\.tumblr\.com/.exec(url.hostname) + // *.media.tumblr.com + const reg = /^([0-9]+)\.media\.tumblr\.com/.exec(url.hostname); if (reg) - return `${randomInstance}/media/${reg[1]}${url.pathname}${url.search}` - return `${randomInstance}${url.pathname}${url.search}` + return `${randomInstance}/tblr/media/${reg[1]}${url.pathname}${url.search}`; + + // .tumblr.com + const blogregex = /^(www.)?([a-z\d]{1}[a-z\d-]{0,30}[a-z\d]{0,1})\.tumblr\.com/.exec(url.hostname); + const blog_name = blogregex[2]; + + if (blogregex) + // Under the .tumblr.com domain posts are under a /post path + if (url.pathname.startsWith("/post")) { + return `${randomInstance}/${blog_name}${url.pathname.slice(5)}${url.search}`; + } else { + return `${randomInstance}/${blog_name}${url.pathname}${url.search}`; + } + + return `${randomInstance}${url.pathname}${url.search}`; } default: { return `${randomInstance}${url.pathname}${url.search}` diff --git a/src/config.json b/src/config.json index 13d5dc30..a99a3907 100644 --- a/src/config.json +++ b/src/config.json @@ -1006,8 +1006,9 @@ } }, "targets": [ - "^https?:\\/{2}(media\\.|blog\\.|assets\\.|static\\.)?tumblr\\.com\\/", - "^https?:\\/{2}[0-9]+\\.media\\.tumblr\\.com\\/" + "^https?:\\/{2}(media\\.|assets\\.|static\\.)?tumblr\\.com\\/", + "^https?:\\/{2}[0-9]+\\.media\\.tumblr\\.com\\/", + "^https?:\\/{2}(www\\.)?(.*)\\.tumblr.com\\/" ], "name": "Tumblr", "options": { -- cgit 1.4.1 From 5db2536eae8b71d68b576b34061999feacc051f7 Mon Sep 17 00:00:00 2001 From: syeopite Date: Sun, 10 Dec 2023 02:01:34 -0800 Subject: Remove debug console.log statements --- src/assets/javascripts/services.js | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 4bcc7618..a9a87830 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -445,9 +445,7 @@ function redirect(url, type, initiator, forceRedirection, incognito) { return `${randomInstance}${url.pathname}${url.search}` } case "mikuInvidious": { - console.log("Hello?") if (url.hostname == "bilibili.com" || url.hostname == "www.bilibili.com" || url.hostname == 'b23.tv') { - console.log('wewe') return `${randomInstance}${url.pathname}${url.search}` } if (url.hostname == "space.bilibili.com") { @@ -500,7 +498,6 @@ function redirect(url, type, initiator, forceRedirection, incognito) { } case "quetre": { const regex = /([a-z]+)\.quora\.com/.exec(url.hostname) - console.log(regex) if (regex) { const lang = regex[1] url.searchParams.append("lang", lang) -- cgit 1.4.1 From fa9f55978e1fe5c5bd39a5a252d99ea15ed29a6b Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Sun, 10 Dec 2023 22:51:11 +0300 Subject: Modified Tumblr redirection https://github.com/libredirect/browser_extension/pull/869 --- src/assets/javascripts/services.js | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index c03f7c22..b1b0fdaa 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -569,35 +569,29 @@ function redirect(url, type, initiator, forceRedirection, incognito) { return `${randomInstance}?url=${encodeURIComponent(url.href)}` } case "priviblur": { - // www.tumblr.com - if (url.hostname === "www.tumblr.com") - return `${randomInstance}${url.pathname}${url.search}`; + if (url.hostname == "www.tumblr.com") + return `${randomInstance}${url.pathname}${url.search}` - // assets.tumblr.com if (url.hostname.startsWith("assets")) - return `${randomInstance}/tblr/assets${url.pathname}${url.search}`; + return `${randomInstance}/tblr/assets${url.pathname}${url.search}` - // static.tumblr.com if (url.hostname.startsWith("static")) - return `${randomInstance}/tblr/static${url.pathname}${url.search}`; + return `${randomInstance}/tblr/static${url.pathname}${url.search}` - // *.media.tumblr.com - const reg = /^([0-9]+)\.media\.tumblr\.com/.exec(url.hostname); + const reg = /^([0-9]+)\.media\.tumblr\.com/.exec(url.hostname) // *.media.tumblr.com if (reg) - return `${randomInstance}/tblr/media/${reg[1]}${url.pathname}${url.search}`; - - // .tumblr.com - const blogregex = /^(www.)?([a-z\d]{1}[a-z\d-]{0,30}[a-z\d]{0,1})\.tumblr\.com/.exec(url.hostname); - const blog_name = blogregex[2]; - - if (blogregex) + return `${randomInstance}/tblr/media/${reg[1]}${url.pathname}${url.search}` + + const blogregex = /^(?:www\.)?([a-z\d]+)\.tumblr\.com/.exec(url.hostname) // .tumblr.com + if (blogregex) { + const blog_name = blogregex[1]; // Under the .tumblr.com domain posts are under a /post path if (url.pathname.startsWith("/post")) { - return `${randomInstance}/${blog_name}${url.pathname.slice(5)}${url.search}`; + return `${randomInstance}/${blog_name}${url.pathname.slice(5)}${url.search}` } else { return `${randomInstance}/${blog_name}${url.pathname}${url.search}`; } - + } return `${randomInstance}${url.pathname}${url.search}`; } default: { -- cgit 1.4.1 From 94f7690e1dc238dbc65e4261c83c5085796b4007 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Mon, 11 Dec 2023 10:58:32 +0000 Subject: Update services.js --- src/assets/javascripts/services.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index b1b0fdaa..4649c8e3 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -582,7 +582,7 @@ function redirect(url, type, initiator, forceRedirection, incognito) { if (reg) return `${randomInstance}/tblr/media/${reg[1]}${url.pathname}${url.search}` - const blogregex = /^(?:www\.)?([a-z\d]+)\.tumblr\.com/.exec(url.hostname) // .tumblr.com + const blogregex = /^(?:www\.)?([a-z\d-]+)\.tumblr\.com/.exec(url.hostname) // .tumblr.com if (blogregex) { const blog_name = blogregex[1]; // Under the .tumblr.com domain posts are under a /post path -- cgit 1.4.1 From e48f68126d620bafe312a6caecc21a63612f8e69 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Tue, 12 Dec 2023 14:42:45 +0300 Subject: Fixed a bug that bypassses iframes in frontends pages https://github.com/libredirect/browser_extension/issues/866 --- src/assets/javascripts/services.js | 7 +++++-- src/pages/background/background.js | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 4649c8e3..fc97799a 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -104,7 +104,10 @@ function redirect(url, type, initiator, forceRedirection, incognito) { initiator && instanceList.includes(initiator.origin) - ) return "BYPASSTAB" + ) { + if (type != "main_frame") return null + else return "BYPASSTAB" + } randomInstance = utils.getRandomInstance(instanceList) if (config.services[service].frontends[frontend].localhost && options[service].instance == "localhost") { @@ -581,7 +584,7 @@ function redirect(url, type, initiator, forceRedirection, incognito) { const reg = /^([0-9]+)\.media\.tumblr\.com/.exec(url.hostname) // *.media.tumblr.com if (reg) return `${randomInstance}/tblr/media/${reg[1]}${url.pathname}${url.search}` - + const blogregex = /^(?:www\.)?([a-z\d-]+)\.tumblr\.com/.exec(url.hostname) // .tumblr.com if (blogregex) { const blog_name = blogregex[1]; diff --git a/src/pages/background/background.js b/src/pages/background/background.js index 4b8f1ca2..9057f64a 100644 --- a/src/pages/background/background.js +++ b/src/pages/background/background.js @@ -71,7 +71,7 @@ browser.webRequest.onBeforeRequest.addListener( if (tabIdRedirects[details.tabId] != false) tabIdRedirects[details.tabId] = false return null } - console.info("Redirecting", url.href, "=>", newUrl) + console.log("Redirecting", url.href, "=>", newUrl) return { redirectUrl: newUrl } } return null -- cgit 1.4.1 From c599ad9ed6cf8d3f5c7715ca898b7d280602c476 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Mon, 1 Jan 2024 03:02:29 +0300 Subject: Removed incorrect redirections for Binternet https://github.com/libredirect/browser_extension/issues/876 --- src/assets/javascripts/services.js | 1 - 1 file changed, 1 deletion(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index fc97799a..3316ebe8 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -492,7 +492,6 @@ function redirect(url, type, initiator, forceRedirection, incognito) { } case "binternet": { if (url.hostname == "i.pinimg.com") return `${randomInstance}/image_proxy.php?url=${url.href}` - return randomInstance } case "laboratory": { let path = url.pathname -- cgit 1.4.1 From b79a485f61894c0e2b8aef5c27f901e91350ad6c Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Wed, 3 Jan 2024 15:12:21 +0300 Subject: Cleaned OSM redirection code --- package.json | 2 +- src/assets/javascripts/services.js | 98 ++++++++++++++------------------------ 2 files changed, 37 insertions(+), 63 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/package.json b/package.json index d388da1f..fe0ac5aa 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ }, "scripts": { "start": "web-ext run", - "start-nightly": "web-ext run --firefox=/home/manerakai/Downloads/firefox/firefox", + "start-nightly": "web-ext run --firefox=/home/manerakai/software/firefox_nightly/firefox", "build": "web-ext build", "test": "web-ext lint", "html": "pug --basedir ./ --obj ./src/config.json src/pages/options/index.pug --out src/pages/options/ && pug --basedir ./ --obj ./src/config.json src/pages/popup/popup.pug --out src/pages/popup/" diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 3316ebe8..a1935bff 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -210,9 +210,8 @@ function redirect(url, type, initiator, forceRedirection, incognito) { return `${randomInstance}/${search}` } case "osm": { - const dataLatLngRegex = /!3d(-?[0-9]{1,}.[0-9]{1,})!4d(-?[0-9]{1,}.[0-9]{1,})/ - const placeRegex = /\/place\/(.*)\// - function convertMapCentre() { + const placeRegex = /\/place\/(.*?)\// + function convertMapCentre(url) { let [lat, lon, zoom] = [null, null, null] const reg = url.pathname.match(/@(-?\d[0-9.]*),(-?\d[0-9.]*),(\d{1,2})[.z]/) if (reg) { @@ -224,14 +223,6 @@ function redirect(url, type, initiator, forceRedirection, incognito) { } return { zoom, lon, lat } } - if (initiator && initiator.host === "earth.google.com") return randomInstance - const travelModes = { - driving: "fossgis_osrm_car", - walking: "fossgis_osrm_foot", - bicycling: "fossgis_osrm_bike", - transit: "fossgis_osrm_car", // not implemented on OSM, default to car. - } - function addressToLatLng(address) { const http = new XMLHttpRequest() http.open("GET", `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(address)}&format=json&limit=1`, false) @@ -247,86 +238,69 @@ function redirect(url, type, initiator, forceRedirection, incognito) { return {} } } + function getQuery(url) { + let query = "" + if (url.searchParams.has("q")) query = url.searchParams.get("q") + else if (url.searchParams.has("query")) query = url.searchParams.has("query") + return query + } + function prefsEncoded(prefs) { + return new URLSearchParams(prefs).toString() + } + + if (initiator && initiator.host === "earth.google.com") return randomInstance let mapCentre = "#" - let prefs = {} + let prefs = { layers: "mapnik" } - const mapCentreData = convertMapCentre() + const mapCentreData = convertMapCentre(url) if (mapCentreData.zoom && mapCentreData.lon && mapCentreData.lat) mapCentre = `#map=${mapCentreData.zoom}/${mapCentreData.lon}/${mapCentreData.lat}` - if (url.searchParams.get("layer")) prefs.layers = osmLayers[url.searchParams.get("layer")] - - if (url.pathname.includes("/embed")) { - // Handle Google Maps Embed API - // https://www.google.com/maps/embed/v1/place?key=AIzaSyD4iE2xVSpkLLOXoyqT-RuPwURN3ddScAI&q=Eiffel+Tower,Paris+France - let query = "" - if (url.searchParams.has("q")) query = url.searchParams.get("q") - else if (url.searchParams.has("query")) query = url.searchParams.has("query") - else if (url.searchParams.has("pb")) - try { - query = url.searchParams.get("pb").split(/!2s(.*?)!/)[1] - } catch (error) { - // Unable to find map marker in URL. - console.error(error) - } + if (url.pathname.includes("/embed")) { // https://www.google.com/maps/embed/v1/place?key=AIzaSyD4iE2xVSpkLLOXoyqT-RuPwURN3ddScAI&q=Eiffel+Tower,Paris+France + const query = getQuery(url) let { coordinate, boundingbox } = addressToLatLng(query) prefs.bbox = boundingbox prefs.marker = coordinate - prefs.layers = "mapnik" - let prefsEncoded = new URLSearchParams(prefs).toString() - return `${randomInstance}/export/embed.html?${prefsEncoded}` + return `${randomInstance}/export/embed.html?${prefsEncoded(prefs)}` } else if (url.pathname.includes("/dir")) { - // Handle Google Maps Directions if (url.searchParams.has("travelmode")) { + const travelModes = { + driving: "fossgis_osrm_car", + walking: "fossgis_osrm_foot", + bicycling: "fossgis_osrm_bike", + transit: "fossgis_osrm_car", // not implemented on OSM, default to car. + } prefs.engine = travelModes[url.searchParams.get("travelmode")] } const regex1 = /\/dir\/([^@/]+)\/([^@/]+)\/@-?\d[0-9.]*,-?\d[0-9.]*,\d{1,2}[.z]/.exec(url.pathname) const regex2 = /\/dir\/([^@/]+)\//.exec(url.pathname) - if (regex1) { - // https://www.google.com/maps/dir/92+Rue+Moncey,+69003+Lyon,+France/M%C3%A9dip%C3%B4le+Lyon-Villeurbanne/@45.760254,4.8486298,13z?travelmode=bicycling + if (regex1) { // https://www.google.com/maps/dir/92+Rue+Moncey,+69003+Lyon,+France/M%C3%A9dip%C3%B4le+Lyon-Villeurbanne/@45.760254,4.8486298,13z?travelmode=bicycling const origin = addressToLatLng(decodeURIComponent(regex1[1])).coordinate ?? '' const destination = addressToLatLng(decodeURIComponent(regex1[2])).coordinate ?? '' prefs.route = `${origin};${destination}` - } else if (regex2) { - // https://www.google.com/maps/dir/92+Rue+Moncey,+69003+Lyon,+France/@45.760254,4.8486298,13z?travelmode=bicycling + } else if (regex2) { // https://www.google.com/maps/dir/92+Rue+Moncey,+69003+Lyon,+France/@45.760254,4.8486298,13z?travelmode=bicycling const origin = addressToLatLng(decodeURIComponent(regex2[1])).coordinate ?? '' prefs.route = `${origin};` - } else { - // https://www.google.com/maps/dir/?api=1&origin=Space+Needle+Seattle+WA&destination=Pike+Place+Market+Seattle+WA&travelmode=bicycling + } else { // https://www.google.com/maps/dir/?api=1&origin=Space+Needle+Seattle+WA&destination=Pike+Place+Market+Seattle+WA&travelmode=bicycling const origin = addressToLatLng(url.searchParams.get("origin")).coordinate ?? '' const destination = addressToLatLng(url.searchParams.get("destination")).coordinate ?? '' prefs.route = `${origin};${destination}` } - const prefsEncoded = new URLSearchParams(prefs).toString() - return `${randomInstance}/directions?${prefsEncoded}${mapCentre}` - } else if (url.pathname.includes("data=") && url.pathname.match(dataLatLngRegex)) { - // Get marker from data attribute - // https://www.google.com/maps/place/41%C2%B001'58.2%22N+40%C2%B029'18.2%22E/@41.032833,40.4862063,17z/data=!3m1!4b1!4m6!3m5!1s0x0:0xf64286eaf72fc49d!7e2!8m2!3d41.0328329!4d40.4883948 - let [, mlat, mlon] = url.pathname.match(dataLatLngRegex) - return `${randomInstance}/search?query=${mlat}%2C${mlon}` - } else if (url.searchParams.has("ll")) { - // Get marker from ll param - // https://maps.google.com/?ll=38.882147,-76.99017 + return `${randomInstance}/directions?${prefsEncoded(prefs)}${mapCentre}` + } else if (url.pathname.match(placeRegex)) { // https://www.google.com/maps/place/H%C3%B4tel+de+Londres+Eiffel/@40.9845265,28.7081268,14z + const query = url.pathname.match(placeRegex)[1] + return `${randomInstance}/search?query=${query}${mapCentre}` + } else if (url.searchParams.has("ll")) { // https://maps.google.com/?ll=38.882147,-76.99017 const [mlat, mlon] = url.searchParams.get("ll").split(",") return `${randomInstance}/search?query=${mlat}%2C${mlon}` - } else if (url.searchParams.has("viewpoint")) { - // Get marker from viewpoint param. - // https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=48.857832,2.295226&heading=-45&pitch=38&fov=80 + } else if (url.searchParams.has("viewpoint")) { // https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=48.857832,2.295226&heading=-45&pitch=38&fov=80 const [mlat, mlon] = url.searchParams.get("viewpoint").split(",") return `${randomInstance}/search?query=${mlat}%2C${mlon}` } else { - // Use query as search if present. - let query - if (url.searchParams.has("q")) query = url.searchParams.get("q") - else if (url.searchParams.has("query")) query = url.searchParams.get("query") - else if (url.pathname.match(placeRegex)) query = url.pathname.match(placeRegex)[1] - - let prefsEncoded = new URLSearchParams(prefs).toString() - if (query) return `${randomInstance}/search?query="${query}${mapCentre}&${prefsEncoded}` + const query = getQuery(url) + if (query) return `${randomInstance}/search?query="${query}${mapCentre}&${prefsEncoded(prefs)}` } - - let prefsEncoded = new URLSearchParams(prefs).toString() - return `${randomInstance}/${mapCentre}&${prefsEncoded}` + return `${randomInstance}/${mapCentre}&${prefsEncoded(prefs)}` } case "breezeWiki": { let wiki, urlpath = "" -- cgit 1.4.1 From cfa6c887f1a9136f9ac96607fb3ff43be409bf99 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Mon, 8 Jan 2024 23:58:18 +0300 Subject: Fixed a bug in Switch Instance https://github.com/libredirect/browser_extension/issues/877 --- src/assets/javascripts/services.js | 13 ++++++++++--- src/pages/background/background.js | 4 +--- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index a1935bff..3aba28d7 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -617,7 +617,11 @@ function switchInstance(url, customService) { if (customService) { const instancesList = options[options[customService].frontend] if (instancesList !== undefined) { - resolve(`${utils.getNextInstance(url.origin, instancesList)}${url.pathname}${url.search}`) + const newInstance = utils.getNextInstance(url.origin, instancesList) + if (newInstance) { + resolve(`${newInstance}${url.pathname}${url.search}`) + return + } } } else { for (const service in config.services) { @@ -630,8 +634,11 @@ function switchInstance(url, customService) { resolve() return } - resolve(`${utils.getNextInstance(url.origin, instancesList)}${url.pathname}${url.search}`) - return + const newInstance = utils.getNextInstance(url.origin, instancesList) + if (newInstance) { + resolve(`${newInstance}${url.pathname}${url.search}`) + return + } } } resolve() diff --git a/src/pages/background/background.js b/src/pages/background/background.js index 9057f64a..3df43b52 100644 --- a/src/pages/background/background.js +++ b/src/pages/background/background.js @@ -160,9 +160,7 @@ browser.contextMenus.onClicked.addListener(async (info) => { case 'switchInstanceTab': { const url = new URL(info.pageUrl) const newUrl = await servicesHelper.switchInstance(url) - if (newUrl) { - browser.tabs.update({ url: newUrl }) - } + if (newUrl) browser.tabs.update({ url: newUrl }) return } case 'settingsTab': { -- cgit 1.4.1 From 1b95b1ce527cda1812caaa68da4c55a61092a471 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Sun, 28 Jan 2024 16:52:03 +0300 Subject: Added raw.githubusercontent.co support for GotHub https://github.com/libredirect/browser_extension/issues/890 --- src/assets/javascripts/services.js | 1 + src/config.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 3aba28d7..e1013c01 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -419,6 +419,7 @@ function redirect(url, type, initiator, forceRedirection, incognito) { } case "gothub": { if (url.hostname == "gist.github.com") return `${randomInstance}/gist${url.pathname}${url.search}` + if (url.hostname == "raw.githubusercontent.com") return `${randomInstance}/raw${url.pathname}${url.search}` return `${randomInstance}${url.pathname}${url.search}` } case "mikuInvidious": { diff --git a/src/config.json b/src/config.json index 4029d536..567fcb14 100644 --- a/src/config.json +++ b/src/config.json @@ -637,7 +637,8 @@ }, "targets": [ "^https?:\\/{2}github\\.com\\/", - "^https?:\\/{2}gist\\.github\\.com\\/[^\\/]+\\/[^\\/]+\\/?" + "^https?:\\/{2}gist\\.github\\.com\\/[^\\/]+\\/[^\\/]+\\/?", + "^https?:\\/{2}raw\\.githubusercontent\\.com\\/[^\\/]+\\/[^\\/]+\\/?" ], "name": "GitHub", "options": { -- cgit 1.4.1 From 9cf2b977840cf634a3c9ed4ecd2e71b57391f4ac Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Wed, 31 Jan 2024 19:10:52 +0300 Subject: Added Redlib https://github.com/libredirect/browser_extension/issues/879 --- src/assets/javascripts/services.js | 2 ++ src/config.json | 6 ++++++ 2 files changed, 8 insertions(+) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index e1013c01..a11b73ef 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -328,6 +328,7 @@ function redirect(url, type, initiator, forceRedirection, incognito) { } return `${randomInstance}${url.pathname}${url.search}` } + case "redlib": case "libreddit": { const subdomain = url.hostname.match(/^(?:(?:external-)?preview|i)(?=\.redd\.it)/) if (!subdomain) return `${randomInstance}${url.pathname}${url.search}` @@ -709,6 +710,7 @@ const defaultInstances = { 'poketube': ['https://poketube.fun'], 'proxiTok': ['https://proxitok.pabloferreiro.es'], 'nitter': ['https://nitter.net'], + 'redlib': ['https://safereddit.com'], 'libreddit': ['https://libreddit.spike.codes'], 'teddit': ['https://teddit.net'], 'scribe': ['https://scribe.rip'], diff --git a/src/config.json b/src/config.json index 567fcb14..b49426e3 100644 --- a/src/config.json +++ b/src/config.json @@ -213,6 +213,12 @@ "url": "https://github.com/spikecodes/libreddit", "localhost": true }, + "redlib": { + "name": "Redlib", + "instanceList": true, + "url": "https://github.com/redlib-org/redlib", + "localhost": true + }, "teddit": { "name": "Teddit", "instanceList": true, -- cgit 1.4.1 From 3feaaa0ebab89e3217d51a165bd8c7daa0b9412c Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Wed, 31 Jan 2024 19:15:14 +0300 Subject: Removed LibreX. Added LibreY https://github.com/libredirect/browser_extension/issues/871 --- src/assets/javascripts/services.js | 2 +- src/config.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index a11b73ef..344153f5 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -134,7 +134,7 @@ function redirect(url, type, initiator, forceRedirection, incognito) { } return randomInstance } - case "librex": { + case "librey": { return `${randomInstance}/search.php${url.search}` } case "send": { diff --git a/src/config.json b/src/config.json index b49426e3..f9a00ad2 100644 --- a/src/config.json +++ b/src/config.json @@ -886,10 +886,10 @@ "instanceList": true, "url": "https://benbusby.com/projects/whoogle-search/" }, - "librex": { - "name": "LibreX", + "librey": { + "name": "LibreY", "instanceList": true, - "url": "https://github.com/hnhx/librex" + "url": "https://github.com/Ahwxorg/librey/" }, "4get": { "name": "4get", -- cgit 1.4.1 From 4fc8c6cdcda3c9e609b28be5e71e0f4937bd08f1 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Wed, 31 Jan 2024 19:26:16 +0300 Subject: Added ViewTube https://github.com/libredirect/browser_extension/issues/115 --- src/assets/javascripts/services.js | 1 + src/config.json | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 344153f5..084214ce 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -704,6 +704,7 @@ async function reverse(url) { const defaultInstances = { 'invidious': ['https://inv.vern.cc'], + 'viewtube': ['https://viewtube.io'], 'piped': ['https://pipedapi-libre.kavin.rocks'], 'pipedMaterial': ['https://piped-material.xn--17b.net'], 'cloudtube': ['https://tube.cadence.moe'], diff --git a/src/config.json b/src/config.json index f9a00ad2..5ed5c967 100644 --- a/src/config.json +++ b/src/config.json @@ -107,6 +107,12 @@ "embeddable": false, "instanceList": false, "url": "https://github.com/MarmadileManteater/FreeTubeCordova" + }, + "viewtube": { + "name": "ViewTube", + "embeddable": false, + "instanceList": true, + "url": "https://github.com/ViewTube/viewtube" } }, "targets": [ -- cgit 1.4.1 From a7665994f05bf7f4cd5ddc215dc73a5d71008b0e Mon Sep 17 00:00:00 2001 From: Hamza <74574779+hamzakat@users.noreply.github.com> Date: Thu, 22 Feb 2024 15:56:35 +0300 Subject: Disable redirection when a link in the YouTube description section is entered --- src/assets/javascripts/services.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 084214ce..9eefbe20 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -496,6 +496,9 @@ function redirect(url, type, initiator, forceRedirection, incognito) { const watch = url.pathname.substring(url.pathname.lastIndexOf('/') + 1) return `${randomInstance}/watch?v=${watch}` } + if (url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/redirect?")) { + return url.href + } return `${randomInstance}${url.pathname}${url.search}` } case "invidiousMusic": { -- cgit 1.4.1 From b6c98028b991c66d3f417023eb391683c09a8728 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Sun, 10 Mar 2024 10:19:48 +0300 Subject: Removed Nitter https://github.com/libredirect/browser_extension/issues/898 --- src/assets/javascripts/services.js | 25 ------------------------- src/config.json | 30 ------------------------------ 2 files changed, 55 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 9eefbe20..4e243bb0 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -140,30 +140,6 @@ function redirect(url, type, initiator, forceRedirection, incognito) { case "send": { return randomInstance } - case "nitter": { - let search = new URLSearchParams(url.search) - - search.delete("ref_src") - search.delete("ref_url") - search.delete("s") // type of device that shared the link - search.delete("t") // some sort of tracking ID - - search = search.toString() - if (search !== "") search = `?${search}` - - if (url.host.split(".")[0] === "pbs" || url.host.split(".")[0] === "video") { - try { - const [, id, format, extra] = search.match(/(.*)\?format=(.*)&(.*)/) - const query = encodeURIComponent(`${id}.${format}?${extra}`) - return `${randomInstance}/pic${url.pathname}${query}` - } catch { - return `${randomInstance}/pic${url.pathname}${search}` - } - } - if (url.pathname.split("/").includes("tweets")) return `${randomInstance}${url.pathname.replace("/tweets", "")}${search}` - if (url.host == "t.co") return `${randomInstance}/t.co${url.pathname}` - return `${randomInstance}${url.pathname}${search}#m` - } case "yattee": { return url.href.replace(/^https?:\/{2}/, "yattee://") } @@ -713,7 +689,6 @@ const defaultInstances = { 'cloudtube': ['https://tube.cadence.moe'], 'poketube': ['https://poketube.fun'], 'proxiTok': ['https://proxitok.pabloferreiro.es'], - 'nitter': ['https://nitter.net'], 'redlib': ['https://safereddit.com'], 'libreddit': ['https://libreddit.spike.codes'], 'teddit': ['https://teddit.net'], diff --git a/src/config.json b/src/config.json index 4b65e4d5..b70cb074 100644 --- a/src/config.json +++ b/src/config.json @@ -161,36 +161,6 @@ "imageType": "png", "url": "https://music.youtube.com" }, - "twitter": { - "frontends": { - "nitter": { - "name": "Nitter", - "embeddable": true, - "instanceList": true, - "url": "https://github.com/zedeus/nitter", - "localhost": true - } - }, - "targets": [ - "^https?:\\/{2}(www\\.|mobile\\.)?twitter\\.com\\/", - "^https?:\\/{2}(www\\.|mobile\\.)?x\\.com\\/", - "^https?:\\/{2}(pbs\\.|video\\.)twimg\\.com\\/", - "^https?:\\/{2}platform\\.x\\.com/embed\\/", - "^https?:\\/{2}platform\\.twitter\\.com/embed\\/", - "^https?:\\/{2}t\\.co\\/" - ], - "name": "Twitter", - "options": { - "enabled": false, - "redirectType": "main_frame", - "unsupportedUrls": "bypass", - "frontend": "nitter", - "instance": "public" - }, - "imageType": "png", - "embeddable": true, - "url": "https://twitter.com" - }, "bluesky": { "frontends": { "skyview": { -- cgit 1.4.1 From 2a239a2fb29b3a594602cc555a4e8f1946efb542 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Mon, 11 Mar 2024 07:51:30 +0300 Subject: Fixed settings conversion on update --- src/assets/javascripts/services.js | 37 +++++++++++++++++++++++------------ src/pages/options/widgets/general.pug | 2 +- 2 files changed, 25 insertions(+), 14 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 4e243bb0..1a9c3f29 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -642,7 +642,6 @@ async function reverse(url) { case "imdb": case "imgur": case "tiktok": - case "twitter": case "reddit": case "imdb": case "snopes": @@ -702,7 +701,6 @@ const defaultInstances = { '4get': ['https://4get.ca'], 'rimgo': ['https://rimgo.vern.cc'], 'hyperpipe': ['https://hyperpipe.surge.sh'], - 'facil': [' https://facilmap.org '], 'osm': ['https://www.openstreetmap.org'], 'breezeWiki': ['https://breezewiki.com'], 'neuters': ['https://neuters.de'], @@ -749,12 +747,12 @@ function initDefaults() { } } } - options['exceptions'] = { + options.exceptions = { url: [], regex: [], } options.theme = "detect" - options.popupServices = ["youtube", "twitter", "tiktok", "imgur", "reddit", "quora", "translate", "maps"] + options.popupServices = ["youtube", "tiktok", "imgur", "reddit", "quora", "translate", "maps"] options.fetchInstances = 'github' options.redirectOnlyInIncognito = false @@ -781,28 +779,27 @@ function upgradeOptions() { function processUpdate() { return new Promise(async resolve => { - let config = await utils.getConfig() + let frontends = [] + const config = await utils.getConfig() let options = await utils.getOptions() for (const service in config.services) { if (!options[service]) options[service] = {} if (!(options[service].frontend in config.services[service].frontends)) { - options[service] = config.services[service].options - delete options[options[service].frontend] + options[service] = config.services[service].options // Reset settings for service + delete options[options[service].frontend] // Remove deprecated frontend } for (const defaultOption in config.services[service].options) { - if (options[service][defaultOption] === undefined) { + if (!(defaultOption in options[service])) { options[service][defaultOption] = config.services[service].options[defaultOption] } } for (const frontend in config.services[service].frontends) { - if (options[frontend] === undefined && config.services[service].frontends[frontend].instanceList) { - options[frontend] = defaultInstances[frontend] - } - else if (frontend in options && !(frontend in config.services[service].frontends)) { - delete options[frontend] + frontends.push(frontend) + if (!(frontend in options) && config.services[service].frontends[frontend].instanceList) { + options[frontend] = defaultInstances[frontend] || [] } } @@ -813,6 +810,20 @@ function processUpdate() { } } } + const general = ['theme', 'popupServices', 'fetchInstances', 'redirectOnlyInIncognito'] + const combined = [ + ...Object.keys(config.services), + ...frontends, + ...general, + 'exceptions', + 'popupServices', + 'version', + ] + for (const key in options) { + if (combined.indexOf(key) < 0) { + delete options[key] // Remove any unknown settings in options + } + } browser.storage.local.set({ options }, () => { resolve() }) diff --git a/src/pages/options/widgets/general.pug b/src/pages/options/widgets/general.pug index 70316473..1388584a 100644 --- a/src/pages/options/widgets/general.pug +++ b/src/pages/options/widgets/general.pug @@ -51,7 +51,7 @@ section(class="block-option" id="general_page") path(d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z") |  x(data-localise="__MSG_importSettings__") Import Settings - input(id="import-settings" type="file" style="display: none") + input(id="import-settings" type="file" accept=".json" style="display: none") |   -- cgit 1.4.1 From 1f8e0d00e13fcd5d26f7e58499c534509ecc44ae Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 12 Mar 2024 16:27:18 +0100 Subject: Move rewrite logic to own function --- src/assets/javascripts/services.js | 119 ++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 54 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 1a9c3f29..b23295db 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -62,61 +62,13 @@ async function redirectAsync(url, type, initiator, forceRedirection) { } /** - * @param {URL} url - * @param {string} type - * @param {URL} initiator - * @param {boolean} forceRedirection - * @returns {string | undefined} + * @param url + * @param frontend + * @param randomInstance + * @returns {undefined|string} */ -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 - - frontend = options[service].frontend - - - if (config.services[service].frontends[frontend].desktopApp && type != "main_frame" && options[service].redirectType != "main_frame") - frontend = options[service].embedFrontend - - - if (!regexArray(service, url, config, frontend)) { - frontend = null - continue - } - - if ( - config.services[service].embeddable && - type != options[service].redirectType && options[service].redirectType != "both" - ) { - if (options[service].unsupportedUrls == 'block') return 'CANCEL' - return - } - - let instanceList = options[frontend] - if (instanceList === undefined) break - if (instanceList.length === 0) return null - - if ( - initiator - && - instanceList.includes(initiator.origin) - ) { - if (type != "main_frame") return null - else return "BYPASSTAB" - } - - randomInstance = utils.getRandomInstance(instanceList) - if (config.services[service].frontends[frontend].localhost && options[service].instance == "localhost") { - randomInstance = `http://${frontend}.localhost:8080` - } - break - } - if (!frontend) return - +function rewrite(url, frontend, randomInstance){ + if (!frontend || !randomInstance) return switch (frontend) { case "hyperpipe": { return `${randomInstance}${url.pathname}${url.search}`.replace(/\/search\?q=.*/, searchQuery => searchQuery.replace("?q=", "/")) @@ -557,6 +509,65 @@ function redirect(url, type, initiator, forceRedirection, incognito) { } } +/** + * @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 + + frontend = options[service].frontend + + + if (config.services[service].frontends[frontend].desktopApp && type != "main_frame" && options[service].redirectType != "main_frame") + frontend = options[service].embedFrontend + + + if (!regexArray(service, url, config, frontend)) { + frontend = null + continue + } + + if ( + config.services[service].embeddable && + type != options[service].redirectType && options[service].redirectType != "both" + ) { + if (options[service].unsupportedUrls == 'block') return 'CANCEL' + return + } + + let instanceList = options[frontend] + if (instanceList === undefined) break + if (instanceList.length === 0) return null + + if ( + initiator + && + instanceList.includes(initiator.origin) + ) { + if (type != "main_frame") return null + else return "BYPASSTAB" + } + + randomInstance = utils.getRandomInstance(instanceList) + if (config.services[service].frontends[frontend].localhost && options[service].instance == "localhost") { + randomInstance = `http://${frontend}.localhost:8080` + } + break + } + if (!frontend) return + + return rewrite(url, frontend, randomInstance) +} + /** * @param {URL} url * @param {*} returnFrontend -- cgit 1.4.1 From ab7a702accc0c4f28867762621357ff1ef3f1443 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Thu, 14 Mar 2024 12:49:42 +0300 Subject: Cleaned code --- src/assets/javascripts/services.js | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index b23295db..8bbc6de4 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -67,15 +67,16 @@ async function redirectAsync(url, type, initiator, forceRedirection) { * @param randomInstance * @returns {undefined|string} */ -function rewrite(url, frontend, randomInstance){ +function rewrite(url, frontend, randomInstance) { if (!frontend || !randomInstance) return switch (frontend) { case "hyperpipe": { return `${randomInstance}${url.pathname}${url.search}`.replace(/\/search\?q=.*/, searchQuery => searchQuery.replace("?q=", "/")) } case "searx": - case "searxng": + case "searxng": { return `${randomInstance}/${url.search}` + } case "whoogle": { return `${randomInstance}/search${url.search}` } @@ -101,7 +102,6 @@ function rewrite(url, frontend, randomInstance){ case "freetubePwa": { return 'freetube://' + url.href } - case "poketube": { if (url.pathname.startsWith('/channel')) { const reg = /\/channel\/(.*)\/?$/.exec(url.pathname) @@ -526,18 +526,17 @@ function redirect(url, type, initiator, forceRedirection, incognito) { frontend = options[service].frontend - if (config.services[service].frontends[frontend].desktopApp && type != "main_frame" && options[service].redirectType != "main_frame") frontend = options[service].embedFrontend - if (!regexArray(service, url, config, frontend)) { frontend = null continue } if ( - config.services[service].embeddable && + config.services[service].embeddable + && type != options[service].redirectType && options[service].redirectType != "both" ) { if (options[service].unsupportedUrls == 'block') return 'CANCEL' @@ -548,11 +547,7 @@ function redirect(url, type, initiator, forceRedirection, incognito) { if (instanceList === undefined) break if (instanceList.length === 0) return null - if ( - initiator - && - instanceList.includes(initiator.origin) - ) { + if (initiator && instanceList.includes(initiator.origin)) { if (type != "main_frame") return null else return "BYPASSTAB" } -- cgit 1.4.1 From 95ddb93edd0a0372c033e7dbb78cd5fc57a50a8a Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Thu, 14 Mar 2024 13:50:28 +0300 Subject: Added UNfunny https://github.com/libredirect/browser_extension/issues/888 --- src/assets/images/ifunny-icon.svg | 56 ++++++++++++++++++++++++++++++++++++++ src/assets/javascripts/services.js | 1 + src/config.json | 20 ++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 src/assets/images/ifunny-icon.svg (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/images/ifunny-icon.svg b/src/assets/images/ifunny-icon.svg new file mode 100644 index 00000000..b8f37515 --- /dev/null +++ b/src/assets/images/ifunny-icon.svg @@ -0,0 +1,56 @@ + + + + diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 8bbc6de4..96595fda 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -717,6 +717,7 @@ const defaultInstances = { 'biblioReads': ['https://biblioreads.ml'], 'wikiless': ['https://wikiless.org'], 'suds': ['https://sd.vern.cc'], + 'unfunny': ['https://uf.vern.cc'], 'waybackClassic': ['https://wayback-classic.net'], 'gothub': ['https://gh.odyssey346.dev'], 'mikuInvidious': ['https://mikuinv.resrv.org'], diff --git a/src/config.json b/src/config.json index b70cb074..808a32b9 100644 --- a/src/config.json +++ b/src/config.json @@ -717,6 +717,26 @@ "imageType": "svg", "url": "https://www.snopes.com" }, + "ifunny": { + "frontends": { + "unfunny": { + "name": "UNfunny", + "instanceList": true, + "url": "https://git.vern.cc/cobra/UNfunny" + } + }, + "targets": [ + "^https?:\\/{2}(www\\.)?ifunny\\.co\\/" + ], + "name": "iFunny", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "unfunny" + }, + "imageType": "svg", + "url": "https://ifunny.co" + }, "urbanDictionary": { "frontends": { "ruralDictionary": { -- cgit 1.4.1 From b9b2a53fd38a6573231ceee86b2c9ab2b55003e7 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Thu, 14 Mar 2024 14:03:10 +0300 Subject: Added Soprano https://github.com/libredirect/browser_extension/issues/888 --- src/assets/images/tenor-icon.svg | 51 ++++++++++++++++++++++++++++++++++++++ src/assets/javascripts/services.js | 1 + src/config.json | 20 +++++++++++++++ src/pages/stylesheets/styles.css | 2 +- 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/assets/images/tenor-icon.svg (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/images/tenor-icon.svg b/src/assets/images/tenor-icon.svg new file mode 100644 index 00000000..8cdc1214 --- /dev/null +++ b/src/assets/images/tenor-icon.svg @@ -0,0 +1,51 @@ + +TENOR_VECTORCreated with Sketch. diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 96595fda..dceb1c2d 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -718,6 +718,7 @@ const defaultInstances = { 'wikiless': ['https://wikiless.org'], 'suds': ['https://sd.vern.cc'], 'unfunny': ['https://uf.vern.cc'], + 'soprano': ['https://sp.vern.cc'], 'waybackClassic': ['https://wayback-classic.net'], 'gothub': ['https://gh.odyssey346.dev'], 'mikuInvidious': ['https://mikuinv.resrv.org'], diff --git a/src/config.json b/src/config.json index 808a32b9..cf4ed558 100644 --- a/src/config.json +++ b/src/config.json @@ -737,6 +737,26 @@ "imageType": "svg", "url": "https://ifunny.co" }, + "tenor": { + "frontends": { + "soprano": { + "name": "Soprano", + "instanceList": true, + "url": "https://git.vern.cc/cobra/Soprano" + } + }, + "targets": [ + "^https?:\\/{2}(www\\.)?tenor\\.com\\/" + ], + "name": "Tenor", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "soprano" + }, + "imageType": "svg", + "url": "https://tenor.com" + }, "urbanDictionary": { "frontends": { "ruralDictionary": { diff --git a/src/pages/stylesheets/styles.css b/src/pages/stylesheets/styles.css index 5de72477..e3212a66 100644 --- a/src/pages/stylesheets/styles.css +++ b/src/pages/stylesheets/styles.css @@ -131,7 +131,7 @@ section.links { flex-wrap: wrap; flex-direction: column; width: 350px; - max-height: 930px; + max-height: 970px; } section.links div { -- cgit 1.4.1 From b3457faf1bdcca0b17872e30b379a7ae55bc8fd0 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Thu, 14 Mar 2024 14:21:20 +0300 Subject: Added MeMe https://github.com/libredirect/browser_extension/issues/888 --- src/assets/images/knowyourmeme-icon.svg | 76 +++++++++++++++++++++++++++++++++ src/assets/javascripts/services.js | 1 + src/config.json | 20 +++++++++ 3 files changed, 97 insertions(+) create mode 100644 src/assets/images/knowyourmeme-icon.svg (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/images/knowyourmeme-icon.svg b/src/assets/images/knowyourmeme-icon.svg new file mode 100644 index 00000000..9f249b08 --- /dev/null +++ b/src/assets/images/knowyourmeme-icon.svg @@ -0,0 +1,76 @@ + +TENOR_VECTORCreated with Sketch.TENOR_VECTOR diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index dceb1c2d..01e79493 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -719,6 +719,7 @@ const defaultInstances = { 'suds': ['https://sd.vern.cc'], 'unfunny': ['https://uf.vern.cc'], 'soprano': ['https://sp.vern.cc'], + 'meme': ['https://mm.vern.cc'], 'waybackClassic': ['https://wayback-classic.net'], 'gothub': ['https://gh.odyssey346.dev'], 'mikuInvidious': ['https://mikuinv.resrv.org'], diff --git a/src/config.json b/src/config.json index cf4ed558..0b4a3ee6 100644 --- a/src/config.json +++ b/src/config.json @@ -757,6 +757,26 @@ "imageType": "svg", "url": "https://tenor.com" }, + "knowyourmeme": { + "frontends": { + "meme": { + "name": "MeMe", + "instanceList": true, + "url": "https://git.vern.cc/cobra/MeMe" + } + }, + "targets": [ + "^https?:\\/{2}(www\\.)?knowyourmeme\\.com\\/" + ], + "name": "KnowYourMeme", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "meme" + }, + "imageType": "svg", + "url": "https://knowyourmeme.com" + }, "urbanDictionary": { "frontends": { "ruralDictionary": { -- cgit 1.4.1 From 2a3ae7d9151dcc46545b4e70eb5f96506bdd4d30 Mon Sep 17 00:00:00 2001 From: Solomon Victorino Date: Wed, 20 Mar 2024 22:29:36 -0600 Subject: Redirect Bandcamp /music to Tent artist page --- src/assets/javascripts/services.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 1a9c3f29..d63f0fab 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -415,7 +415,7 @@ function redirect(url, type, initiator, forceRedirection, incognito) { if (url.hostname.endsWith('bandcamp.com')) { const regex = /^(.*)\.bandcamp\.com/.exec(url.hostname) const artist = regex[1] - if (url.pathname == '/') { + if (url.pathname == '/' || url.pathname == '/music') { return `${randomInstance}/artist.php?name=${artist}` } else { const regex = /^\/(.*)\/(.*)/.exec(url.pathname) -- cgit 1.4.1 From 9034a2fb843ec4f341953ee7f398b97eeb2ff2c3 Mon Sep 17 00:00:00 2001 From: NoPlagiarism <37241775+NoPlagiarism@users.noreply.github.com> Date: Sun, 31 Mar 2024 21:00:56 +0500 Subject: anonoverflow: support other StackExchange sites --- src/assets/javascripts/services.js | 10 ++++++++++ src/config.json | 5 +++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index c7f12bc0..640fd8a8 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -309,11 +309,21 @@ function rewrite(url, frontend, randomInstance) { if (threadID) return `${randomInstance}/questions/${threadID[1]}${url.search}` return `${randomInstance}${url.pathname}${url.search}` } + if (url.pathname == "/" || url.pathname == "") { + // https://stackexchange.com or https://superuser.com + return `${randomInstance}${url.pathname}${url.search}` + } const regex = url.href.match(/https?:\/{2}(?:([a-zA-Z0-9-]+)\.)?stackexchange\.com\//) if (regex && regex.length > 1) { const subdomain = regex[1] return `${randomInstance}/exchange/${subdomain}${url.pathname}${url.search}` } + const notExchangeRegex = url.hostname.match(/(?:[a-zA-Z]+\.)?(?:askubuntu\.com|mathoverflow\.net|serverfault\.com|stackapps\.com|superuser\.com|stackoverflow\.com)/) + if (notExchangeRegex) { + return `${randomInstance}/exchange/${notExchangeRegex[0]}${url.pathname}${url.search}` + } + // "Default case" + return `${randomInstance}${url.pathname}${url.search}` } case "biblioReads": { return `${randomInstance}${url.pathname}${url.search}` diff --git a/src/config.json b/src/config.json index 4288d2db..fbb2ddc2 100644 --- a/src/config.json +++ b/src/config.json @@ -663,8 +663,9 @@ } }, "targets": [ - "^https?:\\/{2}(www\\.)?stackoverflow\\.com\\/", - "^https?:\\/{2}([a-zA-Z0-9-]+\\.)?stackexchange\\.com\\/" + "^https?:\\/{2}(www\\.)?([a-zA-Z]+\\.)?stackoverflow\\.com\\/", + "^https?:\\/{2}([a-zA-Z0-9-]+\\.)?stackexchange\\.com\\/", + "^https?:\\/{2}(www\\.)?([a-zA-Z]+\\.)?(askubuntu\\.com|mathoverflow\\.net|serverfault\\.com|stackapps\\.com|superuser\\.com)\\/" ], "name": "Stack Overflow", "options": { -- cgit 1.4.1 From ff93a22b980aed20ee3966070ea39143feb4c9fb Mon Sep 17 00:00:00 2001 From: Pierce Thompson <52843537+Insprill@users.noreply.github.com> Date: Wed, 3 Apr 2024 14:12:20 -0400 Subject: Update Intellectual redirects --- src/assets/javascripts/services.js | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 640fd8a8..8ff2318f 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -291,12 +291,6 @@ function rewrite(url, frontend, randomInstance) { return `${randomInstance}${url.pathname}${url.search}` } case "intellectual": { - if (url.pathname.endsWith('-lyrics')) { - return `${randomInstance}/lyrics?path=${encodeURIComponent(url.pathname)}` - } - if (url.pathname.startsWith('/artists/')) { - return `${randomInstance}/artist?path=${url.pathname}` - } return `${randomInstance}${url.pathname}${url.search}` } case "ruralDictionary": { -- cgit 1.4.1 From 1b529ed39283a37fd05aeae677727a49c4acb9b6 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Thu, 2 May 2024 02:47:44 +0300 Subject: Fixed bug. 2.8.3 => 2.8.4 --- src/assets/javascripts/services.js | 8 +++----- src/manifest.json | 2 +- src/updates/updates.xml | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 8ff2318f..e51a1d43 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -62,13 +62,12 @@ async function redirectAsync(url, type, initiator, forceRedirection) { } /** - * @param url - * @param frontend - * @param randomInstance + * @param {URL} url + * @param {string} frontend + * @param {string} randomInstance * @returns {undefined|string} */ function rewrite(url, frontend, randomInstance) { - if (!frontend || !randomInstance) return switch (frontend) { case "hyperpipe": { return `${randomInstance}${url.pathname}${url.search}`.replace(/\/search\?q=.*/, searchQuery => searchQuery.replace("?q=", "/")) @@ -316,7 +315,6 @@ function rewrite(url, frontend, randomInstance) { if (notExchangeRegex) { return `${randomInstance}/exchange/${notExchangeRegex[0]}${url.pathname}${url.search}` } - // "Default case" return `${randomInstance}${url.pathname}${url.search}` } case "biblioReads": { diff --git a/src/manifest.json b/src/manifest.json index 13908f0e..0cacd75f 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_extensionName__", "description": "__MSG_extensionDescription__", - "version": "2.8.3", + "version": "2.8.4", "manifest_version": 2, "browser_specific_settings": { "gecko": { diff --git a/src/updates/updates.xml b/src/updates/updates.xml index c6d151cc..957f01da 100644 --- a/src/updates/updates.xml +++ b/src/updates/updates.xml @@ -1,6 +1,6 @@ - + -- cgit 1.4.1 From 9d750897ec4b36766ca876549c0af31746f9c05b Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Mon, 20 May 2024 13:57:31 +0300 Subject: Cleaning code --- src/assets/javascripts/services.js | 174 +++++++++++------------------------ src/assets/javascripts/utils.js | 23 +---- src/pages/options/index.js | 6 +- src/pages/options/widgets/general.js | 5 +- 4 files changed, 63 insertions(+), 145 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index e51a1d43..e5a57890 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -5,12 +5,9 @@ window.browser = window.browser || window.chrome let config, options -function init() { - return new Promise(async resolve => { - options = await utils.getOptions() - config = await utils.getConfig() - resolve() - }) +async function init() { + options = await utils.getOptions() + config = await utils.getConfig() } init() @@ -69,38 +66,26 @@ async function redirectAsync(url, type, initiator, forceRedirection) { */ function rewrite(url, frontend, randomInstance) { switch (frontend) { - case "hyperpipe": { + case "hyperpipe": return `${randomInstance}${url.pathname}${url.search}`.replace(/\/search\?q=.*/, searchQuery => searchQuery.replace("?q=", "/")) - } case "searx": - case "searxng": { + case "searxng": return `${randomInstance}/${url.search}` - } - case "whoogle": { + case "whoogle": return `${randomInstance}/search${url.search}` - } case "4get": { const s = url.searchParams.get("q") - if (s !== null) { - return `${randomInstance}/web?s=${encodeURIComponent(s)}` - } + if (s !== null) return `${randomInstance}/web?s=${encodeURIComponent(s)}` return randomInstance } - case "librey": { + case "librey": return `${randomInstance}/search.php${url.search}` - } - case "send": { - return randomInstance - } - case "yattee": { + case "yattee": return url.href.replace(/^https?:\/{2}/, "yattee://") - } - case "freetube": { + case "freetube": return 'freetube://' + url.href - } - case "freetubePwa": { + case "freetubePwa": return 'freetube://' + url.href - } case "poketube": { if (url.pathname.startsWith('/channel')) { const reg = /\/channel\/(.*)\/?$/.exec(url.pathname) @@ -123,19 +108,13 @@ function rewrite(url, frontend, randomInstance) { } return `${randomInstance}${url.pathname}${url.search}` } - case "simplyTranslate": { + case "simplyTranslate": return `${randomInstance}/${url.search}` - } - case "mozhi": { - return `${randomInstance}` - } - case "libreTranslate": { - let search = url.search - .replace("sl", "source") - .replace("tl", "target") - .replace("text", "q") - return `${randomInstance}/${search}` - } + case "send": + case "mozhi": + return randomInstance + case "libreTranslate": + return `${randomInstance}/${url.search.replace("sl", "source").replace("tl", "target").replace("text", "q")}` case "osm": { const placeRegex = /\/place\/(.*?)\// function convertMapCentre(url) { @@ -249,12 +228,9 @@ function rewrite(url, frontend, randomInstance) { } return `${randomInstance}${wiki}${urlpath}${url.search}` } - case "rimgo": { - if (url.href.search(/^https?:\/{2}(?:[im]\.)?stack\./) > -1) { - return `${randomInstance}/stack${url.pathname}${url.search}` - } + case "rimgo": + if (url.href.search(/^https?:\/{2}(?:[im]\.)?stack\./) > -1) return `${randomInstance}/stack${url.pathname}${url.search}` return `${randomInstance}${url.pathname}${url.search}` - } case "redlib": case "libreddit": { const subdomain = url.hostname.match(/^(?:(?:external-)?preview|i)(?=\.redd\.it)/) @@ -269,13 +245,12 @@ function rewrite(url, frontend, randomInstance) { } return randomInstance } - case "teddit": { + case "teddit": if (/^(?:(?:external-)?preview|i)\.redd\.it/.test(url.hostname)) { if (url.search == "") return `${randomInstance}${url.pathname}?teddit_proxy=${url.hostname}` else return `${randomInstance}${url.pathname}${url.search}&teddit_proxy=${url.hostname}` } return `${randomInstance}${url.pathname}${url.search}` - } case "neuters": { const p = url.pathname if (p.startsWith('/article/') || p.startsWith('/pf/') || p.startsWith('/arc/') || p.startsWith('/resizer/')) { @@ -283,19 +258,14 @@ function rewrite(url, frontend, randomInstance) { } return `${randomInstance}${p}` } - case "dumb": { - if (url.pathname.endsWith('-lyrics')) { - return `${randomInstance}${url.pathname}` - } + case "dumb": + if (url.pathname.endsWith('-lyrics')) return `${randomInstance}${url.pathname}` return `${randomInstance}${url.pathname}${url.search}` - } - case "intellectual": { + case "intellectual": return `${randomInstance}${url.pathname}${url.search}` - } - case "ruralDictionary": { + case "ruralDictionary": if (!url.pathname.includes('/define.php') && !url.pathname.includes('/random.php') && url.pathname != '/') return randomInstance return `${randomInstance}${url.pathname}${url.search}` - } case "anonymousOverflow": { if (url.hostname == "stackoverflow.com") { const threadID = /^\/a\/(\d+)\/?/.exec(url.pathname) @@ -317,9 +287,8 @@ function rewrite(url, frontend, randomInstance) { } return `${randomInstance}${url.pathname}${url.search}` } - case "biblioReads": { + case "biblioReads": return `${randomInstance}${url.pathname}${url.search}` - } case "wikiless": { let hostSplit = url.host.split(".") // wikiless doesn't have mobile view support yet @@ -330,10 +299,9 @@ function rewrite(url, frontend, randomInstance) { } return `${randomInstance}${url.pathname}${url.search}${url.hash}` } - case "proxiTok": { + case "proxiTok": if (url.pathname.startsWith('/email')) return randomInstance return `${randomInstance}${url.pathname}${url.search}` - } case "waybackClassic": { const regex = /^\/\web\/(?:[0-9]+)?\*\/(.*)/.exec(url.pathname) if (regex) { @@ -348,19 +316,13 @@ function rewrite(url, frontend, randomInstance) { } return } - case "gothub": { + case "gothub": if (url.hostname == "gist.github.com") return `${randomInstance}/gist${url.pathname}${url.search}` if (url.hostname == "raw.githubusercontent.com") return `${randomInstance}/raw${url.pathname}${url.search}` return `${randomInstance}${url.pathname}${url.search}` - } - case "mikuInvidious": { - if (url.hostname == "bilibili.com" || url.hostname == "www.bilibili.com" || url.hostname == 'b23.tv') { - return `${randomInstance}${url.pathname}${url.search}` - } - if (url.hostname == "space.bilibili.com") { - return `${randomInstance}/space${url.pathname}${url.search}` - } - } + case "mikuInvidious": + if (url.hostname == "bilibili.com" || url.hostname == "www.bilibili.com" || url.hostname == 'b23.tv') return `${randomInstance}${url.pathname}${url.search}` + if (url.hostname == "space.bilibili.com") return `${randomInstance}/space${url.pathname}${url.search}` case "tent": { if (url.hostname == 'bandcamp.com' && url.pathname == '/search') { const query = url.searchParams.get('q') @@ -396,9 +358,8 @@ function rewrite(url, frontend, randomInstance) { } } } - case "binternet": { + case "binternet": if (url.hostname == "i.pinimg.com") return `${randomInstance}/image_proxy.php?url=${url.href}` - } case "laboratory": { let path = url.pathname if (path == "/") path = "" @@ -446,68 +407,44 @@ function rewrite(url, frontend, randomInstance) { } return `${randomInstance}${url.pathname}${url.search}` } - case "tuboYoutube": { - if (url.pathname.startsWith("/channel")) { - return `${randomInstance}/channel?url=${encodeURIComponent(url.href)}` - } - if (url.pathname.startsWith("/watch")) { - return `${randomInstance}/stream?url=${encodeURIComponent(url.href)}` - } - return `${randomInstance}` - } - case "tuboSoundcloud": { + case "tuboYoutube": + if (url.pathname.startsWith("/channel")) return `${randomInstance}/channel?url=${encodeURIComponent(url.href)}` + if (url.pathname.startsWith("/watch")) return `${randomInstance}/stream?url=${encodeURIComponent(url.href)}` + return randomInstance + case "tuboSoundcloud": if (url.pathname == '/') return `${randomInstance}?kiosk?serviceId=1` - if (url.pathname.match(/^\/[^\/]+(\/$|$)/)) { - return `${randomInstance}/channel?url=${encodeURIComponent(url.href)}` - } - if (url.pathname.match(/^\/[^\/]+\/[^\/]+/)) { - return `${randomInstance}/stream?url=${encodeURIComponent(url.href)}` - } - return `${randomInstance}` - } + if (url.pathname.match(/^\/[^\/]+(\/$|$)/)) return `${randomInstance}/channel?url=${encodeURIComponent(url.href)}` + 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}` - } + case "safetwitch": + if (url.hostname.startsWith("clips.")) return `${randomInstance}/clip${url.pathname}${url.search}` return `${randomInstance}${url.pathname}${url.search}` - } - case "tekstoLibre": { + + case "tekstoLibre": return `${randomInstance}/?${url.pathname.slice(1)}`; - } - case "skyview": { + case "skyview": if (url.pathname == '/') return randomInstance return `${randomInstance}?url=${encodeURIComponent(url.href)}` - } case "priviblur": { - if (url.hostname == "www.tumblr.com") - return `${randomInstance}${url.pathname}${url.search}` - - if (url.hostname.startsWith("assets")) - return `${randomInstance}/tblr/assets${url.pathname}${url.search}` - - if (url.hostname.startsWith("static")) - return `${randomInstance}/tblr/static${url.pathname}${url.search}` + if (url.hostname == "www.tumblr.com") return `${randomInstance}${url.pathname}${url.search}` + if (url.hostname.startsWith("assets")) return `${randomInstance}/tblr/assets${url.pathname}${url.search}` + if (url.hostname.startsWith("static")) return `${randomInstance}/tblr/static${url.pathname}${url.search}` const reg = /^([0-9]+)\.media\.tumblr\.com/.exec(url.hostname) // *.media.tumblr.com - if (reg) - return `${randomInstance}/tblr/media/${reg[1]}${url.pathname}${url.search}` + if (reg) return `${randomInstance}/tblr/media/${reg[1]}${url.pathname}${url.search}` const blogregex = /^(?:www\.)?([a-z\d-]+)\.tumblr\.com/.exec(url.hostname) // .tumblr.com if (blogregex) { const blog_name = blogregex[1]; // Under the .tumblr.com domain posts are under a /post path - if (url.pathname.startsWith("/post")) { - return `${randomInstance}/${blog_name}${url.pathname.slice(5)}${url.search}` - } else { - return `${randomInstance}/${blog_name}${url.pathname}${url.search}`; - } + if (url.pathname.startsWith("/post")) return `${randomInstance}/${blog_name}${url.pathname.slice(5)}${url.search}` + else return `${randomInstance}/${blog_name}${url.pathname}${url.search}`; } return `${randomInstance}${url.pathname}${url.search}`; } - default: { + default: return `${randomInstance}${url.pathname}${url.search}` - } } } @@ -657,10 +594,11 @@ async function reverse(url) { case "quora": case "medium": return `${config.services[service].url}${url.pathname}${url.search}` - case "fandom": + case "fandom": { let regex = url.pathname.match(/^\/([a-zA-Z0-9-]+)\/wiki\/(.*)/) if (regex) return `https://${regex[1]}.fandom.com/wiki/${regex[2]}` return + } case "wikipedia": { const lang = url.searchParams.get("lang") if (lang != null) { @@ -678,9 +616,8 @@ async function reverse(url) { } return } - case "tekstowo": { + case "tekstowo": return `${config.services[service].url}/${url.search.slice(1)}` - } default: return } @@ -875,8 +812,7 @@ function isException(url) { if (exceptions.url) { for (let item of exceptions.url) { item = new URL(item) - item = item.href - item = item.replace(/^http:\/\//, 'https://') + item = item.href.replace(/^http:\/\//, 'https://') if (item == url.href) return true } } diff --git a/src/assets/javascripts/utils.js b/src/assets/javascripts/utils.js index fe08e576..af972d22 100644 --- a/src/assets/javascripts/utils.js +++ b/src/assets/javascripts/utils.js @@ -15,13 +15,8 @@ function getRandomInstance(instances) { */ function getNextInstance(currentInstanceUrl, instances) { const currentInstanceIndex = instances.indexOf(currentInstanceUrl); - - if (currentInstanceIndex === -1){ - return getRandomInstance(instances); - } - + if (currentInstanceIndex === -1) return getRandomInstance(instances); const nextInstanceIndex = (currentInstanceIndex + 1) % instances.length; - return instances[nextInstanceIndex]; } @@ -101,12 +96,8 @@ function getPingCache() { function getBlacklist(options) { return new Promise(resolve => { let url - if (options.fetchInstances == 'github') { - url = 'https://raw.githubusercontent.com/libredirect/instances/main/blacklist.json' - } - else if (options.fetchInstances == 'codeberg') { - url = 'https://codeberg.org/LibRedirect/instances/raw/branch/main/blacklist.json' - } + if (options.fetchInstances == 'github') url = 'https://raw.githubusercontent.com/libredirect/instances/main/blacklist.json' + else if (options.fetchInstances == 'codeberg') url = 'https://codeberg.org/LibRedirect/instances/raw/branch/main/blacklist.json' else { resolve('disabled') return @@ -134,12 +125,8 @@ function getBlacklist(options) { function getList(options) { return new Promise(resolve => { let url - if (options.fetchInstances == 'github') { - url = 'https://raw.githubusercontent.com/libredirect/instances/main/data.json' - } - else if (options.fetchInstances == 'codeberg') { - url = 'https://codeberg.org/LibRedirect/instances/raw/branch/main/data.json' - } + if (options.fetchInstances == 'github') url = 'https://raw.githubusercontent.com/libredirect/instances/main/data.json' + else if (options.fetchInstances == 'codeberg') url = 'https://codeberg.org/LibRedirect/instances/raw/branch/main/data.json' else { resolve('disabled') return diff --git a/src/pages/options/index.js b/src/pages/options/index.js index fcc51298..ec47f3c5 100644 --- a/src/pages/options/index.js +++ b/src/pages/options/index.js @@ -260,7 +260,7 @@ async function processCustomInstances(frontend, document) { /** * @param {string} frontend * @param {*} networks - * @param {*} document + * @param {Document} document * @param {*} redirects * @param {*} blacklist */ @@ -393,7 +393,5 @@ function processTime(time) { color = "red" text = 'Server not found' } - return { - color, text - } + return { color, text } } diff --git a/src/pages/options/widgets/general.js b/src/pages/options/widgets/general.js index 8322a378..64172287 100644 --- a/src/pages/options/widgets/general.js +++ b/src/pages/options/widgets/general.js @@ -206,10 +206,7 @@ document.getElementById("custom-exceptions-instance-form").addEventListener("sub if (val) { options = await utils.getOptions() options.exceptions = exceptionsCustomInstances - browser.storage.local.set({ options }, () => - nameCustomInstanceInput.value = "" - ) - + browser.storage.local.set({ options }, () => nameCustomInstanceInput.value = "") } calcExceptionsCustomInstances() }) -- cgit 1.4.1 From 33fc116bac0e1e3a6e3dab39d21116c078d04567 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Mon, 20 May 2024 14:05:09 +0300 Subject: Fixed timestamps being removed for invidious https://github.com/libredirect/browser_extension/issues/922 --- src/assets/javascripts/services.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index e5a57890..b78cbb99 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -385,11 +385,10 @@ function rewrite(url, frontend, randomInstance) { case "invidious": { if (url.hostname == "youtu.be" || url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/live")) { const watch = url.pathname.substring(url.pathname.lastIndexOf('/') + 1) - return `${randomInstance}/watch?v=${watch}` + return `${randomInstance}/watch?v=${watch}${url.search.replace("?", "&")}` } - if (url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/redirect?")) { + if (url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/redirect?")) return url.href - } return `${randomInstance}${url.pathname}${url.search}` } case "invidiousMusic": { -- cgit 1.4.1 From abcd566305d0ede82bf81c4809fd59ea7c67591c Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Mon, 20 May 2024 14:34:18 +0300 Subject: Removed ?si= from youtube frontends https://github.com/libredirect/browser_extension/issues/922 --- src/assets/javascripts/services.js | 11 +++++++++++ src/pages/background/background.js | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index b78cbb99..4f9fdac1 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -81,12 +81,16 @@ function rewrite(url, frontend, randomInstance) { case "librey": return `${randomInstance}/search.php${url.search}` case "yattee": + url.searchParams.delete("si") return url.href.replace(/^https?:\/{2}/, "yattee://") case "freetube": + url.searchParams.delete("si") return 'freetube://' + url.href case "freetubePwa": + url.searchParams.delete("si") return 'freetube://' + url.href case "poketube": { + url.searchParams.delete("si") if (url.pathname.startsWith('/channel')) { const reg = /\/channel\/(.*)\/?$/.exec(url.pathname) if (reg) { @@ -383,6 +387,7 @@ function rewrite(url, frontend, randomInstance) { return `${randomInstance}${url.pathname}${url.search}` } case "invidious": { + url.searchParams.delete("si") if (url.hostname == "youtu.be" || url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/live")) { const watch = url.pathname.substring(url.pathname.lastIndexOf('/') + 1) return `${randomInstance}/watch?v=${watch}${url.search.replace("?", "&")}` @@ -407,6 +412,7 @@ function rewrite(url, frontend, randomInstance) { return `${randomInstance}${url.pathname}${url.search}` } case "tuboYoutube": + url.searchParams.delete("si") if (url.pathname.startsWith("/channel")) return `${randomInstance}/channel?url=${encodeURIComponent(url.href)}` if (url.pathname.startsWith("/watch")) return `${randomInstance}/stream?url=${encodeURIComponent(url.href)}` return randomInstance @@ -442,6 +448,11 @@ function rewrite(url, frontend, randomInstance) { } return `${randomInstance}${url.pathname}${url.search}`; } + case "piped": + case "pipedMaterial": + case "cloudtube": + case "viewtube": + url.searchParams.delete("si") default: return `${randomInstance}${url.pathname}${url.search}` } diff --git a/src/pages/background/background.js b/src/pages/background/background.js index 3df43b52..0754f8a5 100644 --- a/src/pages/background/background.js +++ b/src/pages/background/background.js @@ -32,6 +32,7 @@ let tabIdRedirects = {} browser.webRequest.onBeforeRequest.addListener( details => { const url = new URL(details.url) + const old_href = url.href if (new RegExp(/^chrome-extension:\/{2}.*\/instances\/.*.json$/).test(url.href) && details.type == "xmlhttprequest") return let initiator try { @@ -71,7 +72,7 @@ browser.webRequest.onBeforeRequest.addListener( if (tabIdRedirects[details.tabId] != false) tabIdRedirects[details.tabId] = false return null } - console.log("Redirecting", url.href, "=>", newUrl) + console.log("Redirecting", old_href, "=>", newUrl) return { redirectUrl: newUrl } } return null -- cgit 1.4.1 From 9ebfbd9e779b6a349ed13054dea90e81117f85bf Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Tue, 21 May 2024 00:37:57 +0300 Subject: Added LightTube https://github.com/libredirect/browser_extension/issues/913 --- src/assets/javascripts/services.js | 2 ++ src/config.json | 6 ++++++ 2 files changed, 8 insertions(+) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 4f9fdac1..567ffc84 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -451,6 +451,7 @@ function rewrite(url, frontend, randomInstance) { case "piped": case "pipedMaterial": case "cloudtube": + case "lightTube": case "viewtube": url.searchParams.delete("si") default: @@ -641,6 +642,7 @@ const defaultInstances = { 'piped': ['https://pipedapi-libre.kavin.rocks'], 'pipedMaterial': ['https://piped-material.xn--17b.net'], 'cloudtube': ['https://tube.cadence.moe'], + 'lightTube': ['https://tube.kuylar.dev'], 'poketube': ['https://poketube.fun'], 'proxiTok': ['https://proxitok.pabloferreiro.es'], 'redlib': ['https://safereddit.com'], diff --git a/src/config.json b/src/config.json index 937ef37e..6985fac8 100644 --- a/src/config.json +++ b/src/config.json @@ -66,6 +66,12 @@ 3 ] }, + "lightTube": { + "name": "LightTube", + "embeddable": false, + "instanceList": true, + "url": "https://github.com/lighttube-org/LightTube" + }, "tuboYoutube": { "name": "Tubo", "embeddable": false, -- cgit 1.4.1 From 462011d2c30b1e0b6d60295c85216545c41a4a22 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Tue, 21 May 2024 02:05:37 +0300 Subject: Cleaning code --- src/assets/javascripts/services.js | 26 +++++------ src/assets/javascripts/utils.js | 52 +++++----------------- src/pages/background/background.js | 61 +++++++------------------ src/pages/options/index.js | 86 ++++++++++++++---------------------- src/pages/options/init.js | 53 +++++++++++----------- src/pages/options/widgets/general.js | 16 ++++--- src/pages/popup/popup.js | 34 +++++--------- 7 files changed, 118 insertions(+), 210 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 567ffc84..6801d54b 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -792,25 +792,21 @@ function processUpdate() { /** * @param {URL} url - * @param {boolean} test */ -async function copyRaw(url, test) { +async function copyRaw(url) { const newUrl = await reverse(url) if (newUrl) { - if (!test) { - if (!isChrome) { - navigator.clipboard.writeText(newUrl) - } else { - var copyFrom = document.createElement("textarea"); - copyFrom.textContent = newUrl; - document.body.appendChild(copyFrom); - copyFrom.select() - document.execCommand('copy') - copyFrom.blur(); - document.body.removeChild(copyFrom); - } + if (!isChrome) { + navigator.clipboard.writeText(newUrl) + } else { + var copyFrom = document.createElement("textarea"); + copyFrom.textContent = newUrl; + document.body.appendChild(copyFrom); + copyFrom.select() + document.execCommand('copy') + copyFrom.blur(); + document.body.removeChild(copyFrom); } - return newUrl } } diff --git a/src/assets/javascripts/utils.js b/src/assets/javascripts/utils.js index af972d22..d28f9701 100644 --- a/src/assets/javascripts/utils.js +++ b/src/assets/javascripts/utils.js @@ -78,19 +78,11 @@ function getConfig() { * @returns {Promise>} */ function getOptions() { - return new Promise(resolve => - browser.storage.local.get("options", r => { - resolve(r.options) - }) - ) + return new Promise(resolve => browser.storage.local.get("options", r => resolve(r.options))) } function getPingCache() { - return new Promise(resolve => - browser.storage.local.get("pingCache", r => { - resolve(r.pingCache ?? {}) - }) - ) + return new Promise(resolve => browser.storage.local.get("pingCache", r => resolve(r.pingCache ?? {}))) } function getBlacklist(options) { @@ -98,26 +90,15 @@ function getBlacklist(options) { let url if (options.fetchInstances == 'github') url = 'https://raw.githubusercontent.com/libredirect/instances/main/blacklist.json' else if (options.fetchInstances == 'codeberg') url = 'https://codeberg.org/LibRedirect/instances/raw/branch/main/blacklist.json' - else { - resolve('disabled') - return - } + else return resolve('disabled') const http = new XMLHttpRequest() http.open("GET", url, true) http.onreadystatechange = () => { - if (http.status === 200 && http.readyState == XMLHttpRequest.DONE) { + if (http.status === 200 && http.readyState == XMLHttpRequest.DONE) resolve(JSON.parse(http.responseText)) - return - } - } - http.onerror = () => { - resolve() - return - } - http.ontimeout = () => { - resolve() - return } + http.onerror = () => resolve() + http.ontimeout = () => resolve() http.send(null) }) } @@ -127,26 +108,15 @@ function getList(options) { let url if (options.fetchInstances == 'github') url = 'https://raw.githubusercontent.com/libredirect/instances/main/data.json' else if (options.fetchInstances == 'codeberg') url = 'https://codeberg.org/LibRedirect/instances/raw/branch/main/data.json' - else { - resolve('disabled') - return - } + else return resolve('disabled') const http = new XMLHttpRequest() http.open("GET", url, true) http.onreadystatechange = () => { - if (http.status === 200 && http.readyState == XMLHttpRequest.DONE) { - resolve(JSON.parse(http.responseText)) - return - } - } - http.onerror = () => { - resolve() - return - } - http.ontimeout = () => { - resolve() - return + if (http.status === 200 && http.readyState == XMLHttpRequest.DONE) + return resolve(JSON.parse(http.responseText)) } + http.onerror = () => resolve() + http.ontimeout = () => resolve() http.send(null) }) } diff --git a/src/pages/background/background.js b/src/pages/background/background.js index 0754f8a5..0c4d0923 100644 --- a/src/pages/background/background.js +++ b/src/pages/background/background.js @@ -92,15 +92,15 @@ browser.commands.onCommand.addListener(async command => { browser.tabs.query({ active: true, currentWindow: true }, async tabs => { const url = new URL(tabs[0].url) switch (command) { - case "switchInstance": + case "switchInstance": { const newUrl = await servicesHelper.switchInstance(url) if (newUrl) browser.tabs.update({ url: newUrl }) break - case "copyRaw": { + } + case "copyRaw": servicesHelper.copyRaw(url) break - } - case "redirect": { + case "redirect": browser.tabs.query({ active: true, currentWindow: true }, async tabs => { if (tabs[0].url) { const url = new URL(tabs[0].url) @@ -113,8 +113,7 @@ browser.commands.onCommand.addListener(async command => { } }) break - } - case "reverse": { + case "reverse": browser.tabs.query({ active: true, currentWindow: true }, async tabs => { if (tabs[0].url) { const url = new URL(tabs[0].url) @@ -127,7 +126,6 @@ browser.commands.onCommand.addListener(async command => { } }) break - } } }) }) @@ -164,11 +162,10 @@ browser.contextMenus.onClicked.addListener(async (info) => { if (newUrl) browser.tabs.update({ url: newUrl }) return } - case 'settingsTab': { + case 'settingsTab': browser.runtime.openOptionsPage() return - } - case 'copyReverseTab': { + case 'copyReverseTab': browser.tabs.query({ active: true, currentWindow: true }, async tabs => { if (tabs[0].url) { const url = new URL(tabs[0].url) @@ -176,8 +173,7 @@ browser.contextMenus.onClicked.addListener(async (info) => { } }) return - } - case 'reverseTab': { + case 'reverseTab': browser.tabs.query({ active: true, currentWindow: true }, async tabs => { if (tabs[0].url) { const url = new URL(tabs[0].url) @@ -190,8 +186,7 @@ browser.contextMenus.onClicked.addListener(async (info) => { } }) return - } - case 'redirectTab': { + case 'redirectTab': browser.tabs.query({ active: true, currentWindow: true }, async tabs => { if (tabs[0].url) { const url = new URL(tabs[0].url) @@ -204,8 +199,6 @@ browser.contextMenus.onClicked.addListener(async (info) => { } }) return - } - case 'copyReverseLink': { const url = new URL(info.linkUrl) await servicesHelper.copyRaw(url) @@ -238,7 +231,6 @@ browser.contextMenus.onClicked.addListener(async (info) => { } return } - case 'bypassLink': case 'bypassLinkInNewTab': { const url = new URL(info.linkUrl) @@ -253,17 +245,14 @@ browser.contextMenus.onClicked.addListener(async (info) => { } return } - - case 'copyReverseBookmark': { + case 'copyReverseBookmark': browser.bookmarks.get(info.bookmarkId, bookmarks => { const url = new URL(bookmarks[0].url) servicesHelper.copyRaw(url) }); return - } - case 'redirectBookmark': - case 'redirectBookmarkInNewTab': { + case 'redirectBookmarkInNewTab': browser.bookmarks.get(info.bookmarkId, bookmarks => { const url = new URL(bookmarks[0].url) const newUrl = servicesHelper.redirect(url, "main_frame", null, true) @@ -273,9 +262,8 @@ browser.contextMenus.onClicked.addListener(async (info) => { } }) return - } case 'reverseBookmark': - case 'reverseBookmarkInNewTab': { + case 'reverseBookmarkInNewTab': browser.bookmarks.get(info.bookmarkId, async bookmarks => { const url = new URL(bookmarks[0].url) const newUrl = await servicesHelper.reverse(url) @@ -292,24 +280,17 @@ browser.contextMenus.onClicked.addListener(async (info) => { } }) return - } - case 'bypassBookmark': - case 'bypassBookmarkInNewTab': { + case 'bypassBookmarkInNewTab': browser.bookmarks.get(info.bookmarkId, async bookmarks => { const url = new URL(bookmarks[0].url) if (info.menuItemId == "bypassBookmark") { - browser.tabs.update({ url: url.href }, tab => { - tabIdRedirects[tab.id] = false - }) + browser.tabs.update({ url: url.href }, tab => tabIdRedirects[tab.id] = false) } else { - browser.tabs.create({ url: url.href }, tab => { - tabIdRedirects[tab.id] = false - }) + browser.tabs.create({ url: url.href }, tab => tabIdRedirects[tab.id] = false) } return }) - } } }) @@ -319,11 +300,7 @@ browser.runtime.onMessage.addListener((request, sender, sendResponse) => { if (tabs[0].url) { const url = new URL(tabs[0].url) const newUrl = await servicesHelper.reverse(url) - if (newUrl) { - browser.tabs.update(tabs[0].id, { url: newUrl }, () => { - tabIdRedirects[tabs[0].id] = false - }) - } + if (newUrl) browser.tabs.update(tabs[0].id, { url: newUrl }, () => tabIdRedirects[tabs[0].id] = false) } }) } @@ -332,11 +309,7 @@ browser.runtime.onMessage.addListener((request, sender, sendResponse) => { if (tabs[0].url) { const url = new URL(tabs[0].url) const newUrl = servicesHelper.redirect(url, "main_frame", null, true) - if (newUrl) { - browser.tabs.update(tabs[0].id, { url: newUrl }, () => { - tabIdRedirects[tabs[0].id] = true - }) - } + if (newUrl) browser.tabs.update(tabs[0].id, { url: newUrl }, () => tabIdRedirects[tabs[0].id] = true) } }) } diff --git a/src/pages/options/index.js b/src/pages/options/index.js index 9274023f..0066df0d 100644 --- a/src/pages/options/index.js +++ b/src/pages/options/index.js @@ -129,9 +129,7 @@ async function loadPage(path) { if (path != 'general') { const service = path; - divs[service] = {} - for (const option in config.services[service].options) { divs[service][option] = document.getElementById(`${service}-${option}`) if (typeof config.services[service].options[option] == "boolean") divs[service][option].checked = options[service][option] @@ -146,46 +144,39 @@ async function loadPage(path) { changeFrontendsSettings(service) }) } - changeFrontendsSettings(service) - - - - !async function () { - blacklist = await utils.getBlacklist(options) - redirects = await utils.getList(options) - - for (const frontend in config.services[service].frontends) { - if (config.services[service].frontends[frontend].instanceList) { - if (redirects == 'disabled' || blacklist == 'disabled') { - document.getElementById(frontend).getElementsByClassName('clearnet')[0].style.display = 'none' - document.getElementById(frontend).getElementsByClassName('ping')[0].style.display = 'none' - } - else if (!redirects || !blacklist) { - document.getElementById(frontend) - .getElementsByClassName('clearnet')[0] - .getElementsByClassName("checklist")[0] - .getElementsByClassName('loading')[0] - .innerHTML = 'Could not fetch instances.' - } - else { - createList(frontend) - } + blacklist = await utils.getBlacklist(options) + redirects = await utils.getList(options) + for (const frontend in config.services[service].frontends) { + if (config.services[service].frontends[frontend].instanceList) { + if (redirects == 'disabled' || blacklist == 'disabled') { + document.getElementById(frontend).getElementsByClassName('clearnet')[0].style.display = 'none' + document.getElementById(frontend).getElementsByClassName('ping')[0].style.display = 'none' + } + else if (!redirects || !blacklist) { + document.getElementById(frontend) + .getElementsByClassName('clearnet')[0] + .getElementsByClassName("checklist")[0] + .getElementsByClassName('loading')[0] + .innerHTML = 'Could not fetch instances.' + } + else { + createList(frontend) } } + } - for (const frontend in config.services[service].frontends) { - if (config.services[service].frontends[frontend].instanceList) { - processCustomInstances(frontend) - document.getElementById(`ping-${frontend}`).addEventListener("click", async () => { - document.getElementById(`ping-${frontend}`).getElementsByTagName('x')[0].innerHTML = "Pinging..." - await ping(frontend) - document.getElementById(`ping-${frontend}`).getElementsByTagName('x')[0].innerHTML = "Ping instances" - }) - } + for (const frontend in config.services[service].frontends) { + if (config.services[service].frontends[frontend].instanceList) { + processCustomInstances(frontend) + document.getElementById(`ping-${frontend}`).addEventListener("click", async () => { + document.getElementById(`ping-${frontend}`).getElementsByTagName('x')[0].innerHTML = "Pinging..." + await ping(frontend) + document.getElementById(`ping-${frontend}`).getElementsByTagName('x')[0].innerHTML = "Ping instances" + }) } - }() + } } } @@ -197,11 +188,10 @@ async function calcCustomInstances(frontend) { document.getElementById(frontend).getElementsByClassName("custom-checklist")[0].innerHTML = customInstances .map( x => { - let time = pingCache[x] - let timeText = "" + const time = pingCache[x] if (time) { const { color, text } = processTime(time) - timeText = `${text}` + var timeText = `${text}` } const custom = isCustomInstance(frontend, x) ? "" : `custom` return `
@@ -226,8 +216,6 @@ async function calcCustomInstances(frontend) { options = await utils.getOptions() options[frontend] = customInstances browser.storage.local.set({ options }, async () => { - blacklist = await utils.getBlacklist(options) - redirects = await utils.getList(options) calcCustomInstances(frontend) createList(frontend) }) @@ -242,9 +230,8 @@ async function processCustomInstances(frontend) { let options = await utils.getOptions() let customInstances = options[frontend] let frontendCustomInstanceInput = document.getElementById(frontend).getElementsByClassName("custom-instance")[0] - let url try { - url = new URL(frontendCustomInstanceInput.value) + var url = new URL(frontendCustomInstanceInput.value) } catch (error) { return } @@ -270,9 +257,7 @@ async function createList(frontend) { const pingCache = await utils.getPingCache() const options = await utils.getOptions() for (const network in config.networks) { - const checklist = document.getElementById(frontend) - .getElementsByClassName(network)[0] - .getElementsByClassName("checklist")[0] + const checklist = document.getElementById(frontend).getElementsByClassName(network)[0].getElementsByClassName("checklist")[0] if (!redirects[frontend]) { checklist.innerHTML = '
No instances found.
' @@ -282,13 +267,10 @@ async function createList(frontend) { const instances = redirects[frontend][network] if (!instances || instances.length === 0) continue - document.getElementById(frontend) - .getElementsByClassName("custom-instance")[0] - .placeholder = redirects[frontend].clearnet[0] - - const sortedInstances = instances.sort((a, b) => blacklist.cloudflare.includes(a) && !blacklist.cloudflare.includes(b)) + document.getElementById(frontend).getElementsByClassName("custom-instance")[0].placeholder = redirects[frontend].clearnet[0] - const content = sortedInstances + instances.sort((a, b) => blacklist.cloudflare.includes(a) && !blacklist.cloudflare.includes(b)) + const content = instances .map(x => { const cloudflare = blacklist.cloudflare.includes(x) ? ` diff --git a/src/pages/options/init.js b/src/pages/options/init.js index f88c9ef9..baf3eebe 100644 --- a/src/pages/options/init.js +++ b/src/pages/options/init.js @@ -8,40 +8,37 @@ if (!(await utils.getOptions())) { await servicesHelper.initDefaults() } -function changeTheme() { - return new Promise(async resolve => { - switch ((await utils.getOptions()).theme) { - case "dark": - document.body.classList.add("dark-theme") - document.body.classList.remove("light-theme") - for (const element of document.body.getElementsByClassName('dark')) { - element.style.display = 'none'; - } - break - case "light": +async function changeTheme() { + switch ((await utils.getOptions()).theme) { + case "dark": + document.body.classList.add("dark-theme") + document.body.classList.remove("light-theme") + for (const element of document.body.getElementsByClassName('dark')) { + element.style.display = 'none'; + } + break + case "light": + document.body.classList.add("light-theme") + document.body.classList.remove("dark-theme") + for (const element of document.body.getElementsByClassName('light')) { + element.style.display = 'none'; + } + break + default: + if (matchMedia("(prefers-color-scheme: light)").matches) { document.body.classList.add("light-theme") document.body.classList.remove("dark-theme") for (const element of document.body.getElementsByClassName('light')) { element.style.display = 'none'; } - break - default: - if (matchMedia("(prefers-color-scheme: light)").matches) { - document.body.classList.add("light-theme") - document.body.classList.remove("dark-theme") - for (const element of document.body.getElementsByClassName('light')) { - element.style.display = 'none'; - } - } else { - document.body.classList.add("dark-theme") - document.body.classList.remove("light-theme") - for (const element of document.body.getElementsByClassName('dark')) { - element.style.display = 'none'; - } + } else { + document.body.classList.add("dark-theme") + document.body.classList.remove("light-theme") + for (const element of document.body.getElementsByClassName('dark')) { + element.style.display = 'none'; } - } - resolve() - }) + } + } } changeTheme() diff --git a/src/pages/options/widgets/general.js b/src/pages/options/widgets/general.js index 64172287..30a8a0c8 100644 --- a/src/pages/options/widgets/general.js +++ b/src/pages/options/widgets/general.js @@ -8,12 +8,16 @@ const isChrome = browser.runtime.getBrowserInfo === undefined async function setOption(option, type, event) { let options = await utils.getOptions() - if (type == "select") { - options[option] = event.target.options[event.target.options.selectedIndex].value - } else if (type == "checkbox") { - options[option] = event.target.checked - } else if (type == "range") { - options[option] = event.target.value + switch (type) { + case "select": + options[option] = event.target.options[event.target.options.selectedIndex].value + break; + case "checkbox": + options[option] = event.target.checked + break; + case "range": + options[option] = event.target.value + break; } browser.storage.local.set({ options }) } diff --git a/src/pages/popup/popup.js b/src/pages/popup/popup.js index cfb7be27..485ec0e0 100644 --- a/src/pages/popup/popup.js +++ b/src/pages/popup/popup.js @@ -11,13 +11,10 @@ await browser.runtime.getPlatformInfo(r => { switch (r.os) { case "fuchsia": case "ios": - case "android": { + case "android": document.getElementsByTagName("html")[0].classList.add("mobile") - } } -} -) - +}) const allSites = document.getElementById("all_sites") const currSite = document.getElementById("current_site") @@ -66,12 +63,10 @@ for (const service in config.services) { } browser.tabs.query({ active: true, currentWindow: true }, async tabs => { - let url; - // Set visibility of control buttons if (tabs[0].url) { const hr = document.getElementById("hr") - url = new URL(tabs[0].url) + var url = new URL(tabs[0].url) servicesHelper.switchInstance(url).then(r => { if (r) { document.getElementById("change_instance_div").style.display = "" @@ -81,31 +76,22 @@ browser.tabs.query({ active: true, currentWindow: true }, async tabs => { ) } }) - servicesHelper.copyRaw(url, true).then(r => { - if (r) { - document.getElementById("copy_original_div").style.display = "" - hr.style.display = "" - document.getElementById("copy_original").addEventListener("click", () => - servicesHelper.copyRaw(url) - ) - } - }) servicesHelper.reverse(url).then(r => { if (r) { - document.getElementById("redirect_to_original_div").style.display = "" hr.style.display = "" - document.getElementById("redirect_to_original").addEventListener("click", () => - browser.runtime.sendMessage("reverseTab") - ) + + document.getElementById("copy_original_div").style.display = "" + document.getElementById("copy_original").addEventListener("click", () => servicesHelper.copyRaw(url)) + + document.getElementById("redirect_to_original_div").style.display = "" + document.getElementById("redirect_to_original").addEventListener("click", () => browser.runtime.sendMessage("reverseTab")) } }) servicesHelper.redirectAsync(url, "main_frame", null, true).then(r => { if (r) { document.getElementById("redirect_div").style.display = "" hr.style.display = "" - document.getElementById("redirect").addEventListener("click", () => - browser.runtime.sendMessage("redirectTab") - ) + document.getElementById("redirect").addEventListener("click", () => browser.runtime.sendMessage("redirectTab")) } }) } -- cgit 1.4.1 From 416d2f9c9f1c26f37a7fca3ddc8ea6cc2fdfb5df Mon Sep 17 00:00:00 2001 From: PuzzleMoon <32855965+puzzlemoondev@users.noreply.github.com> Date: Fri, 28 Jun 2024 01:52:33 +0800 Subject: Add Materialious --- src/assets/javascripts/services.js | 30 ++++++++++++++++++++++++++++++ src/config.json | 6 ++++++ 2 files changed, 36 insertions(+) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 6801d54b..245cb919 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -403,6 +403,35 @@ function rewrite(url, frontend, randomInstance) { } return `${randomInstance}${url.pathname}${url.search}` } + case 'materialious': { + url.searchParams.delete('si') + if (url.hostname == 'youtu.be' || (url.hostname.endsWith('youtube.com') && url.pathname.startsWith('/live'))) { + const watch = url.pathname.substring(url.pathname.lastIndexOf('/') + 1) + return `${randomInstance}/watch/${watch}${url.search.replace('?', '&')}` + } + if (url.hostname.endsWith("youtube.com")) { + if (url.pathname.startsWith('/watch')) { + if (url.searchParams.has('v')) { + const watch = url.searchParams.get('v') + url.searchParams.delete('v') + return `${randomInstance}/watch/${watch}${url.search.replace('?', '&')}` + } + return `${randomInstance}/watch/${url.search.replace('?', '&')}` + } + if (url.pathname.startsWith('/results')) { + if (url.searchParams.has('search_query')) { + const search = url.searchParams.get('search_query') + url.searchParams.delete('search_query') + return `${randomInstance}/search/${search}${url.search.replace('?', '&')}` + } + return `${randomInstance}/search/${url.search.replace('?', '&')}` + } + if (url.pathname.startsWith('/redirect?')) { + return url.href + } + } + return `${randomInstance}${url.pathname}${url.search}` + } case "libremdb": { if (url.pathname.startsWith("/Name")) { for (const [key, value] of url.searchParams.entries()) { @@ -638,6 +667,7 @@ async function reverse(url) { const defaultInstances = { 'invidious': ['https://inv.vern.cc'], + 'materialious': ['https://app.materialio.us'], 'viewtube': ['https://viewtube.io'], 'piped': ['https://pipedapi-libre.kavin.rocks'], 'pipedMaterial': ['https://piped-material.xn--17b.net'], diff --git a/src/config.json b/src/config.json index 21e468d7..f0789a7b 100644 --- a/src/config.json +++ b/src/config.json @@ -26,6 +26,12 @@ "instanceList": true, "url": "https://invidious.io/" }, + "materialious": { + "name": "Materialious", + "embeddable": true, + "instanceList": true, + "url": "https://materialio.us/" + }, "piped": { "excludeTargets": [ 2, -- cgit 1.4.1 From ffcb0a887376aa6ecbefd69bbb2d074a46555efa Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Tue, 2 Jul 2024 14:41:12 +0300 Subject: Re-added Nitter https://github.com/libredirect/browser_extension/issues/934 --- src/assets/javascripts/services.js | 25 +++++++++++++++++++++++++ src/config.json | 32 +++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 6801d54b..e47b6293 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -431,6 +431,30 @@ function rewrite(url, frontend, randomInstance) { case "skyview": if (url.pathname == '/') return randomInstance return `${randomInstance}?url=${encodeURIComponent(url.href)}` + case "nitter": { + let search = new URLSearchParams(url.search) + + search.delete("ref_src") + search.delete("ref_url") + search.delete("s") // type of device that shared the link + search.delete("t") // some sort of tracking ID + + search = search.toString() + if (search !== "") search = `?${search}` + + if (url.host.split(".")[0] === "pbs" || url.host.split(".")[0] === "video") { + try { + const [, id, format, extra] = search.match(/(.*)\?format=(.*)&(.*)/) + const query = encodeURIComponent(`${id}.${format}?${extra}`) + return `${randomInstance}/pic${url.pathname}${query}` + } catch { + return `${randomInstance}/pic${url.pathname}${search}` + } + } + if (url.pathname.split("/").includes("tweets")) return `${randomInstance}${url.pathname.replace("/tweets", "")}${search}` + if (url.host == "t.co") return `${randomInstance}/t.co${url.pathname}` + return `${randomInstance}${url.pathname}${search}#m` + } case "priviblur": { if (url.hostname == "www.tumblr.com") return `${randomInstance}${url.pathname}${url.search}` if (url.hostname.startsWith("assets")) return `${randomInstance}/tblr/assets${url.pathname}${url.search}` @@ -689,6 +713,7 @@ const defaultInstances = { 'tekstoLibre': ['https://davilarek.github.io/TekstoLibre'], 'skyview': ['https://skyview.social'], 'priviblur': ['https://pb.bloat.cat'], + 'nitter': ['https://nitter.privacydev.net'], } function initDefaults() { diff --git a/src/config.json b/src/config.json index 21e468d7..941d891e 100644 --- a/src/config.json +++ b/src/config.json @@ -167,6 +167,36 @@ "imageType": "png", "url": "https://music.youtube.com" }, + "twitter": { + "frontends": { + "nitter": { + "name": "Nitter", + "embeddable": true, + "instanceList": true, + "url": "https://github.com/zedeus/nitter", + "localhost": true + } + }, + "targets": [ + "^https?:\\/{2}(www\\.|mobile\\.)?twitter\\.com\\/", + "^https?:\\/{2}(www\\.|mobile\\.)?x\\.com\\/", + "^https?:\\/{2}(pbs\\.|video\\.)twimg\\.com\\/", + "^https?:\\/{2}platform\\.x\\.com/embed\\/", + "^https?:\\/{2}platform\\.twitter\\.com/embed\\/", + "^https?:\\/{2}t\\.co\\/" + ], + "name": "Twitter", + "options": { + "enabled": false, + "redirectType": "main_frame", + "unsupportedUrls": "bypass", + "frontend": "nitter", + "instance": "public" + }, + "imageType": "png", + "embeddable": true, + "url": "https://twitter.com" + }, "bluesky": { "frontends": { "skyview": { @@ -1073,4 +1103,4 @@ "url": "https://paste.libredirect.invalid" } } -} +} \ No newline at end of file -- cgit 1.4.1 From 52319462f8211a069703cfd156250a849adccb4a Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Tue, 9 Jul 2024 11:34:55 +0300 Subject: Added Biblioreads reverse redirect https://github.com/libredirect/browser_extension/issues/945 --- src/assets/javascripts/services.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 1a20dae5..207ca52a 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -682,6 +682,8 @@ async function reverse(url) { } case "tekstowo": return `${config.services[service].url}/${url.search.slice(1)}` + case "goodreads": + return `https://goodreads.com${url.pathname}${url.search}` default: return } -- cgit 1.4.1 From 329a52ea8bf3c3e9e9bf9b00608fa13967985acc Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Tue, 9 Jul 2024 11:44:28 +0300 Subject: Removed not working default instanecs https://github.com/libredirect/browser_extension/issues/939 --- src/assets/javascripts/services.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 207ca52a..b556c223 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -733,13 +733,13 @@ const defaultInstances = { "tent": ['https://tent.sny.sh'], "wolfreeAlpha": ['https://gqq.gitlab.io', 'https://uqq.gitlab.io'], "laboratory": ['https://lab.vern.cc'], - 'binternet': ['https://binternet.ahwx.org'], + 'binternet': ['https://bn.bloat.cat'], 'pixivFe': ['https://pixivfe.exozy.me'], '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'], + 'proxigram': ['https://ig.opnxng.com'], 'tuboYoutube': ['https://tubo.migalmoreno.com'], 'tuboSoundcloud': ['https://tubo.migalmoreno.com'], 'tekstoLibre': ['https://davilarek.github.io/TekstoLibre'], -- cgit 1.4.1 From 9e6862ab1a9be64eec44d71e416ad68639610a9b Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Tue, 9 Jul 2024 13:57:43 +0300 Subject: Added Pasted https://github.com/libredirect/browser_extension/issues/930 --- src/assets/javascripts/services.js | 1 + src/config.json | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index b556c223..ac841427 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -746,6 +746,7 @@ const defaultInstances = { 'skyview': ['https://skyview.social'], 'priviblur': ['https://pb.bloat.cat'], 'nitter': ['https://nitter.privacydev.net'], + 'pasted': ['https://pasted.drakeerv.com'], } function initDefaults() { diff --git a/src/config.json b/src/config.json index 19f85a12..fbe2fe1b 100644 --- a/src/config.json +++ b/src/config.json @@ -1094,6 +1094,11 @@ "name": "PrivateBin", "instanceList": true, "url": "https://privatebin.info" + }, + "pasted": { + "name": "Pasted", + "instanceList": true, + "url": "https://github.com/Dragynfruit/pasted" } }, "targets": [ -- cgit 1.4.1 From a20082de57fce45a25fe3fcd947e9aa50a900516 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Tue, 9 Jul 2024 14:15:00 +0300 Subject: Added Freetube to YouTube Music https://github.com/libredirect/browser_extension/issues/940 --- src/assets/javascripts/services.js | 9 ++++++++- src/config.json | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index ac841427..b9ee64e5 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -396,6 +396,13 @@ function rewrite(url, frontend, randomInstance) { return url.href return `${randomInstance}${url.pathname}${url.search}` } + case "freetubeMusic": { + if (url.hostname == "youtu.be" || url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/live")) { + const watch = url.pathname.substring(url.pathname.lastIndexOf('/') + 1) + return `freetube://youtube.com/watch?v=${watch}` + } + return 'freetube://' + url.href + } case "invidiousMusic": { if (url.hostname == "youtu.be" || url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/live")) { const watch = url.pathname.substring(url.pathname.lastIndexOf('/') + 1) @@ -683,7 +690,7 @@ async function reverse(url) { case "tekstowo": return `${config.services[service].url}/${url.search.slice(1)}` case "goodreads": - return `https://goodreads.com${url.pathname}${url.search}` + return `https://goodreads.com${url.pathname}${url.search}` default: return } diff --git a/src/config.json b/src/config.json index fbe2fe1b..76e4b022 100644 --- a/src/config.json +++ b/src/config.json @@ -159,6 +159,13 @@ "embeddable": true, "instanceList": true, "url": "https://invidious.io/" + }, + "freetubeMusic": { + "name": "FreeTube", + "embeddable": false, + "desktopApp": true, + "instanceList": false, + "url": "https://github.com/FreeTubeApp/FreeTube" } }, "targets": [ -- cgit 1.4.1 From cf8216da008128bc70bf547abcf7290e9a760c66 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Sun, 21 Jul 2024 21:22:09 +0300 Subject: Formatting wiht prettier --- .prettierignore | 3 + .prettierrc | 7 + README.md | 9 + package.json | 74 +- src/assets/javascripts/localise.js | 50 +- src/assets/javascripts/services.js | 1641 +++++++++++++------------- src/assets/javascripts/utils.js | 197 ++-- src/config.json | 2158 ++++++++++++++++------------------ src/manifest.json | 171 ++- src/pages/background/background.html | 10 +- src/pages/background/background.js | 576 ++++----- src/pages/messages/no_instance.html | 36 +- src/pages/options/index.js | 617 +++++----- src/pages/options/init.js | 66 +- src/pages/options/widgets/general.js | 276 ++--- src/pages/popup/popup.js | 192 +-- src/pages/popup/style.css | 48 +- src/pages/stylesheets/styles.css | 463 ++++---- test-conditions.md | 22 +- 19 files changed, 3292 insertions(+), 3324 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc (limited to 'src/assets/javascripts/services.js') diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..665abdb7 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +src/_locales/ +.github/ +.gitea/ \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..2f1b5f52 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "printWidth": 120, + "semi": false, + "singleQuote": false, + "trailingComma": "es5", + "arrowParens": "avoid" +} diff --git a/README.md b/README.md index 6d0ad08b..c71984a1 100644 --- a/README.md +++ b/README.md @@ -11,34 +11,42 @@ A browser extension that redirects YouTube, Twitter, TikTok... requests to alter ## Translate + ## Development + Install [Node.js](https://nodejs.org/) + ```bash git clone https://github.com/libredirect/browser_extension cd browser_extension npm install npm run html # Generates html using Pug ``` + #### Run on Firefox + ```bash npm run start ``` #### Build a zip package for Firefox + ```bash npm run build ``` #### Install the zip package on Firefox (temporarily) + 1. Type in the address bar: `about:debugging#/runtime/this-firefox` 2. Press `Load Temporary Add-on...` 3. Select `libredirect-VERSION.zip` from `web-ext-artifacts` folder #### Install the zip package on Firefox ESR, Developer Edition, Nightly + 1. Type in the address bar: `about:config` 2. Set `xpinstall.signatures.required` to `false` 3. Type in the address bar: `about:addons` @@ -46,6 +54,7 @@ npm run build 5. Select `libredirect-VERSION.zip` from `web-ext-artifacts` folder #### Run on Chromium + 1. Open `chrome://extensions` 2. Enable `dev mode` 3. Select `load unpacked extension` diff --git a/package.json b/package.json index 79147f4d..dba432a5 100644 --- a/package.json +++ b/package.json @@ -1,39 +1,39 @@ { - "name": "libredirect", - "description": "Redirects YouTube, Twitter, TikTok and more to privacy friendly frontends.", - "engines": { - "node": ">=16.13.1", - "npm": ">=8.1.2" - }, - "scripts": { - "start": "web-ext run", - "nightly": "web-ext run --firefox=/home/esmail/software/firefox_nightly/firefox", - "android": "web-ext run -t firefox-android --adb-device emulator-5554 --firefox-apk org.mozilla.fenix", - "build": "web-ext build", - "test": "web-ext lint", - "html": "pug --basedir ./ --obj ./src/config.json src/pages/options/index.pug --out src/pages/options/ && pug --basedir ./ --obj ./src/config.json src/pages/popup/popup.pug --out src/pages/popup/" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/libredirect/libredirect.git" - }, - "author": "LibRedirect", - "license": "GPL-3.0-only", - "bugs": { - "url": "https://github.com/libredirect/libredirect/issues" - }, - "homepage": "https://libredirect.github.io", - "devDependencies": { - "pug-cli": "^1.0.0-alpha6", - "web-ext": "^7.2.0" - }, - "webExt": { - "sourceDir": "./src/", - "run": { - "browserConsole": true - }, - "build": { - "overwriteDest": true - } - } + "name": "libredirect", + "description": "Redirects YouTube, Twitter, TikTok and more to privacy friendly frontends.", + "engines": { + "node": ">=16.13.1", + "npm": ">=8.1.2" + }, + "scripts": { + "start": "web-ext run", + "nightly": "web-ext run --firefox=/home/esmail/software/firefox_nightly/firefox", + "android": "web-ext run -t firefox-android --adb-device emulator-5554 --firefox-apk org.mozilla.fenix", + "build": "web-ext build", + "test": "web-ext lint", + "html": "pug --basedir ./ --obj ./src/config.json src/pages/options/index.pug --out src/pages/options/ && pug --basedir ./ --obj ./src/config.json src/pages/popup/popup.pug --out src/pages/popup/" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/libredirect/libredirect.git" + }, + "author": "LibRedirect", + "license": "GPL-3.0-only", + "bugs": { + "url": "https://github.com/libredirect/libredirect/issues" + }, + "homepage": "https://libredirect.github.io", + "devDependencies": { + "pug-cli": "^1.0.0-alpha6", + "web-ext": "^7.2.0" + }, + "webExt": { + "sourceDir": "./src/", + "run": { + "browserConsole": true + }, + "build": { + "overwriteDest": true + } + } } diff --git a/src/assets/javascripts/localise.js b/src/assets/javascripts/localise.js index c0936873..d26d07d4 100644 --- a/src/assets/javascripts/localise.js +++ b/src/assets/javascripts/localise.js @@ -1,34 +1,34 @@ 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 - }) - } + /** + * @param {string} tag + */ + function getMessage(tag) { + return tag.replace(/__MSG_(\w+)__/g, (_match, v1) => { + return v1 ? browser.i18n.getMessage(v1) : null + }) + } - const elements = document.querySelectorAll("[data-localise]") - for (let i in elements) - if (elements.hasOwnProperty(i)) { - const obj = elements[i] - const tag = obj.getAttribute("data-localise").toString() - const msg = getMessage(tag) - if (msg && msg !== tag) obj.textContent = msg - } + const elements = document.querySelectorAll("[data-localise]") + for (let i in elements) + if (elements.hasOwnProperty(i)) { + const obj = elements[i] + const tag = obj.getAttribute("data-localise").toString() + const msg = getMessage(tag) + if (msg && msg !== tag) obj.textContent = msg + } - const placeholders = document.querySelectorAll("[data-localise-placeholder]") - for (let i in placeholders) - if (placeholders.hasOwnProperty(i)) { - const obj = placeholders[i] - const tag = obj.getAttribute("data-localise-placeholder").toString() - const msg = getMessage(tag) - if (msg && msg !== tag) obj.placeholder = msg - } + const placeholders = document.querySelectorAll("[data-localise-placeholder]") + for (let i in placeholders) + if (placeholders.hasOwnProperty(i)) { + const obj = placeholders[i] + const tag = obj.getAttribute("data-localise-placeholder").toString() + const msg = getMessage(tag) + if (msg && msg !== tag) obj.placeholder = msg + } } export default { - localisePage, + localisePage, } diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index b9ee64e5..39347845 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -6,25 +6,25 @@ window.browser = window.browser || window.chrome let config, options async function init() { - options = await utils.getOptions() - config = await utils.getConfig() + options = await utils.getOptions() + config = await utils.getConfig() } init() browser.storage.onChanged.addListener(init) function all(service, frontend, options, config) { - let instances = [] - if (!frontend) { - for (const frontend in config.services[service].frontends) { - if (options[frontend]) { - instances.push(...options[frontend]) - } - } - } else if (options[frontend]) { - instances = options[frontend] - } - return instances + let instances = [] + if (!frontend) { + for (const frontend in config.services[service].frontends) { + if (options[frontend]) { + instances.push(...options[frontend]) + } + } + } else if (options[frontend]) { + instances = options[frontend] + } + return instances } /** @@ -34,17 +34,17 @@ function all(service, frontend, options, 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]) { - targetList = targetList.filter(val => - !config.services[service].frontends[frontend].excludeTargets.includes(targetList.indexOf(val)) - ) - } - for (const targetString in targetList) { - const target = new RegExp(targetList[targetString]) - if (target.test(url.href)) return true - } - return false + let targetList = config.services[service].targets + if (frontend && "excludeTargets" in config.services[service].frontends[frontend]) { + targetList = targetList.filter( + val => !config.services[service].frontends[frontend].excludeTargets.includes(targetList.indexOf(val)) + ) + } + for (const targetString in targetList) { + const target = new RegExp(targetList[targetString]) + if (target.test(url.href)) return true + } + return false } /** @@ -54,8 +54,8 @@ function regexArray(service, url, config, frontend) { * @param {boolean} forceRedirection */ async function redirectAsync(url, type, initiator, forceRedirection) { - await init() - return redirect(url, type, initiator, forceRedirection) + await init() + return redirect(url, type, initiator, forceRedirection) } /** @@ -65,458 +65,481 @@ async function redirectAsync(url, type, initiator, forceRedirection) { * @returns {undefined|string} */ function rewrite(url, frontend, randomInstance) { - switch (frontend) { - case "hyperpipe": - return `${randomInstance}${url.pathname}${url.search}`.replace(/\/search\?q=.*/, searchQuery => searchQuery.replace("?q=", "/")) - case "searx": - case "searxng": - return `${randomInstance}/${url.search}` - case "whoogle": - return `${randomInstance}/search${url.search}` - case "4get": { - const s = url.searchParams.get("q") - if (s !== null) return `${randomInstance}/web?s=${encodeURIComponent(s)}` - return randomInstance - } - case "librey": - return `${randomInstance}/search.php${url.search}` - case "yattee": - url.searchParams.delete("si") - return url.href.replace(/^https?:\/{2}/, "yattee://") - case "freetube": - url.searchParams.delete("si") - return 'freetube://' + url.href - case "freetubePwa": - url.searchParams.delete("si") - return 'freetube://' + url.href - case "poketube": { - url.searchParams.delete("si") - if (url.pathname.startsWith('/channel')) { - const reg = /\/channel\/(.*)\/?$/.exec(url.pathname) - if (reg) { - const id = reg[1] - return `${randomInstance}/channel?id=${id}${url.search}` - } - } - if (/\/@[a-z]+\//.exec(url.pathname)) return randomInstance - return `${randomInstance}${url.pathname}${url.search}` - } - case "libMedium": - case "scribe": { - const regex = url.hostname.match(/^(link|cdn-images-\d+|.*)\.medium\.com/) - if (regex && regex.length > 1) { - const subdomain = regex[1] - if (subdomain != "link" || !subdomain.startsWith("cdn-images")) { - return `${randomInstance}/@${subdomain}${url.pathname}${url.search}` - } - } - return `${randomInstance}${url.pathname}${url.search}` - } - case "simplyTranslate": - return `${randomInstance}/${url.search}` - case "send": - case "mozhi": - return randomInstance - case "libreTranslate": - return `${randomInstance}/${url.search.replace("sl", "source").replace("tl", "target").replace("text", "q")}` - case "osm": { - const placeRegex = /\/place\/(.*?)\// - function convertMapCentre(url) { - let [lat, lon, zoom] = [null, null, null] - const reg = url.pathname.match(/@(-?\d[0-9.]*),(-?\d[0-9.]*),(\d{1,2})[.z]/) - if (reg) { - [, lon, lat, zoom] = reg - } else if (url.searchParams.has("center")) { - // Set map centre if present - [lat, lon] = url.searchParams.get("center").split(",") - zoom = url.searchParams.get("zoom") ?? "17" - } - return { zoom, lon, lat } - } - function addressToLatLng(address) { - const http = new XMLHttpRequest() - http.open("GET", `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(address)}&format=json&limit=1`, false) - http.send() - if (http.status == 200) { - const json = JSON.parse(http.responseText)[0] - if (json) { - return { - coordinate: `${json.lat},${json.lon}`, - boundingbox: `${json.boundingbox[2]},${json.boundingbox[1]},${json.boundingbox[3]},${json.boundingbox[0]}` - } - } - return {} - } - } - function getQuery(url) { - let query = "" - if (url.searchParams.has("q")) query = url.searchParams.get("q") - else if (url.searchParams.has("query")) query = url.searchParams.has("query") - return query - } - function prefsEncoded(prefs) { - return new URLSearchParams(prefs).toString() - } - - if (initiator && initiator.host === "earth.google.com") return randomInstance - - let mapCentre = "#" - let prefs = { layers: "mapnik" } - - const mapCentreData = convertMapCentre(url) - if (mapCentreData.zoom && mapCentreData.lon && mapCentreData.lat) mapCentre = `#map=${mapCentreData.zoom}/${mapCentreData.lon}/${mapCentreData.lat}` - - if (url.pathname.includes("/embed")) { // https://www.google.com/maps/embed/v1/place?key=AIzaSyD4iE2xVSpkLLOXoyqT-RuPwURN3ddScAI&q=Eiffel+Tower,Paris+France - const query = getQuery(url) - let { coordinate, boundingbox } = addressToLatLng(query) - prefs.bbox = boundingbox - prefs.marker = coordinate - return `${randomInstance}/export/embed.html?${prefsEncoded(prefs)}` - } else if (url.pathname.includes("/dir")) { - if (url.searchParams.has("travelmode")) { - const travelModes = { - driving: "fossgis_osrm_car", - walking: "fossgis_osrm_foot", - bicycling: "fossgis_osrm_bike", - transit: "fossgis_osrm_car", // not implemented on OSM, default to car. - } - prefs.engine = travelModes[url.searchParams.get("travelmode")] - } - const regex1 = /\/dir\/([^@/]+)\/([^@/]+)\/@-?\d[0-9.]*,-?\d[0-9.]*,\d{1,2}[.z]/.exec(url.pathname) - const regex2 = /\/dir\/([^@/]+)\//.exec(url.pathname) - if (regex1) { // https://www.google.com/maps/dir/92+Rue+Moncey,+69003+Lyon,+France/M%C3%A9dip%C3%B4le+Lyon-Villeurbanne/@45.760254,4.8486298,13z?travelmode=bicycling - const origin = addressToLatLng(decodeURIComponent(regex1[1])).coordinate ?? '' - const destination = addressToLatLng(decodeURIComponent(regex1[2])).coordinate ?? '' - prefs.route = `${origin};${destination}` - } else if (regex2) { // https://www.google.com/maps/dir/92+Rue+Moncey,+69003+Lyon,+France/@45.760254,4.8486298,13z?travelmode=bicycling - const origin = addressToLatLng(decodeURIComponent(regex2[1])).coordinate ?? '' - prefs.route = `${origin};` - } else { // https://www.google.com/maps/dir/?api=1&origin=Space+Needle+Seattle+WA&destination=Pike+Place+Market+Seattle+WA&travelmode=bicycling - const origin = addressToLatLng(url.searchParams.get("origin")).coordinate ?? '' - const destination = addressToLatLng(url.searchParams.get("destination")).coordinate ?? '' - prefs.route = `${origin};${destination}` - } - return `${randomInstance}/directions?${prefsEncoded(prefs)}${mapCentre}` - } else if (url.pathname.match(placeRegex)) { // https://www.google.com/maps/place/H%C3%B4tel+de+Londres+Eiffel/@40.9845265,28.7081268,14z - const query = url.pathname.match(placeRegex)[1] - return `${randomInstance}/search?query=${query}${mapCentre}` - } else if (url.searchParams.has("ll")) { // https://maps.google.com/?ll=38.882147,-76.99017 - const [mlat, mlon] = url.searchParams.get("ll").split(",") - return `${randomInstance}/search?query=${mlat}%2C${mlon}` - } else if (url.searchParams.has("viewpoint")) { // https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=48.857832,2.295226&heading=-45&pitch=38&fov=80 - const [mlat, mlon] = url.searchParams.get("viewpoint").split(",") - return `${randomInstance}/search?query=${mlat}%2C${mlon}` - } else { - const query = getQuery(url) - if (query) return `${randomInstance}/search?query="${query}${mapCentre}&${prefsEncoded(prefs)}` - } - return `${randomInstance}/${mapCentre}&${prefsEncoded(prefs)}` - } - case "breezeWiki": { - let wiki, urlpath = "" - if (url.hostname.match(/^[a-zA-Z0-9-]+\.(?:fandom|wikia)\.com/)) { - wiki = url.hostname.match(/^[a-zA-Z0-9-]+(?=\.(?:fandom|wikia)\.com)/) - if (wiki == "www" || !wiki) wiki = "" - else wiki = `/${wiki}` - urlpath = url.pathname - } else { - wiki = url.pathname.match(/(?<=wiki\/w:c:)[a-zA-Z0-9-]+(?=:)/) - if (!wiki) wiki = "" - else { - wiki = "/" + wiki + "/wiki/" - urlpath = url.pathname.match(/(?<=wiki\/w:c:[a-zA-Z0-9-]+:).+/) - } - } - if (url.href.search(/Special:Search\?query/) > -1) { - return `${randomInstance}${wiki}${urlpath}${url.search}`.replace(/Special:Search\?query/, "search?q").replace(/\/wiki/, "") - } - return `${randomInstance}${wiki}${urlpath}${url.search}` - } - case "rimgo": - if (url.href.search(/^https?:\/{2}(?:[im]\.)?stack\./) > -1) return `${randomInstance}/stack${url.pathname}${url.search}` - return `${randomInstance}${url.pathname}${url.search}` - case "redlib": - case "libreddit": { - const subdomain = url.hostname.match(/^(?:(?:external-)?preview|i)(?=\.redd\.it)/) - if (!subdomain) return `${randomInstance}${url.pathname}${url.search}` - switch (subdomain[0]) { - case "preview": - return `${randomInstance}/preview/pre${url.pathname}${url.search}` - case "external-preview": - return `${randomInstance}/preview/external-pre${url.pathname}${url.search}` - case "i": - return `${randomInstance}/img${url.pathname}` - } - return randomInstance - } - case "teddit": - if (/^(?:(?:external-)?preview|i)\.redd\.it/.test(url.hostname)) { - if (url.search == "") return `${randomInstance}${url.pathname}?teddit_proxy=${url.hostname}` - else return `${randomInstance}${url.pathname}${url.search}&teddit_proxy=${url.hostname}` - } - return `${randomInstance}${url.pathname}${url.search}` - case "neuters": { - const p = url.pathname - if (p.startsWith('/article/') || p.startsWith('/pf/') || p.startsWith('/arc/') || p.startsWith('/resizer/')) { - return randomInstance - } - return `${randomInstance}${p}` - } - case "dumb": - if (url.pathname.endsWith('-lyrics')) return `${randomInstance}${url.pathname}` - return `${randomInstance}${url.pathname}${url.search}` - case "intellectual": - return `${randomInstance}${url.pathname}${url.search}` - case "ruralDictionary": - if (!url.pathname.includes('/define.php') && !url.pathname.includes('/random.php') && url.pathname != '/') return randomInstance - return `${randomInstance}${url.pathname}${url.search}` - case "anonymousOverflow": { - if (url.hostname == "stackoverflow.com") { - const threadID = /^\/a\/(\d+)\/?/.exec(url.pathname) - if (threadID) return `${randomInstance}/questions/${threadID[1]}${url.search}` - return `${randomInstance}${url.pathname}${url.search}` - } - if (url.pathname == "/" || url.pathname == "") { - // https://stackexchange.com or https://superuser.com - return `${randomInstance}${url.pathname}${url.search}` - } - const regex = url.href.match(/https?:\/{2}(?:([a-zA-Z0-9-]+)\.)?stackexchange\.com\//) - if (regex && regex.length > 1) { - const subdomain = regex[1] - return `${randomInstance}/exchange/${subdomain}${url.pathname}${url.search}` - } - const notExchangeRegex = url.hostname.match(/(?:[a-zA-Z]+\.)?(?:askubuntu\.com|mathoverflow\.net|serverfault\.com|stackapps\.com|superuser\.com|stackoverflow\.com)/) - if (notExchangeRegex) { - return `${randomInstance}/exchange/${notExchangeRegex[0]}${url.pathname}${url.search}` - } - return `${randomInstance}${url.pathname}${url.search}` - } - case "biblioReads": - return `${randomInstance}${url.pathname}${url.search}` - case "wikiless": { - let hostSplit = url.host.split(".") - // wikiless doesn't have mobile view support yet - if (hostSplit[0] != "wikipedia" && hostSplit[0] != "www") { - if (hostSplit[0] == "m") url.searchParams.append("mobileaction", "toggle_view_mobile") - else url.searchParams.append("lang", hostSplit[0]) - if (hostSplit[1] == "m") url.searchParams.append("mobileaction", "toggle_view_mobile") - } - return `${randomInstance}${url.pathname}${url.search}${url.hash}` - } - case "proxiTok": - if (url.pathname.startsWith('/email')) return randomInstance - return `${randomInstance}${url.pathname}${url.search}` - case "waybackClassic": { - const regex = /^\/\web\/(?:[0-9]+)?\*\/(.*)/.exec(url.pathname) - if (regex) { - const link = regex[1] - return `${randomInstance}/cgi-bin/history.cgi?utf8=✓&q=${encodeURIComponent(link)}` - } - const regex2 = /(^\/\web\/([0-9]+)\/.*)/.exec(url.pathname) - if (regex2) { - let link = regex2[1] - link = link.replace(regex2[2], regex2[2] + 'if_') - return `https://web.archive.org${link}` - } - return - } - case "gothub": - if (url.hostname == "gist.github.com") return `${randomInstance}/gist${url.pathname}${url.search}` - if (url.hostname == "raw.githubusercontent.com") return `${randomInstance}/raw${url.pathname}${url.search}` - return `${randomInstance}${url.pathname}${url.search}` - case "mikuInvidious": - if (url.hostname == "bilibili.com" || url.hostname == "www.bilibili.com" || url.hostname == 'b23.tv') return `${randomInstance}${url.pathname}${url.search}` - if (url.hostname == "space.bilibili.com") return `${randomInstance}/space${url.pathname}${url.search}` - case "tent": { - if (url.hostname == 'bandcamp.com' && url.pathname == '/search') { - const query = url.searchParams.get('q') - return `${randomInstance}/search.php?query=${encodeURIComponent(query)}` - } - if (url.hostname.endsWith('bandcamp.com')) { - const regex = /^(.*)\.bandcamp\.com/.exec(url.hostname) - const artist = regex[1] - if (url.pathname == '/' || url.pathname == '/music') { - return `${randomInstance}/artist.php?name=${artist}` - } else { - const regex = /^\/(.*)\/(.*)/.exec(url.pathname) - if (regex) { - const type = regex[1] - const name = regex[2] - return `${randomInstance}/release.php?artist=${artist}&type=${type}&name=${name}` - } - } - } - if (url.hostname == 'f4.bcbits.com') { - const regex = /\/img\/(.*)/.exec(url.pathname) - const image = regex[1] - return `${randomInstance}/image.php?file=${image}` - } - if (url.hostname == 't4.bcbits.com') { - const regex = /\/stream\/(.*)\/(.*)\/(.*)/.exec(url.pathname) - if (regex) { - const directory = regex[1] - const format = regex[2] - const file = regex[3] - const token = url.searchParams.get('token') - return `${randomInstance}/audio.php/?directory=${directory}&format=${format}&file=${file}&token=${encodeURIComponent(token)}` - } - } - } - case "binternet": - if (url.hostname == "i.pinimg.com") return `${randomInstance}/image_proxy.php?url=${url.href}` - case "laboratory": { - let path = url.pathname - if (path == "/") path = "" - return `${randomInstance}/${url.hostname}${path}${url.search}` - } - case "quetre": { - const regex = /([a-z]+)\.quora\.com/.exec(url.hostname) - if (regex) { - const lang = regex[1] - url.searchParams.append("lang", lang) - return `${randomInstance}${url.pathname}${url.search}` - } - return `${randomInstance}${url.pathname}${url.search}` - } - case "pixivFe": { - const regex = /\/[a-z]{1,3}\/(.*)/.exec(url.pathname) - if (regex) { - const path = regex[1] - return `${randomInstance}/${path}${url.search}` - } - return `${randomInstance}${url.pathname}${url.search}` - } - case "invidious": { - url.searchParams.delete("si") - if (url.hostname == "youtu.be" || url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/live")) { - const watch = url.pathname.substring(url.pathname.lastIndexOf('/') + 1) - return `${randomInstance}/watch?v=${watch}${url.search.replace("?", "&")}` - } - if (url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/redirect?")) - return url.href - return `${randomInstance}${url.pathname}${url.search}` - } - case "freetubeMusic": { - if (url.hostname == "youtu.be" || url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/live")) { - const watch = url.pathname.substring(url.pathname.lastIndexOf('/') + 1) - return `freetube://youtube.com/watch?v=${watch}` - } - return 'freetube://' + url.href - } - case "invidiousMusic": { - if (url.hostname == "youtu.be" || url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/live")) { - const watch = url.pathname.substring(url.pathname.lastIndexOf('/') + 1) - return `${randomInstance}/watch?v=${watch}` - } - return `${randomInstance}${url.pathname}${url.search}` - } - case 'materialious': { - url.searchParams.delete('si') - if (url.hostname == 'youtu.be' || (url.hostname.endsWith('youtube.com') && url.pathname.startsWith('/live'))) { - const watch = url.pathname.substring(url.pathname.lastIndexOf('/') + 1) - return `${randomInstance}/watch/${watch}${url.search.replace('?', '&')}` - } - if (url.hostname.endsWith("youtube.com")) { - if (url.pathname.startsWith('/watch')) { - if (url.searchParams.has('v')) { - const watch = url.searchParams.get('v') - url.searchParams.delete('v') - return `${randomInstance}/watch/${watch}${url.search.replace('?', '&')}` - } - return `${randomInstance}/watch/${url.search.replace('?', '&')}` - } - if (url.pathname.startsWith('/results')) { - if (url.searchParams.has('search_query')) { - const search = url.searchParams.get('search_query') - url.searchParams.delete('search_query') - return `${randomInstance}/search/${search}${url.search.replace('?', '&')}` - } - return `${randomInstance}/search/${url.search.replace('?', '&')}` - } - if (url.pathname.startsWith('/redirect?')) { - return url.href - } - } - return `${randomInstance}${url.pathname}${url.search}` - } - case "libremdb": { - if (url.pathname.startsWith("/Name")) { - for (const [key, value] of url.searchParams.entries()) { - return `${randomInstance}/title/${encodeURIComponent(key)}` - } - } - return `${randomInstance}${url.pathname}${url.search}` - } - case "tuboYoutube": - url.searchParams.delete("si") - if (url.pathname.startsWith("/channel")) return `${randomInstance}/channel?url=${encodeURIComponent(url.href)}` - if (url.pathname.startsWith("/watch")) return `${randomInstance}/stream?url=${encodeURIComponent(url.href)}` - return randomInstance - case "tuboSoundcloud": - if (url.pathname == '/') return `${randomInstance}?kiosk?serviceId=1` - if (url.pathname.match(/^\/[^\/]+(\/$|$)/)) return `${randomInstance}/channel?url=${encodeURIComponent(url.href)}` - 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)}` - case "nitter": { - let search = new URLSearchParams(url.search) - - search.delete("ref_src") - search.delete("ref_url") - search.delete("s") // type of device that shared the link - search.delete("t") // some sort of tracking ID - - search = search.toString() - if (search !== "") search = `?${search}` - - if (url.host.split(".")[0] === "pbs" || url.host.split(".")[0] === "video") { - try { - const [, id, format, extra] = search.match(/(.*)\?format=(.*)&(.*)/) - const query = encodeURIComponent(`${id}.${format}?${extra}`) - return `${randomInstance}/pic${url.pathname}${query}` - } catch { - return `${randomInstance}/pic${url.pathname}${search}` - } - } - if (url.pathname.split("/").includes("tweets")) return `${randomInstance}${url.pathname.replace("/tweets", "")}${search}` - if (url.host == "t.co") return `${randomInstance}/t.co${url.pathname}` - return `${randomInstance}${url.pathname}${search}#m` - } - case "priviblur": { - if (url.hostname == "www.tumblr.com") return `${randomInstance}${url.pathname}${url.search}` - if (url.hostname.startsWith("assets")) return `${randomInstance}/tblr/assets${url.pathname}${url.search}` - if (url.hostname.startsWith("static")) return `${randomInstance}/tblr/static${url.pathname}${url.search}` - - const reg = /^([0-9]+)\.media\.tumblr\.com/.exec(url.hostname) // *.media.tumblr.com - if (reg) return `${randomInstance}/tblr/media/${reg[1]}${url.pathname}${url.search}` - - const blogregex = /^(?:www\.)?([a-z\d-]+)\.tumblr\.com/.exec(url.hostname) // .tumblr.com - if (blogregex) { - const blog_name = blogregex[1]; - // Under the .tumblr.com domain posts are under a /post path - if (url.pathname.startsWith("/post")) return `${randomInstance}/${blog_name}${url.pathname.slice(5)}${url.search}` - else return `${randomInstance}/${blog_name}${url.pathname}${url.search}`; - } - return `${randomInstance}${url.pathname}${url.search}`; - } - case "piped": - case "pipedMaterial": - case "cloudtube": - case "lightTube": - case "viewtube": - url.searchParams.delete("si") - default: - return `${randomInstance}${url.pathname}${url.search}` - } + switch (frontend) { + case "hyperpipe": + return `${randomInstance}${url.pathname}${url.search}`.replace(/\/search\?q=.*/, searchQuery => + searchQuery.replace("?q=", "/") + ) + case "searx": + case "searxng": + return `${randomInstance}/${url.search}` + case "whoogle": + return `${randomInstance}/search${url.search}` + case "4get": { + const s = url.searchParams.get("q") + if (s !== null) return `${randomInstance}/web?s=${encodeURIComponent(s)}` + return randomInstance + } + case "librey": + return `${randomInstance}/search.php${url.search}` + case "yattee": + url.searchParams.delete("si") + return url.href.replace(/^https?:\/{2}/, "yattee://") + case "freetube": + url.searchParams.delete("si") + return "freetube://" + url.href + case "freetubePwa": + url.searchParams.delete("si") + return "freetube://" + url.href + case "poketube": { + url.searchParams.delete("si") + if (url.pathname.startsWith("/channel")) { + const reg = /\/channel\/(.*)\/?$/.exec(url.pathname) + if (reg) { + const id = reg[1] + return `${randomInstance}/channel?id=${id}${url.search}` + } + } + if (/\/@[a-z]+\//.exec(url.pathname)) return randomInstance + return `${randomInstance}${url.pathname}${url.search}` + } + case "libMedium": + case "scribe": { + const regex = url.hostname.match(/^(link|cdn-images-\d+|.*)\.medium\.com/) + if (regex && regex.length > 1) { + const subdomain = regex[1] + if (subdomain != "link" || !subdomain.startsWith("cdn-images")) { + return `${randomInstance}/@${subdomain}${url.pathname}${url.search}` + } + } + return `${randomInstance}${url.pathname}${url.search}` + } + case "simplyTranslate": + return `${randomInstance}/${url.search}` + case "send": + case "mozhi": + return randomInstance + case "libreTranslate": + return `${randomInstance}/${url.search.replace("sl", "source").replace("tl", "target").replace("text", "q")}` + case "osm": { + const placeRegex = /\/place\/(.*?)\// + function convertMapCentre(url) { + let [lat, lon, zoom] = [null, null, null] + const reg = url.pathname.match(/@(-?\d[0-9.]*),(-?\d[0-9.]*),(\d{1,2})[.z]/) + if (reg) { + ;[, lon, lat, zoom] = reg + } else if (url.searchParams.has("center")) { + // Set map centre if present + ;[lat, lon] = url.searchParams.get("center").split(",") + zoom = url.searchParams.get("zoom") ?? "17" + } + return { zoom, lon, lat } + } + function addressToLatLng(address) { + const http = new XMLHttpRequest() + http.open( + "GET", + `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(address)}&format=json&limit=1`, + false + ) + http.send() + if (http.status == 200) { + const json = JSON.parse(http.responseText)[0] + if (json) { + return { + coordinate: `${json.lat},${json.lon}`, + boundingbox: `${json.boundingbox[2]},${json.boundingbox[1]},${json.boundingbox[3]},${json.boundingbox[0]}`, + } + } + return {} + } + } + function getQuery(url) { + let query = "" + if (url.searchParams.has("q")) query = url.searchParams.get("q") + else if (url.searchParams.has("query")) query = url.searchParams.has("query") + return query + } + function prefsEncoded(prefs) { + return new URLSearchParams(prefs).toString() + } + + if (initiator && initiator.host === "earth.google.com") return randomInstance + + let mapCentre = "#" + let prefs = { layers: "mapnik" } + + const mapCentreData = convertMapCentre(url) + if (mapCentreData.zoom && mapCentreData.lon && mapCentreData.lat) + mapCentre = `#map=${mapCentreData.zoom}/${mapCentreData.lon}/${mapCentreData.lat}` + + if (url.pathname.includes("/embed")) { + // https://www.google.com/maps/embed/v1/place?key=AIzaSyD4iE2xVSpkLLOXoyqT-RuPwURN3ddScAI&q=Eiffel+Tower,Paris+France + const query = getQuery(url) + let { coordinate, boundingbox } = addressToLatLng(query) + prefs.bbox = boundingbox + prefs.marker = coordinate + return `${randomInstance}/export/embed.html?${prefsEncoded(prefs)}` + } else if (url.pathname.includes("/dir")) { + if (url.searchParams.has("travelmode")) { + const travelModes = { + driving: "fossgis_osrm_car", + walking: "fossgis_osrm_foot", + bicycling: "fossgis_osrm_bike", + transit: "fossgis_osrm_car", // not implemented on OSM, default to car. + } + prefs.engine = travelModes[url.searchParams.get("travelmode")] + } + const regex1 = /\/dir\/([^@/]+)\/([^@/]+)\/@-?\d[0-9.]*,-?\d[0-9.]*,\d{1,2}[.z]/.exec(url.pathname) + const regex2 = /\/dir\/([^@/]+)\//.exec(url.pathname) + if (regex1) { + // https://www.google.com/maps/dir/92+Rue+Moncey,+69003+Lyon,+France/M%C3%A9dip%C3%B4le+Lyon-Villeurbanne/@45.760254,4.8486298,13z?travelmode=bicycling + const origin = addressToLatLng(decodeURIComponent(regex1[1])).coordinate ?? "" + const destination = addressToLatLng(decodeURIComponent(regex1[2])).coordinate ?? "" + prefs.route = `${origin};${destination}` + } else if (regex2) { + // https://www.google.com/maps/dir/92+Rue+Moncey,+69003+Lyon,+France/@45.760254,4.8486298,13z?travelmode=bicycling + const origin = addressToLatLng(decodeURIComponent(regex2[1])).coordinate ?? "" + prefs.route = `${origin};` + } else { + // https://www.google.com/maps/dir/?api=1&origin=Space+Needle+Seattle+WA&destination=Pike+Place+Market+Seattle+WA&travelmode=bicycling + const origin = addressToLatLng(url.searchParams.get("origin")).coordinate ?? "" + const destination = addressToLatLng(url.searchParams.get("destination")).coordinate ?? "" + prefs.route = `${origin};${destination}` + } + return `${randomInstance}/directions?${prefsEncoded(prefs)}${mapCentre}` + } else if (url.pathname.match(placeRegex)) { + // https://www.google.com/maps/place/H%C3%B4tel+de+Londres+Eiffel/@40.9845265,28.7081268,14z + const query = url.pathname.match(placeRegex)[1] + return `${randomInstance}/search?query=${query}${mapCentre}` + } else if (url.searchParams.has("ll")) { + // https://maps.google.com/?ll=38.882147,-76.99017 + const [mlat, mlon] = url.searchParams.get("ll").split(",") + return `${randomInstance}/search?query=${mlat}%2C${mlon}` + } else if (url.searchParams.has("viewpoint")) { + // https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=48.857832,2.295226&heading=-45&pitch=38&fov=80 + const [mlat, mlon] = url.searchParams.get("viewpoint").split(",") + return `${randomInstance}/search?query=${mlat}%2C${mlon}` + } else { + const query = getQuery(url) + if (query) return `${randomInstance}/search?query="${query}${mapCentre}&${prefsEncoded(prefs)}` + } + return `${randomInstance}/${mapCentre}&${prefsEncoded(prefs)}` + } + case "breezeWiki": { + let wiki, + urlpath = "" + if (url.hostname.match(/^[a-zA-Z0-9-]+\.(?:fandom|wikia)\.com/)) { + wiki = url.hostname.match(/^[a-zA-Z0-9-]+(?=\.(?:fandom|wikia)\.com)/) + if (wiki == "www" || !wiki) wiki = "" + else wiki = `/${wiki}` + urlpath = url.pathname + } else { + wiki = url.pathname.match(/(?<=wiki\/w:c:)[a-zA-Z0-9-]+(?=:)/) + if (!wiki) wiki = "" + else { + wiki = "/" + wiki + "/wiki/" + urlpath = url.pathname.match(/(?<=wiki\/w:c:[a-zA-Z0-9-]+:).+/) + } + } + if (url.href.search(/Special:Search\?query/) > -1) { + return `${randomInstance}${wiki}${urlpath}${url.search}` + .replace(/Special:Search\?query/, "search?q") + .replace(/\/wiki/, "") + } + return `${randomInstance}${wiki}${urlpath}${url.search}` + } + case "rimgo": + if (url.href.search(/^https?:\/{2}(?:[im]\.)?stack\./) > -1) + return `${randomInstance}/stack${url.pathname}${url.search}` + return `${randomInstance}${url.pathname}${url.search}` + case "redlib": + case "libreddit": { + const subdomain = url.hostname.match(/^(?:(?:external-)?preview|i)(?=\.redd\.it)/) + if (!subdomain) return `${randomInstance}${url.pathname}${url.search}` + switch (subdomain[0]) { + case "preview": + return `${randomInstance}/preview/pre${url.pathname}${url.search}` + case "external-preview": + return `${randomInstance}/preview/external-pre${url.pathname}${url.search}` + case "i": + return `${randomInstance}/img${url.pathname}` + } + return randomInstance + } + case "teddit": + if (/^(?:(?:external-)?preview|i)\.redd\.it/.test(url.hostname)) { + if (url.search == "") return `${randomInstance}${url.pathname}?teddit_proxy=${url.hostname}` + else return `${randomInstance}${url.pathname}${url.search}&teddit_proxy=${url.hostname}` + } + return `${randomInstance}${url.pathname}${url.search}` + case "neuters": { + const p = url.pathname + if (p.startsWith("/article/") || p.startsWith("/pf/") || p.startsWith("/arc/") || p.startsWith("/resizer/")) { + return randomInstance + } + return `${randomInstance}${p}` + } + case "dumb": + if (url.pathname.endsWith("-lyrics")) return `${randomInstance}${url.pathname}` + return `${randomInstance}${url.pathname}${url.search}` + case "intellectual": + return `${randomInstance}${url.pathname}${url.search}` + case "ruralDictionary": + if (!url.pathname.includes("/define.php") && !url.pathname.includes("/random.php") && url.pathname != "/") + return randomInstance + return `${randomInstance}${url.pathname}${url.search}` + case "anonymousOverflow": { + if (url.hostname == "stackoverflow.com") { + const threadID = /^\/a\/(\d+)\/?/.exec(url.pathname) + if (threadID) return `${randomInstance}/questions/${threadID[1]}${url.search}` + return `${randomInstance}${url.pathname}${url.search}` + } + if (url.pathname == "/" || url.pathname == "") { + // https://stackexchange.com or https://superuser.com + return `${randomInstance}${url.pathname}${url.search}` + } + const regex = url.href.match(/https?:\/{2}(?:([a-zA-Z0-9-]+)\.)?stackexchange\.com\//) + if (regex && regex.length > 1) { + const subdomain = regex[1] + return `${randomInstance}/exchange/${subdomain}${url.pathname}${url.search}` + } + const notExchangeRegex = url.hostname.match( + /(?:[a-zA-Z]+\.)?(?:askubuntu\.com|mathoverflow\.net|serverfault\.com|stackapps\.com|superuser\.com|stackoverflow\.com)/ + ) + if (notExchangeRegex) { + return `${randomInstance}/exchange/${notExchangeRegex[0]}${url.pathname}${url.search}` + } + return `${randomInstance}${url.pathname}${url.search}` + } + case "biblioReads": + return `${randomInstance}${url.pathname}${url.search}` + case "wikiless": { + let hostSplit = url.host.split(".") + // wikiless doesn't have mobile view support yet + if (hostSplit[0] != "wikipedia" && hostSplit[0] != "www") { + if (hostSplit[0] == "m") url.searchParams.append("mobileaction", "toggle_view_mobile") + else url.searchParams.append("lang", hostSplit[0]) + if (hostSplit[1] == "m") url.searchParams.append("mobileaction", "toggle_view_mobile") + } + return `${randomInstance}${url.pathname}${url.search}${url.hash}` + } + case "proxiTok": + if (url.pathname.startsWith("/email")) return randomInstance + return `${randomInstance}${url.pathname}${url.search}` + case "waybackClassic": { + const regex = /^\/\web\/(?:[0-9]+)?\*\/(.*)/.exec(url.pathname) + if (regex) { + const link = regex[1] + return `${randomInstance}/cgi-bin/history.cgi?utf8=✓&q=${encodeURIComponent(link)}` + } + const regex2 = /(^\/\web\/([0-9]+)\/.*)/.exec(url.pathname) + if (regex2) { + let link = regex2[1] + link = link.replace(regex2[2], regex2[2] + "if_") + return `https://web.archive.org${link}` + } + return + } + case "gothub": + if (url.hostname == "gist.github.com") return `${randomInstance}/gist${url.pathname}${url.search}` + if (url.hostname == "raw.githubusercontent.com") return `${randomInstance}/raw${url.pathname}${url.search}` + return `${randomInstance}${url.pathname}${url.search}` + case "mikuInvidious": + if (url.hostname == "bilibili.com" || url.hostname == "www.bilibili.com" || url.hostname == "b23.tv") + return `${randomInstance}${url.pathname}${url.search}` + if (url.hostname == "space.bilibili.com") return `${randomInstance}/space${url.pathname}${url.search}` + case "tent": { + if (url.hostname == "bandcamp.com" && url.pathname == "/search") { + const query = url.searchParams.get("q") + return `${randomInstance}/search.php?query=${encodeURIComponent(query)}` + } + if (url.hostname.endsWith("bandcamp.com")) { + const regex = /^(.*)\.bandcamp\.com/.exec(url.hostname) + const artist = regex[1] + if (url.pathname == "/" || url.pathname == "/music") { + return `${randomInstance}/artist.php?name=${artist}` + } else { + const regex = /^\/(.*)\/(.*)/.exec(url.pathname) + if (regex) { + const type = regex[1] + const name = regex[2] + return `${randomInstance}/release.php?artist=${artist}&type=${type}&name=${name}` + } + } + } + if (url.hostname == "f4.bcbits.com") { + const regex = /\/img\/(.*)/.exec(url.pathname) + const image = regex[1] + return `${randomInstance}/image.php?file=${image}` + } + if (url.hostname == "t4.bcbits.com") { + const regex = /\/stream\/(.*)\/(.*)\/(.*)/.exec(url.pathname) + if (regex) { + const directory = regex[1] + const format = regex[2] + const file = regex[3] + const token = url.searchParams.get("token") + return `${randomInstance}/audio.php/?directory=${directory}&format=${format}&file=${file}&token=${encodeURIComponent(token)}` + } + } + } + case "binternet": + if (url.hostname == "i.pinimg.com") return `${randomInstance}/image_proxy.php?url=${url.href}` + case "laboratory": { + let path = url.pathname + if (path == "/") path = "" + return `${randomInstance}/${url.hostname}${path}${url.search}` + } + case "quetre": { + const regex = /([a-z]+)\.quora\.com/.exec(url.hostname) + if (regex) { + const lang = regex[1] + url.searchParams.append("lang", lang) + return `${randomInstance}${url.pathname}${url.search}` + } + return `${randomInstance}${url.pathname}${url.search}` + } + case "pixivFe": { + const regex = /\/[a-z]{1,3}\/(.*)/.exec(url.pathname) + if (regex) { + const path = regex[1] + return `${randomInstance}/${path}${url.search}` + } + return `${randomInstance}${url.pathname}${url.search}` + } + case "invidious": { + url.searchParams.delete("si") + if (url.hostname == "youtu.be" || (url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/live"))) { + const watch = url.pathname.substring(url.pathname.lastIndexOf("/") + 1) + return `${randomInstance}/watch?v=${watch}${url.search.replace("?", "&")}` + } + if (url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/redirect?")) return url.href + return `${randomInstance}${url.pathname}${url.search}` + } + case "freetubeMusic": { + if (url.hostname == "youtu.be" || (url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/live"))) { + const watch = url.pathname.substring(url.pathname.lastIndexOf("/") + 1) + return `freetube://youtube.com/watch?v=${watch}` + } + return "freetube://" + url.href + } + case "invidiousMusic": { + if (url.hostname == "youtu.be" || (url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/live"))) { + const watch = url.pathname.substring(url.pathname.lastIndexOf("/") + 1) + return `${randomInstance}/watch?v=${watch}` + } + return `${randomInstance}${url.pathname}${url.search}` + } + case "materialious": { + url.searchParams.delete("si") + if (url.hostname == "youtu.be" || (url.hostname.endsWith("youtube.com") && url.pathname.startsWith("/live"))) { + const watch = url.pathname.substring(url.pathname.lastIndexOf("/") + 1) + return `${randomInstance}/watch/${watch}${url.search.replace("?", "&")}` + } + if (url.hostname.endsWith("youtube.com")) { + if (url.pathname.startsWith("/watch")) { + if (url.searchParams.has("v")) { + const watch = url.searchParams.get("v") + url.searchParams.delete("v") + return `${randomInstance}/watch/${watch}${url.search.replace("?", "&")}` + } + return `${randomInstance}/watch/${url.search.replace("?", "&")}` + } + if (url.pathname.startsWith("/results")) { + if (url.searchParams.has("search_query")) { + const search = url.searchParams.get("search_query") + url.searchParams.delete("search_query") + return `${randomInstance}/search/${search}${url.search.replace("?", "&")}` + } + return `${randomInstance}/search/${url.search.replace("?", "&")}` + } + if (url.pathname.startsWith("/redirect?")) { + return url.href + } + } + return `${randomInstance}${url.pathname}${url.search}` + } + case "libremdb": { + if (url.pathname.startsWith("/Name")) { + for (const [key, value] of url.searchParams.entries()) { + return `${randomInstance}/title/${encodeURIComponent(key)}` + } + } + return `${randomInstance}${url.pathname}${url.search}` + } + case "tuboYoutube": + url.searchParams.delete("si") + if (url.pathname.startsWith("/channel")) return `${randomInstance}/channel?url=${encodeURIComponent(url.href)}` + if (url.pathname.startsWith("/watch")) return `${randomInstance}/stream?url=${encodeURIComponent(url.href)}` + return randomInstance + case "tuboSoundcloud": + if (url.pathname == "/") return `${randomInstance}?kiosk?serviceId=1` + if (url.pathname.match(/^\/[^\/]+(\/$|$)/)) return `${randomInstance}/channel?url=${encodeURIComponent(url.href)}` + 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)}` + case "nitter": { + let search = new URLSearchParams(url.search) + + search.delete("ref_src") + search.delete("ref_url") + search.delete("s") // type of device that shared the link + search.delete("t") // some sort of tracking ID + + search = search.toString() + if (search !== "") search = `?${search}` + + if (url.host.split(".")[0] === "pbs" || url.host.split(".")[0] === "video") { + try { + const [, id, format, extra] = search.match(/(.*)\?format=(.*)&(.*)/) + const query = encodeURIComponent(`${id}.${format}?${extra}`) + return `${randomInstance}/pic${url.pathname}${query}` + } catch { + return `${randomInstance}/pic${url.pathname}${search}` + } + } + if (url.pathname.split("/").includes("tweets")) + return `${randomInstance}${url.pathname.replace("/tweets", "")}${search}` + if (url.host == "t.co") return `${randomInstance}/t.co${url.pathname}` + return `${randomInstance}${url.pathname}${search}#m` + } + case "priviblur": { + if (url.hostname == "www.tumblr.com") return `${randomInstance}${url.pathname}${url.search}` + if (url.hostname.startsWith("assets")) return `${randomInstance}/tblr/assets${url.pathname}${url.search}` + if (url.hostname.startsWith("static")) return `${randomInstance}/tblr/static${url.pathname}${url.search}` + + const reg = /^([0-9]+)\.media\.tumblr\.com/.exec(url.hostname) // *.media.tumblr.com + if (reg) return `${randomInstance}/tblr/media/${reg[1]}${url.pathname}${url.search}` + + const blogregex = /^(?:www\.)?([a-z\d-]+)\.tumblr\.com/.exec(url.hostname) // .tumblr.com + if (blogregex) { + const blog_name = blogregex[1] + // Under the .tumblr.com domain posts are under a /post path + if (url.pathname.startsWith("/post")) + return `${randomInstance}/${blog_name}${url.pathname.slice(5)}${url.search}` + else return `${randomInstance}/${blog_name}${url.pathname}${url.search}` + } + return `${randomInstance}${url.pathname}${url.search}` + } + case "piped": + case "pipedMaterial": + case "cloudtube": + case "lightTube": + case "viewtube": + url.searchParams.delete("si") + default: + return `${randomInstance}${url.pathname}${url.search}` + } } /** @@ -527,50 +550,54 @@ function rewrite(url, frontend, randomInstance) { * @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 - - frontend = options[service].frontend - - if (config.services[service].frontends[frontend].desktopApp && type != "main_frame" && options[service].redirectType != "main_frame") - frontend = options[service].embedFrontend - - if (!regexArray(service, url, config, frontend)) { - frontend = null - continue - } - - if ( - config.services[service].embeddable - && - type != options[service].redirectType && options[service].redirectType != "both" - ) { - if (options[service].unsupportedUrls == 'block') return 'CANCEL' - return - } - - let instanceList = options[frontend] - if (instanceList === undefined) break - if (instanceList.length === 0) return null - - if (initiator && instanceList.includes(initiator.origin)) { - if (type != "main_frame") return null - else return "BYPASSTAB" - } - - randomInstance = utils.getRandomInstance(instanceList) - if (config.services[service].frontends[frontend].localhost && options[service].instance == "localhost") { - randomInstance = `http://${frontend}.localhost:8080` - } - break - } - if (!frontend) return - - return rewrite(url, frontend, randomInstance) + 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 + + frontend = options[service].frontend + + if ( + config.services[service].frontends[frontend].desktopApp && + type != "main_frame" && + options[service].redirectType != "main_frame" + ) + frontend = options[service].embedFrontend + + if (!regexArray(service, url, config, frontend)) { + frontend = null + continue + } + + if ( + config.services[service].embeddable && + type != options[service].redirectType && + options[service].redirectType != "both" + ) { + if (options[service].unsupportedUrls == "block") return "CANCEL" + return + } + + let instanceList = options[frontend] + if (instanceList === undefined) break + if (instanceList.length === 0) return null + + if (initiator && instanceList.includes(initiator.origin)) { + if (type != "main_frame") return null + else return "BYPASSTAB" + } + + randomInstance = utils.getRandomInstance(instanceList) + if (config.services[service].frontends[frontend].localhost && options[service].instance == "localhost") { + randomInstance = `http://${frontend}.localhost:8080` + } + break + } + if (!frontend) return + + return rewrite(url, frontend, randomInstance) } /** @@ -578,27 +605,25 @@ function redirect(url, type, initiator, forceRedirection, incognito) { * @param {*} returnFrontend */ function computeService(url, returnFrontend) { - return new Promise(async resolve => { - const config = await utils.getConfig() - const options = await utils.getOptions() - for (const service in config.services) { - if (regexArray(service, url, config)) { - resolve(service) - return - } else { - for (const frontend in config.services[service].frontends) { - if (all(service, frontend, options, config).includes(utils.protocolHost(url))) { - if (returnFrontend) - resolve([service, frontend, utils.protocolHost(url)]) - else - resolve(service) - return - } - } - } - } - resolve() - }) + return new Promise(async resolve => { + const config = await utils.getConfig() + const options = await utils.getOptions() + for (const service in config.services) { + if (regexArray(service, url, config)) { + resolve(service) + return + } else { + for (const frontend in config.services[service].frontends) { + if (all(service, frontend, options, config).includes(utils.protocolHost(url))) { + if (returnFrontend) resolve([service, frontend, utils.protocolHost(url)]) + else resolve(service) + return + } + } + } + } + resolve() + }) } /** @@ -606,303 +631,301 @@ function computeService(url, returnFrontend) { * @param {string} customService */ function switchInstance(url, customService) { - return new Promise(async resolve => { - let options = await utils.getOptions() - let config = await utils.getConfig() - - const protocolHost = utils.protocolHost(url) - if (customService) { - const instancesList = options[options[customService].frontend] - if (instancesList !== undefined) { - const newInstance = utils.getNextInstance(url.origin, instancesList) - if (newInstance) { - resolve(`${newInstance}${url.pathname}${url.search}`) - return - } - } - } else { - for (const service in config.services) { - let instancesList = options[options[service].frontend] - if (instancesList === undefined) continue - if (!instancesList.includes(protocolHost)) continue - - instancesList.splice(instancesList.indexOf(protocolHost), 1) - if (instancesList.length === 0) { - resolve() - return - } - const newInstance = utils.getNextInstance(url.origin, instancesList) - if (newInstance) { - resolve(`${newInstance}${url.pathname}${url.search}`) - return - } - } - } - resolve() - }) + return new Promise(async resolve => { + let options = await utils.getOptions() + let config = await utils.getConfig() + + const protocolHost = utils.protocolHost(url) + if (customService) { + const instancesList = options[options[customService].frontend] + if (instancesList !== undefined) { + const newInstance = utils.getNextInstance(url.origin, instancesList) + if (newInstance) { + resolve(`${newInstance}${url.pathname}${url.search}`) + return + } + } + } else { + for (const service in config.services) { + let instancesList = options[options[service].frontend] + if (instancesList === undefined) continue + if (!instancesList.includes(protocolHost)) continue + + instancesList.splice(instancesList.indexOf(protocolHost), 1) + if (instancesList.length === 0) { + resolve() + return + } + const newInstance = utils.getNextInstance(url.origin, instancesList) + if (newInstance) { + resolve(`${newInstance}${url.pathname}${url.search}`) + return + } + } + } + resolve() + }) } /** * @param {URL} url */ async function reverse(url) { - let options = await utils.getOptions() - let config = await utils.getConfig() - let protocolHost = utils.protocolHost(url) - for (const service in config.services) { - let frontend = options[service].frontend - if (options[frontend] == undefined) continue - if (!options[frontend].includes(protocolHost) && protocolHost != `http://${frontend}.localhost:8080`) continue - switch (service) { - case "youtube": - case "imdb": - case "imgur": - case "tiktok": - case "reddit": - case "imdb": - case "snopes": - case "urbanDictionary": - case "quora": - case "medium": - return `${config.services[service].url}${url.pathname}${url.search}` - case "fandom": { - let regex = url.pathname.match(/^\/([a-zA-Z0-9-]+)\/wiki\/(.*)/) - if (regex) return `https://${regex[1]}.fandom.com/wiki/${regex[2]}` - return - } - case "wikipedia": { - const lang = url.searchParams.get("lang") - if (lang != null) { - return `https://${lang}.wikipedia.org${url.pathname}${url.search}${url.hash}` - } - return `https://wikipedia.org${url.pathname}${url.search}${url.hash}` - } - case "stackOverflow": { - if (url.pathname.startsWith("/questions/")) { - return `https://stackoverflow.com${url.pathname}${url.search}` - } - if (url.pathname.startsWith("/exchange/")) { - const regex = /\/exchange\/(.*?)(\/.*)/.exec(url.pathname) - if (regex) return `https://${regex[1]}.stackexchange.com${regex[2]}` - } - return - } - case "tekstowo": - return `${config.services[service].url}/${url.search.slice(1)}` - case "goodreads": - return `https://goodreads.com${url.pathname}${url.search}` - default: - return - } - } - return + let options = await utils.getOptions() + let config = await utils.getConfig() + let protocolHost = utils.protocolHost(url) + for (const service in config.services) { + let frontend = options[service].frontend + if (options[frontend] == undefined) continue + if (!options[frontend].includes(protocolHost) && protocolHost != `http://${frontend}.localhost:8080`) continue + switch (service) { + case "youtube": + case "imdb": + case "imgur": + case "tiktok": + case "reddit": + case "imdb": + case "snopes": + case "urbanDictionary": + case "quora": + case "medium": + return `${config.services[service].url}${url.pathname}${url.search}` + case "fandom": { + let regex = url.pathname.match(/^\/([a-zA-Z0-9-]+)\/wiki\/(.*)/) + if (regex) return `https://${regex[1]}.fandom.com/wiki/${regex[2]}` + return + } + case "wikipedia": { + const lang = url.searchParams.get("lang") + if (lang != null) { + return `https://${lang}.wikipedia.org${url.pathname}${url.search}${url.hash}` + } + return `https://wikipedia.org${url.pathname}${url.search}${url.hash}` + } + case "stackOverflow": { + if (url.pathname.startsWith("/questions/")) { + return `https://stackoverflow.com${url.pathname}${url.search}` + } + if (url.pathname.startsWith("/exchange/")) { + const regex = /\/exchange\/(.*?)(\/.*)/.exec(url.pathname) + if (regex) return `https://${regex[1]}.stackexchange.com${regex[2]}` + } + return + } + case "tekstowo": + return `${config.services[service].url}/${url.search.slice(1)}` + case "goodreads": + return `https://goodreads.com${url.pathname}${url.search}` + default: + return + } + } + return } const defaultInstances = { - 'invidious': ['https://inv.vern.cc'], - 'materialious': ['https://app.materialio.us'], - 'viewtube': ['https://viewtube.io'], - 'piped': ['https://pipedapi-libre.kavin.rocks'], - 'pipedMaterial': ['https://piped-material.xn--17b.net'], - 'cloudtube': ['https://tube.cadence.moe'], - 'lightTube': ['https://tube.kuylar.dev'], - 'poketube': ['https://poketube.fun'], - 'proxiTok': ['https://proxitok.pabloferreiro.es'], - 'redlib': ['https://safereddit.com'], - 'libreddit': ['https://libreddit.spike.codes'], - 'teddit': ['https://teddit.net'], - 'scribe': ['https://scribe.rip'], - 'libMedium': ['https://md.vern.cc'], - 'quetre': ['https://quetre.iket.me'], - 'libremdb': ['https://libremdb.iket.me'], - 'simplyTranslate': ['https://simplytranslate.org'], - 'mozhi': ['https://mozhi.aryak.me'], - 'searxng': ['https://search.bus-hit.me'], - '4get': ['https://4get.ca'], - 'rimgo': ['https://rimgo.vern.cc'], - 'hyperpipe': ['https://hyperpipe.surge.sh'], - 'osm': ['https://www.openstreetmap.org'], - 'breezeWiki': ['https://breezewiki.com'], - 'neuters': ['https://neuters.de'], - 'dumb': ['https://dm.vern.cc'], - "intellectual": ['https://intellectual.insprill.net'], - 'ruralDictionary': ['https://rd.vern.cc'], - 'anonymousOverflow': ['https://code.whatever.social'], - 'biblioReads': ['https://biblioreads.ml'], - 'wikiless': ['https://wikiless.org'], - 'suds': ['https://sd.vern.cc'], - 'unfunny': ['https://uf.vern.cc'], - 'soprano': ['https://sp.vern.cc'], - 'meme': ['https://mm.vern.cc'], - 'waybackClassic': ['https://wayback-classic.net'], - 'gothub': ['https://gh.odyssey346.dev'], - 'mikuInvidious': ['https://mikuinv.resrv.org'], - "tent": ['https://tent.sny.sh'], - "wolfreeAlpha": ['https://gqq.gitlab.io', 'https://uqq.gitlab.io'], - "laboratory": ['https://lab.vern.cc'], - 'binternet': ['https://bn.bloat.cat'], - 'pixivFe': ['https://pixivfe.exozy.me'], - 'indestructables': ['https://indestructables.private.coffee'], - 'destructables': ['https://ds.vern.cc'], - 'safetwitch': ['https://safetwitch.drgns.space'], - 'twineo': ['https://twineo.exozy.me'], - 'proxigram': ['https://ig.opnxng.com'], - 'tuboYoutube': ['https://tubo.migalmoreno.com'], - 'tuboSoundcloud': ['https://tubo.migalmoreno.com'], - 'tekstoLibre': ['https://davilarek.github.io/TekstoLibre'], - 'skyview': ['https://skyview.social'], - 'priviblur': ['https://pb.bloat.cat'], - 'nitter': ['https://nitter.privacydev.net'], - 'pasted': ['https://pasted.drakeerv.com'], + invidious: ["https://inv.vern.cc"], + materialious: ["https://app.materialio.us"], + viewtube: ["https://viewtube.io"], + piped: ["https://pipedapi-libre.kavin.rocks"], + pipedMaterial: ["https://piped-material.xn--17b.net"], + cloudtube: ["https://tube.cadence.moe"], + lightTube: ["https://tube.kuylar.dev"], + poketube: ["https://poketube.fun"], + proxiTok: ["https://proxitok.pabloferreiro.es"], + redlib: ["https://safereddit.com"], + libreddit: ["https://libreddit.spike.codes"], + teddit: ["https://teddit.net"], + scribe: ["https://scribe.rip"], + libMedium: ["https://md.vern.cc"], + quetre: ["https://quetre.iket.me"], + libremdb: ["https://libremdb.iket.me"], + simplyTranslate: ["https://simplytranslate.org"], + mozhi: ["https://mozhi.aryak.me"], + searxng: ["https://search.bus-hit.me"], + "4get": ["https://4get.ca"], + rimgo: ["https://rimgo.vern.cc"], + hyperpipe: ["https://hyperpipe.surge.sh"], + osm: ["https://www.openstreetmap.org"], + breezeWiki: ["https://breezewiki.com"], + neuters: ["https://neuters.de"], + dumb: ["https://dm.vern.cc"], + intellectual: ["https://intellectual.insprill.net"], + ruralDictionary: ["https://rd.vern.cc"], + anonymousOverflow: ["https://code.whatever.social"], + biblioReads: ["https://biblioreads.ml"], + wikiless: ["https://wikiless.org"], + suds: ["https://sd.vern.cc"], + unfunny: ["https://uf.vern.cc"], + soprano: ["https://sp.vern.cc"], + meme: ["https://mm.vern.cc"], + waybackClassic: ["https://wayback-classic.net"], + gothub: ["https://gh.odyssey346.dev"], + mikuInvidious: ["https://mikuinv.resrv.org"], + tent: ["https://tent.sny.sh"], + wolfreeAlpha: ["https://gqq.gitlab.io", "https://uqq.gitlab.io"], + laboratory: ["https://lab.vern.cc"], + binternet: ["https://bn.bloat.cat"], + pixivFe: ["https://pixivfe.exozy.me"], + indestructables: ["https://indestructables.private.coffee"], + destructables: ["https://ds.vern.cc"], + safetwitch: ["https://safetwitch.drgns.space"], + twineo: ["https://twineo.exozy.me"], + proxigram: ["https://ig.opnxng.com"], + tuboYoutube: ["https://tubo.migalmoreno.com"], + tuboSoundcloud: ["https://tubo.migalmoreno.com"], + tekstoLibre: ["https://davilarek.github.io/TekstoLibre"], + skyview: ["https://skyview.social"], + priviblur: ["https://pb.bloat.cat"], + nitter: ["https://nitter.privacydev.net"], + pasted: ["https://pasted.drakeerv.com"], } function initDefaults() { - return new Promise(resolve => { - browser.storage.local.clear(async () => { - let config = await utils.getConfig() - let options = {} - for (const service in config.services) { - options[service] = {} - for (const defaultOption in config.services[service].options) { - options[service][defaultOption] = config.services[service].options[defaultOption] - } - for (const frontend in config.services[service].frontends) { - if (config.services[service].frontends[frontend].instanceList) { - options[frontend] = [] - } - } - } - options.exceptions = { - url: [], - regex: [], - } - options.theme = "detect" - options.popupServices = ["youtube", "tiktok", "imgur", "reddit", "quora", "translate", "maps"] - options.fetchInstances = 'github' - options.redirectOnlyInIncognito = false - - options = { ...options, ...defaultInstances } - - browser.storage.local.set({ options }, - () => resolve() - ) - }) - }) + return new Promise(resolve => { + browser.storage.local.clear(async () => { + let config = await utils.getConfig() + let options = {} + for (const service in config.services) { + options[service] = {} + for (const defaultOption in config.services[service].options) { + options[service][defaultOption] = config.services[service].options[defaultOption] + } + for (const frontend in config.services[service].frontends) { + if (config.services[service].frontends[frontend].instanceList) { + options[frontend] = [] + } + } + } + options.exceptions = { + url: [], + regex: [], + } + options.theme = "detect" + options.popupServices = ["youtube", "tiktok", "imgur", "reddit", "quora", "translate", "maps"] + options.fetchInstances = "github" + options.redirectOnlyInIncognito = false + + options = { ...options, ...defaultInstances } + + browser.storage.local.set({ options }, () => resolve()) + }) + }) } function upgradeOptions() { - return new Promise(async resolve => { - let options = await utils.getOptions() - - browser.storage.local.clear(() => { - browser.storage.local.set({ options }, () => { - resolve() - }) - }) - }) + return new Promise(async resolve => { + let options = await utils.getOptions() + + browser.storage.local.clear(() => { + browser.storage.local.set({ options }, () => { + resolve() + }) + }) + }) } function processUpdate() { - return new Promise(async resolve => { - let frontends = [] - const config = await utils.getConfig() - let options = await utils.getOptions() - for (const service in config.services) { - if (!options[service]) options[service] = {} - - if (!(options[service].frontend in config.services[service].frontends)) { - options[service] = config.services[service].options // Reset settings for service - delete options[options[service].frontend] // Remove deprecated frontend - } - - for (const defaultOption in config.services[service].options) { - if (!(defaultOption in options[service])) { - options[service][defaultOption] = config.services[service].options[defaultOption] - } - } - - for (const frontend in config.services[service].frontends) { - frontends.push(frontend) - if (!(frontend in options) && config.services[service].frontends[frontend].instanceList) { - options[frontend] = defaultInstances[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); - } - } - } - const general = ['theme', 'popupServices', 'fetchInstances', 'redirectOnlyInIncognito'] - const combined = [ - ...Object.keys(config.services), - ...frontends, - ...general, - 'exceptions', - 'popupServices', - 'version', - ] - for (const key in options) { - if (combined.indexOf(key) < 0) { - delete options[key] // Remove any unknown settings in options - } - } - browser.storage.local.set({ options }, () => { - resolve() - }) - }) + return new Promise(async resolve => { + let frontends = [] + const config = await utils.getConfig() + let options = await utils.getOptions() + for (const service in config.services) { + if (!options[service]) options[service] = {} + + if (!(options[service].frontend in config.services[service].frontends)) { + options[service] = config.services[service].options // Reset settings for service + delete options[options[service].frontend] // Remove deprecated frontend + } + + for (const defaultOption in config.services[service].options) { + if (!(defaultOption in options[service])) { + options[service][defaultOption] = config.services[service].options[defaultOption] + } + } + + for (const frontend in config.services[service].frontends) { + frontends.push(frontend) + if (!(frontend in options) && config.services[service].frontends[frontend].instanceList) { + options[frontend] = defaultInstances[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) + } + } + } + const general = ["theme", "popupServices", "fetchInstances", "redirectOnlyInIncognito"] + const combined = [ + ...Object.keys(config.services), + ...frontends, + ...general, + "exceptions", + "popupServices", + "version", + ] + for (const key in options) { + if (combined.indexOf(key) < 0) { + delete options[key] // Remove any unknown settings in options + } + } + browser.storage.local.set({ options }, () => { + resolve() + }) + }) } /** * @param {URL} url */ async function copyRaw(url) { - const newUrl = await reverse(url) - if (newUrl) { - if (!isChrome) { - navigator.clipboard.writeText(newUrl) - } else { - var copyFrom = document.createElement("textarea"); - copyFrom.textContent = newUrl; - document.body.appendChild(copyFrom); - copyFrom.select() - document.execCommand('copy') - copyFrom.blur(); - document.body.removeChild(copyFrom); - } - } + const newUrl = await reverse(url) + if (newUrl) { + if (!isChrome) { + navigator.clipboard.writeText(newUrl) + } else { + var copyFrom = document.createElement("textarea") + copyFrom.textContent = newUrl + document.body.appendChild(copyFrom) + copyFrom.select() + document.execCommand("copy") + copyFrom.blur() + document.body.removeChild(copyFrom) + } + } } /** * @param {URL} url */ function isException(url) { - if (!options.exceptions) return false - let exceptions = options.exceptions - if (exceptions && url) { - if (exceptions.url) { - for (let item of exceptions.url) { - item = new URL(item) - item = item.href.replace(/^http:\/\//, 'https://') - if (item == url.href) return true - } - } - if (exceptions.regex) for (const item of exceptions.regex) if (new RegExp(item).test(url.href)) return true - } - return false + if (!options.exceptions) return false + let exceptions = options.exceptions + if (exceptions && url) { + if (exceptions.url) { + for (let item of exceptions.url) { + item = new URL(item) + item = item.href.replace(/^http:\/\//, "https://") + if (item == url.href) return true + } + } + if (exceptions.regex) for (const item of exceptions.regex) if (new RegExp(item).test(url.href)) return true + } + return false } export default { - redirect, - redirectAsync, - computeService, - reverse, - initDefaults, - upgradeOptions, - processUpdate, - copyRaw, - switchInstance, - isException + redirect, + redirectAsync, + computeService, + reverse, + initDefaults, + upgradeOptions, + processUpdate, + copyRaw, + switchInstance, + isException, } diff --git a/src/assets/javascripts/utils.js b/src/assets/javascripts/utils.js index d28f9701..439826dd 100644 --- a/src/assets/javascripts/utils.js +++ b/src/assets/javascripts/utils.js @@ -1,11 +1,11 @@ window.browser = window.browser || window.chrome /** - * @param {Array.} instances + * @param {Array.} instances * @returns {T} */ function getRandomInstance(instances) { - return instances[~~(instances.length * Math.random())] + return instances[~~(instances.length * Math.random())] } /** @@ -14,27 +14,28 @@ function getRandomInstance(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]; + 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) + 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}` + 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}` } /** @@ -59,14 +60,14 @@ function protocolHost(url) { * @returns {Promise} */ function getConfig() { - return new Promise(resolve => { - fetch("/config.json") - .then(response => response.text()) - .then(json => { - resolve(JSON.parse(json)) - return - }) - }) + return new Promise(resolve => { + fetch("/config.json") + .then(response => response.text()) + .then(json => { + resolve(JSON.parse(json)) + return + }) + }) } /** @@ -78,106 +79,108 @@ function getConfig() { * @returns {Promise>} */ function getOptions() { - return new Promise(resolve => browser.storage.local.get("options", r => resolve(r.options))) + return new Promise(resolve => browser.storage.local.get("options", r => resolve(r.options))) } function getPingCache() { - return new Promise(resolve => browser.storage.local.get("pingCache", r => resolve(r.pingCache ?? {}))) + return new Promise(resolve => browser.storage.local.get("pingCache", r => resolve(r.pingCache ?? {}))) } function getBlacklist(options) { - return new Promise(resolve => { - let url - if (options.fetchInstances == 'github') url = 'https://raw.githubusercontent.com/libredirect/instances/main/blacklist.json' - else if (options.fetchInstances == 'codeberg') url = 'https://codeberg.org/LibRedirect/instances/raw/branch/main/blacklist.json' - else return resolve('disabled') - const http = new XMLHttpRequest() - http.open("GET", url, true) - http.onreadystatechange = () => { - if (http.status === 200 && http.readyState == XMLHttpRequest.DONE) - resolve(JSON.parse(http.responseText)) - } - http.onerror = () => resolve() - http.ontimeout = () => resolve() - http.send(null) - }) + return new Promise(resolve => { + let url + if (options.fetchInstances == "github") + url = "https://raw.githubusercontent.com/libredirect/instances/main/blacklist.json" + else if (options.fetchInstances == "codeberg") + url = "https://codeberg.org/LibRedirect/instances/raw/branch/main/blacklist.json" + else return resolve("disabled") + const http = new XMLHttpRequest() + http.open("GET", url, true) + http.onreadystatechange = () => { + if (http.status === 200 && http.readyState == XMLHttpRequest.DONE) resolve(JSON.parse(http.responseText)) + } + http.onerror = () => resolve() + http.ontimeout = () => resolve() + http.send(null) + }) } function getList(options) { - return new Promise(resolve => { - let url - if (options.fetchInstances == 'github') url = 'https://raw.githubusercontent.com/libredirect/instances/main/data.json' - else if (options.fetchInstances == 'codeberg') url = 'https://codeberg.org/LibRedirect/instances/raw/branch/main/data.json' - else return resolve('disabled') - const http = new XMLHttpRequest() - http.open("GET", url, true) - http.onreadystatechange = () => { - if (http.status === 200 && http.readyState == XMLHttpRequest.DONE) - return resolve(JSON.parse(http.responseText)) - } - http.onerror = () => resolve() - http.ontimeout = () => resolve() - http.send(null) - }) + return new Promise(resolve => { + let url + if (options.fetchInstances == "github") + url = "https://raw.githubusercontent.com/libredirect/instances/main/data.json" + else if (options.fetchInstances == "codeberg") + url = "https://codeberg.org/LibRedirect/instances/raw/branch/main/data.json" + else return resolve("disabled") + const http = new XMLHttpRequest() + http.open("GET", url, true) + http.onreadystatechange = () => { + if (http.status === 200 && http.readyState == XMLHttpRequest.DONE) return resolve(JSON.parse(http.responseText)) + } + http.onerror = () => resolve() + http.ontimeout = () => resolve() + http.send(null) + }) } /** * @param {string} href */ function pingOnce(href) { - return new Promise(async resolve => { - let started - let http = new XMLHttpRequest() - http.timeout = 5000 - http.ontimeout = () => resolve(5000) - http.onerror = () => resolve() - http.onreadystatechange = () => { - if (http.readyState == 2) { - if (http.status == 200) { - let ended = new Date().getTime() - http.abort() - resolve(ended - started) - } else { - resolve(5000 + http.status) - } - } - } - http.open("GET", `${href}?_=${new Date().getTime()}`, true) - started = new Date().getTime() - http.send(null) - }) + return new Promise(async resolve => { + let started + let http = new XMLHttpRequest() + http.timeout = 5000 + http.ontimeout = () => resolve(5000) + http.onerror = () => resolve() + http.onreadystatechange = () => { + if (http.readyState == 2) { + if (http.status == 200) { + let ended = new Date().getTime() + http.abort() + resolve(ended - started) + } else { + resolve(5000 + http.status) + } + } + } + http.open("GET", `${href}?_=${new Date().getTime()}`, true) + started = new Date().getTime() + http.send(null) + }) } /** * @param {string} href */ function ping(href) { - return new Promise(async resolve => { - let average = 0 - let time - for (let i = 0; i < 3; i++) { - time = await pingOnce(href) - if (i == 0) continue - if (time >= 5000) { - resolve(time) - return - } - average += time - } - average = parseInt(average / 3) - resolve(average) - }) + return new Promise(async resolve => { + let average = 0 + let time + for (let i = 0; i < 3; i++) { + time = await pingOnce(href) + if (i == 0) continue + if (time >= 5000) { + resolve(time) + return + } + average += time + } + average = parseInt(average / 3) + resolve(average) + }) } export default { - getRandomInstance, - getNextInstance, - protocolHost, - getList, - getBlacklist, - camelCase, - getConfig, - getOptions, - getPingCache, - ping, + getRandomInstance, + getNextInstance, + protocolHost, + getList, + getBlacklist, + camelCase, + getConfig, + getOptions, + getPingCache, + ping, } diff --git a/src/config.json b/src/config.json index 76e4b022..6375357f 100644 --- a/src/config.json +++ b/src/config.json @@ -1,1124 +1,1036 @@ { - "networks": { - "clearnet": { - "tld": "org", - "name": "Clearnet" - }, - "tor": { - "tld": "onion", - "name": "Tor" - }, - "i2p": { - "tld": "i2p", - "name": "I2P" - }, - "loki": { - "tld": "loki", - "name": "Lokinet" - } - }, - "services": { - "youtube": { - "frontends": { - "invidious": { - "name": "Invidious", - "embeddable": true, - "instanceList": true, - "url": "https://invidious.io/" - }, - "materialious": { - "name": "Materialious", - "embeddable": true, - "instanceList": true, - "url": "https://materialio.us/" - }, - "piped": { - "excludeTargets": [ - 2, - 3 - ], - "name": "Piped", - "embeddable": true, - "instanceList": true, - "url": "https://github.com/TeamPiped/Piped" - }, - "pipedMaterial": { - "excludeTargets": [ - 2, - 3 - ], - "name": "Piped-Material", - "embeddable": false, - "instanceList": true, - "url": "https://github.com/mmjee/Piped-Material" - }, - "poketube": { - "excludeTargets": [ - 2, - 3 - ], - "name": "PokeTube", - "embeddable": true, - "instanceList": true, - "url": "https://codeberg.org/Ashley/poketube" - }, - "cloudtube": { - "name": "CloudTube", - "embeddable": false, - "instanceList": true, - "url": "https://sr.ht/~cadence/tube", - "excludeTargets": [ - 2, - 3 - ] - }, - "lightTube": { - "name": "LightTube", - "embeddable": false, - "instanceList": true, - "url": "https://github.com/lighttube-org/LightTube" - }, - "tuboYoutube": { - "name": "Tubo", - "embeddable": false, - "instanceList": true, - "url": "https://git.migalmoreno.com/tubo/about/", - "excludeTargets": [ - 2, - 3 - ] - }, - "freetube": { - "excludeTargets": [ - 2, - 3 - ], - "name": "FreeTube", - "embeddable": false, - "desktopApp": true, - "instanceList": false, - "url": "https://github.com/FreeTubeApp/FreeTube" - }, - "yattee": { - "excludeTargets": [ - 2, - 3 - ], - "name": "Yattee", - "embeddable": false, - "desktopApp": true, - "instanceList": false, - "url": "https://github.com/yattee/yattee" - }, - "freetubePwa": { - "excludeTargets": [ - 2, - 3 - ], - "name": "FreeTube PWA", - "embeddable": false, - "instanceList": false, - "url": "https://github.com/MarmadileManteater/FreeTubeCordova" - }, - "viewtube": { - "name": "ViewTube", - "embeddable": false, - "instanceList": true, - "url": "https://github.com/ViewTube/viewtube" - } - }, - "targets": [ - "^https?:\\/{2}(www\\.|m\\.)?youtube.com(\\/|$)(?!iframe_api\\/|redirect\\/)", - "^https?:\\/{2}img\\.youtube.com\\/vi\\/.*\\/..*", - "^https?:\\/{2}(i|s)\\.ytimg.com\\/vi\\/.*\\/..*", - "^https?:\\/{2}(www\\.)?youtube.com\\/watch?v=..*", - "^https?:\\/{2}(www\\.)?youtu\\.be\\/..*", - "^https?:\\/{2}(www\\.)?(youtube|youtube-nocookie)\\.com\\/embed\\/..*" - ], - "name": "YouTube", - "options": { - "enabled": false, - "redirectType": "main_frame", - "frontend": "invidious", - "embedFrontend": "invidious", - "unsupportedUrls": "bypass" - }, - "imageType": "png", - "embeddable": true, - "url": "https://youtube.com" - }, - "youtubeMusic": { - "frontends": { - "hyperpipe": { - "name": "Hyperpipe", - "instanceList": true, - "url": "https://codeberg.org/Hyperpipe/Hyperpipe" - }, - "invidiousMusic": { - "name": "Invidious", - "embeddable": true, - "instanceList": true, - "url": "https://invidious.io/" - }, - "freetubeMusic": { - "name": "FreeTube", - "embeddable": false, - "desktopApp": true, - "instanceList": false, - "url": "https://github.com/FreeTubeApp/FreeTube" - } - }, - "targets": [ - "^https?:\\/{2}music\\.youtube\\.com\\/" - ], - "name": "YT Music", - "options": { - "enabled": false, - "frontend": "hyperpipe", - "unsupportedUrls": "bypass" - }, - "imageType": "png", - "url": "https://music.youtube.com" - }, - "twitter": { - "frontends": { - "nitter": { - "name": "Nitter", - "embeddable": true, - "instanceList": true, - "url": "https://github.com/zedeus/nitter", - "localhost": true - } - }, - "targets": [ - "^https?:\\/{2}(www\\.|mobile\\.)?twitter\\.com\\/", - "^https?:\\/{2}(www\\.|mobile\\.)?x\\.com\\/", - "^https?:\\/{2}(pbs\\.|video\\.)twimg\\.com\\/", - "^https?:\\/{2}platform\\.x\\.com/embed\\/", - "^https?:\\/{2}platform\\.twitter\\.com/embed\\/", - "^https?:\\/{2}t\\.co\\/" - ], - "name": "Twitter", - "options": { - "enabled": false, - "redirectType": "main_frame", - "unsupportedUrls": "bypass", - "frontend": "nitter", - "instance": "public" - }, - "imageType": "png", - "embeddable": true, - "url": "https://twitter.com" - }, - "bluesky": { - "frontends": { - "skyview": { - "name": "Skyview", - "instanceList": true, - "url": "https://github.com/badlogic/skyview" - } - }, - "targets": [ - "^https?:\\/{2}bsky\\.app\\/" - ], - "name": "Bluesky", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "skyview" - }, - "imageType": "svg", - "url": "https://bsky.app/" - }, - "reddit": { - "frontends": { - "libreddit": { - "name": "Libreddit", - "instanceList": true, - "url": "https://github.com/spikecodes/libreddit", - "localhost": true - }, - "redlib": { - "name": "Redlib", - "instanceList": true, - "url": "https://github.com/redlib-org/redlib", - "localhost": true - }, - "teddit": { - "name": "Teddit", - "instanceList": true, - "url": "https://codeberg.org/teddit/teddit", - "localhost": true - } - }, - "targets": [ - "^https?:\\/{2}(www\\.|old\\.|np\\.|new\\.|amp\\.)?(reddit|reddittorjg6rue252oqsxryoxengawnmo46qy4kyii5wtqnwfj4ooad)\\.(com|onion)(?=\\/u(ser)?\\/|\\/r\\/|\\/search|\\/new|\\/?$)", - "^https?:\\/{2}(i|(external-)?preview)\\.redd\\.it" - ], - "name": "Reddit", - "options": { - "enabled": false, - "frontend": "libreddit", - "unsupportedUrls": "bypass", - "instance": "public" - }, - "imageType": "png", - "url": "https://reddit.com" - }, - "tumblr": { - "frontends": { - "priviblur": { - "name": "Priviblur", - "embeddable": true, - "instanceList": true, - "url": "https://github.com/syeopite/priviblur", - "localhost": true - } - }, - "targets": [ - "^https?:\\/{2}(media\\.|assets\\.|static\\.)?tumblr\\.com\\/", - "^https?:\\/{2}[0-9]+\\.media\\.tumblr\\.com\\/", - "^https?:\\/{2}(www\\.)?(.*)\\.tumblr.com\\/" - ], - "name": "Tumblr", - "options": { - "enabled": false, - "redirectType": "main_frame", - "unsupportedUrls": "bypass", - "frontend": "priviblur", - "instance": "public" - }, - "imageType": "svg", - "embeddable": true, - "url": "https://tumblr.com" - }, - "twitch": { - "frontends": { - "safetwitch": { - "name": "SafeTwitch", - "embeddable": true, - "instanceList": true, - "url": "https://codeberg.org/dragongoose/safetwitch", - "localhost": false - }, - "twineo": { - "name": "Twineo", - "embeddable": true, - "instanceList": true, - "url": "https://codeberg.org/CloudyyUw/twineo", - "localhost": false - } - }, - "targets": [ - "^https?:\\/{2}(www\\.|clips\\.)?twitch\\.(tv|com)\\/" - ], - "name": "Twitch", - "options": { - "enabled": false, - "redirectType": "main_frame", - "unsupportedUrls": "bypass", - "frontend": "safetwitch", - "instance": "public" - }, - "imageType": "svg", - "embeddable": true, - "url": "https://twitch.tv" - }, - "tiktok": { - "frontends": { - "proxiTok": { - "name": "ProxiTok", - "instanceList": true, - "url": "https://github.com/pablouser1/ProxiTok", - "localhost": true - } - }, - "targets": [ - "^https?:\\/{2}(www\\.)?tiktok\\.com\\/" - ], - "name": "TikTok", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "proxiTok", - "instance": "public" - }, - "imageType": "png", - "url": "https://tiktok.com" - }, - "instagram": { - "frontends": { - "proxigram": { - "name": "Proxigram", - "instanceList": true, - "url": "https://codeberg.org/ThePenguinDev/Proxigram", - "localhost": false - } - }, - "targets": [ - "^https?:\\/{2}(www\\.)?instagram\\.com" - ], - "name": "Instagram", - "options": { - "enabled": false, - "frontend": "proxigram", - "unsupportedUrls": "bypass", - "instance": "public" - }, - "imageType": "png", - "url": "https://www.instagram.com" - }, - "imdb": { - "frontends": { - "libremdb": { - "name": "libremdb", - "instanceList": true, - "url": "https://github.com/zyachel/libremdb", - "localhost": true - } - }, - "targets": [ - "^https?:\\/{2}(www\\.|m\\.)?imdb\\.com" - ], - "name": "IMDb", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "libremdb", - "instance": "public" - }, - "imageType": "svg", - "url": "https://imdb.com" - }, - "bilibili": { - "frontends": { - "mikuInvidious": { - "name": "MikuInvidious", - "instanceList": true, - "url": "https://0xacab.org/johnxina/mikuinvidious" - } - }, - "targets": [ - "^https?:\\/{2}(www\\.|space\\.)?bilibili\\.com\\/", - "^https?:\\/{2}b23\\.tv\\/" - ], - "name": "Bilibili", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "mikuInvidious" - }, - "imageType": "svgMono", - "url": "https://bilibili.com/" - }, - "pixiv": { - "name": "Pixiv", - "frontends": { - "pixivFe": { - "name": "PixivFE", - "instanceList": true, - "url": "https://codeberg.org/VnPower/pixivfe" - } - }, - "targets": [ - "^https?:\\/{2}(www\\.)?pixiv\\.net\\/" - ], - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "pixivFe" - }, - "imageType": "svg", - "url": "https://www.pixiv.net" - }, - "fandom": { - "frontends": { - "breezeWiki": { - "name": "BreezeWiki", - "instanceList": true, - "url": "https://breezewiki.com" - } - }, - "targets": [ - "^https?:\\/{2}([a-zA-Z0-9-]+\\.)?(fandom|wikia)\\.com(?=\\/wiki|\\/?$)" - ], - "name": "Fandom", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "instance": "public", - "frontend": "breezeWiki" - }, - "imageType": "svg", - "url": "https://fandom.com" - }, - "imgur": { - "frontends": { - "rimgo": { - "name": "rimgo", - "instanceList": true, - "url": "https://codeberg.org/video-prize-ranch/rimgo", - "localhost": true, - "embeddable": true - } - }, - "targets": [ - "^https?:\\/{2}([im]\\.)?(stack\\.)?imgur\\.(com|io)\\/" - ], - "name": "Imgur", - "options": { - "enabled": false, - "redirectType": "main_frame", - "unsupportedUrls": "bypass", - "frontend": "rimgo", - "instance": "public" - }, - "imageType": "png", - "embeddable": true, - "url": "https://imgur.com" - }, - "pinterest": { - "name": "Pinterest", - "frontends": { - "binternet": { - "name": "Binternet", - "instanceList": true, - "url": "https://github.com/Ahwxorg/Binternet", - "embeddable": true - } - }, - "targets": [ - "^https?:\\/{2}i\\.pinimg\\.com", - "^https?:\\/{2}(www\\.)?pinterest\\.com" - ], - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "redirectType": "main_frame", - "frontend": "binternet" - }, - "imageType": "svg", - "embeddable": true, - "url": "https://pinterest.com" - }, - "soundcloud": { - "frontends": { - "tuboSoundcloud": { - "name": "Tubo", - "embeddable": false, - "instanceList": true, - "url": "https://git.migalmoreno.com/tubo/about/" - } - }, - "targets": [ - "^https?:\\/{2}soundcloud\\.com" - ], - "name": "SoundCloud", - "options": { - "enabled": false, - "redirectType": "main_frame", - "frontend": "tuboSoundcloud", - "unsupportedUrls": "bypass" - }, - "imageType": "svg", - "embeddable": false, - "url": "https://soundcloud.com" - }, - "bandcamp": { - "frontends": { - "tent": { - "name": "Tent", - "instanceList": true, - "url": "https://forgejo.sny.sh/sun/Tent" - } - }, - "targets": [ - "^https?:\\/{2}(.*\\.)?bandcamp\\.com\\/", - "^https?:\\/{2}(f4|t4)\\.bcbits\\.com\\/" - ], - "name": "Bandcamp", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "tent" - }, - "imageType": "svg", - "url": "https://bandcamp.com" - }, - "tekstowo": { - "frontends": { - "tekstoLibre": { - "name": "TekstoLibre", - "instanceList": true, - "url": "https://github.com/Davilarek/TekstoLibre" - } - }, - "targets": [ - "^https?:\\/{2}(www\\.)?tekstowo\\.pl\\/" - ], - "name": "Tekstowo.pl", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "tekstoLibre" - }, - "imageType": "svg", - "url": "https://www.tekstowo.pl" - }, - "genius": { - "frontends": { - "dumb": { - "name": "Dumb", - "instanceList": true, - "url": "https://github.com/rramiachraf/dumb", - "localhost": true - }, - "intellectual": { - "name": "Intellectual", - "instanceList": true, - "url": "https://github.com/Insprill/intellectual", - "localhost": false - } - }, - "targets": [ - "^https?:\\/{2}(www\\.)?genius\\.com\\/" - ], - "name": "Genius", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "dumb", - "instance": "public" - }, - "imageType": "svg", - "url": "https://genius.com" - }, - "medium": { - "frontends": { - "scribe": { - "name": "Scribe", - "instanceList": true, - "url": "https://sr.ht/~edwardloveall/Scribe" - }, - "libMedium": { - "name": "LibMedium", - "instanceList": true, - "url": "https://github.com/realaravinth/libmedium" - } - }, - "targets": [ - "^https:\\/{2}([a-zA-Z0-9-]+\\.)?medium\\.com", - "^https?:\\/{2}towardsdatascience\\.com\\/", - "^https?:\\/{2}uxdesign\\.cc\\/", - "^https?:\\/{2}uxplanet\\.org\\/", - "^https?:\\/{2}betterprogramming\\.pub\\/", - "^https?:\\/{2}aninjusticemag\\.com\\/", - "^https?:\\/{2}betterhumans\\.pub\\/", - "^https?:\\/{2}psiloveyou\\.xyz\\/", - "^https?:\\/{2}entrepreneurshandbook\\.co\\/", - "^https?:\\/{2}blog\\.coinbase\\.com\\/", - "^https?:\\/{2}levelup\\.gitconnected\\.com\\/", - "^https?:\\/{2}javascript\\.plainenglish\\.io\\/", - "^https?:\\/{2}blog\\.bitsrc\\.io\\/", - "^https?:\\/{2}itnext\\.io\\/", - "^https?:\\/{2}codeburst\\.io\\/", - "^https?:\\/{2}infosecwriteups\\.com\\/", - "^https?:\\/{2}blog\\.devgenius\\.io\\/", - "^https?:\\/{2}writingcooperative\\.com\\/", - "^https?:\\/{2}proandroiddev\\.com\\/" - ], - "name": "Medium", - "options": { - "frontend": "scribe", - "enabled": false, - "unsupportedUrls": "bypass" - }, - "imageType": "svg", - "url": "https://medium.com" - }, - "quora": { - "frontends": { - "quetre": { - "name": "Quetre", - "instanceList": true, - "url": "https://github.com/zyachel/quetre", - "localhost": true - } - }, - "targets": [ - "^https?:\\/{2}([a-zA-Z0-9-]+\\.)*quora\\.com\\/" - ], - "name": "Quora", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "quetre", - "instance": "public" - }, - "imageType": "png", - "url": "https://quora.com" - }, - "github": { - "frontends": { - "gothub": { - "name": "Gothub", - "instanceList": true, - "url": "https://codeberg.org/gothub/gothub" - } - }, - "targets": [ - "^https?:\\/{2}github\\.com\\/", - "^https?:\\/{2}gist\\.github\\.com\\/[^\\/]+\\/[^\\/]+\\/?", - "^https?:\\/{2}raw\\.githubusercontent\\.com\\/[^\\/]+\\/[^\\/]+\\/?" - ], - "name": "GitHub", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "gothub" - }, - "imageType": "svgMono", - "url": "https://github.com" - }, - "gitlab": { - "frontends": { - "laboratory": { - "name": "Laboratory", - "instanceList": true, - "url": "https://git.vitali64.duckdns.org/utils/laboratory.git/about/" - } - }, - "targets": [ - "^https?:\\/{2}gitlab\\.com\\/", - "^https?:\\/{2}gitlab\\.freedesktop\\.com\\/", - "^https?:\\/{2}gitlab\\.archlinux\\.com\\/" - ], - "name": "Gitlab", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "laboratory" - }, - "imageType": "svg", - "url": "https://gitlab.com/" - }, - "stackOverflow": { - "frontends": { - "anonymousOverflow": { - "name": "AnonymousOverflow", - "instanceList": true, - "url": "https://github.com/httpjamesm/AnonymousOverflow", - "localhost": true - } - }, - "targets": [ - "^https?:\\/{2}(www\\.)?([a-zA-Z]+\\.)?stackoverflow\\.com\\/", - "(?!^https?:\\/{2}(api|data|blog)\\.)^https?:\\/{2}([a-zA-Z0-9-]+\\.)stackexchange\\.com\\/", - "^https?:\\/{2}(www\\.)?([a-zA-Z]+\\.)?(askubuntu\\.com|mathoverflow\\.net|serverfault\\.com|stackapps\\.com|superuser\\.com)\\/" - ], - "name": "Stack Overflow", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "anonymousOverflow", - "instance": "public" - }, - "imageType": "svgMono", - "url": "https://stackoverflow.com/" - }, - "reuters": { - "frontends": { - "neuters": { - "name": "Neuters", - "instanceList": true, - "url": "https://github.com/HookedBehemoth/neuters" - } - }, - "targets": [ - "^https?:\\/{2}(www\\.)?reuters\\.com\\/" - ], - "name": "Reuters", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "neuters" - }, - "imageType": "svg", - "url": "https://reuters.com" - }, - "snopes": { - "frontends": { - "suds": { - "name": "Suds", - "instanceList": true, - "url": "https://git.vern.cc/cobra/Suds" - } - }, - "targets": [ - "^https?:\\/{2}(www\\.)?snopes\\.com\\/" - ], - "name": "Snopes", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "suds" - }, - "imageType": "svg", - "url": "https://www.snopes.com" - }, - "ifunny": { - "frontends": { - "unfunny": { - "name": "UNfunny", - "instanceList": true, - "url": "https://git.vern.cc/cobra/UNfunny" - } - }, - "targets": [ - "^https?:\\/{2}(www\\.)?ifunny\\.co\\/" - ], - "name": "iFunny", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "unfunny" - }, - "imageType": "svg", - "url": "https://ifunny.co" - }, - "tenor": { - "frontends": { - "soprano": { - "name": "Soprano", - "instanceList": true, - "url": "https://git.vern.cc/cobra/Soprano" - } - }, - "targets": [ - "^https?:\\/{2}(www\\.)?tenor\\.com\\/" - ], - "name": "Tenor", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "soprano" - }, - "imageType": "svg", - "url": "https://tenor.com" - }, - "knowyourmeme": { - "frontends": { - "meme": { - "name": "MeMe", - "instanceList": true, - "url": "https://git.vern.cc/cobra/MeMe" - } - }, - "targets": [ - "^https?:\\/{2}(www\\.)?knowyourmeme\\.com\\/" - ], - "name": "KnowYourMeme", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "meme" - }, - "imageType": "svg", - "url": "https://knowyourmeme.com" - }, - "urbanDictionary": { - "frontends": { - "ruralDictionary": { - "name": "Rural Dictionary", - "instanceList": true, - "url": "https://codeberg.org/zortazert/rural-dictionary" - } - }, - "targets": [ - "^https?:\\/{2}(www\\.)?urbandictionary\\.com\\/" - ], - "name": "Urban Dictionary", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "ruralDictionary" - }, - "imageType": "svg", - "url": "https://urbandictionary.com" - }, - "goodreads": { - "frontends": { - "biblioReads": { - "name": "BiblioReads", - "instanceList": true, - "url": "https://github.com/nesaku/BiblioReads", - "localhost": true - } - }, - "targets": [ - "^https?:\\/{2}(www\\.)?goodreads\\.com\\/" - ], - "name": "Goodreads", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "biblioReads", - "instance": "public" - }, - "imageType": "svgMono", - "url": "https://goodreads.com/" - }, - "wolframAlpha": { - "frontends": { - "wolfreeAlpha": { - "name": "WolfreeAlpha", - "instanceList": true, - "url": "https://git.disroot.org/wolfree" - } - }, - "targets": [ - "^https?:\\/{2}(www\\.)?wolframalpha\\.com\\/" - ], - "name": "Wolfram Alpha", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "wolfreeAlpha" - }, - "imageType": "svg", - "url": "https://www.wolframalpha.com" - }, - "instructables": { - "name": "Instructables", - "frontends": { - "indestructables": { - "name": "Indestructables", - "instanceList": true, - "url": "https://indestructables.codeberg.page" - }, - "destructables": { - "name": "Destructables", - "instanceList": true, - "url": "https://git.vern.cc/cobra/Destructables" - } - }, - "targets": [ - "^https?:\\/{2}(www\\.)?instructables\\.com\\/" - ], - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "indestructables" - }, - "imageType": "svg", - "url": "https://www.instructables.com" - }, - "wikipedia": { - "frontends": { - "wikiless": { - "name": "Wikiless", - "instanceList": true, - "url": "https://wikiless.org" - } - }, - "targets": [ - "^https?:\\/{2}([a-z]+\\.)*wikipedia\\.org\\/?" - ], - "name": "Wikipedia", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "wikiless" - }, - "imageType": "svg", - "url": "https://wikipedia.org" - }, - "waybackMachine": { - "frontends": { - "waybackClassic": { - "name": "Wayback Classic", - "instanceList": true, - "url": "https://github.com/ticky/wayback-classic" - } - }, - "targets": [ - "^https?:\\/{2}web\\.archive\\.org\\/" - ], - "name": "Wayback Machine", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "waybackClassic" - }, - "imageType": "svgMono", - "url": "https://web.archive.org" - }, - "search": { - "frontends": { - "searxng": { - "name": "SearXNG", - "instanceList": true, - "url": "https://github.com/searxng/searxng", - "localhost": true - }, - "searx": { - "name": "SearX", - "instanceList": true, - "url": "https://searx.github.io/searx/" - }, - "whoogle": { - "name": "Whoogle", - "instanceList": true, - "url": "https://benbusby.com/projects/whoogle-search/" - }, - "librey": { - "name": "LibreY", - "instanceList": true, - "url": "https://github.com/Ahwxorg/librey/" - }, - "4get": { - "name": "4get", - "instanceList": true, - "url": "https://git.lolcat.ca/lolcat/4get" - } - }, - "targets": [ - "^https?:\\/{2}search\\.libredirect\\.invalid", - "^https?:\\/{2}libredirect\\.github\\.io\\/\\?q" - ], - "name": "Search", - "options": { - "enabled": false, - "frontend": "searxng", - "unsupportedUrls": "bypass", - "instance": "public" - }, - "imageType": "svgMono", - "url": "https://search.libredirect.invalid" - }, - "translate": { - "frontends": { - "simplyTranslate": { - "name": "SimplyTranslate", - "instanceList": true, - "url": "https://git.sr.ht/~metalune/simplytranslate_web", - "localhost": true - }, - "mozhi": { - "name": "Mozhi", - "instanceList": true, - "url": "https://codeberg.org/aryak/mozhi", - "localhost": false - }, - "libreTranslate": { - "name": "LibreTranslate", - "instanceList": true, - "url": "https://github.com/LibreTranslate/LibreTranslate" - } - }, - "targets": [ - "^https?:\\/{2}translate\\.google(\\.[a-z]{2,3}){1,2}\\/", - "^https?:\\/{2}translate\\.libredirect\\.invalid" - ], - "name": "Translate", - "options": { - "enabled": false, - "frontend": "simplyTranslate", - "unsupportedUrls": "bypass", - "instance": "public" - }, - "imageType": "svgMono", - "url": "https://translate.libredirect.invalid" - }, - "maps": { - "frontends": { - "osm": { - "name": "OpenStreetMap", - "instanceList": true, - "embeddable": true, - "url": "https://www.openstreetmap.org/" - } - }, - "targets": [ - "^https?:\\/{2}maps\\.libredirect\\.invalid", - "^https?:\\/{2}(((www|maps)\\.)?(google\\.).*(\\/maps)|maps\\.(google\\.).*)" - ], - "name": "Maps", - "options": { - "redirectType": "main_frame", - "enabled": false, - "frontend": "osm", - "unsupportedUrls": "bypass" - }, - "imageType": "svgMono", - "url": "https://maps.libredirect.invalid" - }, - "meet": { - "name": "Meet", - "frontends": { - "jitsi": { - "name": "Jitsi", - "instanceList": true, - "url": "https://jitsi.org" - } - }, - "targets": [ - "^https?:\\/{2}meet\\.libredirect\\.invalid\\/" - ], - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "jitsi" - }, - "imageType": "svgMono", - "url": "https://meet.libredirect.invalid" - }, - "sendFiles": { - "frontends": { - "send": { - "name": "Send", - "instanceList": true, - "url": "https://gitlab.com/timvisee/send" - } - }, - "targets": [ - "^https?:\\/{2}send\\.libredirect\\.invalid", - "^https?:\\/{2}send\\.firefox\\.com\\/?$", - "^https?:\\/{2}sendfiles\\.online\\/?$" - ], - "name": "Send Files", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "send" - }, - "imageType": "svgMono", - "url": "https://send.libredirect.invalid" - }, - "textStorage": { - "frontends": { - "privateBin": { - "name": "PrivateBin", - "instanceList": true, - "url": "https://privatebin.info" - }, - "pasted": { - "name": "Pasted", - "instanceList": true, - "url": "https://github.com/Dragynfruit/pasted" - } - }, - "targets": [ - "^https?:\\/{2}paste\\.libredirect\\.invalid" - ], - "name": "Paste Text", - "options": { - "enabled": false, - "unsupportedUrls": "bypass", - "frontend": "privateBin" - }, - "imageType": "svgMono", - "url": "https://paste.libredirect.invalid" - } - } -} \ No newline at end of file + "networks": { + "clearnet": { + "tld": "org", + "name": "Clearnet" + }, + "tor": { + "tld": "onion", + "name": "Tor" + }, + "i2p": { + "tld": "i2p", + "name": "I2P" + }, + "loki": { + "tld": "loki", + "name": "Lokinet" + } + }, + "services": { + "youtube": { + "frontends": { + "invidious": { + "name": "Invidious", + "embeddable": true, + "instanceList": true, + "url": "https://invidious.io/" + }, + "materialious": { + "name": "Materialious", + "embeddable": true, + "instanceList": true, + "url": "https://materialio.us/" + }, + "piped": { + "excludeTargets": [2, 3], + "name": "Piped", + "embeddable": true, + "instanceList": true, + "url": "https://github.com/TeamPiped/Piped" + }, + "pipedMaterial": { + "excludeTargets": [2, 3], + "name": "Piped-Material", + "embeddable": false, + "instanceList": true, + "url": "https://github.com/mmjee/Piped-Material" + }, + "poketube": { + "excludeTargets": [2, 3], + "name": "PokeTube", + "embeddable": true, + "instanceList": true, + "url": "https://codeberg.org/Ashley/poketube" + }, + "cloudtube": { + "name": "CloudTube", + "embeddable": false, + "instanceList": true, + "url": "https://sr.ht/~cadence/tube", + "excludeTargets": [2, 3] + }, + "lightTube": { + "name": "LightTube", + "embeddable": false, + "instanceList": true, + "url": "https://github.com/lighttube-org/LightTube" + }, + "tuboYoutube": { + "name": "Tubo", + "embeddable": false, + "instanceList": true, + "url": "https://git.migalmoreno.com/tubo/about/", + "excludeTargets": [2, 3] + }, + "freetube": { + "excludeTargets": [2, 3], + "name": "FreeTube", + "embeddable": false, + "desktopApp": true, + "instanceList": false, + "url": "https://github.com/FreeTubeApp/FreeTube" + }, + "yattee": { + "excludeTargets": [2, 3], + "name": "Yattee", + "embeddable": false, + "desktopApp": true, + "instanceList": false, + "url": "https://github.com/yattee/yattee" + }, + "freetubePwa": { + "excludeTargets": [2, 3], + "name": "FreeTube PWA", + "embeddable": false, + "instanceList": false, + "url": "https://github.com/MarmadileManteater/FreeTubeCordova" + }, + "viewtube": { + "name": "ViewTube", + "embeddable": false, + "instanceList": true, + "url": "https://github.com/ViewTube/viewtube" + } + }, + "targets": [ + "^https?:\\/{2}(www\\.|m\\.)?youtube.com(\\/|$)(?!iframe_api\\/|redirect\\/)", + "^https?:\\/{2}img\\.youtube.com\\/vi\\/.*\\/..*", + "^https?:\\/{2}(i|s)\\.ytimg.com\\/vi\\/.*\\/..*", + "^https?:\\/{2}(www\\.)?youtube.com\\/watch?v=..*", + "^https?:\\/{2}(www\\.)?youtu\\.be\\/..*", + "^https?:\\/{2}(www\\.)?(youtube|youtube-nocookie)\\.com\\/embed\\/..*" + ], + "name": "YouTube", + "options": { + "enabled": false, + "redirectType": "main_frame", + "frontend": "invidious", + "embedFrontend": "invidious", + "unsupportedUrls": "bypass" + }, + "imageType": "png", + "embeddable": true, + "url": "https://youtube.com" + }, + "youtubeMusic": { + "frontends": { + "hyperpipe": { + "name": "Hyperpipe", + "instanceList": true, + "url": "https://codeberg.org/Hyperpipe/Hyperpipe" + }, + "invidiousMusic": { + "name": "Invidious", + "embeddable": true, + "instanceList": true, + "url": "https://invidious.io/" + }, + "freetubeMusic": { + "name": "FreeTube", + "embeddable": false, + "desktopApp": true, + "instanceList": false, + "url": "https://github.com/FreeTubeApp/FreeTube" + } + }, + "targets": ["^https?:\\/{2}music\\.youtube\\.com\\/"], + "name": "YT Music", + "options": { + "enabled": false, + "frontend": "hyperpipe", + "unsupportedUrls": "bypass" + }, + "imageType": "png", + "url": "https://music.youtube.com" + }, + "twitter": { + "frontends": { + "nitter": { + "name": "Nitter", + "embeddable": true, + "instanceList": true, + "url": "https://github.com/zedeus/nitter", + "localhost": true + } + }, + "targets": [ + "^https?:\\/{2}(www\\.|mobile\\.)?twitter\\.com\\/", + "^https?:\\/{2}(www\\.|mobile\\.)?x\\.com\\/", + "^https?:\\/{2}(pbs\\.|video\\.)twimg\\.com\\/", + "^https?:\\/{2}platform\\.x\\.com/embed\\/", + "^https?:\\/{2}platform\\.twitter\\.com/embed\\/", + "^https?:\\/{2}t\\.co\\/" + ], + "name": "Twitter", + "options": { + "enabled": false, + "redirectType": "main_frame", + "unsupportedUrls": "bypass", + "frontend": "nitter", + "instance": "public" + }, + "imageType": "png", + "embeddable": true, + "url": "https://twitter.com" + }, + "bluesky": { + "frontends": { + "skyview": { + "name": "Skyview", + "instanceList": true, + "url": "https://github.com/badlogic/skyview" + } + }, + "targets": ["^https?:\\/{2}bsky\\.app\\/"], + "name": "Bluesky", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "skyview" + }, + "imageType": "svg", + "url": "https://bsky.app/" + }, + "reddit": { + "frontends": { + "libreddit": { + "name": "Libreddit", + "instanceList": true, + "url": "https://github.com/spikecodes/libreddit", + "localhost": true + }, + "redlib": { + "name": "Redlib", + "instanceList": true, + "url": "https://github.com/redlib-org/redlib", + "localhost": true + }, + "teddit": { + "name": "Teddit", + "instanceList": true, + "url": "https://codeberg.org/teddit/teddit", + "localhost": true + } + }, + "targets": [ + "^https?:\\/{2}(www\\.|old\\.|np\\.|new\\.|amp\\.)?(reddit|reddittorjg6rue252oqsxryoxengawnmo46qy4kyii5wtqnwfj4ooad)\\.(com|onion)(?=\\/u(ser)?\\/|\\/r\\/|\\/search|\\/new|\\/?$)", + "^https?:\\/{2}(i|(external-)?preview)\\.redd\\.it" + ], + "name": "Reddit", + "options": { + "enabled": false, + "frontend": "libreddit", + "unsupportedUrls": "bypass", + "instance": "public" + }, + "imageType": "png", + "url": "https://reddit.com" + }, + "tumblr": { + "frontends": { + "priviblur": { + "name": "Priviblur", + "embeddable": true, + "instanceList": true, + "url": "https://github.com/syeopite/priviblur", + "localhost": true + } + }, + "targets": [ + "^https?:\\/{2}(media\\.|assets\\.|static\\.)?tumblr\\.com\\/", + "^https?:\\/{2}[0-9]+\\.media\\.tumblr\\.com\\/", + "^https?:\\/{2}(www\\.)?(.*)\\.tumblr.com\\/" + ], + "name": "Tumblr", + "options": { + "enabled": false, + "redirectType": "main_frame", + "unsupportedUrls": "bypass", + "frontend": "priviblur", + "instance": "public" + }, + "imageType": "svg", + "embeddable": true, + "url": "https://tumblr.com" + }, + "twitch": { + "frontends": { + "safetwitch": { + "name": "SafeTwitch", + "embeddable": true, + "instanceList": true, + "url": "https://codeberg.org/dragongoose/safetwitch", + "localhost": false + }, + "twineo": { + "name": "Twineo", + "embeddable": true, + "instanceList": true, + "url": "https://codeberg.org/CloudyyUw/twineo", + "localhost": false + } + }, + "targets": ["^https?:\\/{2}(www\\.|clips\\.)?twitch\\.(tv|com)\\/"], + "name": "Twitch", + "options": { + "enabled": false, + "redirectType": "main_frame", + "unsupportedUrls": "bypass", + "frontend": "safetwitch", + "instance": "public" + }, + "imageType": "svg", + "embeddable": true, + "url": "https://twitch.tv" + }, + "tiktok": { + "frontends": { + "proxiTok": { + "name": "ProxiTok", + "instanceList": true, + "url": "https://github.com/pablouser1/ProxiTok", + "localhost": true + } + }, + "targets": ["^https?:\\/{2}(www\\.)?tiktok\\.com\\/"], + "name": "TikTok", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "proxiTok", + "instance": "public" + }, + "imageType": "png", + "url": "https://tiktok.com" + }, + "instagram": { + "frontends": { + "proxigram": { + "name": "Proxigram", + "instanceList": true, + "url": "https://codeberg.org/ThePenguinDev/Proxigram", + "localhost": false + } + }, + "targets": ["^https?:\\/{2}(www\\.)?instagram\\.com"], + "name": "Instagram", + "options": { + "enabled": false, + "frontend": "proxigram", + "unsupportedUrls": "bypass", + "instance": "public" + }, + "imageType": "png", + "url": "https://www.instagram.com" + }, + "imdb": { + "frontends": { + "libremdb": { + "name": "libremdb", + "instanceList": true, + "url": "https://github.com/zyachel/libremdb", + "localhost": true + } + }, + "targets": ["^https?:\\/{2}(www\\.|m\\.)?imdb\\.com"], + "name": "IMDb", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "libremdb", + "instance": "public" + }, + "imageType": "svg", + "url": "https://imdb.com" + }, + "bilibili": { + "frontends": { + "mikuInvidious": { + "name": "MikuInvidious", + "instanceList": true, + "url": "https://0xacab.org/johnxina/mikuinvidious" + } + }, + "targets": ["^https?:\\/{2}(www\\.|space\\.)?bilibili\\.com\\/", "^https?:\\/{2}b23\\.tv\\/"], + "name": "Bilibili", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "mikuInvidious" + }, + "imageType": "svgMono", + "url": "https://bilibili.com/" + }, + "pixiv": { + "name": "Pixiv", + "frontends": { + "pixivFe": { + "name": "PixivFE", + "instanceList": true, + "url": "https://codeberg.org/VnPower/pixivfe" + } + }, + "targets": ["^https?:\\/{2}(www\\.)?pixiv\\.net\\/"], + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "pixivFe" + }, + "imageType": "svg", + "url": "https://www.pixiv.net" + }, + "fandom": { + "frontends": { + "breezeWiki": { + "name": "BreezeWiki", + "instanceList": true, + "url": "https://breezewiki.com" + } + }, + "targets": ["^https?:\\/{2}([a-zA-Z0-9-]+\\.)?(fandom|wikia)\\.com(?=\\/wiki|\\/?$)"], + "name": "Fandom", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "instance": "public", + "frontend": "breezeWiki" + }, + "imageType": "svg", + "url": "https://fandom.com" + }, + "imgur": { + "frontends": { + "rimgo": { + "name": "rimgo", + "instanceList": true, + "url": "https://codeberg.org/video-prize-ranch/rimgo", + "localhost": true, + "embeddable": true + } + }, + "targets": ["^https?:\\/{2}([im]\\.)?(stack\\.)?imgur\\.(com|io)\\/"], + "name": "Imgur", + "options": { + "enabled": false, + "redirectType": "main_frame", + "unsupportedUrls": "bypass", + "frontend": "rimgo", + "instance": "public" + }, + "imageType": "png", + "embeddable": true, + "url": "https://imgur.com" + }, + "pinterest": { + "name": "Pinterest", + "frontends": { + "binternet": { + "name": "Binternet", + "instanceList": true, + "url": "https://github.com/Ahwxorg/Binternet", + "embeddable": true + } + }, + "targets": ["^https?:\\/{2}i\\.pinimg\\.com", "^https?:\\/{2}(www\\.)?pinterest\\.com"], + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "redirectType": "main_frame", + "frontend": "binternet" + }, + "imageType": "svg", + "embeddable": true, + "url": "https://pinterest.com" + }, + "soundcloud": { + "frontends": { + "tuboSoundcloud": { + "name": "Tubo", + "embeddable": false, + "instanceList": true, + "url": "https://git.migalmoreno.com/tubo/about/" + } + }, + "targets": ["^https?:\\/{2}soundcloud\\.com"], + "name": "SoundCloud", + "options": { + "enabled": false, + "redirectType": "main_frame", + "frontend": "tuboSoundcloud", + "unsupportedUrls": "bypass" + }, + "imageType": "svg", + "embeddable": false, + "url": "https://soundcloud.com" + }, + "bandcamp": { + "frontends": { + "tent": { + "name": "Tent", + "instanceList": true, + "url": "https://forgejo.sny.sh/sun/Tent" + } + }, + "targets": ["^https?:\\/{2}(.*\\.)?bandcamp\\.com\\/", "^https?:\\/{2}(f4|t4)\\.bcbits\\.com\\/"], + "name": "Bandcamp", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "tent" + }, + "imageType": "svg", + "url": "https://bandcamp.com" + }, + "tekstowo": { + "frontends": { + "tekstoLibre": { + "name": "TekstoLibre", + "instanceList": true, + "url": "https://github.com/Davilarek/TekstoLibre" + } + }, + "targets": ["^https?:\\/{2}(www\\.)?tekstowo\\.pl\\/"], + "name": "Tekstowo.pl", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "tekstoLibre" + }, + "imageType": "svg", + "url": "https://www.tekstowo.pl" + }, + "genius": { + "frontends": { + "dumb": { + "name": "Dumb", + "instanceList": true, + "url": "https://github.com/rramiachraf/dumb", + "localhost": true + }, + "intellectual": { + "name": "Intellectual", + "instanceList": true, + "url": "https://github.com/Insprill/intellectual", + "localhost": false + } + }, + "targets": ["^https?:\\/{2}(www\\.)?genius\\.com\\/"], + "name": "Genius", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "dumb", + "instance": "public" + }, + "imageType": "svg", + "url": "https://genius.com" + }, + "medium": { + "frontends": { + "scribe": { + "name": "Scribe", + "instanceList": true, + "url": "https://sr.ht/~edwardloveall/Scribe" + }, + "libMedium": { + "name": "LibMedium", + "instanceList": true, + "url": "https://github.com/realaravinth/libmedium" + } + }, + "targets": [ + "^https:\\/{2}([a-zA-Z0-9-]+\\.)?medium\\.com", + "^https?:\\/{2}towardsdatascience\\.com\\/", + "^https?:\\/{2}uxdesign\\.cc\\/", + "^https?:\\/{2}uxplanet\\.org\\/", + "^https?:\\/{2}betterprogramming\\.pub\\/", + "^https?:\\/{2}aninjusticemag\\.com\\/", + "^https?:\\/{2}betterhumans\\.pub\\/", + "^https?:\\/{2}psiloveyou\\.xyz\\/", + "^https?:\\/{2}entrepreneurshandbook\\.co\\/", + "^https?:\\/{2}blog\\.coinbase\\.com\\/", + "^https?:\\/{2}levelup\\.gitconnected\\.com\\/", + "^https?:\\/{2}javascript\\.plainenglish\\.io\\/", + "^https?:\\/{2}blog\\.bitsrc\\.io\\/", + "^https?:\\/{2}itnext\\.io\\/", + "^https?:\\/{2}codeburst\\.io\\/", + "^https?:\\/{2}infosecwriteups\\.com\\/", + "^https?:\\/{2}blog\\.devgenius\\.io\\/", + "^https?:\\/{2}writingcooperative\\.com\\/", + "^https?:\\/{2}proandroiddev\\.com\\/" + ], + "name": "Medium", + "options": { + "frontend": "scribe", + "enabled": false, + "unsupportedUrls": "bypass" + }, + "imageType": "svg", + "url": "https://medium.com" + }, + "quora": { + "frontends": { + "quetre": { + "name": "Quetre", + "instanceList": true, + "url": "https://github.com/zyachel/quetre", + "localhost": true + } + }, + "targets": ["^https?:\\/{2}([a-zA-Z0-9-]+\\.)*quora\\.com\\/"], + "name": "Quora", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "quetre", + "instance": "public" + }, + "imageType": "png", + "url": "https://quora.com" + }, + "github": { + "frontends": { + "gothub": { + "name": "Gothub", + "instanceList": true, + "url": "https://codeberg.org/gothub/gothub" + } + }, + "targets": [ + "^https?:\\/{2}github\\.com\\/", + "^https?:\\/{2}gist\\.github\\.com\\/[^\\/]+\\/[^\\/]+\\/?", + "^https?:\\/{2}raw\\.githubusercontent\\.com\\/[^\\/]+\\/[^\\/]+\\/?" + ], + "name": "GitHub", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "gothub" + }, + "imageType": "svgMono", + "url": "https://github.com" + }, + "gitlab": { + "frontends": { + "laboratory": { + "name": "Laboratory", + "instanceList": true, + "url": "https://git.vitali64.duckdns.org/utils/laboratory.git/about/" + } + }, + "targets": [ + "^https?:\\/{2}gitlab\\.com\\/", + "^https?:\\/{2}gitlab\\.freedesktop\\.com\\/", + "^https?:\\/{2}gitlab\\.archlinux\\.com\\/" + ], + "name": "Gitlab", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "laboratory" + }, + "imageType": "svg", + "url": "https://gitlab.com/" + }, + "stackOverflow": { + "frontends": { + "anonymousOverflow": { + "name": "AnonymousOverflow", + "instanceList": true, + "url": "https://github.com/httpjamesm/AnonymousOverflow", + "localhost": true + } + }, + "targets": [ + "^https?:\\/{2}(www\\.)?([a-zA-Z]+\\.)?stackoverflow\\.com\\/", + "(?!^https?:\\/{2}(api|data|blog)\\.)^https?:\\/{2}([a-zA-Z0-9-]+\\.)stackexchange\\.com\\/", + "^https?:\\/{2}(www\\.)?([a-zA-Z]+\\.)?(askubuntu\\.com|mathoverflow\\.net|serverfault\\.com|stackapps\\.com|superuser\\.com)\\/" + ], + "name": "Stack Overflow", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "anonymousOverflow", + "instance": "public" + }, + "imageType": "svgMono", + "url": "https://stackoverflow.com/" + }, + "reuters": { + "frontends": { + "neuters": { + "name": "Neuters", + "instanceList": true, + "url": "https://github.com/HookedBehemoth/neuters" + } + }, + "targets": ["^https?:\\/{2}(www\\.)?reuters\\.com\\/"], + "name": "Reuters", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "neuters" + }, + "imageType": "svg", + "url": "https://reuters.com" + }, + "snopes": { + "frontends": { + "suds": { + "name": "Suds", + "instanceList": true, + "url": "https://git.vern.cc/cobra/Suds" + } + }, + "targets": ["^https?:\\/{2}(www\\.)?snopes\\.com\\/"], + "name": "Snopes", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "suds" + }, + "imageType": "svg", + "url": "https://www.snopes.com" + }, + "ifunny": { + "frontends": { + "unfunny": { + "name": "UNfunny", + "instanceList": true, + "url": "https://git.vern.cc/cobra/UNfunny" + } + }, + "targets": ["^https?:\\/{2}(www\\.)?ifunny\\.co\\/"], + "name": "iFunny", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "unfunny" + }, + "imageType": "svg", + "url": "https://ifunny.co" + }, + "tenor": { + "frontends": { + "soprano": { + "name": "Soprano", + "instanceList": true, + "url": "https://git.vern.cc/cobra/Soprano" + } + }, + "targets": ["^https?:\\/{2}(www\\.)?tenor\\.com\\/"], + "name": "Tenor", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "soprano" + }, + "imageType": "svg", + "url": "https://tenor.com" + }, + "knowyourmeme": { + "frontends": { + "meme": { + "name": "MeMe", + "instanceList": true, + "url": "https://git.vern.cc/cobra/MeMe" + } + }, + "targets": ["^https?:\\/{2}(www\\.)?knowyourmeme\\.com\\/"], + "name": "KnowYourMeme", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "meme" + }, + "imageType": "svg", + "url": "https://knowyourmeme.com" + }, + "urbanDictionary": { + "frontends": { + "ruralDictionary": { + "name": "Rural Dictionary", + "instanceList": true, + "url": "https://codeberg.org/zortazert/rural-dictionary" + } + }, + "targets": ["^https?:\\/{2}(www\\.)?urbandictionary\\.com\\/"], + "name": "Urban Dictionary", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "ruralDictionary" + }, + "imageType": "svg", + "url": "https://urbandictionary.com" + }, + "goodreads": { + "frontends": { + "biblioReads": { + "name": "BiblioReads", + "instanceList": true, + "url": "https://github.com/nesaku/BiblioReads", + "localhost": true + } + }, + "targets": ["^https?:\\/{2}(www\\.)?goodreads\\.com\\/"], + "name": "Goodreads", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "biblioReads", + "instance": "public" + }, + "imageType": "svgMono", + "url": "https://goodreads.com/" + }, + "wolframAlpha": { + "frontends": { + "wolfreeAlpha": { + "name": "WolfreeAlpha", + "instanceList": true, + "url": "https://git.disroot.org/wolfree" + } + }, + "targets": ["^https?:\\/{2}(www\\.)?wolframalpha\\.com\\/"], + "name": "Wolfram Alpha", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "wolfreeAlpha" + }, + "imageType": "svg", + "url": "https://www.wolframalpha.com" + }, + "instructables": { + "name": "Instructables", + "frontends": { + "indestructables": { + "name": "Indestructables", + "instanceList": true, + "url": "https://indestructables.codeberg.page" + }, + "destructables": { + "name": "Destructables", + "instanceList": true, + "url": "https://git.vern.cc/cobra/Destructables" + } + }, + "targets": ["^https?:\\/{2}(www\\.)?instructables\\.com\\/"], + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "indestructables" + }, + "imageType": "svg", + "url": "https://www.instructables.com" + }, + "wikipedia": { + "frontends": { + "wikiless": { + "name": "Wikiless", + "instanceList": true, + "url": "https://wikiless.org" + } + }, + "targets": ["^https?:\\/{2}([a-z]+\\.)*wikipedia\\.org\\/?"], + "name": "Wikipedia", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "wikiless" + }, + "imageType": "svg", + "url": "https://wikipedia.org" + }, + "waybackMachine": { + "frontends": { + "waybackClassic": { + "name": "Wayback Classic", + "instanceList": true, + "url": "https://github.com/ticky/wayback-classic" + } + }, + "targets": ["^https?:\\/{2}web\\.archive\\.org\\/"], + "name": "Wayback Machine", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "waybackClassic" + }, + "imageType": "svgMono", + "url": "https://web.archive.org" + }, + "search": { + "frontends": { + "searxng": { + "name": "SearXNG", + "instanceList": true, + "url": "https://github.com/searxng/searxng", + "localhost": true + }, + "searx": { + "name": "SearX", + "instanceList": true, + "url": "https://searx.github.io/searx/" + }, + "whoogle": { + "name": "Whoogle", + "instanceList": true, + "url": "https://benbusby.com/projects/whoogle-search/" + }, + "librey": { + "name": "LibreY", + "instanceList": true, + "url": "https://github.com/Ahwxorg/librey/" + }, + "4get": { + "name": "4get", + "instanceList": true, + "url": "https://git.lolcat.ca/lolcat/4get" + } + }, + "targets": ["^https?:\\/{2}search\\.libredirect\\.invalid", "^https?:\\/{2}libredirect\\.github\\.io\\/\\?q"], + "name": "Search", + "options": { + "enabled": false, + "frontend": "searxng", + "unsupportedUrls": "bypass", + "instance": "public" + }, + "imageType": "svgMono", + "url": "https://search.libredirect.invalid" + }, + "translate": { + "frontends": { + "simplyTranslate": { + "name": "SimplyTranslate", + "instanceList": true, + "url": "https://git.sr.ht/~metalune/simplytranslate_web", + "localhost": true + }, + "mozhi": { + "name": "Mozhi", + "instanceList": true, + "url": "https://codeberg.org/aryak/mozhi", + "localhost": false + }, + "libreTranslate": { + "name": "LibreTranslate", + "instanceList": true, + "url": "https://github.com/LibreTranslate/LibreTranslate" + } + }, + "targets": [ + "^https?:\\/{2}translate\\.google(\\.[a-z]{2,3}){1,2}\\/", + "^https?:\\/{2}translate\\.libredirect\\.invalid" + ], + "name": "Translate", + "options": { + "enabled": false, + "frontend": "simplyTranslate", + "unsupportedUrls": "bypass", + "instance": "public" + }, + "imageType": "svgMono", + "url": "https://translate.libredirect.invalid" + }, + "maps": { + "frontends": { + "osm": { + "name": "OpenStreetMap", + "instanceList": true, + "embeddable": true, + "url": "https://www.openstreetmap.org/" + } + }, + "targets": [ + "^https?:\\/{2}maps\\.libredirect\\.invalid", + "^https?:\\/{2}(((www|maps)\\.)?(google\\.).*(\\/maps)|maps\\.(google\\.).*)" + ], + "name": "Maps", + "options": { + "redirectType": "main_frame", + "enabled": false, + "frontend": "osm", + "unsupportedUrls": "bypass" + }, + "imageType": "svgMono", + "url": "https://maps.libredirect.invalid" + }, + "meet": { + "name": "Meet", + "frontends": { + "jitsi": { + "name": "Jitsi", + "instanceList": true, + "url": "https://jitsi.org" + } + }, + "targets": ["^https?:\\/{2}meet\\.libredirect\\.invalid\\/"], + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "jitsi" + }, + "imageType": "svgMono", + "url": "https://meet.libredirect.invalid" + }, + "sendFiles": { + "frontends": { + "send": { + "name": "Send", + "instanceList": true, + "url": "https://gitlab.com/timvisee/send" + } + }, + "targets": [ + "^https?:\\/{2}send\\.libredirect\\.invalid", + "^https?:\\/{2}send\\.firefox\\.com\\/?$", + "^https?:\\/{2}sendfiles\\.online\\/?$" + ], + "name": "Send Files", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "send" + }, + "imageType": "svgMono", + "url": "https://send.libredirect.invalid" + }, + "textStorage": { + "frontends": { + "privateBin": { + "name": "PrivateBin", + "instanceList": true, + "url": "https://privatebin.info" + }, + "pasted": { + "name": "Pasted", + "instanceList": true, + "url": "https://github.com/Dragynfruit/pasted" + } + }, + "targets": ["^https?:\\/{2}paste\\.libredirect\\.invalid"], + "name": "Paste Text", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "privateBin" + }, + "imageType": "svgMono", + "url": "https://paste.libredirect.invalid" + } + } +} diff --git a/src/manifest.json b/src/manifest.json index cab3181b..cf763247 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,91 +1,82 @@ { - "name": "__MSG_extensionName__", - "description": "__MSG_extensionDescription__", - "version": "2.8.5", - "manifest_version": 2, - "browser_specific_settings": { - "gecko": { - "id": "7esoorv3@alefvanoon.anonaddy.me", - "strict_min_version": "89.0" - }, - "gecko_android": { - "strict_min_version": "113.0" - } - }, - "background": { - "page": "pages/background/background.html", - "persistent": true - }, - "icons": { - "16": "assets/images/libredirect-16.png", - "32": "assets/images/libredirect-32.png", - "48": "assets/images/libredirect-48.png", - "128": "assets/images/libredirect-128.png" - }, - "permissions": [ - "webRequest", - "webRequestBlocking", - "storage", - "clipboardWrite", - "contextMenus", - "" - ], - "optional_permissions": [ - "bookmarks" - ], - "browser_action": { - "default_title": "__MSG_extensionName__", - "browser_style": false, - "default_popup": "pages/popup/popup.html", - "default_icon": { - "16": "assets/images/libredirect-16.png", - "32": "assets/images/libredirect-32.png", - "48": "assets/images/libredirect-48.png", - "128": "assets/images/libredirect-128.png" - } - }, - "options_ui": { - "page": "pages/options/index.html", - "browser_style": false, - "open_in_tab": true - }, - "chrome_settings_overrides": { - "search_provider": { - "name": "__MSG_extensionName__", - "keyword": "@libredirect", - "favicon_url": "https://raw.githubusercontent.com/libredirect/libredirect/master/src/assets/images/libredirect-16.png", - "search_url": "https://search.libredirect.invalid/?q={searchTerms}", - "encoding": "UTF-8", - "is_default": false - } - }, - "commands": { - "switchInstance": { - "suggested_key": { - "default": "Alt+Shift+L" - }, - "description": "__MSG_switchInstance__" - }, - "copyRaw": { - "suggested_key": { - "default": "Alt+Shift+C" - }, - "description": "Copies the original link. Ex: Copies the original twitter link while in the nitter website" - }, - "reverse": { - "suggested_key": { - "default": "Alt+Shift+O" - }, - "description": "Redirect to the original link. Ex: Redirects to the original twitter link while in the nitter website" - }, - "redirect": { - "suggested_key": { - "default": "Alt+Shift+R" - }, - "description": "Redirect link. Ex: Redirects original twitter link to nitter" - } - }, - "default_locale": "en", - "update_url": "https://raw.githubusercontent.com/libredirect/libredirect/master/src/updates/updates.xml", - "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAroWDSoSRZ1scj+eJRrvnhJbrqXTKnhQuxs6+AJg16sqr0bsMdFV+MSY4i4xnK+K5WOYkBliWXgUyk/wzicoAjOnSJddrL/Md4FuWHI2NVIkrlsLOrYkygi5OLqGPajRH/w8Cdmg7KzEpXe/OnYV0/qS8li8huEdTzdeLdhfbiVl1j3DOr4OJALQ7mPeeNFHFo/oVQ+OkSezWLezA5jUGfhtzPYV6u1TXzX7lCi8E/BbDbwkvvXOMcjXCv08kjdLOY2djCA2a6zr0xAb3q8DlexAMZ8vMof7AQRFtBKhLc9n9VFoipMMdBOVQQj/eIcRILBrmkcZNnJxFKiHNJ+NcZQIDAQAB" -} \ No newline at end of file + "name": "__MSG_extensionName__", + "description": "__MSG_extensionDescription__", + "version": "2.8.5", + "manifest_version": 2, + "browser_specific_settings": { + "gecko": { + "id": "7esoorv3@alefvanoon.anonaddy.me", + "strict_min_version": "89.0" + }, + "gecko_android": { + "strict_min_version": "113.0" + } + }, + "background": { + "page": "pages/background/background.html", + "persistent": true + }, + "icons": { + "16": "assets/images/libredirect-16.png", + "32": "assets/images/libredirect-32.png", + "48": "assets/images/libredirect-48.png", + "128": "assets/images/libredirect-128.png" + }, + "permissions": ["webRequest", "webRequestBlocking", "storage", "clipboardWrite", "contextMenus", ""], + "optional_permissions": ["bookmarks"], + "browser_action": { + "default_title": "__MSG_extensionName__", + "browser_style": false, + "default_popup": "pages/popup/popup.html", + "default_icon": { + "16": "assets/images/libredirect-16.png", + "32": "assets/images/libredirect-32.png", + "48": "assets/images/libredirect-48.png", + "128": "assets/images/libredirect-128.png" + } + }, + "options_ui": { + "page": "pages/options/index.html", + "browser_style": false, + "open_in_tab": true + }, + "chrome_settings_overrides": { + "search_provider": { + "name": "__MSG_extensionName__", + "keyword": "@libredirect", + "favicon_url": "https://raw.githubusercontent.com/libredirect/libredirect/master/src/assets/images/libredirect-16.png", + "search_url": "https://search.libredirect.invalid/?q={searchTerms}", + "encoding": "UTF-8", + "is_default": false + } + }, + "commands": { + "switchInstance": { + "suggested_key": { + "default": "Alt+Shift+L" + }, + "description": "__MSG_switchInstance__" + }, + "copyRaw": { + "suggested_key": { + "default": "Alt+Shift+C" + }, + "description": "Copies the original link. Ex: Copies the original twitter link while in the nitter website" + }, + "reverse": { + "suggested_key": { + "default": "Alt+Shift+O" + }, + "description": "Redirect to the original link. Ex: Redirects to the original twitter link while in the nitter website" + }, + "redirect": { + "suggested_key": { + "default": "Alt+Shift+R" + }, + "description": "Redirect link. Ex: Redirects original twitter link to nitter" + } + }, + "default_locale": "en", + "update_url": "https://raw.githubusercontent.com/libredirect/libredirect/master/src/updates/updates.xml", + "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAroWDSoSRZ1scj+eJRrvnhJbrqXTKnhQuxs6+AJg16sqr0bsMdFV+MSY4i4xnK+K5WOYkBliWXgUyk/wzicoAjOnSJddrL/Md4FuWHI2NVIkrlsLOrYkygi5OLqGPajRH/w8Cdmg7KzEpXe/OnYV0/qS8li8huEdTzdeLdhfbiVl1j3DOr4OJALQ7mPeeNFHFo/oVQ+OkSezWLezA5jUGfhtzPYV6u1TXzX7lCi8E/BbDbwkvvXOMcjXCv08kjdLOY2djCA2a6zr0xAb3q8DlexAMZ8vMof7AQRFtBKhLc9n9VFoipMMdBOVQQj/eIcRILBrmkcZNnJxFKiHNJ+NcZQIDAQAB" +} diff --git a/src/pages/background/background.html b/src/pages/background/background.html index 542df18b..787d419e 100644 --- a/src/pages/background/background.html +++ b/src/pages/background/background.html @@ -1,7 +1,7 @@ - + - - - - + + + + diff --git a/src/pages/background/background.js b/src/pages/background/background.js index 0c4d0923..e3d9fb31 100644 --- a/src/pages/background/background.js +++ b/src/pages/background/background.js @@ -7,310 +7,324 @@ const isChrome = browser.runtime.getBrowserInfo === undefined window.browser = window.browser || window.chrome browser.runtime.onInstalled.addListener(async details => { - if (details.previousVersion != browser.runtime.getManifest().version) { - // ^Used to prevent this running when debugging with auto-reload - if (details.reason == "install") { - if (!(await utils.getOptions())) { - await servicesHelper.initDefaults() - } - browser.runtime.openOptionsPage() - } - else if (details.reason == "update") { - if (details.previousVersion == '2.5.2') { - await servicesHelper.upgradeOptions() - await servicesHelper.processUpdate() - } else { - await servicesHelper.processUpdate() - } - } - } + if (details.previousVersion != browser.runtime.getManifest().version) { + // ^Used to prevent this running when debugging with auto-reload + if (details.reason == "install") { + if (!(await utils.getOptions())) { + await servicesHelper.initDefaults() + } + browser.runtime.openOptionsPage() + } else if (details.reason == "update") { + if (details.previousVersion == "2.5.2") { + await servicesHelper.upgradeOptions() + await servicesHelper.processUpdate() + } else { + await servicesHelper.processUpdate() + } + } + } }) let tabIdRedirects = {} // true == Always redirect, false == Never redirect, null/undefined == follow options for services browser.webRequest.onBeforeRequest.addListener( - details => { - const url = new URL(details.url) - const old_href = url.href - if (new RegExp(/^chrome-extension:\/{2}.*\/instances\/.*.json$/).test(url.href) && details.type == "xmlhttprequest") return - let initiator - try { - if (details.originUrl) initiator = new URL(details.originUrl) - else if (details.initiator && details.initiator !== "null") initiator = new URL(details.initiator) - } catch { - return null - } - if (tabIdRedirects[details.tabId] == false) return null - let newUrl = servicesHelper.redirect(url, details.type, initiator, tabIdRedirects[details.tabId], details.incognito) + details => { + const url = new URL(details.url) + const old_href = url.href + if (new RegExp(/^chrome-extension:\/{2}.*\/instances\/.*.json$/).test(url.href) && details.type == "xmlhttprequest") + return + let initiator + try { + if (details.originUrl) initiator = new URL(details.originUrl) + else if (details.initiator && details.initiator !== "null") initiator = new URL(details.initiator) + } catch { + return null + } + if (tabIdRedirects[details.tabId] == false) return null + let newUrl = servicesHelper.redirect(url, details.type, initiator, tabIdRedirects[details.tabId], details.incognito) - if (details.frameAncestors && details.frameAncestors.length > 0 && servicesHelper.isException(new URL(details.frameAncestors[0].url))) newUrl = null + if ( + details.frameAncestors && + details.frameAncestors.length > 0 && + servicesHelper.isException(new URL(details.frameAncestors[0].url)) + ) + newUrl = null - if (servicesHelper.isException(url)) { - if (details.type == "main_frame") - newUrl = "BYPASSTAB" - else - return null - } + if (servicesHelper.isException(url)) { + if (details.type == "main_frame") newUrl = "BYPASSTAB" + else return null + } - if (!newUrl) { - const match = url.href.match(/^https?:\/{2}.*\.libredirect\.invalid.*/) - if (match) { - browser.tabs.update({ - url: browser.runtime.getURL(`/pages/messages/no_instance.html`) - }); - } - } + if (!newUrl) { + const match = url.href.match(/^https?:\/{2}.*\.libredirect\.invalid.*/) + if (match) { + browser.tabs.update({ + url: browser.runtime.getURL(`/pages/messages/no_instance.html`), + }) + } + } - if (newUrl) { - if (newUrl === "CANCEL") { - console.log(`Canceled ${url}`) - return { cancel: true } - } - if (newUrl === "BYPASSTAB") { - console.log(`Bypassed ${details.tabId} ${url}`) - if (tabIdRedirects[details.tabId] != false) tabIdRedirects[details.tabId] = false - return null - } - console.log("Redirecting", old_href, "=>", newUrl) - return { redirectUrl: newUrl } - } - return null - }, - { urls: [""] }, - ["blocking"] + if (newUrl) { + if (newUrl === "CANCEL") { + console.log(`Canceled ${url}`) + return { cancel: true } + } + if (newUrl === "BYPASSTAB") { + console.log(`Bypassed ${details.tabId} ${url}`) + if (tabIdRedirects[details.tabId] != false) tabIdRedirects[details.tabId] = false + return null + } + console.log("Redirecting", old_href, "=>", newUrl) + return { redirectUrl: newUrl } + } + return null + }, + { urls: [""] }, + ["blocking"] ) browser.tabs.onRemoved.addListener(tabId => { - if (tabIdRedirects[tabId] != undefined) { - delete tabIdRedirects[tabId] - console.log(`Removed tab ${tabId} from tabIdRedirects`) - } + if (tabIdRedirects[tabId] != undefined) { + delete tabIdRedirects[tabId] + console.log(`Removed tab ${tabId} from tabIdRedirects`) + } }) browser.commands.onCommand.addListener(async command => { - browser.tabs.query({ active: true, currentWindow: true }, async tabs => { - const url = new URL(tabs[0].url) - switch (command) { - case "switchInstance": { - const newUrl = await servicesHelper.switchInstance(url) - if (newUrl) browser.tabs.update({ url: newUrl }) - break - } - case "copyRaw": - servicesHelper.copyRaw(url) - break - case "redirect": - browser.tabs.query({ active: true, currentWindow: true }, async tabs => { - if (tabs[0].url) { - const url = new URL(tabs[0].url) - const newUrl = servicesHelper.redirect(url, "main_frame", null, true) - if (newUrl) { - browser.tabs.update(tabs[0].id, { url: newUrl }, () => { - tabIdRedirects[tabs[0].id] = true - }) - } - } - }) - break - case "reverse": - browser.tabs.query({ active: true, currentWindow: true }, async tabs => { - if (tabs[0].url) { - const url = new URL(tabs[0].url) - const newUrl = await servicesHelper.reverse(url) - if (newUrl) { - browser.tabs.update(tabs[0].id, { url: newUrl }, () => { - tabIdRedirects[tabs[0].id] = false - }) - } - } - }) - break - } - }) + browser.tabs.query({ active: true, currentWindow: true }, async tabs => { + const url = new URL(tabs[0].url) + switch (command) { + case "switchInstance": { + const newUrl = await servicesHelper.switchInstance(url) + if (newUrl) browser.tabs.update({ url: newUrl }) + break + } + case "copyRaw": + servicesHelper.copyRaw(url) + break + case "redirect": + browser.tabs.query({ active: true, currentWindow: true }, async tabs => { + if (tabs[0].url) { + const url = new URL(tabs[0].url) + const newUrl = servicesHelper.redirect(url, "main_frame", null, true) + if (newUrl) { + browser.tabs.update(tabs[0].id, { url: newUrl }, () => { + tabIdRedirects[tabs[0].id] = true + }) + } + } + }) + break + case "reverse": + browser.tabs.query({ active: true, currentWindow: true }, async tabs => { + if (tabs[0].url) { + const url = new URL(tabs[0].url) + const newUrl = await servicesHelper.reverse(url) + if (newUrl) { + browser.tabs.update(tabs[0].id, { url: newUrl }, () => { + tabIdRedirects[tabs[0].id] = false + }) + } + } + }) + break + } + }) }) -browser.contextMenus.create({ id: "settingsTab", title: browser.i18n.getMessage("settings"), contexts: ["browser_action"] }) -browser.contextMenus.create({ id: "switchInstanceTab", title: browser.i18n.getMessage("switchInstance"), contexts: ["browser_action"] }) -browser.contextMenus.create({ id: "copyReverseTab", title: 'Copy Original', contexts: ["browser_action"] }) -browser.contextMenus.create({ id: "redirectTab", title: 'Redirect', contexts: ["browser_action"] }) -browser.contextMenus.create({ id: "reverseTab", title: 'Redirect To Original', contexts: ["browser_action"] }) +browser.contextMenus.create({ + id: "settingsTab", + title: browser.i18n.getMessage("settings"), + contexts: ["browser_action"], +}) +browser.contextMenus.create({ + id: "switchInstanceTab", + title: browser.i18n.getMessage("switchInstance"), + contexts: ["browser_action"], +}) +browser.contextMenus.create({ id: "copyReverseTab", title: "Copy Original", contexts: ["browser_action"] }) +browser.contextMenus.create({ id: "redirectTab", title: "Redirect", contexts: ["browser_action"] }) +browser.contextMenus.create({ id: "reverseTab", title: "Redirect To Original", contexts: ["browser_action"] }) -browser.contextMenus.create({ id: "redirectLink", title: 'Redirect', contexts: ["link"] }) -browser.contextMenus.create({ id: "redirectLinkInNewTab", title: 'Redirect In New Tab', contexts: ["link"] }) -browser.contextMenus.create({ id: "reverseLink", title: 'Redirect To Original', contexts: ["link"] }) -browser.contextMenus.create({ id: "reverseLinkInNewTab", title: 'Redirect To Original In New Tab', contexts: ["link"] }) -browser.contextMenus.create({ id: "copyReverseLink", title: 'Copy Original', contexts: ["link"] }) -browser.contextMenus.create({ id: "bypassLink", title: 'Bypass', contexts: ["link"] }) -browser.contextMenus.create({ id: "bypassLinkInNewTab", title: 'Bypass In New Tab', contexts: ["link"] }) +browser.contextMenus.create({ id: "redirectLink", title: "Redirect", contexts: ["link"] }) +browser.contextMenus.create({ id: "redirectLinkInNewTab", title: "Redirect In New Tab", contexts: ["link"] }) +browser.contextMenus.create({ id: "reverseLink", title: "Redirect To Original", contexts: ["link"] }) +browser.contextMenus.create({ id: "reverseLinkInNewTab", title: "Redirect To Original In New Tab", contexts: ["link"] }) +browser.contextMenus.create({ id: "copyReverseLink", title: "Copy Original", contexts: ["link"] }) +browser.contextMenus.create({ id: "bypassLink", title: "Bypass", contexts: ["link"] }) +browser.contextMenus.create({ id: "bypassLinkInNewTab", title: "Bypass In New Tab", contexts: ["link"] }) if (!isChrome) { - browser.contextMenus.create({ id: "redirectBookmark", title: 'Redirect', contexts: ["bookmark"] }) - browser.contextMenus.create({ id: "redirectBookmarkInNewTab", title: 'Redirect In New Tab', contexts: ["bookmark"] }) - browser.contextMenus.create({ id: "reverseBookmark", title: 'Redirect To Original', contexts: ["bookmark"] }) - browser.contextMenus.create({ id: "reverseBookmarkInNewTab", title: 'Redirect To Original In New Tab', contexts: ["bookmark"] }) - browser.contextMenus.create({ id: "copyReverseBookmark", title: 'Copy Original', contexts: ["bookmark"] }) - browser.contextMenus.create({ id: "bypassBookmark", title: 'Bypass', contexts: ["bookmark"] }) - browser.contextMenus.create({ id: "bypassBookmarkInNewTab", title: 'Bypass In New Tab', contexts: ["bookmark"] }) + browser.contextMenus.create({ id: "redirectBookmark", title: "Redirect", contexts: ["bookmark"] }) + browser.contextMenus.create({ id: "redirectBookmarkInNewTab", title: "Redirect In New Tab", contexts: ["bookmark"] }) + browser.contextMenus.create({ id: "reverseBookmark", title: "Redirect To Original", contexts: ["bookmark"] }) + browser.contextMenus.create({ + id: "reverseBookmarkInNewTab", + title: "Redirect To Original In New Tab", + contexts: ["bookmark"], + }) + browser.contextMenus.create({ id: "copyReverseBookmark", title: "Copy Original", contexts: ["bookmark"] }) + browser.contextMenus.create({ id: "bypassBookmark", title: "Bypass", contexts: ["bookmark"] }) + browser.contextMenus.create({ id: "bypassBookmarkInNewTab", title: "Bypass In New Tab", contexts: ["bookmark"] }) } -browser.contextMenus.onClicked.addListener(async (info) => { - switch (info.menuItemId) { - case 'switchInstanceTab': { - const url = new URL(info.pageUrl) - const newUrl = await servicesHelper.switchInstance(url) - if (newUrl) browser.tabs.update({ url: newUrl }) - return - } - case 'settingsTab': - browser.runtime.openOptionsPage() - return - case 'copyReverseTab': - browser.tabs.query({ active: true, currentWindow: true }, async tabs => { - if (tabs[0].url) { - const url = new URL(tabs[0].url) - servicesHelper.copyRaw(url) - } - }) - return - case 'reverseTab': - browser.tabs.query({ active: true, currentWindow: true }, async tabs => { - if (tabs[0].url) { - const url = new URL(tabs[0].url) - const newUrl = await servicesHelper.reverse(url) - if (newUrl) { - browser.tabs.update(tabs[0].id, { url: newUrl }, () => { - tabIdRedirects[tabs[0].id] = false - }) - } - } - }) - return - case 'redirectTab': - browser.tabs.query({ active: true, currentWindow: true }, async tabs => { - if (tabs[0].url) { - const url = new URL(tabs[0].url) - const newUrl = servicesHelper.redirect(url, "main_frame", null, true) - if (newUrl) { - browser.tabs.update(tabs[0].id, { url: newUrl }, () => { - tabIdRedirects[tabs[0].id] = true - }) - } - } - }) - return - case 'copyReverseLink': { - const url = new URL(info.linkUrl) - await servicesHelper.copyRaw(url) - return - } - case 'redirectLink': - case 'redirectLinkInNewTab': { - const url = new URL(info.linkUrl) - const newUrl = servicesHelper.redirect(url, "main_frame", null, true) - if (newUrl) { - if (info.menuItemId == "redirectLink") browser.tabs.update({ url: newUrl }) - else browser.tabs.create({ url: newUrl }) - } - return - } - case 'reverseLink': - case 'reverseLinkInNewTab': { - const url = new URL(info.linkUrl) - const newUrl = await servicesHelper.reverse(url) - if (newUrl) { - if (info.menuItemId == "reverseLink") { - browser.tabs.update({ url: newUrl }, tab => { - tabIdRedirects[tab.id] = false - }) - } else { - browser.tabs.create({ url: newUrl }, tab => { - tabIdRedirects[tab.id] = false - }) - } - } - return - } - case 'bypassLink': - case 'bypassLinkInNewTab': { - const url = new URL(info.linkUrl) - if (info.menuItemId == "bypassLink") { - browser.tabs.update({ url: url.href }, tab => { - tabIdRedirects[tab.id] = false - }) - } else { - browser.tabs.create({ url: url.href }, tab => { - tabIdRedirects[tab.id] = false - }) - } - return - } - case 'copyReverseBookmark': - browser.bookmarks.get(info.bookmarkId, bookmarks => { - const url = new URL(bookmarks[0].url) - servicesHelper.copyRaw(url) - }); - return - case 'redirectBookmark': - case 'redirectBookmarkInNewTab': - browser.bookmarks.get(info.bookmarkId, bookmarks => { - const url = new URL(bookmarks[0].url) - const newUrl = servicesHelper.redirect(url, "main_frame", null, true) - if (newUrl) { - if (info.menuItemId == 'redirectBookmark') browser.tabs.update({ url: newUrl }) - else browser.tabs.create({ url: newUrl }) - } - }) - return - case 'reverseBookmark': - case 'reverseBookmarkInNewTab': - browser.bookmarks.get(info.bookmarkId, async bookmarks => { - const url = new URL(bookmarks[0].url) - const newUrl = await servicesHelper.reverse(url) - if (newUrl) { - if (info.menuItemId == "reverseBookmark") { - browser.tabs.update({ url: newUrl }, tab => { - tabIdRedirects[tab.id] = false - }) - } else { - browser.tabs.create({ url: newUrl }, tab => { - tabIdRedirects[tab.id] = false - }) - } - } - }) - return - case 'bypassBookmark': - case 'bypassBookmarkInNewTab': - browser.bookmarks.get(info.bookmarkId, async bookmarks => { - const url = new URL(bookmarks[0].url) - if (info.menuItemId == "bypassBookmark") { - browser.tabs.update({ url: url.href }, tab => tabIdRedirects[tab.id] = false) - } else { - browser.tabs.create({ url: url.href }, tab => tabIdRedirects[tab.id] = false) - } - return - }) - } +browser.contextMenus.onClicked.addListener(async info => { + switch (info.menuItemId) { + case "switchInstanceTab": { + const url = new URL(info.pageUrl) + const newUrl = await servicesHelper.switchInstance(url) + if (newUrl) browser.tabs.update({ url: newUrl }) + return + } + case "settingsTab": + browser.runtime.openOptionsPage() + return + case "copyReverseTab": + browser.tabs.query({ active: true, currentWindow: true }, async tabs => { + if (tabs[0].url) { + const url = new URL(tabs[0].url) + servicesHelper.copyRaw(url) + } + }) + return + case "reverseTab": + browser.tabs.query({ active: true, currentWindow: true }, async tabs => { + if (tabs[0].url) { + const url = new URL(tabs[0].url) + const newUrl = await servicesHelper.reverse(url) + if (newUrl) { + browser.tabs.update(tabs[0].id, { url: newUrl }, () => { + tabIdRedirects[tabs[0].id] = false + }) + } + } + }) + return + case "redirectTab": + browser.tabs.query({ active: true, currentWindow: true }, async tabs => { + if (tabs[0].url) { + const url = new URL(tabs[0].url) + const newUrl = servicesHelper.redirect(url, "main_frame", null, true) + if (newUrl) { + browser.tabs.update(tabs[0].id, { url: newUrl }, () => { + tabIdRedirects[tabs[0].id] = true + }) + } + } + }) + return + case "copyReverseLink": { + const url = new URL(info.linkUrl) + await servicesHelper.copyRaw(url) + return + } + case "redirectLink": + case "redirectLinkInNewTab": { + const url = new URL(info.linkUrl) + const newUrl = servicesHelper.redirect(url, "main_frame", null, true) + if (newUrl) { + if (info.menuItemId == "redirectLink") browser.tabs.update({ url: newUrl }) + else browser.tabs.create({ url: newUrl }) + } + return + } + case "reverseLink": + case "reverseLinkInNewTab": { + const url = new URL(info.linkUrl) + const newUrl = await servicesHelper.reverse(url) + if (newUrl) { + if (info.menuItemId == "reverseLink") { + browser.tabs.update({ url: newUrl }, tab => { + tabIdRedirects[tab.id] = false + }) + } else { + browser.tabs.create({ url: newUrl }, tab => { + tabIdRedirects[tab.id] = false + }) + } + } + return + } + case "bypassLink": + case "bypassLinkInNewTab": { + const url = new URL(info.linkUrl) + if (info.menuItemId == "bypassLink") { + browser.tabs.update({ url: url.href }, tab => { + tabIdRedirects[tab.id] = false + }) + } else { + browser.tabs.create({ url: url.href }, tab => { + tabIdRedirects[tab.id] = false + }) + } + return + } + case "copyReverseBookmark": + browser.bookmarks.get(info.bookmarkId, bookmarks => { + const url = new URL(bookmarks[0].url) + servicesHelper.copyRaw(url) + }) + return + case "redirectBookmark": + case "redirectBookmarkInNewTab": + browser.bookmarks.get(info.bookmarkId, bookmarks => { + const url = new URL(bookmarks[0].url) + const newUrl = servicesHelper.redirect(url, "main_frame", null, true) + if (newUrl) { + if (info.menuItemId == "redirectBookmark") browser.tabs.update({ url: newUrl }) + else browser.tabs.create({ url: newUrl }) + } + }) + return + case "reverseBookmark": + case "reverseBookmarkInNewTab": + browser.bookmarks.get(info.bookmarkId, async bookmarks => { + const url = new URL(bookmarks[0].url) + const newUrl = await servicesHelper.reverse(url) + if (newUrl) { + if (info.menuItemId == "reverseBookmark") { + browser.tabs.update({ url: newUrl }, tab => { + tabIdRedirects[tab.id] = false + }) + } else { + browser.tabs.create({ url: newUrl }, tab => { + tabIdRedirects[tab.id] = false + }) + } + } + }) + return + case "bypassBookmark": + case "bypassBookmarkInNewTab": + browser.bookmarks.get(info.bookmarkId, async bookmarks => { + const url = new URL(bookmarks[0].url) + if (info.menuItemId == "bypassBookmark") { + browser.tabs.update({ url: url.href }, tab => (tabIdRedirects[tab.id] = false)) + } else { + browser.tabs.create({ url: url.href }, tab => (tabIdRedirects[tab.id] = false)) + } + return + }) + } }) browser.runtime.onMessage.addListener((request, sender, sendResponse) => { - if (request == "reverseTab") { - browser.tabs.query({ active: true, currentWindow: true }, async tabs => { - if (tabs[0].url) { - const url = new URL(tabs[0].url) - const newUrl = await servicesHelper.reverse(url) - if (newUrl) browser.tabs.update(tabs[0].id, { url: newUrl }, () => tabIdRedirects[tabs[0].id] = false) - } - }) - } - else if (request == "redirectTab") { - browser.tabs.query({ active: true, currentWindow: true }, async tabs => { - if (tabs[0].url) { - const url = new URL(tabs[0].url) - const newUrl = servicesHelper.redirect(url, "main_frame", null, true) - if (newUrl) browser.tabs.update(tabs[0].id, { url: newUrl }, () => tabIdRedirects[tabs[0].id] = true) - } - }) - } -}) \ No newline at end of file + if (request == "reverseTab") { + browser.tabs.query({ active: true, currentWindow: true }, async tabs => { + if (tabs[0].url) { + const url = new URL(tabs[0].url) + const newUrl = await servicesHelper.reverse(url) + if (newUrl) browser.tabs.update(tabs[0].id, { url: newUrl }, () => (tabIdRedirects[tabs[0].id] = false)) + } + }) + } else if (request == "redirectTab") { + browser.tabs.query({ active: true, currentWindow: true }, async tabs => { + if (tabs[0].url) { + const url = new URL(tabs[0].url) + const newUrl = servicesHelper.redirect(url, "main_frame", null, true) + if (newUrl) browser.tabs.update(tabs[0].id, { url: newUrl }, () => (tabIdRedirects[tabs[0].id] = true)) + } + }) + } +}) diff --git a/src/pages/messages/no_instance.html b/src/pages/messages/no_instance.html index 76ec19cf..358ff506 100644 --- a/src/pages/messages/no_instance.html +++ b/src/pages/messages/no_instance.html @@ -1,26 +1,24 @@ - + - - - - - - + + + + + No instances found - + - +
-

You have no instance selected for this frontend

+

You have no instance selected for this frontend

- - - \ No newline at end of file + + diff --git a/src/pages/options/index.js b/src/pages/options/index.js index 62708f7b..8d5676e0 100644 --- a/src/pages/options/index.js +++ b/src/pages/options/index.js @@ -1,19 +1,19 @@ import utils from "../../assets/javascripts/utils.js" let config, - options, - blacklist, - redirects, - divs = {} + options, + blacklist, + redirects, + divs = {} for (const a of document.getElementById("links").getElementsByTagName("a")) { - if (!a.href.includes("https://")) { - a.addEventListener("click", e => { - const path = a.getAttribute("href").replace("#", "") - loadPage(path) - e.preventDefault() - }) - } + if (!a.href.includes("https://")) { + a.addEventListener("click", e => { + const path = a.getAttribute("href").replace("#", "") + loadPage(path) + e.preventDefault() + }) + } } config = await utils.getConfig() @@ -23,180 +23,180 @@ options = await utils.getOptions() * @param {string} service */ async function changeFrontendsSettings(service) { - options = await utils.getOptions() - const opacityDiv = document.getElementById(`${service}-opacity`) - if (document.getElementById(`${service}-enabled`).checked) { - opacityDiv.style.pointerEvents = 'auto' - opacityDiv.style.opacity = 1 - opacityDiv.style.userSelect = 'auto' - } else { - opacityDiv.style.pointerEvents = 'none' - opacityDiv.style.opacity = 0.4 - opacityDiv.style.userSelect = 'none' - } - for (const frontend in config.services[service].frontends) { - if (config.services[service].frontends[frontend].instanceList) { - const frontendDiv = document.getElementById(frontend) - if (typeof divs[service].frontend !== "undefined") { - if ( - frontend == divs[service].frontend.value - || - (config.services[service].frontends[divs[service].frontend.value].desktopApp && divs[service].embedFrontend && frontend == divs[service].embedFrontend.value) - ) { - frontendDiv.style.display = "" - if (config.services[service].frontends[frontend].localhost === true) { - document.getElementById(`${service}-instance-div`).style.display = "" - - if (options[service].instance == "localhost") { - frontendDiv.style.display = "none" - } - } else { - document.getElementById(`${service}-instance-div`).style.display = "none" - } - } else { - frontendDiv.style.display = "none" - } - } - } - } - if (document.getElementById(`${service}-redirectType`)) { - const frontend = options[service].frontend - if (config.services[service].frontends[frontend].embeddable) { - document.getElementById(`${service}-redirectType`).innerHTML = ` + options = await utils.getOptions() + const opacityDiv = document.getElementById(`${service}-opacity`) + if (document.getElementById(`${service}-enabled`).checked) { + opacityDiv.style.pointerEvents = "auto" + opacityDiv.style.opacity = 1 + opacityDiv.style.userSelect = "auto" + } else { + opacityDiv.style.pointerEvents = "none" + opacityDiv.style.opacity = 0.4 + opacityDiv.style.userSelect = "none" + } + for (const frontend in config.services[service].frontends) { + if (config.services[service].frontends[frontend].instanceList) { + const frontendDiv = document.getElementById(frontend) + if (typeof divs[service].frontend !== "undefined") { + if ( + frontend == divs[service].frontend.value || + (config.services[service].frontends[divs[service].frontend.value].desktopApp && + divs[service].embedFrontend && + frontend == divs[service].embedFrontend.value) + ) { + frontendDiv.style.display = "" + if (config.services[service].frontends[frontend].localhost === true) { + document.getElementById(`${service}-instance-div`).style.display = "" + + if (options[service].instance == "localhost") { + frontendDiv.style.display = "none" + } + } else { + document.getElementById(`${service}-instance-div`).style.display = "none" + } + } else { + frontendDiv.style.display = "none" + } + } + } + } + if (document.getElementById(`${service}-redirectType`)) { + const frontend = options[service].frontend + if (config.services[service].frontends[frontend].embeddable) { + document.getElementById(`${service}-redirectType`).innerHTML = ` ` - } - else if (config.services[service].frontends[frontend].desktopApp && Object.values(config.services[service].frontends).some(frontend => frontend.embeddable)) { - document.getElementById(`${service}-redirectType`).innerHTML = ` + } else if ( + config.services[service].frontends[frontend].desktopApp && + Object.values(config.services[service].frontends).some(frontend => frontend.embeddable) + ) { + document.getElementById(`${service}-redirectType`).innerHTML = ` ` - if (options[service].redirectType == "sub_frame") { - options[service].redirectType = "main_frame" - browser.storage.local.set({ options }) - } - } else { - document.getElementById(`${service}-redirectType`).innerHTML = - '' - options[service].redirectType = "main_frame" - - browser.storage.local.set({ options }) - } - document.getElementById(`${service}-redirectType`).value = options[service].redirectType - if (config.services[service].frontends[frontend].desktopApp && options[service].redirectType != "main_frame") { - document.getElementById(`${service}-embedFrontend-div`).style.display = '' - document.getElementById(divs[service].embedFrontend.value).style.display = '' - } - else if (config.services[service].frontends[frontend].desktopApp && options[service].redirectType == "main_frame") { - document.getElementById(`${service}-embedFrontend-div`).style.display = 'none' - document.getElementById(divs[service].embedFrontend.value).style.display = 'none' - } else { - document.getElementById(`${service}-embedFrontend-div`).style.display = 'none' - } - } - const frontend_name_element = document.getElementById(`${service}_page`).getElementsByClassName("frontend_name")[0] - frontend_name_element.href = config.services[service].frontends[divs[service].frontend.value].url + if (options[service].redirectType == "sub_frame") { + options[service].redirectType = "main_frame" + browser.storage.local.set({ options }) + } + } else { + document.getElementById(`${service}-redirectType`).innerHTML = + '' + options[service].redirectType = "main_frame" + + browser.storage.local.set({ options }) + } + document.getElementById(`${service}-redirectType`).value = options[service].redirectType + if (config.services[service].frontends[frontend].desktopApp && options[service].redirectType != "main_frame") { + document.getElementById(`${service}-embedFrontend-div`).style.display = "" + document.getElementById(divs[service].embedFrontend.value).style.display = "" + } else if ( + config.services[service].frontends[frontend].desktopApp && + options[service].redirectType == "main_frame" + ) { + document.getElementById(`${service}-embedFrontend-div`).style.display = "none" + document.getElementById(divs[service].embedFrontend.value).style.display = "none" + } else { + document.getElementById(`${service}-embedFrontend-div`).style.display = "none" + } + } + const frontend_name_element = document.getElementById(`${service}_page`).getElementsByClassName("frontend_name")[0] + frontend_name_element.href = config.services[service].frontends[divs[service].frontend.value].url } /** * @param {string} path */ async function loadPage(path) { - options = await utils.getOptions() - for (const section of document.getElementById("pages").getElementsByTagName("section")) section.style.display = "none" - document.getElementById(`${path}_page`).style.display = "block" - - for (const element of document.getElementsByClassName("title")) { - const a = element.getElementsByTagName('a')[0] - if (a.getAttribute("href") == `#${path}`) { - element.classList.add("selected") - } else { - element.classList.remove("selected") - } - } - - for (const service in config.services) { - if (options[service].enabled) { - document.getElementById(`${service}-link`).style.opacity = 1 - } else { - document.getElementById(`${service}-link`).style.opacity = 0.4 - } - } - - window.history.pushState({ id: "100" }, "Page 2", `/pages/options/index.html#${path}`) - - if (path != 'general') { - const service = path; - divs[service] = {} - for (const option in config.services[service].options) { - divs[service][option] = document.getElementById(`${service}-${option}`) - if (typeof config.services[service].options[option] == "boolean") divs[service][option].checked = options[service][option] - else divs[service][option].value = options[service][option] - divs[service][option].addEventListener("change", async () => { - let options = await utils.getOptions() - if (typeof config.services[service].options[option] == "boolean") - options[service][option] = divs[service][option].checked - else - options[service][option] = divs[service][option].value - browser.storage.local.set({ options }) - changeFrontendsSettings(service) - }) - } - changeFrontendsSettings(service) - - blacklist = await utils.getBlacklist(options) - redirects = await utils.getList(options) - for (const frontend in config.services[service].frontends) { - if (config.services[service].frontends[frontend].instanceList) { - if (redirects == 'disabled' || blacklist == 'disabled') { - document.getElementById(frontend).getElementsByClassName('clearnet')[0].style.display = 'none' - document.getElementById(frontend).getElementsByClassName('ping')[0].style.display = 'none' - } - else if (!redirects || !blacklist) { - document.getElementById(frontend) - .getElementsByClassName('clearnet')[0] - .getElementsByClassName("checklist")[0] - .getElementsByClassName('loading')[0] - .innerHTML = 'Could not fetch instances.' - } - else { - createList(frontend) - } - } - } - - for (const frontend in config.services[service].frontends) { - if (config.services[service].frontends[frontend].instanceList) { - processCustomInstances(frontend) - document.getElementById(`ping-${frontend}`).addEventListener("click", async () => { - document.getElementById(`ping-${frontend}`).getElementsByTagName('x')[0].innerHTML = "Pinging..." - await ping(frontend) - document.getElementById(`ping-${frontend}`).getElementsByTagName('x')[0].innerHTML = "Ping instances" - }) - } - } - } + options = await utils.getOptions() + for (const section of document.getElementById("pages").getElementsByTagName("section")) section.style.display = "none" + document.getElementById(`${path}_page`).style.display = "block" + + for (const element of document.getElementsByClassName("title")) { + const a = element.getElementsByTagName("a")[0] + if (a.getAttribute("href") == `#${path}`) { + element.classList.add("selected") + } else { + element.classList.remove("selected") + } + } + + for (const service in config.services) { + if (options[service].enabled) { + document.getElementById(`${service}-link`).style.opacity = 1 + } else { + document.getElementById(`${service}-link`).style.opacity = 0.4 + } + } + + window.history.pushState({ id: "100" }, "Page 2", `/pages/options/index.html#${path}`) + + if (path != "general") { + const service = path + divs[service] = {} + for (const option in config.services[service].options) { + divs[service][option] = document.getElementById(`${service}-${option}`) + if (typeof config.services[service].options[option] == "boolean") + divs[service][option].checked = options[service][option] + else divs[service][option].value = options[service][option] + divs[service][option].addEventListener("change", async () => { + let options = await utils.getOptions() + if (typeof config.services[service].options[option] == "boolean") + options[service][option] = divs[service][option].checked + else options[service][option] = divs[service][option].value + browser.storage.local.set({ options }) + changeFrontendsSettings(service) + }) + } + changeFrontendsSettings(service) + + blacklist = await utils.getBlacklist(options) + redirects = await utils.getList(options) + for (const frontend in config.services[service].frontends) { + if (config.services[service].frontends[frontend].instanceList) { + if (redirects == "disabled" || blacklist == "disabled") { + document.getElementById(frontend).getElementsByClassName("clearnet")[0].style.display = "none" + document.getElementById(frontend).getElementsByClassName("ping")[0].style.display = "none" + } else if (!redirects || !blacklist) { + document + .getElementById(frontend) + .getElementsByClassName("clearnet")[0] + .getElementsByClassName("checklist")[0] + .getElementsByClassName("loading")[0].innerHTML = "Could not fetch instances." + } else { + createList(frontend) + } + } + } + + for (const frontend in config.services[service].frontends) { + if (config.services[service].frontends[frontend].instanceList) { + processCustomInstances(frontend) + document.getElementById(`ping-${frontend}`).addEventListener("click", async () => { + document.getElementById(`ping-${frontend}`).getElementsByTagName("x")[0].innerHTML = "Pinging..." + await ping(frontend) + document.getElementById(`ping-${frontend}`).getElementsByTagName("x")[0].innerHTML = "Ping instances" + }) + } + } + } } async function calcCustomInstances(frontend) { - let options = await utils.getOptions() - let customInstances = options[frontend] - const pingCache = await utils.getPingCache() - - document.getElementById(frontend).getElementsByClassName("custom-checklist")[0].innerHTML = customInstances - .map( - x => { - const time = pingCache[x]; - if (time) { - var { color, text } = processTime(time); - } - const timeText = time - ? `${text}` - : ""; - const custom = isCustomInstance(frontend, x) ? "" : `custom` - return `
+ let options = await utils.getOptions() + let customInstances = options[frontend] + const pingCache = await utils.getPingCache() + + document.getElementById(frontend).getElementsByClassName("custom-checklist")[0].innerHTML = customInstances + .map(x => { + const time = pingCache[x] + if (time) { + var { color, text } = processTime(time) + } + const timeText = time ? `${text}` : "" + const custom = isCustomInstance(frontend, x) ? "" : `custom` + return `
${x} ${timeText} @@ -209,87 +209,97 @@ async function calcCustomInstances(frontend) {

` - }) - .join("\n") - for (const item of customInstances) { - document.getElementById(frontend).getElementsByClassName(`clear-${item}`)[0].addEventListener("click", async () => { - const index = customInstances.indexOf(item) - if (index > -1) customInstances.splice(index, 1) - options = await utils.getOptions() - options[frontend] = customInstances - browser.storage.local.set({ options }, async () => { - calcCustomInstances(frontend) - createList(frontend) - }) - }) - } + }) + .join("\n") + for (const item of customInstances) { + document + .getElementById(frontend) + .getElementsByClassName(`clear-${item}`)[0] + .addEventListener("click", async () => { + const index = customInstances.indexOf(item) + if (index > -1) customInstances.splice(index, 1) + options = await utils.getOptions() + options[frontend] = customInstances + browser.storage.local.set({ options }, async () => { + calcCustomInstances(frontend) + createList(frontend) + }) + }) + } } async function processCustomInstances(frontend) { - calcCustomInstances(frontend) - document.getElementById(frontend).getElementsByClassName("custom-instance-form")[0].addEventListener("submit", async event => { - event.preventDefault() - let options = await utils.getOptions() - let customInstances = options[frontend] - let frontendCustomInstanceInput = document.getElementById(frontend).getElementsByClassName("custom-instance")[0] - try { - var url = new URL(frontendCustomInstanceInput.value) - } catch (error) { - return - } - let protocolHostVar = utils.protocolHost(url) - if (frontendCustomInstanceInput.validity.valid) { - if (!customInstances.includes(protocolHostVar)) { - customInstances.push(protocolHostVar) - options = await utils.getOptions() - options[frontend] = customInstances - browser.storage.local.set({ options }, () => { - frontendCustomInstanceInput.value = "" - calcCustomInstances(frontend) - }) - } - } - }) + calcCustomInstances(frontend) + document + .getElementById(frontend) + .getElementsByClassName("custom-instance-form")[0] + .addEventListener("submit", async event => { + event.preventDefault() + let options = await utils.getOptions() + let customInstances = options[frontend] + let frontendCustomInstanceInput = document.getElementById(frontend).getElementsByClassName("custom-instance")[0] + try { + var url = new URL(frontendCustomInstanceInput.value) + } catch (error) { + return + } + let protocolHostVar = utils.protocolHost(url) + if (frontendCustomInstanceInput.validity.valid) { + if (!customInstances.includes(protocolHostVar)) { + customInstances.push(protocolHostVar) + options = await utils.getOptions() + options[frontend] = customInstances + browser.storage.local.set({ options }, () => { + frontendCustomInstanceInput.value = "" + calcCustomInstances(frontend) + }) + } + } + }) } /** * @param {string} frontend */ async function createList(frontend) { - const pingCache = await utils.getPingCache() - const options = await utils.getOptions() - for (const network in config.networks) { - const checklist = document.getElementById(frontend).getElementsByClassName(network)[0].getElementsByClassName("checklist")[0] - - if (!redirects[frontend]) { - checklist.innerHTML = '
No instances found.
' - break - } - - const instances = redirects[frontend][network] - if (!instances || instances.length === 0) continue - - document.getElementById(frontend).getElementsByClassName("custom-instance")[0].placeholder = redirects[frontend].clearnet[0] - - instances.sort((a, b) => blacklist.cloudflare.includes(a) && !blacklist.cloudflare.includes(b)) - const content = instances - .map(x => { - const cloudflare = blacklist.cloudflare.includes(x) ? - ` + const pingCache = await utils.getPingCache() + const options = await utils.getOptions() + for (const network in config.networks) { + const checklist = document + .getElementById(frontend) + .getElementsByClassName(network)[0] + .getElementsByClassName("checklist")[0] + + if (!redirects[frontend]) { + checklist.innerHTML = '
No instances found.
' + break + } + + const instances = redirects[frontend][network] + if (!instances || instances.length === 0) continue + + document.getElementById(frontend).getElementsByClassName("custom-instance")[0].placeholder = + redirects[frontend].clearnet[0] + + instances.sort((a, b) => blacklist.cloudflare.includes(a) && !blacklist.cloudflare.includes(b)) + const content = instances.map(x => { + const cloudflare = blacklist.cloudflare.includes(x) + ? `
cloudflare - ` : "" + ` + : "" - let time = pingCache[x] - let timeText = "" - if (time) { - const { color, text } = processTime(time) - timeText = `${text}` - } + let time = pingCache[x] + let timeText = "" + if (time) { + const { color, text } = processTime(time) + timeText = `${text}` + } - const chosen = options[frontend].includes(x) ? `chosen` : "" + const chosen = options[frontend].includes(x) ? `chosen` : "" - const warnings = [cloudflare, timeText, chosen].join(" ") - return `
+ const warnings = [cloudflare, timeText, chosen].join(" ") + return `
${x} ${warnings} @@ -300,30 +310,29 @@ async function createList(frontend) {
` - }) + }) - checklist.innerHTML = [ - `
+ checklist.innerHTML = [ + `
`, - ...content, - "
" - ].join("\n
\n") - - for (const instance of instances) { - checklist.getElementsByClassName(`add-${instance}`)[0] - .addEventListener("click", async () => { - let options = await utils.getOptions() - if (!options[frontend].includes(instance)) { - options[frontend].push(instance) - browser.storage.local.set({ options }, () => { - calcCustomInstances(frontend) - createList(frontend) - }) - } - }) - } - } + ...content, + "
", + ].join("\n
\n") + + for (const instance of instances) { + checklist.getElementsByClassName(`add-${instance}`)[0].addEventListener("click", async () => { + let options = await utils.getOptions() + if (!options[frontend].includes(instance)) { + options[frontend].push(instance) + browser.storage.local.set({ options }, () => { + calcCustomInstances(frontend) + createList(frontend) + }) + } + }) + } + } } const r = window.location.href.match(/#(.*)/) @@ -334,59 +343,57 @@ else loadPage("general") * @param {string} frontend */ async function ping(frontend) { - const instanceElements = [ - ...document.getElementById(frontend).getElementsByClassName("custom-checklist")[0].getElementsByTagName('x'), - ...document.getElementById(frontend).getElementsByClassName('clearnet')[0].getElementsByTagName('x') - ] - - let pingCache = await utils.getPingCache() - let redundancyList = {} - for (const element of instanceElements) { - let span = element.getElementsByClassName('ping')[0] - if (!span) span = document.createElement('span') - span.classList = ['ping'] - span.innerHTML = 'pinging...' - element.appendChild(span) - const href = element.getElementsByTagName('a')[0].href - const innerHTML = element.getElementsByTagName('a')[0].innerHTML - const time = redundancyList[innerHTML] ?? await utils.ping(href) - const { color, text } = processTime(time) - span.innerHTML = `${text}` - pingCache[innerHTML] = time - redundancyList[innerHTML] = time - - browser.storage.local.set({ pingCache }) - } + const instanceElements = [ + ...document.getElementById(frontend).getElementsByClassName("custom-checklist")[0].getElementsByTagName("x"), + ...document.getElementById(frontend).getElementsByClassName("clearnet")[0].getElementsByTagName("x"), + ] + + let pingCache = await utils.getPingCache() + let redundancyList = {} + for (const element of instanceElements) { + let span = element.getElementsByClassName("ping")[0] + if (!span) span = document.createElement("span") + span.classList = ["ping"] + span.innerHTML = 'pinging...' + element.appendChild(span) + const href = element.getElementsByTagName("a")[0].href + const innerHTML = element.getElementsByTagName("a")[0].innerHTML + const time = redundancyList[innerHTML] ?? (await utils.ping(href)) + const { color, text } = processTime(time) + span.innerHTML = `${text}` + pingCache[innerHTML] = time + redundancyList[innerHTML] = time + + browser.storage.local.set({ pingCache }) + } } /** * @param {number} time */ function processTime(time) { - let text - let color - if (time < 5000) { - text = `${time}ms` - if (time <= 1000) color = "green" - else if (time <= 2000) color = "orange" - } - else if (time >= 5000) { - color = "red" - if (time == 5000) text = "5000ms+" - if (time > 5000) text = `Error: ${time - 5000}` - } - else { - color = "red" - text = 'Server not found' - } - return { color, text } + let text + let color + if (time < 5000) { + text = `${time}ms` + if (time <= 1000) color = "green" + else if (time <= 2000) color = "orange" + } else if (time >= 5000) { + color = "red" + if (time == 5000) text = "5000ms+" + if (time > 5000) text = `Error: ${time - 5000}` + } else { + color = "red" + text = "Server not found" + } + return { color, text } } function isCustomInstance(frontend, instance) { - for (const network in config.networks) { - if (!redirects[frontend]) return false; - const instances = redirects[frontend][network] - if (instances.includes(instance)) return true - } - return false -} \ No newline at end of file + for (const network in config.networks) { + if (!redirects[frontend]) return false + const instances = redirects[frontend][network] + if (instances.includes(instance)) return true + } + return false +} diff --git a/src/pages/options/init.js b/src/pages/options/init.js index baf3eebe..07da1859 100644 --- a/src/pages/options/init.js +++ b/src/pages/options/init.js @@ -5,46 +5,46 @@ import utils from "../../assets/javascripts/utils.js" import servicesHelper from "../../assets/javascripts/services.js" if (!(await utils.getOptions())) { - await servicesHelper.initDefaults() + await servicesHelper.initDefaults() } async function changeTheme() { - switch ((await utils.getOptions()).theme) { - case "dark": - document.body.classList.add("dark-theme") - document.body.classList.remove("light-theme") - for (const element of document.body.getElementsByClassName('dark')) { - element.style.display = 'none'; - } - break - case "light": - document.body.classList.add("light-theme") - document.body.classList.remove("dark-theme") - for (const element of document.body.getElementsByClassName('light')) { - element.style.display = 'none'; - } - break - default: - if (matchMedia("(prefers-color-scheme: light)").matches) { - document.body.classList.add("light-theme") - document.body.classList.remove("dark-theme") - for (const element of document.body.getElementsByClassName('light')) { - element.style.display = 'none'; - } - } else { - document.body.classList.add("dark-theme") - document.body.classList.remove("light-theme") - for (const element of document.body.getElementsByClassName('dark')) { - element.style.display = 'none'; - } - } - } + switch ((await utils.getOptions()).theme) { + case "dark": + document.body.classList.add("dark-theme") + document.body.classList.remove("light-theme") + for (const element of document.body.getElementsByClassName("dark")) { + element.style.display = "none" + } + break + case "light": + document.body.classList.add("light-theme") + document.body.classList.remove("dark-theme") + for (const element of document.body.getElementsByClassName("light")) { + element.style.display = "none" + } + break + default: + if (matchMedia("(prefers-color-scheme: light)").matches) { + document.body.classList.add("light-theme") + document.body.classList.remove("dark-theme") + for (const element of document.body.getElementsByClassName("light")) { + element.style.display = "none" + } + } else { + document.body.classList.add("dark-theme") + document.body.classList.remove("light-theme") + for (const element of document.body.getElementsByClassName("dark")) { + element.style.display = "none" + } + } + } } changeTheme() if (["ar", "iw", "ku", "fa", "ur"].includes(browser.i18n.getUILanguage())) { - document.getElementsByTagName("body")[0].classList.add("rtl") - document.getElementsByTagName("body")[0].dir = "rtl" + document.getElementsByTagName("body")[0].classList.add("rtl") + document.getElementsByTagName("body")[0].dir = "rtl" } localise.localisePage() diff --git a/src/pages/options/widgets/general.js b/src/pages/options/widgets/general.js index 30a8a0c8..b9ddfd08 100644 --- a/src/pages/options/widgets/general.js +++ b/src/pages/options/widgets/general.js @@ -7,29 +7,29 @@ import servicesHelper from "../../../assets/javascripts/services.js" const isChrome = browser.runtime.getBrowserInfo === undefined async function setOption(option, type, event) { - let options = await utils.getOptions() - switch (type) { - case "select": - options[option] = event.target.options[event.target.options.selectedIndex].value - break; - case "checkbox": - options[option] = event.target.checked - break; - case "range": - options[option] = event.target.value - break; - } - browser.storage.local.set({ options }) + let options = await utils.getOptions() + switch (type) { + case "select": + options[option] = event.target.options[event.target.options.selectedIndex].value + break + case "checkbox": + options[option] = event.target.checked + break + case "range": + options[option] = event.target.value + break + } + browser.storage.local.set({ options }) } const exportSettingsElement = document.getElementById("export-settings") async function exportSettings() { - const options = await utils.getOptions() - options.version = browser.runtime.getManifest().version - let resultString = JSON.stringify(options, null, " ") - exportSettingsElement.href = "data:application/json;base64," + btoa(resultString) - exportSettingsElement.download = `libredirect-settings-v${options.version}.json` - return + const options = await utils.getOptions() + options.version = browser.runtime.getManifest().version + let resultString = JSON.stringify(options, null, " ") + exportSettingsElement.href = "data:application/json;base64," + btoa(resultString) + exportSettingsElement.download = `libredirect-settings-v${options.version}.json` + return } exportSettings() document.getElementById("general_page").onclick = exportSettings @@ -37,35 +37,32 @@ document.getElementById("general_page").onclick = exportSettings const importSettingsElement = document.getElementById("import-settings") const importSettingsElementText = document.getElementById("import_settings_text") importSettingsElement.addEventListener("change", () => { - function importError() { - const oldHTML = importSettingsElementText.innerHTML - importSettingsElementText.innerHTML = 'Error!' - setTimeout(() => (importSettingsElementText.innerHTML = oldHTML), 1000) - } - importSettingsElementText.innerHTML = "..." - let file = importSettingsElement.files[0] - const reader = new FileReader() - reader.readAsText(file) - reader.onload = async () => { - const data = JSON.parse(reader.result) - if ( - "theme" in data - && data.version == browser.runtime.getManifest().version - ) { - browser.storage.local.clear(async () => { - browser.storage.local.set({ options: data }, () => { - location.reload() - }) - }) - } else { - console.log("incompatible settings") - importError() - } - } - reader.onerror = error => { - console.log("error", error) - importError() - } + function importError() { + const oldHTML = importSettingsElementText.innerHTML + importSettingsElementText.innerHTML = 'Error!' + setTimeout(() => (importSettingsElementText.innerHTML = oldHTML), 1000) + } + importSettingsElementText.innerHTML = "..." + let file = importSettingsElement.files[0] + const reader = new FileReader() + reader.readAsText(file) + reader.onload = async () => { + const data = JSON.parse(reader.result) + if ("theme" in data && data.version == browser.runtime.getManifest().version) { + browser.storage.local.clear(async () => { + browser.storage.local.set({ options: data }, () => { + location.reload() + }) + }) + } else { + console.log("incompatible settings") + importError() + } + } + reader.onerror = error => { + console.log("error", error) + importError() + } }) const exportSettingsSync = document.getElementById("export-settings-sync") @@ -73,58 +70,57 @@ const importSettingsSync = document.getElementById("import-settings-sync") const importSettingsSyncText = document.getElementById("import_settings_sync_text") exportSettingsSync.addEventListener("click", async () => { - let options = await utils.getOptions() - options.version = browser.runtime.getManifest().version - browser.storage.sync.set({ options }, () => location.reload()) + let options = await utils.getOptions() + options.version = browser.runtime.getManifest().version + browser.storage.sync.set({ options }, () => location.reload()) }) importSettingsSync.addEventListener("click", () => { - function importError() { - importSettingsSyncText.innerHTML = 'Error!' - setTimeout(() => (importSettingsSyncText.innerHTML = oldHTML), 1000) - } - const oldHTML = importSettingsSyncText.innerHTML - importSettingsSyncText.innerHTML = "..." - browser.storage.sync.get({ options }, r => { - const options = r.options - if (options.version == browser.runtime.getManifest().version) { - browser.storage.local.set({ options }, () => location.reload()) - } else { - importError() - } - }) + function importError() { + importSettingsSyncText.innerHTML = 'Error!' + setTimeout(() => (importSettingsSyncText.innerHTML = oldHTML), 1000) + } + const oldHTML = importSettingsSyncText.innerHTML + importSettingsSyncText.innerHTML = "..." + browser.storage.sync.get({ options }, r => { + const options = r.options + if (options.version == browser.runtime.getManifest().version) { + browser.storage.local.set({ options }, () => location.reload()) + } else { + importError() + } + }) }) const resetSettings = document.getElementById("reset-settings") resetSettings.addEventListener("click", async () => { - resetSettings.innerHTML = "..." - await servicesHelper.initDefaults() - location.reload() + resetSettings.innerHTML = "..." + await servicesHelper.initDefaults() + location.reload() }) -const fetchInstancesElement = document.getElementById('fetch-instances') -fetchInstancesElement.addEventListener('change', event => { - setOption('fetchInstances', 'select', event) - location.reload() +const fetchInstancesElement = document.getElementById("fetch-instances") +fetchInstancesElement.addEventListener("change", event => { + setOption("fetchInstances", "select", event) + location.reload() }) -const redirectOnlyInIncognitoElement = document.getElementById('redirectOnlyInIncognito') -redirectOnlyInIncognitoElement.addEventListener('change', event => { - setOption('redirectOnlyInIncognito', 'checkbox', event) +const redirectOnlyInIncognitoElement = document.getElementById("redirectOnlyInIncognito") +redirectOnlyInIncognitoElement.addEventListener("change", event => { + setOption("redirectOnlyInIncognito", "checkbox", event) }) -const bookmarksMenuElement = document.getElementById('bookmarksMenu') -bookmarksMenuElement.addEventListener('change', async event => { - if (event.target.checked) - browser.permissions.request({ permissions: ["bookmarks"] }, r => bookmarksMenuElement.checked = r) - else - browser.permissions.remove({ permissions: ["bookmarks"] }, r => bookmarksMenuElement.checked = !r) +const bookmarksMenuElement = document.getElementById("bookmarksMenu") +bookmarksMenuElement.addEventListener("change", async event => { + if (event.target.checked) + browser.permissions.request({ permissions: ["bookmarks"] }, r => (bookmarksMenuElement.checked = r)) + else browser.permissions.remove({ permissions: ["bookmarks"] }, r => (bookmarksMenuElement.checked = !r)) }) let themeElement = document.getElementById("theme") themeElement.addEventListener("change", event => { - setOption("theme", "select", event) - location.reload() + setOption("theme", "select", event) + location.reload() }) let nameCustomInstanceInput = document.getElementById("exceptions-custom-instance") @@ -134,40 +130,44 @@ let instanceType = "url" let config = await utils.getConfig() for (const service in config.services) { - document.getElementById(service).addEventListener("change", async event => { - let options = await utils.getOptions() - if (event.target.checked && !options.popupServices.includes(service)) options.popupServices.push(service) - else if (options.popupServices.includes(service)) { - var index = options.popupServices.indexOf(service) - if (index !== -1) options.popupServices.splice(index, 1) - } - browser.storage.local.set({ options }) - }) + document.getElementById(service).addEventListener("change", async event => { + let options = await utils.getOptions() + if (event.target.checked && !options.popupServices.includes(service)) options.popupServices.push(service) + else if (options.popupServices.includes(service)) { + var index = options.popupServices.indexOf(service) + if (index !== -1) options.popupServices.splice(index, 1) + } + browser.storage.local.set({ options }) + }) } let options = await utils.getOptions() themeElement.value = options.theme fetchInstancesElement.value = options.fetchInstances redirectOnlyInIncognitoElement.checked = options.redirectOnlyInIncognito -browser.permissions.contains({ permissions: ["bookmarks"] }, r => bookmarksMenuElement.checked = r) -for (const service in config.services) document.getElementById(service).checked = options.popupServices.includes(service) +browser.permissions.contains({ permissions: ["bookmarks"] }, r => (bookmarksMenuElement.checked = r)) +for (const service in config.services) + document.getElementById(service).checked = options.popupServices.includes(service) instanceTypeElement.addEventListener("change", event => { - instanceType = event.target.options[instanceTypeElement.selectedIndex].value - if (instanceType == "url") { - nameCustomInstanceInput.setAttribute("type", "url") - nameCustomInstanceInput.setAttribute("placeholder", "https://www.google.com") - } else if (instanceType == "regex") { - nameCustomInstanceInput.setAttribute("type", "text") - nameCustomInstanceInput.setAttribute("placeholder", "https?://(www.|)youtube.com/") - } + instanceType = event.target.options[instanceTypeElement.selectedIndex].value + if (instanceType == "url") { + nameCustomInstanceInput.setAttribute("type", "url") + nameCustomInstanceInput.setAttribute("placeholder", "https://www.google.com") + } else if (instanceType == "regex") { + nameCustomInstanceInput.setAttribute("type", "text") + nameCustomInstanceInput.setAttribute("placeholder", "https?://(www.|)youtube.com/") + } }) let exceptionsCustomInstances = options.exceptions function calcExceptionsCustomInstances() { - document.getElementById("exceptions-custom-checklist").innerHTML = [...exceptionsCustomInstances.url, ...exceptionsCustomInstances.regex] - .map( - x => `
+ document.getElementById("exceptions-custom-checklist").innerHTML = [ + ...exceptionsCustomInstances.url, + ...exceptionsCustomInstances.regex, + ] + .map( + x => `
${x}

` - ) - .join("\n") - - for (const x of [...exceptionsCustomInstances.url, ...exceptionsCustomInstances.regex]) { - document.getElementById(`clear-${x}`).addEventListener("click", async () => { - let index - index = exceptionsCustomInstances.url.indexOf(x) - if (index > -1) exceptionsCustomInstances.url.splice(index, 1) - else { - index = exceptionsCustomInstances.regex.indexOf(x) - if (index > -1) exceptionsCustomInstances.regex.splice(index, 1) - } - options = await utils.getOptions() - options.exceptions = exceptionsCustomInstances - browser.storage.local.set({ options }) - calcExceptionsCustomInstances() - }) - } + ) + .join("\n") + + for (const x of [...exceptionsCustomInstances.url, ...exceptionsCustomInstances.regex]) { + document.getElementById(`clear-${x}`).addEventListener("click", async () => { + let index + index = exceptionsCustomInstances.url.indexOf(x) + if (index > -1) exceptionsCustomInstances.url.splice(index, 1) + else { + index = exceptionsCustomInstances.regex.indexOf(x) + if (index > -1) exceptionsCustomInstances.regex.splice(index, 1) + } + options = await utils.getOptions() + options.exceptions = exceptionsCustomInstances + browser.storage.local.set({ options }) + calcExceptionsCustomInstances() + }) + } } calcExceptionsCustomInstances() document.getElementById("custom-exceptions-instance-form").addEventListener("submit", async event => { - event.preventDefault() - let val - if (instanceType == "url" && nameCustomInstanceInput.validity.valid) { - val = nameCustomInstanceInput.value - if (!exceptionsCustomInstances.url.includes(val)) exceptionsCustomInstances.url.push(val) - } else if (instanceType == "regex") { - val = nameCustomInstanceInput.value - if (val.trim() != "" && !exceptionsCustomInstances.regex.includes(val)) exceptionsCustomInstances.regex.push(val) - } - if (val) { - options = await utils.getOptions() - options.exceptions = exceptionsCustomInstances - browser.storage.local.set({ options }, () => nameCustomInstanceInput.value = "") - } - calcExceptionsCustomInstances() + event.preventDefault() + let val + if (instanceType == "url" && nameCustomInstanceInput.validity.valid) { + val = nameCustomInstanceInput.value + if (!exceptionsCustomInstances.url.includes(val)) exceptionsCustomInstances.url.push(val) + } else if (instanceType == "regex") { + val = nameCustomInstanceInput.value + if (val.trim() != "" && !exceptionsCustomInstances.regex.includes(val)) exceptionsCustomInstances.regex.push(val) + } + if (val) { + options = await utils.getOptions() + options.exceptions = exceptionsCustomInstances + browser.storage.local.set({ options }, () => (nameCustomInstanceInput.value = "")) + } + calcExceptionsCustomInstances() }) diff --git a/src/pages/popup/popup.js b/src/pages/popup/popup.js index 485ec0e0..77a43000 100644 --- a/src/pages/popup/popup.js +++ b/src/pages/popup/popup.js @@ -5,15 +5,15 @@ import servicesHelper from "../../assets/javascripts/services.js" import utils from "../../assets/javascripts/utils.js" document.getElementById("more-options").href = browser.runtime.getURL("pages/options/index.html") -document.getElementById("more-options").setAttribute('target', '_blank') +document.getElementById("more-options").setAttribute("target", "_blank") await browser.runtime.getPlatformInfo(r => { - switch (r.os) { - case "fuchsia": - case "ios": - case "android": - document.getElementsByTagName("html")[0].classList.add("mobile") - } + switch (r.os) { + case "fuchsia": + case "ios": + case "android": + document.getElementsByTagName("html")[0].classList.add("mobile") + } }) const allSites = document.getElementById("all_sites") @@ -24,94 +24,96 @@ const config = await utils.getConfig() const divs = {} for (const service in config.services) { - divs[service] = {} - - divs[service].all = allSites.getElementsByClassName(service)[0] - divs[service].current = currSite.getElementsByClassName(service)[0] - - divs[service].all_toggle = allSites.getElementsByClassName(`${service}-enabled`)[0] - divs[service].all_toggle.addEventListener("change", async () => { - const options = await utils.getOptions() - options[service].enabled = divs[service].all_toggle.checked - browser.storage.local.set({ options }) - }) - - allSites.getElementsByClassName(`${service}-change_instance`)[0].addEventListener("click", () => { - browser.tabs.query({ active: true, currentWindow: true }, async tabs => { - if (tabs[0].url) { - const url = new URL(tabs[0].url) - browser.tabs.update({ url: await servicesHelper.switchInstance(url, service) }) - } - }) - }) - - divs[service].current_toggle = currSite.getElementsByClassName(`${service}-enabled`)[0] - divs[service].current_toggle.addEventListener("change", async () => { - const options = await utils.getOptions() - options[service].enabled = divs[service].current_toggle.checked - browser.storage.local.set({ options }) - }) - - currSite.getElementsByClassName(`${service}-change_instance`)[0].addEventListener("click", () => { - browser.tabs.query({ active: true, currentWindow: true }, async tabs => { - if (tabs[0].url) { - const url = new URL(tabs[0].url) - browser.tabs.update({ url: await servicesHelper.switchInstance(url, service) }) - } - }) - }) + divs[service] = {} + + divs[service].all = allSites.getElementsByClassName(service)[0] + divs[service].current = currSite.getElementsByClassName(service)[0] + + divs[service].all_toggle = allSites.getElementsByClassName(`${service}-enabled`)[0] + divs[service].all_toggle.addEventListener("change", async () => { + const options = await utils.getOptions() + options[service].enabled = divs[service].all_toggle.checked + browser.storage.local.set({ options }) + }) + + allSites.getElementsByClassName(`${service}-change_instance`)[0].addEventListener("click", () => { + browser.tabs.query({ active: true, currentWindow: true }, async tabs => { + if (tabs[0].url) { + const url = new URL(tabs[0].url) + browser.tabs.update({ url: await servicesHelper.switchInstance(url, service) }) + } + }) + }) + + divs[service].current_toggle = currSite.getElementsByClassName(`${service}-enabled`)[0] + divs[service].current_toggle.addEventListener("change", async () => { + const options = await utils.getOptions() + options[service].enabled = divs[service].current_toggle.checked + browser.storage.local.set({ options }) + }) + + currSite.getElementsByClassName(`${service}-change_instance`)[0].addEventListener("click", () => { + browser.tabs.query({ active: true, currentWindow: true }, async tabs => { + if (tabs[0].url) { + const url = new URL(tabs[0].url) + browser.tabs.update({ url: await servicesHelper.switchInstance(url, service) }) + } + }) + }) } browser.tabs.query({ active: true, currentWindow: true }, async tabs => { - // Set visibility of control buttons - if (tabs[0].url) { - const hr = document.getElementById("hr") - var url = new URL(tabs[0].url) - servicesHelper.switchInstance(url).then(r => { - if (r) { - document.getElementById("change_instance_div").style.display = "" - hr.style.display = "" - document.getElementById("change_instance").addEventListener("click", async () => - browser.tabs.update({ url: await servicesHelper.switchInstance(url) }) - ) - } - }) - servicesHelper.reverse(url).then(r => { - if (r) { - hr.style.display = "" - - document.getElementById("copy_original_div").style.display = "" - document.getElementById("copy_original").addEventListener("click", () => servicesHelper.copyRaw(url)) - - document.getElementById("redirect_to_original_div").style.display = "" - document.getElementById("redirect_to_original").addEventListener("click", () => browser.runtime.sendMessage("reverseTab")) - } - }) - servicesHelper.redirectAsync(url, "main_frame", null, true).then(r => { - if (r) { - document.getElementById("redirect_div").style.display = "" - hr.style.display = "" - document.getElementById("redirect").addEventListener("click", () => browser.runtime.sendMessage("redirectTab")) - } - }) - } - - const options = await utils.getOptions() - - // Set visibility of all service buttons - for (const service of options.popupServices) { - divs[service].all.classList.remove("hide") - divs[service].all_toggle.checked = options[service].enabled - } - - // Set visibility of current page service button - if (url) { - const service = await servicesHelper.computeService(url) - if (service) { - divs[service].all.classList.add("hide") - divs[service].current.classList.remove("hide") - divs[service].current_toggle.checked = options[service].enabled - currentSiteDivider.style.display = "" - } - } -}) \ No newline at end of file + // Set visibility of control buttons + if (tabs[0].url) { + const hr = document.getElementById("hr") + var url = new URL(tabs[0].url) + servicesHelper.switchInstance(url).then(r => { + if (r) { + document.getElementById("change_instance_div").style.display = "" + hr.style.display = "" + document + .getElementById("change_instance") + .addEventListener("click", async () => browser.tabs.update({ url: await servicesHelper.switchInstance(url) })) + } + }) + servicesHelper.reverse(url).then(r => { + if (r) { + hr.style.display = "" + + document.getElementById("copy_original_div").style.display = "" + document.getElementById("copy_original").addEventListener("click", () => servicesHelper.copyRaw(url)) + + document.getElementById("redirect_to_original_div").style.display = "" + document + .getElementById("redirect_to_original") + .addEventListener("click", () => browser.runtime.sendMessage("reverseTab")) + } + }) + servicesHelper.redirectAsync(url, "main_frame", null, true).then(r => { + if (r) { + document.getElementById("redirect_div").style.display = "" + hr.style.display = "" + document.getElementById("redirect").addEventListener("click", () => browser.runtime.sendMessage("redirectTab")) + } + }) + } + + const options = await utils.getOptions() + + // Set visibility of all service buttons + for (const service of options.popupServices) { + divs[service].all.classList.remove("hide") + divs[service].all_toggle.checked = options[service].enabled + } + + // Set visibility of current page service button + if (url) { + const service = await servicesHelper.computeService(url) + if (service) { + divs[service].all.classList.add("hide") + divs[service].current.classList.remove("hide") + divs[service].current_toggle.checked = options[service].enabled + currentSiteDivider.style.display = "" + } + } +}) diff --git a/src/pages/popup/style.css b/src/pages/popup/style.css index 5e39b4ed..41510615 100644 --- a/src/pages/popup/style.css +++ b/src/pages/popup/style.css @@ -1,65 +1,65 @@ body { - width: 270px; - min-height: auto; + width: 270px; + min-height: auto; } html, body { - margin: 0; + margin: 0; } .hide { - display: none !important; + display: none !important; } .button { - display: flex; - margin: 0 auto; - justify-content: space-between; + display: flex; + margin: 0 auto; + justify-content: space-between; } .button svg { - width: 26px; - height: 26px; + width: 26px; + height: 26px; } .bottom-button { - width: 100%; + width: 100%; } .space { - height: 10px; + height: 10px; } input { - height: 23px; - width: 46px; + height: 23px; + width: 46px; } div.block label { - margin: 0; - font-size: 18px; - font-weight: bold; - max-width: 180px; + margin: 0; + font-size: 18px; + font-weight: bold; + max-width: 180px; } div.block label:hover { - cursor: pointer; + cursor: pointer; } div.block div { - display: flex; + display: flex; } html.mobile body { - width: 100%; + width: 100%; } html.mobile div.block label { - font-size: 24px; + font-size: 24px; } html.mobile .button svg { - width: 30px; - height: 30px; -} \ No newline at end of file + width: 30px; + height: 30px; +} diff --git a/src/pages/stylesheets/styles.css b/src/pages/stylesheets/styles.css index b220efdb..ca6f0dca 100644 --- a/src/pages/stylesheets/styles.css +++ b/src/pages/stylesheets/styles.css @@ -1,450 +1,449 @@ body { - --text: #fff; - --bg-main: #121212; - --bg-secondary: #202020; - --active: #fbc117; - --danger: #f04141; - --light-grey: #c3c3c3; + --text: #fff; + --bg-main: #121212; + --bg-secondary: #202020; + --active: #fbc117; + --danger: #f04141; + --light-grey: #c3c3c3; } @font-face { - font-family: "Inter"; - src: url("Inter-VariableFont_slnt,wght.ttf"); - font-weight: normal; - font-style: normal; + font-family: "Inter"; + src: url("Inter-VariableFont_slnt,wght.ttf"); + font-weight: normal; + font-style: normal; } @font-face { - font-family: "Vazirmatn"; - src: url("Vazirmatn-VariableFont_wght.ttf"); - font-weight: normal; - font-style: normal; + font-family: "Vazirmatn"; + src: url("Vazirmatn-VariableFont_wght.ttf"); + font-weight: normal; + font-style: normal; } body { - margin: auto; - padding: 0; - font-family: "Inter"; - font-size: 16px; - background-color: var(--bg-main); - color: var(--text); + margin: auto; + padding: 0; + font-family: "Inter"; + font-size: 16px; + background-color: var(--bg-main); + color: var(--text); } body * { - font-family: "Inter"; + font-family: "Inter"; } body.rtl { - font-family: "Vazirmatn"; + font-family: "Vazirmatn"; } body.rtl * { - font-family: "Vazirmatn"; + font-family: "Vazirmatn"; } div.block input[type="checkbox"] { - appearance: none; - -moz-appearance: none; - -webkit-appearance: none; + appearance: none; + -moz-appearance: none; + -webkit-appearance: none; } .title { - display: flex; - align-items: center; - text-decoration: none; - width: min-content; - color: var(--text); - transition: .1s; + display: flex; + align-items: center; + text-decoration: none; + width: min-content; + color: var(--text); + transition: 0.1s; } .title:hover { - opacity: 1 !important; + opacity: 1 !important; } .title:hover a { - color: var(--active); + color: var(--active); } img, svg { - margin-right: 10px; - height: 26px; - width: 26px; - color: var(--text); + margin-right: 10px; + height: 26px; + width: 26px; + color: var(--text); } body.rtl img, body.rtl svg { - margin-right: 0px; - margin-left: 10px; + margin-right: 0px; + margin-left: 10px; } input[type="url"], input[type="text"], select { - font-weight: bold; - box-sizing: border-box; - border-style: solid; - border-color: #767676; - color: var(--text); - font-size: 16px; - padding: 8px; - background-color: var(--bg-secondary); - border: none; - margin: 0; - max-width: 500px; - border-radius: 3px; + font-weight: bold; + box-sizing: border-box; + border-style: solid; + border-color: #767676; + color: var(--text); + font-size: 16px; + padding: 8px; + background-color: var(--bg-secondary); + border: none; + margin: 0; + max-width: 500px; + border-radius: 3px; } input[type="url"], input[type="text"] { - width: 400px; - cursor: text; + width: 400px; + cursor: text; } input:invalid { - color: var(--danger); + color: var(--danger); } .button svg { - height: 18px; - width: 18px; + height: 18px; + width: 18px; } section.block-option { - width: 750px; - margin: 0 50px; + width: 750px; + margin: 0 50px; } section.block-option h2 { - margin: 0; + margin: 0; } body.option { - display: flex; - padding: 40px; - width: 1160px; + display: flex; + padding: 40px; + width: 1160px; } section.links { - display: flex; - flex-wrap: wrap; - flex-direction: column; - width: 350px; - max-height: 1030px; + display: flex; + flex-wrap: wrap; + flex-direction: column; + width: 350px; + max-height: 1030px; } section.links div { - margin: 10px; - width: max-content; + margin: 10px; + width: max-content; } a { - text-decoration: none; - color: var(--text); - transition: 0.1s; + text-decoration: none; + color: var(--text); + transition: 0.1s; } a:hover { - color: var(--active); + color: var(--active); } section.links a { - display: flex; - align-items: center; - font-size: 18px; - text-decoration: none; - color: white; - transition: 0.1s; + display: flex; + align-items: center; + font-size: 18px; + text-decoration: none; + color: white; + transition: 0.1s; } section.links a:hover, section.links .selected { - opacity: 1 !important; + opacity: 1 !important; } section.links .selected a { - color: var(--active); + color: var(--active); } ::placeholder { - color: var(--text); - opacity: 0.7; + color: var(--text); + opacity: 0.7; } hr { - height: 2px; - margin: 0 15px; - background-color: rgb(77, 77, 77); - border: none; + height: 2px; + margin: 0 15px; + background-color: rgb(77, 77, 77); + border: none; } div.block { - padding: 0 15px; - justify-content: space-between; - display: flex; - align-items: center; - margin-top: 10px; - margin-bottom: 10px; + padding: 0 15px; + justify-content: space-between; + display: flex; + align-items: center; + margin-top: 10px; + margin-bottom: 10px; } div.block-option { - margin: 30px 0; + margin: 30px 0; } div.block-option label { - margin-right: 5px; - width: 80%; - min-width: 150px; - font-size: 18px; + margin-right: 5px; + width: 80%; + min-width: 150px; + font-size: 18px; } div.block-option h1 { - margin: 0; - font-size: 28px; - color: var(--text); + margin: 0; + font-size: 28px; + color: var(--text); } div.block-option div { - text-align: center; + text-align: center; } div.block input[type="checkbox"] { - width: 46px; - height: 24px; - background-color: var(--light-grey); - border-radius: 50px; - transition: 0.4s; - cursor: pointer; + width: 46px; + height: 24px; + background-color: var(--light-grey); + border-radius: 50px; + transition: 0.4s; + cursor: pointer; } div.block input[type="checkbox"]:checked { - background-color: var(--active); + background-color: var(--active); } div.block input[type="checkbox"]::before { - content: ""; - display: inline-block; - width: 18px; - height: 18px; - box-sizing: border-box; - position: relative; - top: 2.5px; - left: 3.5px; - background-color: white; - border-radius: 50%; - transition: 0.3s; + content: ""; + display: inline-block; + width: 18px; + height: 18px; + box-sizing: border-box; + position: relative; + top: 2.5px; + left: 3.5px; + background-color: white; + border-radius: 50%; + transition: 0.3s; } body.rtl div.block input[type="checkbox"]::before { - left: auto; - right: 4px; + left: auto; + right: 4px; } div.block input[type="checkbox"]:checked::before { - left: 24px; + left: 24px; } body.rtl div.block input[type="checkbox"]:checked::before { - left: auto; - right: 24px; + left: auto; + right: 24px; } div.buttons { - display: flex; - margin: 0 15px; - margin-bottom: 15px; - margin-top: 15px; - flex-wrap: wrap; - align-items: center; - justify-content: start; + display: flex; + margin: 0 15px; + margin-bottom: 15px; + margin-top: 15px; + flex-wrap: wrap; + align-items: center; + justify-content: start; } .button { - color: var(--text); - font-size: 16px; - font-weight: bold; - text-decoration: none; - cursor: pointer; - transition-duration: 0.1s; + color: var(--text); + font-size: 16px; + font-weight: bold; + text-decoration: none; + cursor: pointer; + transition-duration: 0.1s; } .button:hover { - color: var(--active); + color: var(--active); } .button svg { - width: auto; - height: auto; - padding: 0; - margin-right: 5px; + width: auto; + height: auto; + padding: 0; + margin-right: 5px; } .button:hover svg { - color: var(--active); + color: var(--active); } .button-inline { - display: inline-flex; - align-items: center; - margin: 7.5px 0; - background-color: var(--bg-secondary); - border-radius: 5px; - padding: 10px; + display: inline-flex; + align-items: center; + margin: 7.5px 0; + background-color: var(--bg-secondary); + border-radius: 5px; + padding: 10px; } .button:active { - transform: translateY(1px); + transform: translateY(1px); } button svg { - color: var(--text); + color: var(--text); } div.checklist div { - justify-content: space-between; - margin: 5px 15px; - padding: 10px 0; - word-wrap: break-word; - display: flex; + justify-content: space-between; + margin: 5px 15px; + padding: 10px 0; + word-wrap: break-word; + display: flex; } div.checklist a { - text-decoration: none; - color: var(--text); + text-decoration: none; + color: var(--text); } div.checklist a:hover { - text-decoration: underline; + text-decoration: underline; } div.custom-checklist x a { - color: var(--active); + color: var(--active); } button.add { - background-color: transparent; - border: none; - padding: 0; - margin: 0; - text-decoration: none; - display: inline-block; - cursor: pointer; + background-color: transparent; + border: none; + padding: 0; + margin: 0; + text-decoration: none; + display: inline-block; + cursor: pointer; } body.light-theme { - --text: black; - --bg-main: white; - --bg-secondary: #e4e4e4; - --active: #fb9817; + --text: black; + --bg-main: white; + --bg-secondary: #e4e4e4; + --active: #fb9817; } body.light-theme select { - border: 1px solid black; + border: 1px solid black; } body.light-theme a { - color: black; + color: black; } body.light-theme a:hover { - color: var(--active) + color: var(--active); } button { - background-color: transparent; - color: var(--text); - border: none; - text-decoration: none; - display: inline-block; - cursor: pointer; - border-radius: 5px; + background-color: transparent; + color: var(--text); + border: none; + text-decoration: none; + display: inline-block; + cursor: pointer; + border-radius: 5px; } body div section { - display: none; + display: none; } select:disabled { - opacity: 0.6; - cursor: not-allowed; + opacity: 0.6; + cursor: not-allowed; } input:disabled { - opacity: 0.6; - cursor: not-allowed; + opacity: 0.6; + cursor: not-allowed; } @media (max-width: 1250px) { - body.option { - flex-direction: column; - width: 95vw; - align-items: center; - padding: 40px 0px; - } + body.option { + flex-direction: column; + width: 95vw; + align-items: center; + padding: 40px 0px; + } - section.links { - flex-direction: row; - width: 95vw; - padding: 0 55px; - } + section.links { + flex-direction: row; + width: 95vw; + padding: 0 55px; + } - section.block-option { - width: 95vw; - } + section.block-option { + width: 95vw; + } - div.checklist div x { - overflow: hidden; - } + div.checklist div x { + overflow: hidden; + } } html.mobile img, html.mobile svg { - margin-right: 10px; - height: 30px; - width: 30px; - color: var(--text); + margin-right: 10px; + height: 30px; + width: 30px; + color: var(--text); } html.mobile div.block { - padding: 0 15px; - justify-content: space-between; - display: flex; - align-items: center; - margin-top: 20px; - margin-bottom: 20px; + padding: 0 15px; + justify-content: space-between; + display: flex; + align-items: center; + margin-top: 20px; + margin-bottom: 20px; } html.mobile div.block input[type="checkbox"] { - width: 58px; - height: 30px; + width: 58px; + height: 30px; } html.mobile div.block input[type="checkbox"]::before { - width: 24px; - height: 24px; - top: 3px; - left: 3.5px; + width: 24px; + height: 24px; + top: 3px; + left: 3.5px; } html.mobile div.block input[type="checkbox"]:checked::before { - left: 30px; + left: 30px; } html.mobile body.option { - flex-direction: column; - width: 100%; - padding: 0; - align-items: center; + flex-direction: column; + width: 100%; + padding: 0; + align-items: center; } - html.mobile section.links { - flex-direction: row; - width: 100%; - padding: 0 55px; + flex-direction: row; + width: 100%; + padding: 0 55px; } html.mobile section.block-option { - width: 100%; -} \ No newline at end of file + width: 100%; +} diff --git a/test-conditions.md b/test-conditions.md index 843b263e..7909a1a2 100644 --- a/test-conditions.md +++ b/test-conditions.md @@ -16,11 +16,11 @@ YouTube Music (Tested with YouTube turned off) Homepage - [https://music.youtube.com](https://music.youtube.com) Page - [https://hyperpipe.surge.sh/channel/UCPC0L1d253x-KuMNwa05TpA](https://hyperpipe.surge.sh/channel/UCPC0L1d253x-KuMNwa05TpA) Explore - [https://hyperpipe.surge.sh/explore/](https://hyperpipe.surge.sh/explore/) - + YT Embeds - [https://famiboards.com/threads/nintendo-switch-sports-announced-launches-april-29th-update-main-theme-in-threadmarks.1907/](https://famiboards.com/threads/nintendo-switch-sports-announced-launches-april-29th-update-main-theme-in-threadmarks.1907/) Twitch -[https://www.twitch.tv/pokimane](https://www.twitch.tv/pokimane) - + TikTok - [https://www.tiktok.com/@zoecolletti?lang=en](https://www.tiktok.com/@zoecolletti?lang=en) Reddit & Imgur `(Embeds)` - [https://www.reddit.com/61ns2w/](https://www.reddit.com/61ns2w/) @@ -32,22 +32,22 @@ Quora - [https://www.quora.com/What-is-the-equivalent-weight-of-hydrocloric-acid Pinterest - [https://www.pinterest.com/aldiukstores/aldi-recipes/](https://www.pinterest.com/aldiukstores/aldi-recipes/) IMDb - [https://www.imdb.com/title/tt23556786/](https://www.imdb.com/title/tt23556786/) **[Check if new URL schemes are supported by the Dev.]** - + Fandom - [https://naruto.fandom.com](https://naruto.fandom.com) - + Genius - [https://genius.com/Doja-cat-demons-lyrics](https://genius.com/Doja-cat-demons-lyrics) - + Urbandictionary - [https://urbandictionary.com/define.php?term=Roads](https://urbandictionary.com/define.php?term=Roads) - + Stackoverflow - [https://stackoverflow.com/questions/16330404/how-to-remove-remote-origin-from-a-git-repository](https://stackoverflow.com/questions/16330404/how-to-remove-remote-origin-from-a-git-repository) - + Goodreads - [https://www.goodreads.com/book/show/3869.A_Brief_History_of_Time](https://www.goodreads.com/book/show/3869.A_Brief_History_of_Time) - + Bandcamp - [https://thorwegian.bandcamp.com/track/just-because](https://thorwegian.bandcamp.com/track/just-because) - + Instructables - [https://instructables.com/DIY-Arduino-Obstacle-Avoiding-Car-at-Home/](https://instructables.com/DIY-Arduino-Obstacle-Avoiding-Car-at-Home/) - -Web archive - [https://web.archive.org/web/20230131222432if_/https://www.dailymail.co.uk/news/article-11687675/Army-spied-lockdown-critics-Sceptics-including-Peter-Hitchens-suspected-watched.html](https://web.archive.org/web/20230131222432if_/https://www.dailymail.co.uk/news/article-11687675/Army-spied-lockdown-critics-Sceptics-including-Peter-Hitchens-suspected-watched.html) + +Web archive - [https://web.archive.org/web/20230131222432if\_/https://www.dailymail.co.uk/news/article-11687675/Army-spied-lockdown-critics-Sceptics-including-Peter-Hitchens-suspected-watched.html](https://web.archive.org/web/20230131222432if_/https://www.dailymail.co.uk/news/article-11687675/Army-spied-lockdown-critics-Sceptics-including-Peter-Hitchens-suspected-watched.html) --- -- cgit 1.4.1 From ff16ab40f8a315df049fc602db57b1e40eeaaaad Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Thu, 1 Aug 2024 12:31:26 +0300 Subject: Added Freetar https://github.com/libredirect/browser_extension/issues/942 --- src/assets/images/ultimateGuitar-icon.svg | 1 + src/assets/javascripts/services.js | 10 ++++++++++ src/config.json | 18 ++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 src/assets/images/ultimateGuitar-icon.svg (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/images/ultimateGuitar-icon.svg b/src/assets/images/ultimateGuitar-icon.svg new file mode 100644 index 00000000..5f587c3c --- /dev/null +++ b/src/assets/images/ultimateGuitar-icon.svg @@ -0,0 +1 @@ + diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 39347845..cc10b75c 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -531,6 +531,15 @@ function rewrite(url, frontend, randomInstance) { } return `${randomInstance}${url.pathname}${url.search}` } + case "freetar": + if (url.pathname.startsWith("/search.php")) { + url.searchParams.set("search_term", url.searchParams.get("value")) + url.searchParams.delete("value") + url.searchParams.delete("search_type") + return `${randomInstance}/search${url.search}` + } + if (url.pathname.startsWith("/artist")) return + return `${randomInstance}${url.pathname}${url.search}` case "piped": case "pipedMaterial": case "cloudtube": @@ -779,6 +788,7 @@ const defaultInstances = { priviblur: ["https://pb.bloat.cat"], nitter: ["https://nitter.privacydev.net"], pasted: ["https://pasted.drakeerv.com"], + freetar: ["https://freetar.de"], } function initDefaults() { diff --git a/src/config.json b/src/config.json index 9728cdc3..5ce60310 100644 --- a/src/config.json +++ b/src/config.json @@ -1032,6 +1032,24 @@ }, "imageType": "svgMono", "url": "https://paste.libredirect.invalid" + }, + "ultimateGuitar": { + "frontends": { + "freetar": { + "name": "Freetar", + "instanceList": true, + "url": "https://github.com/kmille/freetar" + } + }, + "targets": ["^https?:\\/{2}(tabs\\.|www\\.)?ultimate-guitar\\.com"], + "name": "Ultimate Guitar", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "freetar" + }, + "imageType": "svg", + "url": "https://www.ultimate-guitar.com" } } } -- cgit 1.4.1 From 76820c56e74f47fa63f220d0b9c23d4635dac4f4 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Wed, 7 Aug 2024 18:34:25 +0300 Subject: Added Nitter Reverse Redirect https://github.com/libredirect/browser_extension/issues/958 --- src/assets/javascripts/services.js | 1 + 1 file changed, 1 insertion(+) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index cc10b75c..5c263256 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -697,6 +697,7 @@ async function reverse(url) { case "snopes": case "urbanDictionary": case "quora": + case "twitter": case "medium": return `${config.services[service].url}${url.pathname}${url.search}` case "fandom": { -- cgit 1.4.1 From 64b765d775b0adadc1ac20db54cc9501503d9200 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Fri, 9 Aug 2024 22:24:03 +0300 Subject: Added Eddrit https://github.com/libredirect/browser_extension/issues/938 --- src/assets/javascripts/services.js | 4 ++++ src/config.json | 10 ++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 5c263256..8dee83db 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -273,6 +273,9 @@ function rewrite(url, frontend, randomInstance) { else return `${randomInstance}${url.pathname}${url.search}&teddit_proxy=${url.hostname}` } return `${randomInstance}${url.pathname}${url.search}` + case "eddrit": + if (/^(?:(?:external-)?preview|i)\.redd\.it/.test(url.hostname)) return randomInstance + return `${randomInstance}${url.pathname}${url.search}` case "neuters": { const p = url.pathname if (p.startsWith("/article/") || p.startsWith("/pf/") || p.startsWith("/arc/") || p.startsWith("/resizer/")) { @@ -746,6 +749,7 @@ const defaultInstances = { redlib: ["https://safereddit.com"], libreddit: ["https://libreddit.spike.codes"], teddit: ["https://teddit.net"], + eddrit: ["https://eddrit.com"], scribe: ["https://scribe.rip"], libMedium: ["https://md.vern.cc"], quetre: ["https://quetre.iket.me"], diff --git a/src/config.json b/src/config.json index 5ce60310..350559bd 100644 --- a/src/config.json +++ b/src/config.json @@ -214,13 +214,19 @@ "name": "Redlib", "instanceList": true, "url": "https://github.com/redlib-org/redlib", - "localhost": true + "localhost": false }, "teddit": { "name": "Teddit", "instanceList": true, "url": "https://codeberg.org/teddit/teddit", - "localhost": true + "localhost": false + }, + "eddrit": { + "name": "Eddrit", + "instanceList": true, + "url": "https://github.com/corenting/eddrit", + "localhost": false } }, "targets": [ -- cgit 1.4.1 From 77f233437c891dcc041158eee46b60e50bd3c993 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Fri, 9 Aug 2024 23:14:48 +0300 Subject: Added RAT https://github.com/libredirect/browser_extension/issues/937 --- src/assets/images/baiduTieba-icon.svg | 72 +++++++++++++++++++++++++++++++++++ src/assets/javascripts/services.js | 4 ++ src/config.json | 18 +++++++++ 3 files changed, 94 insertions(+) create mode 100644 src/assets/images/baiduTieba-icon.svg (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/images/baiduTieba-icon.svg b/src/assets/images/baiduTieba-icon.svg new file mode 100644 index 00000000..70f8c46d --- /dev/null +++ b/src/assets/images/baiduTieba-icon.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 8dee83db..dbd3ea2c 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -543,6 +543,9 @@ function rewrite(url, frontend, randomInstance) { } if (url.pathname.startsWith("/artist")) return return `${randomInstance}${url.pathname}${url.search}` + case "ratAintTieba": + url.searchParams.delete("ie") + return `${randomInstance}${url.pathname}${url.search}` case "piped": case "pipedMaterial": case "cloudtube": @@ -794,6 +797,7 @@ const defaultInstances = { nitter: ["https://nitter.privacydev.net"], pasted: ["https://pasted.drakeerv.com"], freetar: ["https://freetar.de"], + ratAintTieba: ["https://rat.fis.land"], } function initDefaults() { diff --git a/src/config.json b/src/config.json index 350559bd..848f2a21 100644 --- a/src/config.json +++ b/src/config.json @@ -1056,6 +1056,24 @@ }, "imageType": "svg", "url": "https://www.ultimate-guitar.com" + }, + "baiduTieba": { + "frontends": { + "ratAintTieba": { + "name": "Rat Aint Tieba", + "instanceList": true, + "url": "https://0xacab.org/johnxina/rat" + } + }, + "targets": ["^https?:\\/{2}tieba\\.baidu\\.com"], + "name": "Baidu Tieba", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "ratAintTieba" + }, + "imageType": "svg", + "url": "https://tieba.baidu.com" } } } -- cgit 1.4.1 From 27877339bd99cbd1e5d0fd1b103c162265709542 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Fri, 16 Aug 2024 21:42:08 +0300 Subject: Added Shoelace https://github.com/libredirect/browser_extension/issues/932 --- src/assets/images/threads-icon-light.svg | 21 ++++ src/assets/images/threads-icon.svg | 18 +++ src/assets/javascripts/services.js | 6 + src/config.json | 194 ++++++++++++++++++++++++------- 4 files changed, 198 insertions(+), 41 deletions(-) create mode 100644 src/assets/images/threads-icon-light.svg create mode 100644 src/assets/images/threads-icon.svg (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/images/threads-icon-light.svg b/src/assets/images/threads-icon-light.svg new file mode 100644 index 00000000..809c12d8 --- /dev/null +++ b/src/assets/images/threads-icon-light.svg @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/src/assets/images/threads-icon.svg b/src/assets/images/threads-icon.svg new file mode 100644 index 00000000..e99823bb --- /dev/null +++ b/src/assets/images/threads-icon.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index dbd3ea2c..b319d46b 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -546,6 +546,11 @@ function rewrite(url, frontend, randomInstance) { case "ratAintTieba": url.searchParams.delete("ie") return `${randomInstance}${url.pathname}${url.search}` + case "shoelace": { + const reg = /\/(?:(?:(?:.*)?\/post)|t)\/(.*)(?:\/)?/.exec(url.pathname) + if (reg) return `${randomInstance}/t/${reg[1]}${url.search}` + return `${randomInstance}${url.pathname}${url.search}` + } case "piped": case "pipedMaterial": case "cloudtube": @@ -798,6 +803,7 @@ const defaultInstances = { pasted: ["https://pasted.drakeerv.com"], freetar: ["https://freetar.de"], ratAintTieba: ["https://rat.fis.land"], + shoelace: ["https://shoelace.mint.lgbt"], } function initDefaults() { diff --git a/src/config.json b/src/config.json index 45220990..a42b7c73 100644 --- a/src/config.json +++ b/src/config.json @@ -33,21 +33,30 @@ "url": "https://materialio.us/" }, "piped": { - "excludeTargets": [2, 3], + "excludeTargets": [ + 2, + 3 + ], "name": "Piped", "embeddable": true, "instanceList": true, "url": "https://github.com/TeamPiped/Piped" }, "pipedMaterial": { - "excludeTargets": [2, 3], + "excludeTargets": [ + 2, + 3 + ], "name": "Piped-Material", "embeddable": false, "instanceList": true, "url": "https://github.com/mmjee/Piped-Material" }, "poketube": { - "excludeTargets": [2, 3], + "excludeTargets": [ + 2, + 3 + ], "name": "PokeTube", "embeddable": true, "instanceList": true, @@ -58,7 +67,10 @@ "embeddable": false, "instanceList": true, "url": "https://sr.ht/~cadence/tube", - "excludeTargets": [2, 3] + "excludeTargets": [ + 2, + 3 + ] }, "lightTube": { "name": "LightTube", @@ -71,10 +83,16 @@ "embeddable": false, "instanceList": true, "url": "https://git.migalmoreno.com/tubo/about/", - "excludeTargets": [2, 3] + "excludeTargets": [ + 2, + 3 + ] }, "freetube": { - "excludeTargets": [2, 3], + "excludeTargets": [ + 2, + 3 + ], "name": "FreeTube", "embeddable": false, "desktopApp": true, @@ -82,7 +100,10 @@ "url": "https://github.com/FreeTubeApp/FreeTube" }, "yattee": { - "excludeTargets": [2, 3], + "excludeTargets": [ + 2, + 3 + ], "name": "Yattee", "embeddable": false, "desktopApp": true, @@ -90,7 +111,10 @@ "url": "https://github.com/yattee/yattee" }, "freetubePwa": { - "excludeTargets": [2, 3], + "excludeTargets": [ + 2, + 3 + ], "name": "FreeTube PWA", "embeddable": false, "instanceList": false, @@ -144,7 +168,9 @@ "url": "https://github.com/FreeTubeApp/FreeTube" } }, - "targets": ["^https?:\\/{2}music\\.youtube\\.com\\/"], + "targets": [ + "^https?:\\/{2}music\\.youtube\\.com\\/" + ], "name": "YT Music", "options": { "enabled": false, @@ -192,7 +218,9 @@ "url": "https://github.com/badlogic/skyview" } }, - "targets": ["^https?:\\/{2}bsky\\.app\\/"], + "targets": [ + "^https?:\\/{2}bsky\\.app\\/" + ], "name": "Bluesky", "options": { "enabled": false, @@ -287,7 +315,9 @@ "localhost": false } }, - "targets": ["^https?:\\/{2}(www\\.|clips\\.)?twitch\\.(tv|com)\\/"], + "targets": [ + "^https?:\\/{2}(www\\.|clips\\.)?twitch\\.(tv|com)\\/" + ], "name": "Twitch", "options": { "enabled": false, @@ -309,7 +339,9 @@ "localhost": true } }, - "targets": ["^https?:\\/{2}(www\\.)?tiktok\\.com\\/"], + "targets": [ + "^https?:\\/{2}(www\\.)?tiktok\\.com\\/" + ], "name": "TikTok", "options": { "enabled": false, @@ -329,7 +361,9 @@ "localhost": false } }, - "targets": ["^https?:\\/{2}(www\\.)?instagram\\.com"], + "targets": [ + "^https?:\\/{2}(www\\.)?instagram\\.com" + ], "name": "Instagram", "options": { "enabled": false, @@ -349,7 +383,9 @@ "localhost": true } }, - "targets": ["^https?:\\/{2}(www\\.|m\\.)?imdb\\.com"], + "targets": [ + "^https?:\\/{2}(www\\.|m\\.)?imdb\\.com" + ], "name": "IMDb", "options": { "enabled": false, @@ -368,7 +404,10 @@ "url": "https://0xacab.org/johnxina/mikuinvidious" } }, - "targets": ["^https?:\\/{2}(www\\.|space\\.)?bilibili\\.com\\/", "^https?:\\/{2}b23\\.tv\\/"], + "targets": [ + "^https?:\\/{2}(www\\.|space\\.)?bilibili\\.com\\/", + "^https?:\\/{2}b23\\.tv\\/" + ], "name": "Bilibili", "options": { "enabled": false, @@ -387,7 +426,9 @@ "url": "https://codeberg.org/VnPower/pixivfe" } }, - "targets": ["^https?:\\/{2}(www\\.)?pixiv\\.net\\/"], + "targets": [ + "^https?:\\/{2}(www\\.)?pixiv\\.net\\/" + ], "options": { "enabled": false, "unsupportedUrls": "bypass", @@ -404,7 +445,9 @@ "url": "https://breezewiki.com" } }, - "targets": ["^https?:\\/{2}([a-zA-Z0-9-]+\\.)?(fandom|wikia)\\.com(?=\\/wiki|\\/?$)"], + "targets": [ + "^https?:\\/{2}([a-zA-Z0-9-]+\\.)?(fandom|wikia)\\.com(?=\\/wiki|\\/?$)" + ], "name": "Fandom", "options": { "enabled": false, @@ -425,7 +468,9 @@ "embeddable": true } }, - "targets": ["^https?:\\/{2}([im]\\.)?(stack\\.)?imgur\\.(com|io)\\/"], + "targets": [ + "^https?:\\/{2}([im]\\.)?(stack\\.)?imgur\\.(com|io)\\/" + ], "name": "Imgur", "options": { "enabled": false, @@ -448,7 +493,10 @@ "embeddable": true } }, - "targets": ["^https?:\\/{2}i\\.pinimg\\.com", "^https?:\\/{2}(www\\.)?pinterest\\.com"], + "targets": [ + "^https?:\\/{2}i\\.pinimg\\.com", + "^https?:\\/{2}(www\\.)?pinterest\\.com" + ], "options": { "enabled": false, "unsupportedUrls": "bypass", @@ -468,7 +516,9 @@ "url": "https://git.migalmoreno.com/tubo/about/" } }, - "targets": ["^https?:\\/{2}soundcloud\\.com"], + "targets": [ + "^https?:\\/{2}soundcloud\\.com" + ], "name": "SoundCloud", "options": { "enabled": false, @@ -488,7 +538,10 @@ "url": "https://forgejo.sny.sh/sun/Tent" } }, - "targets": ["^https?:\\/{2}(.*\\.)?bandcamp\\.com\\/", "^https?:\\/{2}(f4|t4)\\.bcbits\\.com\\/"], + "targets": [ + "^https?:\\/{2}(.*\\.)?bandcamp\\.com\\/", + "^https?:\\/{2}(f4|t4)\\.bcbits\\.com\\/" + ], "name": "Bandcamp", "options": { "enabled": false, @@ -506,7 +559,9 @@ "url": "https://github.com/Davilarek/TekstoLibre" } }, - "targets": ["^https?:\\/{2}(www\\.)?tekstowo\\.pl\\/"], + "targets": [ + "^https?:\\/{2}(www\\.)?tekstowo\\.pl\\/" + ], "name": "Tekstowo.pl", "options": { "enabled": false, @@ -531,7 +586,9 @@ "localhost": false } }, - "targets": ["^https?:\\/{2}(www\\.)?genius\\.com\\/"], + "targets": [ + "^https?:\\/{2}(www\\.)?genius\\.com\\/" + ], "name": "Genius", "options": { "enabled": false, @@ -594,7 +651,9 @@ "localhost": true } }, - "targets": ["^https?:\\/{2}([a-zA-Z0-9-]+\\.)*quora\\.com\\/"], + "targets": [ + "^https?:\\/{2}([a-zA-Z0-9-]+\\.)*quora\\.com\\/" + ], "name": "Quora", "options": { "enabled": false, @@ -681,7 +740,9 @@ "url": "https://github.com/HookedBehemoth/neuters" } }, - "targets": ["^https?:\\/{2}(www\\.)?reuters\\.com\\/"], + "targets": [ + "^https?:\\/{2}(www\\.)?reuters\\.com\\/" + ], "name": "Reuters", "options": { "enabled": false, @@ -699,7 +760,9 @@ "url": "https://git.vern.cc/cobra/Suds" } }, - "targets": ["^https?:\\/{2}(www\\.)?snopes\\.com\\/"], + "targets": [ + "^https?:\\/{2}(www\\.)?snopes\\.com\\/" + ], "name": "Snopes", "options": { "enabled": false, @@ -717,7 +780,9 @@ "url": "https://git.vern.cc/cobra/UNfunny" } }, - "targets": ["^https?:\\/{2}(www\\.)?ifunny\\.co\\/"], + "targets": [ + "^https?:\\/{2}(www\\.)?ifunny\\.co\\/" + ], "name": "iFunny", "options": { "enabled": false, @@ -735,7 +800,9 @@ "url": "https://git.vern.cc/cobra/Soprano" } }, - "targets": ["^https?:\\/{2}(www\\.)?tenor\\.com\\/"], + "targets": [ + "^https?:\\/{2}(www\\.)?tenor\\.com\\/" + ], "name": "Tenor", "options": { "enabled": false, @@ -753,7 +820,9 @@ "url": "https://git.vern.cc/cobra/MeMe" } }, - "targets": ["^https?:\\/{2}(www\\.)?knowyourmeme\\.com\\/"], + "targets": [ + "^https?:\\/{2}(www\\.)?knowyourmeme\\.com\\/" + ], "name": "KnowYourMeme", "options": { "enabled": false, @@ -771,7 +840,9 @@ "url": "https://codeberg.org/zortazert/rural-dictionary" } }, - "targets": ["^https?:\\/{2}(www\\.)?urbandictionary\\.com\\/"], + "targets": [ + "^https?:\\/{2}(www\\.)?urbandictionary\\.com\\/" + ], "name": "Urban Dictionary", "options": { "enabled": false, @@ -790,7 +861,9 @@ "localhost": true } }, - "targets": ["^https?:\\/{2}(www\\.)?goodreads\\.com\\/"], + "targets": [ + "^https?:\\/{2}(www\\.)?goodreads\\.com\\/" + ], "name": "Goodreads", "options": { "enabled": false, @@ -809,7 +882,9 @@ "url": "https://git.disroot.org/wolfree" } }, - "targets": ["^https?:\\/{2}(www\\.)?wolframalpha\\.com\\/"], + "targets": [ + "^https?:\\/{2}(www\\.)?wolframalpha\\.com\\/" + ], "name": "Wolfram Alpha", "options": { "enabled": false, @@ -833,7 +908,9 @@ "url": "https://git.vern.cc/cobra/Destructables" } }, - "targets": ["^https?:\\/{2}(www\\.)?instructables\\.com\\/"], + "targets": [ + "^https?:\\/{2}(www\\.)?instructables\\.com\\/" + ], "options": { "enabled": false, "unsupportedUrls": "bypass", @@ -850,7 +927,9 @@ "url": "https://wikiless.org" } }, - "targets": ["^https?:\\/{2}([a-z]+\\.)*wikipedia\\.org\\/?"], + "targets": [ + "^https?:\\/{2}([a-z]+\\.)*wikipedia\\.org\\/?" + ], "name": "Wikipedia", "options": { "enabled": false, @@ -868,7 +947,9 @@ "url": "https://github.com/ticky/wayback-classic" } }, - "targets": ["^https?:\\/{2}web\\.archive\\.org\\/"], + "targets": [ + "^https?:\\/{2}web\\.archive\\.org\\/" + ], "name": "Wayback Machine", "options": { "enabled": false, @@ -929,7 +1010,10 @@ "url": "https://git.lolcat.ca/lolcat/4get" } }, - "targets": ["^https?:\\/{2}search\\.libredirect\\.invalid", "^https?:\\/{2}libredirect\\.github\\.io\\/\\?q"], + "targets": [ + "^https?:\\/{2}search\\.libredirect\\.invalid", + "^https?:\\/{2}libredirect\\.github\\.io\\/\\?q" + ], "name": "Search", "options": { "enabled": false, @@ -1007,7 +1091,9 @@ "url": "https://jitsi.org" } }, - "targets": ["^https?:\\/{2}meet\\.libredirect\\.invalid\\/"], + "targets": [ + "^https?:\\/{2}meet\\.libredirect\\.invalid\\/" + ], "options": { "enabled": false, "unsupportedUrls": "bypass", @@ -1051,7 +1137,9 @@ "url": "https://github.com/Dragynfruit/pasted" } }, - "targets": ["^https?:\\/{2}paste\\.libredirect\\.invalid"], + "targets": [ + "^https?:\\/{2}paste\\.libredirect\\.invalid" + ], "name": "Paste Text", "options": { "enabled": false, @@ -1069,7 +1157,9 @@ "url": "https://github.com/kmille/freetar" } }, - "targets": ["^https?:\\/{2}(tabs\\.|www\\.)?ultimate-guitar\\.com"], + "targets": [ + "^https?:\\/{2}(tabs\\.|www\\.)?ultimate-guitar\\.com" + ], "name": "Ultimate Guitar", "options": { "enabled": false, @@ -1087,7 +1177,9 @@ "url": "https://0xacab.org/johnxina/rat" } }, - "targets": ["^https?:\\/{2}tieba\\.baidu\\.com"], + "targets": [ + "^https?:\\/{2}tieba\\.baidu\\.com" + ], "name": "Baidu Tieba", "options": { "enabled": false, @@ -1096,6 +1188,26 @@ }, "imageType": "svg", "url": "https://tieba.baidu.com" + }, + "threads": { + "frontends": { + "shoelace": { + "name": "Shoelace", + "instanceList": true, + "url": "https://git.sr.ht/~nixgoat/shoelace" + } + }, + "targets": [ + "^https?:\\/{2}(www\\.)?threads\\.net" + ], + "name": "Threads", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "shoelace" + }, + "imageType": "svgMono", + "url": "https://threads.net" } } -} +} \ No newline at end of file -- cgit 1.4.1 From 5a503e9e20d14ad524c3c2b297da9a8b4316b362 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Fri, 16 Aug 2024 23:03:11 +0300 Subject: Added SkunkyArt https://github.com/libredirect/browser_extension/issues/948 --- src/assets/images/deviantArt-icon.svg | 474 ++++++++++++++++++++++++++++++++++ src/assets/javascripts/services.js | 17 +- src/config.json | 20 ++ 3 files changed, 510 insertions(+), 1 deletion(-) create mode 100644 src/assets/images/deviantArt-icon.svg (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/images/deviantArt-icon.svg b/src/assets/images/deviantArt-icon.svg new file mode 100644 index 00000000..30836c15 --- /dev/null +++ b/src/assets/images/deviantArt-icon.svg @@ -0,0 +1,474 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index b319d46b..94d8d980 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -547,10 +547,24 @@ function rewrite(url, frontend, randomInstance) { url.searchParams.delete("ie") return `${randomInstance}${url.pathname}${url.search}` case "shoelace": { - const reg = /\/(?:(?:(?:.*)?\/post)|t)\/(.*)(?:\/)?/.exec(url.pathname) + const reg = /^\/(?:(?:(?:[^\/])?\/post)|t)\/([^\/])/.exec(url.pathname) if (reg) return `${randomInstance}/t/${reg[1]}${url.search}` return `${randomInstance}${url.pathname}${url.search}` } + case "skunkyArt": { + if (url.pathname.startsWith('/search')) return `${randomInstance}${url.pathname}${url.search}&scope=all` + + const artReg = /^\/.*?\/art\/(.*)\/?/.exec(url.pathname) + if (artReg) return `${randomInstance}/post/art/${artReg[1]}${url.search}` + + const userReg = /^\/([^\/]+)$/.exec(url.pathname) + if (userReg) return `${randomInstance}/user/${userReg[1]}${url.search}` + + const galleryReg = /^\/.*?\/gallery(\/$|$)$/.exec(url.pathname) + if (galleryReg) return `${randomInstance}/user/${userReg[1]}?a=gallery` + + return `${randomInstance}${url.pathname}${url.search}` + } case "piped": case "pipedMaterial": case "cloudtube": @@ -804,6 +818,7 @@ const defaultInstances = { freetar: ["https://freetar.de"], ratAintTieba: ["https://rat.fis.land"], shoelace: ["https://shoelace.mint.lgbt"], + skunkyArt: ["https://skunky.bloat.cat/"], } function initDefaults() { diff --git a/src/config.json b/src/config.json index a42b7c73..a4abc44e 100644 --- a/src/config.json +++ b/src/config.json @@ -1208,6 +1208,26 @@ }, "imageType": "svgMono", "url": "https://threads.net" + }, + "deviantArt": { + "frontends": { + "skunkyArt": { + "name": "SkunkyArt", + "instanceList": true, + "url": "https://git.sr.ht/~nixgoat/shoelace" + } + }, + "targets": [ + "^https?:\\/{2}(www\\.)?deviantart\\.com" + ], + "name": "DeviantArt", + "options": { + "enabled": false, + "unsupportedUrls": "bypass", + "frontend": "skunkyArt" + }, + "imageType": "svg", + "url": "https://deviantart.com" } } } \ No newline at end of file -- cgit 1.4.1 From e96ac0c310f992136c1f15fdfcfe089f26e20bbe Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Sat, 17 Aug 2024 09:13:58 +0300 Subject: Added ytify https://github.com/libredirect/browser_extension/issues/951 --- src/assets/javascripts/services.js | 12 +++++++++++- src/config.json | 6 ++++++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 94d8d980..417f66c3 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -565,6 +565,15 @@ function rewrite(url, frontend, randomInstance) { return `${randomInstance}${url.pathname}${url.search}` } + case "ytify": { + if (url.pathname.startsWith('/watch')) return `${randomInstance}/?s=${encodeURIComponent(url.searchParams.get('v'))}` + + const channelReg = /\/channel\/([^\/]+)/.exec(url.pathname) + if (channelReg) return `${randomInstance}/list?channel=${channelReg[1]}` + + if (url.pathname.startsWith('/playlist')) return `${randomInstance}/list?playlists=${encodeURIComponent(url.searchParams.get('list'))}` + return `${randomInstance}${url.pathname}${url.search}` + } case "piped": case "pipedMaterial": case "cloudtube": @@ -818,7 +827,8 @@ const defaultInstances = { freetar: ["https://freetar.de"], ratAintTieba: ["https://rat.fis.land"], shoelace: ["https://shoelace.mint.lgbt"], - skunkyArt: ["https://skunky.bloat.cat/"], + skunkyArt: ["https://skunky.bloat.cat"], + ytify: ["https://ytify.netlify.app"], } function initDefaults() { diff --git a/src/config.json b/src/config.json index a4abc44e..16bd9076 100644 --- a/src/config.json +++ b/src/config.json @@ -125,6 +125,12 @@ "embeddable": false, "instanceList": true, "url": "https://github.com/ViewTube/viewtube" + }, + "ytify": { + "name": "ytify", + "embeddable": false, + "instanceList": true, + "url": "https://github.com/n-ce/ytify/" } }, "targets": [ -- cgit 1.4.1 From a94ad51a346d58f090e4d9a26fe5e78f15474acd Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Sun, 18 Aug 2024 13:00:57 +0300 Subject: Allowing to import from previous version https://github.com/libredirect/browser_extension/issues/961 --- src/assets/javascripts/services.js | 134 +++++++++------------ src/pages/background/background.js | 8 +- .../options_src/General/SettingsButtons.svelte | 28 ++--- src/pages/options_src/Services/Services.svelte | 2 +- src/pages/popup_src/App.svelte | 2 +- 5 files changed, 76 insertions(+), 98 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 417f66c3..9b6ef325 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -831,99 +831,86 @@ const defaultInstances = { ytify: ["https://ytify.netlify.app"], } +async function getDefaults() { + let config = await utils.getConfig() + let options = {} + for (const service in config.services) { + options[service] = {} + for (const defaultOption in config.services[service].options) { + options[service][defaultOption] = config.services[service].options[defaultOption] + } + for (const frontend in config.services[service].frontends) { + if (config.services[service].frontends[frontend].instanceList) { + options[frontend] = [] + } + } + } + options.exceptions = { + url: [], + regex: [], + } + options.theme = "detect" + options.popupServices = ["youtube", "tiktok", "imgur", "reddit", "quora", "translate", "maps"] + options.fetchInstances = "github" + options.redirectOnlyInIncognito = false + options = { ...options, ...defaultInstances } + return options +} + function initDefaults() { return new Promise(resolve => { browser.storage.local.clear(async () => { - let config = await utils.getConfig() - let options = {} - for (const service in config.services) { - options[service] = {} - for (const defaultOption in config.services[service].options) { - options[service][defaultOption] = config.services[service].options[defaultOption] - } - for (const frontend in config.services[service].frontends) { - if (config.services[service].frontends[frontend].instanceList) { - options[frontend] = [] - } - } - } - options.exceptions = { - url: [], - regex: [], - } - options.theme = "detect" - options.popupServices = ["youtube", "tiktok", "imgur", "reddit", "quora", "translate", "maps"] - options.fetchInstances = "github" - options.redirectOnlyInIncognito = false - - options = { ...options, ...defaultInstances } - + options = await getDefaults() browser.storage.local.set({ options }, () => resolve()) }) }) } -function upgradeOptions() { - return new Promise(async resolve => { - let options = await utils.getOptions() - - browser.storage.local.clear(() => { - browser.storage.local.set({ options }, () => { - resolve() - }) - }) - }) -} - -function processUpdate() { +function processUpdate(_options) { return new Promise(async resolve => { - let frontends = [] const config = await utils.getConfig() - let options = await utils.getOptions() - for (const service in config.services) { - if (!options[service]) options[service] = {} + let options = _options ?? await utils.getOptions() - if (!(options[service].frontend in config.services[service].frontends)) { - options[service] = config.services[service].options // Reset settings for service - delete options[options[service].frontend] // Remove deprecated frontend - } + const defaults = await getDefaults() - for (const defaultOption in config.services[service].options) { - if (!(defaultOption in options[service])) { - options[service][defaultOption] = config.services[service].options[defaultOption] + // Remove any unknown option or subOption + for (const optionName in options) { + if (!(optionName in defaults)) delete options[optionName] + else if (typeof optionName === 'object' && optionName !== null) { + for (const subOptionName in options[optionName]) { + if (!(subOptionName in defaults[optionName])) delete options[optionName][subOptionName] } } + } + + // Remove any unknwon popupService + options.popupServices = options.popupServices.filter(service => service in config.services) + + // Add missing options + for (const [defaultName, defaultValue] of Object.entries(defaults)) { + if (!(defaultName in options)) { + options[defaultName] = defaultValue + } + } - for (const frontend in config.services[service].frontends) { - frontends.push(frontend) - if (!(frontend in options) && config.services[service].frontends[frontend].instanceList) { - options[frontend] = defaultInstances[frontend] || [] - } + for (const [serviceName, serviceValue] of Object.entries(config.services)) { + // Reset service options if selected frontend is deprecated + if (!(options[serviceName].frontend in serviceValue.frontends)) { + options[serviceName] = serviceValue.options } - 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) + // Add a default service option if it's not present + for (const optionName in serviceValue.options) { + if (!(optionName in options[serviceName])) { + options[serviceName][optionName] = serviceValue.options[optionName] } } } - const general = ["theme", "popupServices", "fetchInstances", "redirectOnlyInIncognito"] - const combined = [ - ...Object.keys(config.services), - ...frontends, - ...general, - "exceptions", - "popupServices", - "version", - ] - for (const key in options) { - if (combined.indexOf(key) < 0) { - delete options[key] // Remove any unknown settings in options - } - } - browser.storage.local.set({ options }, () => { - resolve() + + browser.storage.local.clear(() => { + browser.storage.local.set({ options }, () => { + resolve(options) + }) }) }) } @@ -973,7 +960,6 @@ export default { computeService, reverse, initDefaults, - upgradeOptions, processUpdate, copyRaw, switchInstance, diff --git a/src/pages/background/background.js b/src/pages/background/background.js index d42e5027..576365bd 100644 --- a/src/pages/background/background.js +++ b/src/pages/background/background.js @@ -13,14 +13,8 @@ browser.runtime.onInstalled.addListener(async details => { if (!(await utils.getOptions())) { await servicesHelper.initDefaults() } - browser.runtime.openOptionsPage() } else if (details.reason == "update") { - if (details.previousVersion == "2.5.2") { - await servicesHelper.upgradeOptions() - await servicesHelper.processUpdate() - } else { - await servicesHelper.processUpdate() - } + await servicesHelper.processUpdate() } } }) diff --git a/src/pages/options_src/General/SettingsButtons.svelte b/src/pages/options_src/General/SettingsButtons.svelte index 2f574199..29b756d2 100644 --- a/src/pages/options_src/General/SettingsButtons.svelte +++ b/src/pages/options_src/General/SettingsButtons.svelte @@ -20,14 +20,12 @@ const reader = new FileReader() reader.readAsText(importSettingsFiles[0]) reader.onload = async () => { - const data = JSON.parse(reader.result) - if ("theme" in data && data.version == browser.runtime.getManifest().version) { - browser.storage.local.clear(async () => { - options.set(data) - }) - } else { - alert("Incompatible settings") + let data = JSON.parse(reader.result) + if (data.version != browser.runtime.getManifest().version) { + alert("Importing from a previous version. Be careful") } + data = await servicesHelper.processUpdate(data) + options.set(data) } reader.onerror = error => { console.log("error", error) @@ -51,20 +49,20 @@ } async function importSettingsSync() { - browser.storage.sync.get({ options }, r => { - const optionsSync = r.options - if (optionsSync.version == browser.runtime.getManifest().version) { - options.set(optionsSync) - } else { - alert("Error") + browser.storage.sync.get({ options }, async r => { + let data = r.options + if (data.version != browser.runtime.getManifest().version) { + alert("Importing from a previous version. Be careful") } + data = await servicesHelper.processUpdate(data) + options.set(data) }) } async function resetSettings() { browser.storage.local.clear(async () => { - await servicesHelper.initDefaults() - options.set(await utils.getOptions()) + const data = await servicesHelper.initDefaults() + options.set(data) }) } diff --git a/src/pages/options_src/Services/Services.svelte b/src/pages/options_src/Services/Services.svelte index 481afb83..6b16e824 100644 --- a/src/pages/options_src/Services/Services.svelte +++ b/src/pages/options_src/Services/Services.svelte @@ -72,7 +72,7 @@ {selection.label} {:else} - {browser.i18n.getMessage("search_service") || "Search Service"} + {browser.i18n.getMessage("searchService") || "Search Service"} {/if}
🮦
diff --git a/src/pages/popup_src/App.svelte b/src/pages/popup_src/App.svelte index 3409052d..2bd16169 100644 --- a/src/pages/popup_src/App.svelte +++ b/src/pages/popup_src/App.svelte @@ -88,7 +88,7 @@ diff --git a/src/pages/messages/index.html b/src/pages/messages/index.html new file mode 100644 index 00000000..8701c152 --- /dev/null +++ b/src/pages/messages/index.html @@ -0,0 +1,14 @@ + + + + + + + Settings + + + + + + + diff --git a/src/pages/messages/no_instance.html b/src/pages/messages/no_instance.html deleted file mode 100644 index 55e5fac7..00000000 --- a/src/pages/messages/no_instance.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - No instances found - - - - -
-

LibRedirect: You have no instance selected for this frontend

-
- - diff --git a/src/pages/messages_src/App.svelte b/src/pages/messages_src/App.svelte new file mode 100644 index 00000000..b08a143b --- /dev/null +++ b/src/pages/messages_src/App.svelte @@ -0,0 +1,132 @@ + + +{#if _options && _config} +
+ {#if window.location.search.includes("message=disabled")} +
+

You disabled redirections for this service

+ +
+ {:else if window.location.search.includes("message=no_instance")} +
+

You have no instance selected for this frontend

+ +
+ {/if} +
+{:else} +

Loading...

+{/if} + + diff --git a/src/pages/messages_src/main.js b/src/pages/messages_src/main.js new file mode 100644 index 00000000..c4012f4a --- /dev/null +++ b/src/pages/messages_src/main.js @@ -0,0 +1,7 @@ +import App from "./App.svelte" + +const app = new App({ + target: document.body, +}) + +export default app diff --git a/src/pages/messages_src/stores.js b/src/pages/messages_src/stores.js new file mode 100644 index 00000000..782f6064 --- /dev/null +++ b/src/pages/messages_src/stores.js @@ -0,0 +1,5 @@ +import { writable } from "svelte/store" + +export const options = writable(null) +export const config = writable(null) +export const page = writable("general") diff --git a/src/pages/options_src/App.svelte b/src/pages/options_src/App.svelte index 565aacef..1c4830bf 100644 --- a/src/pages/options_src/App.svelte +++ b/src/pages/options_src/App.svelte @@ -2,7 +2,7 @@ const browser = window.browser || window.chrome import General from "./General/General.svelte" - import url from './url' + import url from "./url" import utils from "../../assets/javascripts/utils.js" import { onDestroy } from "svelte" import servicesHelper from "../../assets/javascripts/services.js" @@ -37,51 +37,15 @@ config.set(await utils.getConfig()) }) - const dark = { - text: "#fff", - bgMain: "#121212", - bgSecondary: "#202020", - active: "#fbc117", - danger: "#f04141", - lightGrey: "#c3c3c3", - } - const light = { - text: "black", - bgMain: "white", - bgSecondary: "#e4e4e4", - active: "#fb9817", - danger: "#f04141", - lightGrey: "#c3c3c3", - } - let cssVariables - $: if (_options) { - if (_options.theme == "dark") { - cssVariables = dark - } else if (_options.theme == "light") { - cssVariables = light - } else if (window.matchMedia("(prefers-color-scheme: dark)").matches) { - cssVariables = dark - } else { - cssVariables = light - } - } + let style + $: if (_options) style = utils.style(_options, window) const dir = ["ar", "iw", "ku", "fa", "ur"].includes(browser.i18n.getUILanguage()) ? "rtl" : "ltr" document.body.dir = dir {#if _options && _config} -
+
{#if !$url.hash || $url.hash == "#general"} diff --git a/src/pages/options_src/Services/Instances.svelte b/src/pages/options_src/Services/Instances.svelte index 32425b80..4e5d1e7d 100644 --- a/src/pages/options_src/Services/Instances.svelte +++ b/src/pages/options_src/Services/Instances.svelte @@ -64,16 +64,9 @@ pingCache[instance] = colorTime(time) } } - function randomInstances(n) { - let instances = [] - for (let i = 0; i < n; i++) { - instances.push(redirects[selectedFrontend]["clearnet"][Math.floor(Math.random() * allInstances.length)]) - } - return instances - } async function autoPickInstance() { - const instances = randomInstances(5) + const instances = utils.randomInstances(redirects[selectedFrontend]["clearnet"], 5) const myInstancesCache = [] for (const instance of instances) { pingCache[instance] = { color: "lightblue", value: "pinging..." } @@ -81,9 +74,7 @@ pingCache[instance] = colorTime(time) myInstancesCache.push([instance, time]) } - myInstancesCache.sort(function (a, b) { - return a[1] - b[1] - }) + myInstancesCache.sort((a, b) => a[1] - b[1]) _options[selectedFrontend].push(myInstancesCache[0][0]) options.set(_options) diff --git a/src/pages/popup_src/App.svelte b/src/pages/popup_src/App.svelte index 8f958a3e..f6699312 100644 --- a/src/pages/popup_src/App.svelte +++ b/src/pages/popup_src/App.svelte @@ -38,48 +38,12 @@ let _page page.subscribe(val => (_page = val)) - const dark = { - text: "#fff", - bgMain: "#121212", - bgSecondary: "#202020", - active: "#fbc117", - danger: "#f04141", - lightGrey: "#c3c3c3", - } - const light = { - text: "black", - bgMain: "white", - bgSecondary: "#e4e4e4", - active: "#fb9817", - danger: "#f04141", - lightGrey: "#c3c3c3", - } - let cssVariables - $: if (_options) { - if (_options.theme == "dark") { - cssVariables = dark - } else if (_options.theme == "light") { - cssVariables = light - } else if (window.matchMedia("(prefers-color-scheme: dark)").matches) { - cssVariables = dark - } else { - cssVariables = light - } - } + let style + $: if (_options) style = utils.style(_options, window) {#if _options && _config} -
+
{:else} -- cgit 1.4.1 From 1492345b0d2f0f4d6d4a7a6f8814596785a472b0 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Thu, 29 Aug 2024 15:29:51 +0300 Subject: Added message popup for Server Errors https://github.com/libredirect/browser_extension/issues/936 --- src/assets/javascripts/services.js | 10 ++++++ src/pages/background/background.js | 34 +++++++++++++------- src/pages/messages_src/App.svelte | 65 +++++++++++++++++++++++++++++++++++++- 3 files changed, 97 insertions(+), 12 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index d1c12375..243f0598 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -667,6 +667,15 @@ function computeService(url) { resolve() }) } +export function computeFrontend(url) { + for (const service in config.services) { + for (const frontend in config.services[service].frontends) { + if (all(service, frontend, options, config).includes(utils.protocolHost(url))) { + return {service, frontend} + } + } + } +} /** * @param {URL} url @@ -975,4 +984,5 @@ export default { copyRaw, switchInstance, isException, + computeFrontend, } diff --git a/src/pages/background/background.js b/src/pages/background/background.js index db7ad087..2bb6cb57 100644 --- a/src/pages/background/background.js +++ b/src/pages/background/background.js @@ -58,7 +58,7 @@ browser.webRequest.onBeforeRequest.addListener( return null } - const newUrl = servicesHelper.redirect( + let newUrl = servicesHelper.redirect( url, details.type, originUrl, @@ -72,20 +72,16 @@ browser.webRequest.onBeforeRequest.addListener( const frontend = url.searchParams.get("frontend") const oldUrl = new URL(url.searchParams.get("url")) - browser.tabs.update({ - url: browser.runtime.getURL( - `/pages/messages/index.html?message=no_instance&url=${encodeURIComponent(oldUrl)}&frontend=${encodeURIComponent(frontend)}` - ), - }) + newUrl = browser.runtime.getURL( + `/pages/messages/index.html?message=no_instance&url=${encodeURIComponent(oldUrl)}&frontend=${encodeURIComponent(frontend)}` + ) } if (!newUrl) { if (url.href.match(/^https?:\/{2}(.*\.)?libredirect\.invalid.*/)) { - browser.tabs.update({ - url: browser.runtime.getURL( - `/pages/messages/index.html?message=disabled&url=${encodeURIComponent(url.href)}` - ), - }) + newUrl = browser.runtime.getURL( + `/pages/messages/index.html?message=disabled&url=${encodeURIComponent(url.href)}` + ) } } @@ -108,6 +104,22 @@ browser.webRequest.onBeforeRequest.addListener( ["blocking"] ) +browser.webRequest.onHeadersReceived.addListener( + details => { + if (details.statusCode >= 501 || details.statusCode == 429 || details.statusCode == 403) { + const url = new URL(details.url) + const { service, frontend } = servicesHelper.computeFrontend(url) + if (!service) return + browser.tabs.update({ + url: browser.runtime.getURL( + `/pages/messages/index.html?message=server_error&code=${details.statusCode}=&url=${encodeURIComponent(url.href)}&frontend=${encodeURIComponent(frontend)}&service=${encodeURIComponent(service)}` + ), + }) + } + }, + { urls: [""] } +) + browser.tabs.onRemoved.addListener(tabId => { if (tabIdRedirects[tabId] != undefined) { delete tabIdRedirects[tabId] diff --git a/src/pages/messages_src/App.svelte b/src/pages/messages_src/App.svelte index b08a143b..05a78044 100644 --- a/src/pages/messages_src/App.svelte +++ b/src/pages/messages_src/App.svelte @@ -9,6 +9,7 @@ import { options, config, page } from "./stores" import Button from "../components/Button.svelte" import AutoPickIcon from "../icons/AutoPickIcon.svelte" + import SwitchInstanceIcon from "../icons/SwitchInstanceIcon.svelte" let _options const unsubscribeOptions = options.subscribe(val => { @@ -49,7 +50,7 @@ const params = new URLSearchParams(window.location.search) const oldUrl = new URL(params.get("url")) - async function autoPickInstance() { + async function autoPick() { const frontend = params.get("frontend") autoPicking = true const instances = utils.randomInstances(redirects[frontend]["clearnet"], 5) @@ -59,6 +60,10 @@ _options[frontend].push(pings[0][0]) options.set(_options) autoPicking = false + } + + async function autoPickInstance() { + await autoPick() await redirectUrl() } @@ -73,6 +78,36 @@ const newUrl = await servicesHelper.redirectAsync(oldUrl, "main_frame", null, null, false, true) browser.tabs.update({ url: newUrl }) } + + async function switchInstance() { + const newUrl = await servicesHelper.switchInstance(oldUrl) + browser.tabs.update({ url: newUrl }) + } + + async function removeInstance() { + const frontend = params.get("frontend") + const i = _options[frontend].indexOf(utils.protocolHost(oldUrl)) + _options[frontend].splice(i, 1) + options.set(_options) + const newUrl = await servicesHelper.switchInstance(oldUrl, service) + browser.tabs.update({ url: newUrl }) + } + + async function removeAndAutoPickInstance() { + const frontend = params.get("frontend") + const i = _options[frontend].indexOf(utils.protocolHost(oldUrl)) + _options[frontend].splice(i, 1) + options.set(_options) + await autoPick() + const newUrl = await servicesHelper.switchInstance(oldUrl, service) + browser.tabs.update({ url: newUrl }) + } + + async function addAutoPickInstance() { + await autoPick() + const newUrl = await servicesHelper.switchInstance(oldUrl) + browser.tabs.update({ url: newUrl }) + } {#if _options && _config} @@ -84,6 +119,34 @@ {browser.i18n.getMessage("enable") || "Enable"}
+ {:else if window.location.search.includes("message=server_error")} + +
+

Your selected instance gave out an error

+ {#if _options[params.get("frontend")].length > 1} + + + {:else} + + + {/if} +
{:else if window.location.search.includes("message=no_instance")}

You have no instance selected for this frontend

-- cgit 1.4.1 From 51686a395eee7e3d325a86ee69b19f0f732bd547 Mon Sep 17 00:00:00 2001 From: ManeraKai Date: Tue, 3 Sep 2024 21:57:18 +0300 Subject: Fixing bugs --- src/assets/javascripts/services.js | 38 ++++++++++++++------------------------ src/pages/background/background.js | 34 +++++++++++++++++++++++++--------- src/pages/messages_src/App.svelte | 17 +++++++++++------ src/pages/popup_src/Buttons.svelte | 17 +++++++++++------ 4 files changed, 61 insertions(+), 45 deletions(-) (limited to 'src/assets/javascripts/services.js') diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js index 243f0598..d19d8aa2 100644 --- a/src/assets/javascripts/services.js +++ b/src/assets/javascripts/services.js @@ -66,7 +66,6 @@ function rewrite(url, originUrl, frontend, randomInstance) { case "searx": case "searxng": for (const key of [...url.searchParams.keys()]) if (key !== "q") url.searchParams.delete(key) - console.log(url.searchParams) return `${randomInstance}/${url.search}` case "whoogle": for (const key of [...url.searchParams.keys()]) if (key !== "q") url.searchParams.delete(key) @@ -658,7 +657,7 @@ function computeService(url) { return } else { for (const frontend in config.services[service].frontends) { - if (all(service, frontend, options, config).includes(utils.protocolHost(url))) { + if (all(service, frontend, options, config).findIndex(instance => url.href.startsWith(instance)) >= 0) { return resolve(service) } } @@ -670,8 +669,8 @@ function computeService(url) { export function computeFrontend(url) { for (const service in config.services) { for (const frontend in config.services[service].frontends) { - if (all(service, frontend, options, config).includes(utils.protocolHost(url))) { - return {service, frontend} + if (all(service, frontend, options, config).findIndex(instance => url.href.startsWith(instance)) >= 0) { + return { service, frontend } } } } @@ -692,25 +691,20 @@ function switchInstance(url, customService) { if (instancesList !== undefined) { const newInstance = utils.getNextInstance(url.origin, instancesList) if (newInstance) { - resolve(`${newInstance}${url.pathname}${url.search}`) - return + return resolve(`${newInstance}${url.pathname}${url.search}`) } } } else { for (const service in config.services) { let instancesList = options[options[service].frontend] if (instancesList === undefined) continue - if (!instancesList.includes(protocolHost)) continue - - instancesList.splice(instancesList.indexOf(protocolHost), 1) - if (instancesList.length === 0) { - resolve() - return - } + const index = instancesList.findIndex(instance => url.href.startsWith(instance)) + if (index < 0) continue + instancesList.splice(index, 1) + if (instancesList.length === 0) return resolve() const newInstance = utils.getNextInstance(url.origin, instancesList) if (newInstance) { - resolve(`${newInstance}${url.pathname}${url.search}`) - return + return resolve(`${newInstance}${url.pathname}${url.search}`) } } } @@ -724,11 +718,14 @@ function switchInstance(url, customService) { async function reverse(url) { let options = await utils.getOptions() let config = await utils.getConfig() - let protocolHost = utils.protocolHost(url) for (const service in config.services) { let frontend = options[service].frontend if (options[frontend] == undefined) continue - if (!options[frontend].includes(protocolHost) && protocolHost != `http://${frontend}.localhost:8080`) continue + if ( + options[frontend].findIndex(instance => url.href.startsWith(instance)) < 0 && + !url.href.startsWith(`http://${frontend}.localhost:8080`) + ) + continue switch (service) { case "youtube": case "imdb": @@ -776,7 +773,6 @@ async function reverse(url) { } const defaultInstances = { - // invidious: ["https://inv.vern.cc"], materialious: ["https://app.materialio.us"], viewtube: ["https://viewtube.io"], piped: ["https://pipedapi-libre.kavin.rocks"], @@ -786,8 +782,6 @@ const defaultInstances = { poketube: ["https://poketube.fun"], proxiTok: ["https://proxitok.pabloferreiro.es"], redlib: ["https://safereddit.com"], - libreddit: ["https://libreddit.spike.codes"], - teddit: ["https://teddit.net"], eddrit: ["https://eddrit.com"], scribe: ["https://scribe.rip"], libMedium: ["https://md.vern.cc"], @@ -807,15 +801,11 @@ const defaultInstances = { intellectual: ["https://intellectual.insprill.net"], ruralDictionary: ["https://rd.vern.cc"], anonymousOverflow: ["https://code.whatever.social"], - biblioReads: ["https://biblioreads.ml"], - wikiless: ["https://wikiless.org"], suds: ["https://sd.vern.cc"], unfunny: ["https://uf.vern.cc"], soprano: ["https://sp.vern.cc"], meme: ["https://mm.vern.cc"], waybackClassic: ["https://wayback-classic.net"], - gothub: ["https://gh.odyssey346.dev"], - mikuInvidious: ["https://mikuinv.resrv.org"], tent: ["https://tent.sny.sh"], wolfreeAlpha: ["https://gqq.gitlab.io", "https://uqq.gitlab.io"], laboratory: ["https://lab.vern.cc"], diff --git a/src/pages/background/background.js b/src/pages/background/background.js index 0d558b01..1fcba190 100644 --- a/src/pages/background/background.js +++ b/src/pages/background/background.js @@ -67,16 +67,22 @@ browser.webRequest.onBeforeRequest.addListener( tabIdRedirects[details.tabId] ) - if (newUrl && newUrl.startsWith("https://no-instance.libredirect.invalid")) { - const url = new URL(newUrl) - const frontend = url.searchParams.get("frontend") - const oldUrl = new URL(url.searchParams.get("url")) + if ( + (newUrl && newUrl.startsWith("https://no-instance.libredirect.invalid")) || + (!newUrl && url.href.startsWith("https://no-instance.libredirect.invalid")) + ) { + newUrl = newUrl ? new URL(newUrl) : url + const frontend = newUrl.searchParams.get("frontend") + const oldUrl = new URL(newUrl.searchParams.get("url")) const params = new URLSearchParams({ message: "no_instance", url: oldUrl, frontend: frontend, }) - newUrl = browser.runtime.getURL(`/pages/messages/index.html?${params.toString()}`) + browser.tabs.update({ + url: browser.runtime.getURL(`/pages/messages/index.html?${params.toString()}`), + }) + return { cancel: true } } if (!newUrl) { @@ -85,7 +91,10 @@ browser.webRequest.onBeforeRequest.addListener( message: "disabled", url: url.href, }) - newUrl = browser.runtime.getURL(`/pages/messages/index.html?${params.toString()}`) + browser.tabs.update({ + url: browser.runtime.getURL(`/pages/messages/index.html?${params.toString()}`), + }) + return { cancel: true } } } @@ -121,9 +130,11 @@ browser.webRequest.onHeadersReceived.addListener( frontend: frontend, service: service, }) - browser.tabs.update({ - url: browser.runtime.getURL(`/pages/messages/index.html?${params.toString()}`), - }) + setTimeout(() => { + browser.tabs.update({ + url: browser.runtime.getURL(`/pages/messages/index.html?${params.toString()}`), + }) + }, 2000) } }, { urls: [""] } @@ -365,3 +376,8 @@ browser.runtime.getPlatformInfo(r => { }) } }) + +browser.runtime.onMessage.addListener(r => { + if (r.message == "reverse") tabIdRedirects[r.tabId] = false + else if (r.message == "redirect") tabIdRedirects[r.tabId] = true +}) diff --git a/src/pages/messages_src/App.svelte b/src/pages/messages_src/App.svelte index 6d68ff5f..1c5170dd 100644 --- a/src/pages/messages_src/App.svelte +++ b/src/pages/messages_src/App.svelte @@ -33,7 +33,6 @@ await servicesHelper.initDefaults() opts = await utils.getOptions() } - redirects = await utils.getList(opts) options.set(opts) config.set(await utils.getConfig()) }) @@ -45,7 +44,6 @@ $: if (_options) style = utils.style(_options, window) let autoPicking = false - let redirects const params = new URLSearchParams(window.location.search) const oldUrl = new URL(params.get("url")) @@ -53,10 +51,14 @@ async function autoPick() { const frontend = params.get("frontend") autoPicking = true + const redirects = await utils.getList(_options) const instances = utils.randomInstances(redirects[frontend]["clearnet"], 5) - const pings = await Promise.all([...instances.map(async instance => [instance, await utils.ping(instance)])]) + const pings = await Promise.all([ + ...instances.map(async instance => { + return [instance, await utils.ping(instance)] + }), + ]) pings.sort((a, b) => a[1] - b[1]) - console.log(pings) _options[frontend].push(pings[0][0]) options.set(_options) autoPicking = false @@ -85,8 +87,9 @@ } async function removeInstance() { + const service = await servicesHelper.computeService(oldUrl) const frontend = params.get("frontend") - const i = _options[frontend].indexOf(utils.protocolHost(oldUrl)) + const i = _options[frontend].findIndex(instance => oldUrl.href.startsWith(instance)) _options[frontend].splice(i, 1) options.set(_options) const newUrl = await servicesHelper.switchInstance(oldUrl, service) @@ -94,8 +97,10 @@ } async function removeAndAutoPickInstance() { + const service = await servicesHelper.computeService(oldUrl) + const frontend = params.get("frontend") - const i = _options[frontend].indexOf(utils.protocolHost(oldUrl)) + const i = _options[frontend].findIndex(instance => oldUrl.href.startsWith(instance)) _options[frontend].splice(i, 1) options.set(_options) await autoPick() diff --git a/src/pages/popup_src/Buttons.svelte b/src/pages/popup_src/Buttons.svelte index c0644ff7..ab5682dc 100644 --- a/src/pages/popup_src/Buttons.svelte +++ b/src/pages/popup_src/Buttons.svelte @@ -44,8 +44,10 @@ { - browser.tabs.update({ url: redirect }, () => { - window.close() + browser.tabs.query({ active: true, currentWindow: true }, tabs => { + browser.runtime.sendMessage({ message: "redirect", tabId: tabs[0].id }, () => { + browser.tabs.update({ url: redirect }) + }) }) }} > @@ -74,10 +76,13 @@ - browser.tabs.update({ url: redirectToOriginal }, () => { - window.close() - })} + on:click={() => { + browser.tabs.query({ active: true, currentWindow: true }, tabs => { + browser.runtime.sendMessage({ message: "reverse", tabId: tabs[0].id }, () => { + browser.tabs.update({ url: redirectToOriginal }) + }) + }) + }} > -- cgit 1.4.1