Formatting wiht prettier

This commit is contained in:
ManeraKai 2024-07-21 21:22:09 +03:00
parent 8bf25954a3
commit cf8216da00
No known key found for this signature in database
GPG Key ID: 5ABC31FFD562E337
19 changed files with 3238 additions and 3270 deletions

3
.prettierignore Normal file
View File

@ -0,0 +1,3 @@
src/_locales/
.github/
.gitea/

7
.prettierrc Normal file
View File

@ -0,0 +1,7 @@
{
"printWidth": 120,
"semi": false,
"singleQuote": false,
"trailingComma": "es5",
"arrowParens": "avoid"
}

View File

@ -11,34 +11,42 @@ A browser extension that redirects YouTube, Twitter, TikTok... requests to alter
</a>
## Translate
<a href="https://hosted.weblate.org/projects/libredirect/extension">
<img src ="./img/weblate.svg">
</a>
## 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`

View File

@ -35,9 +35,9 @@ function all(service, frontend, options, config) {
*/
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))
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) {
@ -67,7 +67,9 @@ async function redirectAsync(url, type, initiator, forceRedirection) {
function rewrite(url, frontend, randomInstance) {
switch (frontend) {
case "hyperpipe":
return `${randomInstance}${url.pathname}${url.search}`.replace(/\/search\?q=.*/, searchQuery => searchQuery.replace("?q=", "/"))
return `${randomInstance}${url.pathname}${url.search}`.replace(/\/search\?q=.*/, searchQuery =>
searchQuery.replace("?q=", "/")
)
case "searx":
case "searxng":
return `${randomInstance}/${url.search}`
@ -85,13 +87,13 @@ function rewrite(url, frontend, randomInstance) {
return url.href.replace(/^https?:\/{2}/, "yattee://")
case "freetube":
url.searchParams.delete("si")
return 'freetube://' + url.href
return "freetube://" + url.href
case "freetubePwa":
url.searchParams.delete("si")
return 'freetube://' + url.href
return "freetube://" + url.href
case "poketube": {
url.searchParams.delete("si")
if (url.pathname.startsWith('/channel')) {
if (url.pathname.startsWith("/channel")) {
const reg = /\/channel\/(.*)\/?$/.exec(url.pathname)
if (reg) {
const id = reg[1]
@ -125,24 +127,28 @@ function rewrite(url, frontend, randomInstance) {
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
;[, lon, lat, zoom] = reg
} else if (url.searchParams.has("center")) {
// Set map centre if present
[lat, lon] = url.searchParams.get("center").split(",")
;[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.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]}`
boundingbox: `${json.boundingbox[2]},${json.boundingbox[1]},${json.boundingbox[3]},${json.boundingbox[0]}`,
}
}
return {}
@ -164,9 +170,11 @@ function rewrite(url, frontend, randomInstance) {
let prefs = { layers: "mapnik" }
const mapCentreData = convertMapCentre(url)
if (mapCentreData.zoom && mapCentreData.lon && mapCentreData.lat) mapCentre = `#map=${mapCentreData.zoom}/${mapCentreData.lon}/${mapCentreData.lat}`
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
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
@ -184,26 +192,32 @@ function rewrite(url, frontend, randomInstance) {
}
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 ?? ''
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 ?? ''
} 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 ?? ''
} 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
} 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
} 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
} 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 {
@ -213,7 +227,8 @@ function rewrite(url, frontend, randomInstance) {
return `${randomInstance}/${mapCentre}&${prefsEncoded(prefs)}`
}
case "breezeWiki": {
let wiki, urlpath = ""
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 = ""
@ -228,12 +243,15 @@ function rewrite(url, frontend, randomInstance) {
}
}
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}`
.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}`
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": {
@ -257,18 +275,19 @@ function rewrite(url, frontend, 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/')) {
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}`
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
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") {
@ -285,7 +304,9 @@ function rewrite(url, frontend, randomInstance) {
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)/)
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}`
}
@ -304,7 +325,7 @@ function rewrite(url, frontend, randomInstance) {
return `${randomInstance}${url.pathname}${url.search}${url.hash}`
}
case "proxiTok":
if (url.pathname.startsWith('/email')) return randomInstance
if (url.pathname.startsWith("/email")) return randomInstance
return `${randomInstance}${url.pathname}${url.search}`
case "waybackClassic": {
const regex = /^\/\web\/(?:[0-9]+)?\*\/(.*)/.exec(url.pathname)
@ -315,7 +336,7 @@ function rewrite(url, frontend, randomInstance) {
const regex2 = /(^\/\web\/([0-9]+)\/.*)/.exec(url.pathname)
if (regex2) {
let link = regex2[1]
link = link.replace(regex2[2], regex2[2] + 'if_')
link = link.replace(regex2[2], regex2[2] + "if_")
return `https://web.archive.org${link}`
}
return
@ -325,17 +346,18 @@ function rewrite(url, frontend, randomInstance) {
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 == "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')
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')) {
if (url.hostname.endsWith("bandcamp.com")) {
const regex = /^(.*)\.bandcamp\.com/.exec(url.hostname)
const artist = regex[1]
if (url.pathname == '/' || url.pathname == '/music') {
if (url.pathname == "/" || url.pathname == "/music") {
return `${randomInstance}/artist.php?name=${artist}`
} else {
const regex = /^\/(.*)\/(.*)/.exec(url.pathname)
@ -346,18 +368,18 @@ function rewrite(url, frontend, randomInstance) {
}
}
}
if (url.hostname == 'f4.bcbits.com') {
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') {
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')
const token = url.searchParams.get("token")
return `${randomInstance}/audio.php/?directory=${directory}&format=${format}&file=${file}&token=${encodeURIComponent(token)}`
}
}
@ -388,52 +410,51 @@ function rewrite(url, frontend, randomInstance) {
}
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)
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
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)
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
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)
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('?', '&')}`
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('?', '&')}`
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('?', '&')}`
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('?', '&')}`
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('?', '&')}`
return `${randomInstance}/search/${url.search.replace("?", "&")}`
}
if (url.pathname.startsWith('/redirect?')) {
if (url.pathname.startsWith("/redirect?")) {
return url.href
}
}
@ -453,7 +474,7 @@ function rewrite(url, frontend, randomInstance) {
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 == "/") 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
@ -463,9 +484,9 @@ function rewrite(url, frontend, randomInstance) {
return `${randomInstance}${url.pathname}${url.search}`
case "tekstoLibre":
return `${randomInstance}/?${url.pathname.slice(1)}`;
return `${randomInstance}/?${url.pathname.slice(1)}`
case "skyview":
if (url.pathname == '/') return randomInstance
if (url.pathname == "/") return randomInstance
return `${randomInstance}?url=${encodeURIComponent(url.href)}`
case "nitter": {
let search = new URLSearchParams(url.search)
@ -487,7 +508,8 @@ function rewrite(url, frontend, randomInstance) {
return `${randomInstance}/pic${url.pathname}${search}`
}
}
if (url.pathname.split("/").includes("tweets")) return `${randomInstance}${url.pathname.replace("/tweets", "")}${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`
}
@ -501,12 +523,13 @@ function rewrite(url, frontend, randomInstance) {
const blogregex = /^(?:www\.)?([a-z\d-]+)\.tumblr\.com/.exec(url.hostname) // <blog>.tumblr.com
if (blogregex) {
const blog_name = blogregex[1];
const blog_name = blogregex[1]
// Under the <blog>.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}`;
return `${randomInstance}${url.pathname}${url.search}`
}
case "piped":
case "pipedMaterial":
@ -536,7 +559,11 @@ 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")
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)) {
@ -545,11 +572,11 @@ function redirect(url, type, initiator, forceRedirection, incognito) {
}
if (
config.services[service].embeddable
&&
type != options[service].redirectType && options[service].redirectType != "both"
config.services[service].embeddable &&
type != options[service].redirectType &&
options[service].redirectType != "both"
) {
if (options[service].unsupportedUrls == 'block') return 'CANCEL'
if (options[service].unsupportedUrls == "block") return "CANCEL"
return
}
@ -588,10 +615,8 @@ function computeService(url, returnFrontend) {
} 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)
if (returnFrontend) resolve([service, frontend, utils.protocolHost(url)])
else resolve(service)
return
}
}
@ -699,61 +724,61 @@ 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'],
'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() {
@ -778,14 +803,12 @@ function initDefaults() {
}
options.theme = "detect"
options.popupServices = ["youtube", "tiktok", "imgur", "reddit", "quora", "translate", "maps"]
options.fetchInstances = 'github'
options.fetchInstances = "github"
options.redirectOnlyInIncognito = false
options = { ...options, ...defaultInstances }
browser.storage.local.set({ options },
() => resolve()
)
browser.storage.local.set({ options }, () => resolve())
})
})
}
@ -830,19 +853,19 @@ function processUpdate() {
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 i = options.popupServices.indexOf(frontend)
if (i > -1) options.popupServices.splice(i, 1)
}
}
}
const general = ['theme', 'popupServices', 'fetchInstances', 'redirectOnlyInIncognito']
const general = ["theme", "popupServices", "fetchInstances", "redirectOnlyInIncognito"]
const combined = [
...Object.keys(config.services),
...frontends,
...general,
'exceptions',
'popupServices',
'version',
"exceptions",
"popupServices",
"version",
]
for (const key in options) {
if (combined.indexOf(key) < 0) {
@ -864,13 +887,13 @@ async function copyRaw(url) {
if (!isChrome) {
navigator.clipboard.writeText(newUrl)
} else {
var copyFrom = document.createElement("textarea");
copyFrom.textContent = newUrl;
document.body.appendChild(copyFrom);
var copyFrom = document.createElement("textarea")
copyFrom.textContent = newUrl
document.body.appendChild(copyFrom)
copyFrom.select()
document.execCommand('copy')
copyFrom.blur();
document.body.removeChild(copyFrom);
document.execCommand("copy")
copyFrom.blur()
document.body.removeChild(copyFrom)
}
}
}
@ -885,7 +908,7 @@ function isException(url) {
if (exceptions.url) {
for (let item of exceptions.url) {
item = new URL(item)
item = item.href.replace(/^http:\/\//, 'https://')
item = item.href.replace(/^http:\/\//, "https://")
if (item == url.href) return true
}
}
@ -904,5 +927,5 @@ export default {
processUpdate,
copyRaw,
switchInstance,
isException
isException,
}

View File

@ -14,10 +14,10 @@ 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]
}
/**
@ -32,7 +32,8 @@ function camelCase(str) {
*/
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
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}`
}
@ -88,14 +89,15 @@ 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'
else return resolve('disabled')
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))
if (http.status === 200 && http.readyState == XMLHttpRequest.DONE) resolve(JSON.parse(http.responseText))
}
http.onerror = () => resolve()
http.ontimeout = () => resolve()
@ -106,14 +108,15 @@ 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'
else return resolve('disabled')
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))
if (http.status === 200 && http.readyState == XMLHttpRequest.DONE) return resolve(JSON.parse(http.responseText))
}
http.onerror = () => resolve()
http.ontimeout = () => resolve()

View File

@ -33,30 +33,21 @@
"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,
@ -67,10 +58,7 @@
"embeddable": false,
"instanceList": true,
"url": "https://sr.ht/~cadence/tube",
"excludeTargets": [
2,
3
]
"excludeTargets": [2, 3]
},
"lightTube": {
"name": "LightTube",
@ -83,16 +71,10 @@
"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,
@ -100,10 +82,7 @@
"url": "https://github.com/FreeTubeApp/FreeTube"
},
"yattee": {
"excludeTargets": [
2,
3
],
"excludeTargets": [2, 3],
"name": "Yattee",
"embeddable": false,
"desktopApp": true,
@ -111,10 +90,7 @@
"url": "https://github.com/yattee/yattee"
},
"freetubePwa": {
"excludeTargets": [
2,
3
],
"excludeTargets": [2, 3],
"name": "FreeTube PWA",
"embeddable": false,
"instanceList": false,
@ -168,9 +144,7 @@
"url": "https://github.com/FreeTubeApp/FreeTube"
}
},
"targets": [
"^https?:\\/{2}music\\.youtube\\.com\\/"
],
"targets": ["^https?:\\/{2}music\\.youtube\\.com\\/"],
"name": "YT Music",
"options": {
"enabled": false,
@ -218,9 +192,7 @@
"url": "https://github.com/badlogic/skyview"
}
},
"targets": [
"^https?:\\/{2}bsky\\.app\\/"
],
"targets": ["^https?:\\/{2}bsky\\.app\\/"],
"name": "Bluesky",
"options": {
"enabled": false,
@ -309,9 +281,7 @@
"localhost": false
}
},
"targets": [
"^https?:\\/{2}(www\\.|clips\\.)?twitch\\.(tv|com)\\/"
],
"targets": ["^https?:\\/{2}(www\\.|clips\\.)?twitch\\.(tv|com)\\/"],
"name": "Twitch",
"options": {
"enabled": false,
@ -333,9 +303,7 @@
"localhost": true
}
},
"targets": [
"^https?:\\/{2}(www\\.)?tiktok\\.com\\/"
],
"targets": ["^https?:\\/{2}(www\\.)?tiktok\\.com\\/"],
"name": "TikTok",
"options": {
"enabled": false,
@ -355,9 +323,7 @@
"localhost": false
}
},
"targets": [
"^https?:\\/{2}(www\\.)?instagram\\.com"
],
"targets": ["^https?:\\/{2}(www\\.)?instagram\\.com"],
"name": "Instagram",
"options": {
"enabled": false,
@ -377,9 +343,7 @@
"localhost": true
}
},
"targets": [
"^https?:\\/{2}(www\\.|m\\.)?imdb\\.com"
],
"targets": ["^https?:\\/{2}(www\\.|m\\.)?imdb\\.com"],
"name": "IMDb",
"options": {
"enabled": false,
@ -398,10 +362,7 @@
"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,
@ -420,9 +381,7 @@
"url": "https://codeberg.org/VnPower/pixivfe"
}
},
"targets": [
"^https?:\\/{2}(www\\.)?pixiv\\.net\\/"
],
"targets": ["^https?:\\/{2}(www\\.)?pixiv\\.net\\/"],
"options": {
"enabled": false,
"unsupportedUrls": "bypass",
@ -439,9 +398,7 @@
"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,
@ -462,9 +419,7 @@
"embeddable": true
}
},
"targets": [
"^https?:\\/{2}([im]\\.)?(stack\\.)?imgur\\.(com|io)\\/"
],
"targets": ["^https?:\\/{2}([im]\\.)?(stack\\.)?imgur\\.(com|io)\\/"],
"name": "Imgur",
"options": {
"enabled": false,
@ -487,10 +442,7 @@
"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",
@ -510,9 +462,7 @@
"url": "https://git.migalmoreno.com/tubo/about/"
}
},
"targets": [
"^https?:\\/{2}soundcloud\\.com"
],
"targets": ["^https?:\\/{2}soundcloud\\.com"],
"name": "SoundCloud",
"options": {
"enabled": false,
@ -532,10 +482,7 @@
"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,
@ -553,9 +500,7 @@
"url": "https://github.com/Davilarek/TekstoLibre"
}
},
"targets": [
"^https?:\\/{2}(www\\.)?tekstowo\\.pl\\/"
],
"targets": ["^https?:\\/{2}(www\\.)?tekstowo\\.pl\\/"],
"name": "Tekstowo.pl",
"options": {
"enabled": false,
@ -580,9 +525,7 @@
"localhost": false
}
},
"targets": [
"^https?:\\/{2}(www\\.)?genius\\.com\\/"
],
"targets": ["^https?:\\/{2}(www\\.)?genius\\.com\\/"],
"name": "Genius",
"options": {
"enabled": false,
@ -645,9 +588,7 @@
"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,
@ -734,9 +675,7 @@
"url": "https://github.com/HookedBehemoth/neuters"
}
},
"targets": [
"^https?:\\/{2}(www\\.)?reuters\\.com\\/"
],
"targets": ["^https?:\\/{2}(www\\.)?reuters\\.com\\/"],
"name": "Reuters",
"options": {
"enabled": false,
@ -754,9 +693,7 @@
"url": "https://git.vern.cc/cobra/Suds"
}
},
"targets": [
"^https?:\\/{2}(www\\.)?snopes\\.com\\/"
],
"targets": ["^https?:\\/{2}(www\\.)?snopes\\.com\\/"],
"name": "Snopes",
"options": {
"enabled": false,
@ -774,9 +711,7 @@
"url": "https://git.vern.cc/cobra/UNfunny"
}
},
"targets": [
"^https?:\\/{2}(www\\.)?ifunny\\.co\\/"
],
"targets": ["^https?:\\/{2}(www\\.)?ifunny\\.co\\/"],
"name": "iFunny",
"options": {
"enabled": false,
@ -794,9 +729,7 @@
"url": "https://git.vern.cc/cobra/Soprano"
}
},
"targets": [
"^https?:\\/{2}(www\\.)?tenor\\.com\\/"
],
"targets": ["^https?:\\/{2}(www\\.)?tenor\\.com\\/"],
"name": "Tenor",
"options": {
"enabled": false,
@ -814,9 +747,7 @@
"url": "https://git.vern.cc/cobra/MeMe"
}
},
"targets": [
"^https?:\\/{2}(www\\.)?knowyourmeme\\.com\\/"
],
"targets": ["^https?:\\/{2}(www\\.)?knowyourmeme\\.com\\/"],
"name": "KnowYourMeme",
"options": {
"enabled": false,
@ -834,9 +765,7 @@
"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,
@ -855,9 +784,7 @@
"localhost": true
}
},
"targets": [
"^https?:\\/{2}(www\\.)?goodreads\\.com\\/"
],
"targets": ["^https?:\\/{2}(www\\.)?goodreads\\.com\\/"],
"name": "Goodreads",
"options": {
"enabled": false,
@ -876,9 +803,7 @@
"url": "https://git.disroot.org/wolfree"
}
},
"targets": [
"^https?:\\/{2}(www\\.)?wolframalpha\\.com\\/"
],
"targets": ["^https?:\\/{2}(www\\.)?wolframalpha\\.com\\/"],
"name": "Wolfram Alpha",
"options": {
"enabled": false,
@ -902,9 +827,7 @@
"url": "https://git.vern.cc/cobra/Destructables"
}
},
"targets": [
"^https?:\\/{2}(www\\.)?instructables\\.com\\/"
],
"targets": ["^https?:\\/{2}(www\\.)?instructables\\.com\\/"],
"options": {
"enabled": false,
"unsupportedUrls": "bypass",
@ -921,9 +844,7 @@
"url": "https://wikiless.org"
}
},
"targets": [
"^https?:\\/{2}([a-z]+\\.)*wikipedia\\.org\\/?"
],
"targets": ["^https?:\\/{2}([a-z]+\\.)*wikipedia\\.org\\/?"],
"name": "Wikipedia",
"options": {
"enabled": false,
@ -941,9 +862,7 @@
"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,
@ -982,10 +901,7 @@
"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,
@ -1062,9 +978,7 @@
"url": "https://jitsi.org"
}
},
"targets": [
"^https?:\\/{2}meet\\.libredirect\\.invalid\\/"
],
"targets": ["^https?:\\/{2}meet\\.libredirect\\.invalid\\/"],
"options": {
"enabled": false,
"unsupportedUrls": "bypass",
@ -1108,9 +1022,7 @@
"url": "https://github.com/Dragynfruit/pasted"
}
},
"targets": [
"^https?:\\/{2}paste\\.libredirect\\.invalid"
],
"targets": ["^https?:\\/{2}paste\\.libredirect\\.invalid"],
"name": "Paste Text",
"options": {
"enabled": false,

View File

@ -22,17 +22,8 @@
"48": "assets/images/libredirect-48.png",
"128": "assets/images/libredirect-128.png"
},
"permissions": [
"webRequest",
"webRequestBlocking",
"storage",
"clipboardWrite",
"contextMenus",
"<all_urls>"
],
"optional_permissions": [
"bookmarks"
],
"permissions": ["webRequest", "webRequestBlocking", "storage", "clipboardWrite", "contextMenus", "<all_urls>"],
"optional_permissions": ["bookmarks"],
"browser_action": {
"default_title": "__MSG_extensionName__",
"browser_style": false,

View File

@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html>
<head>
<meta charset="utf-8" />

View File

@ -14,9 +14,8 @@ browser.runtime.onInstalled.addListener(async details => {
await servicesHelper.initDefaults()
}
browser.runtime.openOptionsPage()
}
else if (details.reason == "update") {
if (details.previousVersion == '2.5.2') {
} else if (details.reason == "update") {
if (details.previousVersion == "2.5.2") {
await servicesHelper.upgradeOptions()
await servicesHelper.processUpdate()
} else {
@ -33,7 +32,8 @@ 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
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)
@ -44,21 +44,24 @@ browser.webRequest.onBeforeRequest.addListener(
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 (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`)
});
url: browser.runtime.getURL(`/pages/messages/no_instance.html`),
})
}
}
@ -130,42 +133,54 @@ browser.commands.onCommand.addListener(async command => {
})
})
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) => {
browser.contextMenus.onClicked.addListener(async info => {
switch (info.menuItemId) {
case 'switchInstanceTab': {
case "switchInstanceTab": {
const url = new URL(info.pageUrl)
const newUrl = await servicesHelper.switchInstance(url)
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)
@ -173,7 +188,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)
@ -186,7 +201,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)
@ -199,13 +214,13 @@ browser.contextMenus.onClicked.addListener(async (info) => {
}
})
return
case 'copyReverseLink': {
case "copyReverseLink": {
const url = new URL(info.linkUrl)
await servicesHelper.copyRaw(url)
return
}
case 'redirectLink':
case 'redirectLinkInNewTab': {
case "redirectLink":
case "redirectLinkInNewTab": {
const url = new URL(info.linkUrl)
const newUrl = servicesHelper.redirect(url, "main_frame", null, true)
if (newUrl) {
@ -214,8 +229,8 @@ browser.contextMenus.onClicked.addListener(async (info) => {
}
return
}
case 'reverseLink':
case 'reverseLinkInNewTab': {
case "reverseLink":
case "reverseLinkInNewTab": {
const url = new URL(info.linkUrl)
const newUrl = await servicesHelper.reverse(url)
if (newUrl) {
@ -231,8 +246,8 @@ browser.contextMenus.onClicked.addListener(async (info) => {
}
return
}
case 'bypassLink':
case 'bypassLinkInNewTab': {
case "bypassLink":
case "bypassLinkInNewTab": {
const url = new URL(info.linkUrl)
if (info.menuItemId == "bypassLink") {
browser.tabs.update({ url: url.href }, tab => {
@ -245,25 +260,25 @@ 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 "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 })
if (info.menuItemId == "redirectBookmark") browser.tabs.update({ url: newUrl })
else browser.tabs.create({ url: newUrl })
}
})
return
case 'reverseBookmark':
case 'reverseBookmarkInNewTab':
case "reverseBookmark":
case "reverseBookmarkInNewTab":
browser.bookmarks.get(info.bookmarkId, async bookmarks => {
const url = new URL(bookmarks[0].url)
const newUrl = await servicesHelper.reverse(url)
@ -280,14 +295,14 @@ browser.contextMenus.onClicked.addListener(async (info) => {
}
})
return
case 'bypassBookmark':
case 'bypassBookmarkInNewTab':
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)
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
})
@ -300,16 +315,15 @@ 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))
}
})
}
else if (request == "redirectTab") {
} 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)
if (newUrl) browser.tabs.update(tabs[0].id, { url: newUrl }, () => (tabIdRedirects[tabs[0].id] = true))
}
})
}

View File

@ -1,11 +1,10 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="../stylesheets/styles.css" rel="stylesheet">
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="../stylesheets/styles.css" rel="stylesheet" />
<title>No instances found</title>
<style>
#body {
@ -22,5 +21,4 @@
<h1>You have no instance selected for this frontend</h1>
</div>
</body>
</html>

View File

@ -26,22 +26,23 @@ 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.pointerEvents = "auto"
opacityDiv.style.opacity = 1
opacityDiv.style.userSelect = 'auto'
opacityDiv.style.userSelect = "auto"
} else {
opacityDiv.style.pointerEvents = 'none'
opacityDiv.style.pointerEvents = "none"
opacityDiv.style.opacity = 0.4
opacityDiv.style.userSelect = 'none'
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)
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) {
@ -67,8 +68,10 @@ async function changeFrontendsSettings(service) {
<option value="sub_frame" data-localise="__MSG_onlyEmbedded__">Only Embedded</option>
<option value="main_frame" data-localise="__MSG_onlyNotEmbedded__">Only Not Embedded</option>
`
}
else if (config.services[service].frontends[frontend].desktopApp && Object.values(config.services[service].frontends).some(frontend => frontend.embeddable)) {
} else if (
config.services[service].frontends[frontend].desktopApp &&
Object.values(config.services[service].frontends).some(frontend => frontend.embeddable)
) {
document.getElementById(`${service}-redirectType`).innerHTML = `
<option value="both" data-localise="__MSG_both__">both</options>
<option value="main_frame" data-localise="__MSG_onlyNotEmbedded__">Only Not Embedded</option>
@ -86,14 +89,16 @@ async function changeFrontendsSettings(service) {
}
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'
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'
document.getElementById(`${service}-embedFrontend-div`).style.display = "none"
}
}
const frontend_name_element = document.getElementById(`${service}_page`).getElementsByClassName("frontend_name")[0]
@ -109,7 +114,7 @@ async function loadPage(path) {
document.getElementById(`${path}_page`).style.display = "block"
for (const element of document.getElementsByClassName("title")) {
const a = element.getElementsByTagName('a')[0]
const a = element.getElementsByTagName("a")[0]
if (a.getAttribute("href") == `#${path}`) {
element.classList.add("selected")
} else {
@ -127,19 +132,19 @@ async function loadPage(path) {
window.history.pushState({ id: "100" }, "Page 2", `/pages/options/index.html#${path}`)
if (path != 'general') {
const service = 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]
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
else options[service][option] = divs[service][option].value
browser.storage.local.set({ options })
changeFrontendsSettings(service)
})
@ -150,18 +155,16 @@ async function loadPage(path) {
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]
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 {
.getElementsByClassName("loading")[0].innerHTML = "Could not fetch instances."
} else {
createList(frontend)
}
}
@ -171,9 +174,9 @@ async function loadPage(path) {
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..."
document.getElementById(`ping-${frontend}`).getElementsByTagName("x")[0].innerHTML = "Pinging..."
await ping(frontend)
document.getElementById(`ping-${frontend}`).getElementsByTagName('x')[0].innerHTML = "Ping instances"
document.getElementById(`ping-${frontend}`).getElementsByTagName("x")[0].innerHTML = "Ping instances"
})
}
}
@ -186,15 +189,12 @@ async function calcCustomInstances(frontend) {
const pingCache = await utils.getPingCache()
document.getElementById(frontend).getElementsByClassName("custom-checklist")[0].innerHTML = customInstances
.map(
x => {
const time = pingCache[x];
.map(x => {
const time = pingCache[x]
if (time) {
var { color, text } = processTime(time);
var { color, text } = processTime(time)
}
const timeText = time
? `<span class="ping" style="color:${color};">${text}</span>`
: "";
const timeText = time ? `<span class="ping" style="color:${color};">${text}</span>` : ""
const custom = isCustomInstance(frontend, x) ? "" : `<span>custom</span>`
return `<div>
<x>
@ -212,7 +212,10 @@ async function calcCustomInstances(frontend) {
})
.join("\n")
for (const item of customInstances) {
document.getElementById(frontend).getElementsByClassName(`clear-${item}`)[0].addEventListener("click", async () => {
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()
@ -227,7 +230,10 @@ async function calcCustomInstances(frontend) {
async function processCustomInstances(frontend) {
calcCustomInstances(frontend)
document.getElementById(frontend).getElementsByClassName("custom-instance-form")[0].addEventListener("submit", async event => {
document
.getElementById(frontend)
.getElementsByClassName("custom-instance-form")[0]
.addEventListener("submit", async event => {
event.preventDefault()
let options = await utils.getOptions()
let customInstances = options[frontend]
@ -259,7 +265,10 @@ 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 = '<div class="block block-option">No instances found.</div>'
@ -269,15 +278,16 @@ 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]
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) ?
`<a target="_blank" href="https://libredirect.github.io/docs.html#instances">
const content = instances.map(x => {
const cloudflare = blacklist.cloudflare.includes(x)
? `<a target="_blank" href="https://libredirect.github.io/docs.html#instances">
<span style="color:red;">cloudflare</span>
</a>` : ""
</a>`
: ""
let time = pingCache[x]
let timeText = ""
@ -307,12 +317,11 @@ async function createList(frontend) {
<label>${utils.camelCase(network)}</label>
</div>`,
...content,
"<br>"
"<br>",
].join("\n<hr>\n")
for (const instance of instances) {
checklist.getElementsByClassName(`add-${instance}`)[0]
.addEventListener("click", async () => {
checklist.getElementsByClassName(`add-${instance}`)[0].addEventListener("click", async () => {
let options = await utils.getOptions()
if (!options[frontend].includes(instance)) {
options[frontend].push(instance)
@ -335,21 +344,21 @@ else loadPage("general")
*/
async function ping(frontend) {
const instanceElements = [
...document.getElementById(frontend).getElementsByClassName("custom-checklist")[0].getElementsByTagName('x'),
...document.getElementById(frontend).getElementsByClassName('clearnet')[0].getElementsByTagName('x')
...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']
let span = element.getElementsByClassName("ping")[0]
if (!span) span = document.createElement("span")
span.classList = ["ping"]
span.innerHTML = '<span style="color:lightblue">pinging...</span>'
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 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 = `<span style="color:${color};">${text}</span>`
pingCache[innerHTML] = time
@ -369,22 +378,20 @@ function processTime(time) {
text = `${time}ms`
if (time <= 1000) color = "green"
else if (time <= 2000) color = "orange"
}
else if (time >= 5000) {
} else if (time >= 5000) {
color = "red"
if (time == 5000) text = "5000ms+"
if (time > 5000) text = `Error: ${time - 5000}`
}
else {
} else {
color = "red"
text = 'Server not found'
text = "Server not found"
}
return { color, text }
}
function isCustomInstance(frontend, instance) {
for (const network in config.networks) {
if (!redirects[frontend]) return false;
if (!redirects[frontend]) return false
const instances = redirects[frontend][network]
if (instances.includes(instance)) return true
}

View File

@ -13,29 +13,29 @@ async function changeTheme() {
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';
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';
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';
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';
for (const element of document.body.getElementsByClassName("dark")) {
element.style.display = "none"
}
}
}

View File

@ -11,13 +11,13 @@ async function setOption(option, type, event) {
switch (type) {
case "select":
options[option] = event.target.options[event.target.options.selectedIndex].value
break;
break
case "checkbox":
options[option] = event.target.checked
break;
break
case "range":
options[option] = event.target.value
break;
break
}
browser.storage.local.set({ options })
}
@ -48,10 +48,7 @@ importSettingsElement.addEventListener("change", () => {
reader.readAsText(file)
reader.onload = async () => {
const data = JSON.parse(reader.result)
if (
"theme" in data
&& data.version == browser.runtime.getManifest().version
) {
if ("theme" in data && data.version == browser.runtime.getManifest().version) {
browser.storage.local.clear(async () => {
browser.storage.local.set({ options: data }, () => {
location.reload()
@ -102,23 +99,22 @@ resetSettings.addEventListener("click", async () => {
location.reload()
})
const fetchInstancesElement = document.getElementById('fetch-instances')
fetchInstancesElement.addEventListener('change', event => {
setOption('fetchInstances', 'select', event)
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 => {
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)
browser.permissions.request({ permissions: ["bookmarks"] }, r => (bookmarksMenuElement.checked = r))
else browser.permissions.remove({ permissions: ["bookmarks"] }, r => (bookmarksMenuElement.checked = !r))
})
let themeElement = document.getElementById("theme")
@ -149,8 +145,9 @@ 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
@ -165,7 +162,10 @@ instanceTypeElement.addEventListener("change", event => {
let exceptionsCustomInstances = options.exceptions
function calcExceptionsCustomInstances() {
document.getElementById("exceptions-custom-checklist").innerHTML = [...exceptionsCustomInstances.url, ...exceptionsCustomInstances.regex]
document.getElementById("exceptions-custom-checklist").innerHTML = [
...exceptionsCustomInstances.url,
...exceptionsCustomInstances.regex,
]
.map(
x => `<div>
${x}
@ -210,7 +210,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()
})

View File

@ -5,7 +5,7 @@ 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) {
@ -71,9 +71,9 @@ browser.tabs.query({ active: true, currentWindow: true }, async tabs => {
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) })
)
document
.getElementById("change_instance")
.addEventListener("click", async () => browser.tabs.update({ url: await servicesHelper.switchInstance(url) }))
}
})
servicesHelper.reverse(url).then(r => {
@ -84,7 +84,9 @@ browser.tabs.query({ active: true, currentWindow: true }, async tabs => {
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"))
document
.getElementById("redirect_to_original")
.addEventListener("click", () => browser.runtime.sendMessage("reverseTab"))
}
})
servicesHelper.redirectAsync(url, "main_frame", null, true).then(r => {

View File

@ -54,7 +54,7 @@ div.block input[type="checkbox"] {
text-decoration: none;
width: min-content;
color: var(--text);
transition: .1s;
transition: 0.1s;
}
.title:hover {
@ -348,7 +348,7 @@ body.light-theme a {
}
body.light-theme a:hover {
color: var(--active)
color: var(--active);
}
button {
@ -438,7 +438,6 @@ html.mobile body.option {
align-items: center;
}
html.mobile section.links {
flex-direction: row;
width: 100%;

View File

@ -47,7 +47,7 @@ Bandcamp - [https://thorwegian.bandcamp.com/track/just-because](https://thorwegi
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)
---