about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorManeraKai <manerakai@protonmail.com>2022-11-21 06:12:40 +0300
committerManeraKai <manerakai@protonmail.com>2022-11-21 06:12:40 +0300
commit5296d833286e7bf75ca3c3cbc85113ca80b3e53e (patch)
treea84ecccacf1f0f107ab13ff355f1c8bdab5543e1
parentupdated instances (diff)
parentFixed Bypass not working https://github.com/libredirect/libredirect/issues/475 (diff)
downloadlibredirect-5296d833286e7bf75ca3c3cbc85113ca80b3e53e.zip
Merge https://github.com/libredirect/libredirect
-rw-r--r--.prettierignore9
-rw-r--r--chromium.md2
-rw-r--r--package.json13
-rw-r--r--src/assets/javascripts/services.js34
-rw-r--r--src/config/config.json204
-rwxr-xr-xsrc/instances/get_instances.py8
-rw-r--r--src/pages/background/background.js1
-rw-r--r--src/pages/options/widgets/about.ejs59
-rw-r--r--src/pages/options/widgets/general.ejs73
-rw-r--r--src/pages/options/widgets/services.ejs55
-rw-r--r--src/pages/options/widgets/services.js34
-rw-r--r--src/pages/stylesheets/styles.css17
12 files changed, 313 insertions, 196 deletions
diff --git a/.prettierignore b/.prettierignore
deleted file mode 100644
index d789b742..00000000
--- a/.prettierignore
+++ /dev/null
@@ -1,9 +0,0 @@
-web-ext-artifacts/
-.DS_Store
-nod
-node_modules
-package-lock.json
-src/instances/data.json
-src/instances/blacklist.json
-src/_locales/
-.vscode
diff --git a/chromium.md b/chromium.md
index 3f3693d2..9d1bcd4f 100644
--- a/chromium.md
+++ b/chromium.md
@@ -8,6 +8,8 @@
 
 Updates are automatic
 
+**NOTE:** If this way failed. Then try the Windows, MacOS way.
+
 ## Windows, MacOS
 
 - Download the latest release [libredirect-2.3.4.zip](https://github.com/libredirect/libredirect/releases/download/v2.3.4/libredirect-2.3.4.zip)
diff --git a/package.json b/package.json
index 98351dad..ade219b1 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,7 @@
 		"build": "web-ext build",
 		"test": "web-ext lint",
 		"instances": "python3 src/instances/get_instances.py && git update-index --assume-unchanged src/instances/blacklist.json src/instances/data.json",
-		"ejs": "ejs src/pages/options/index.ejs -f src/config/config.json -o src/pages/options/index.html && ejs src/pages/popup/popup.ejs -f src/config/config.json -o src/pages/popup/popup.html && prettier -w src/pages/options/index.html src/pages/popup/popup.html"
+		"ejs": "ejs src/pages/options/index.ejs -f src/config/config.json -o src/pages/options/index.html && ejs src/pages/popup/popup.ejs -f src/config/config.json -o src/pages/popup/popup.html"
 	},
 	"repository": {
 		"type": "git",
@@ -24,19 +24,8 @@
 	"homepage": "https://libredirect.codeberg.page",
 	"devDependencies": {
 		"ejs": "^3.1.8",
-		"prettier": "^2.7.1",
 		"web-ext": "^7.2.0"
 	},
-	"prettier": {
-		"semi": false,
-		"tabWidth": 2,
-		"useTabs": true,
-		"arrowParens": "avoid",
-		"printWidth": 200,
-		"bracketSameLine": true,
-		"endOfLine": "lf",
-		"singleQuote": false
-	},
 	"webExt": {
 		"ignoreFiles": [
 			"instances/get_instances.py",
diff --git a/src/assets/javascripts/services.js b/src/assets/javascripts/services.js
index 432420fb..a8d99075 100644
--- a/src/assets/javascripts/services.js
+++ b/src/assets/javascripts/services.js
@@ -45,11 +45,15 @@ function all(service, frontend, options, config, redirects) {
 	return instances
 }
 
-function regexArray(service, url, config) {
+function regexArray(service, url, config, frontend) {
 	if (config.services[service].targets == "datajson") {
-		if (targets[service].includes(utils.protocolHost(url))) return true
+		if (targets[service].startsWith(utils.protocolHost(url))) return true
 	} else {
 		const targetList = config.services[service].targets
+		if (frontend && config.services[service].frontends[frontend].excludeTargets)
+			for (const i in config.services[service].frontends[frontend].excludeTargets) {
+				targetList = targetList.splice(i, 1)
+			}
 		for (const targetString in targetList) {
 			const target = new RegExp(targetList[targetString])
 			if (target.test(url.href)) return true
@@ -59,27 +63,29 @@ function regexArray(service, url, config) {
 }
 
 function redirect(url, type, initiator, forceRedirection) {
-	if (type != "main_frame" && type != "sub_frame") return
+	if (type != "main_frame" && type != "sub_frame" && type != "image") return
 	let randomInstance
 	let frontend
 	for (const service in config.services) {
+
 		if (!forceRedirection && !options[service].enabled) continue
+
 		if (config.services[service].embeddable && type != options[service].redirectType && options[service].redirectType != "both") continue
 		if (!config.services[service].embeddable && type != "main_frame") continue
-		// let targets = new RegExp(config.services[service].targets.join("|"), "i")
-
-		if (!regexArray(service, url, config)) continue
-		// if (initiator) {
-		// 	console.log(initiator.host)
-		// 	if (targets.test(initiator.host)) continue
-		// 	//if (all(service, null, options, config, redirects).includes(initiator.origin) && reverse(initiator) == url) return "BYPASSTAB"
-		// }
 
 		if (Object.keys(config.services[service].frontends).length > 1) {
-			if (type == "sub_frame" && config.services[service].embeddable && !config.services[service].frontends[options[service].frontend].embeddable) frontend = options[service].embedFrontend
+			if (
+				type == "sub_frame" && config.services[service].embeddable
+				&&
+				!config.services[service].frontends[options[service].frontend].embeddable
+			) frontend = options[service].embedFrontend
 			else frontend = options[service].frontend
 		} else frontend = Object.keys(config.services[service].frontends)[0]
 
+		if (!regexArray(service, url, config, frontend)) continue
+
+		if (initiator && all(service, null, options, config, redirects).includes(initiator.origin)) return "BYPASSTAB"
+
 		if (config.services[service].frontends[frontend].instanceList) {
 			let instanceList = [...options[frontend][options.network].enabled, ...options[frontend][options.network].custom]
 			if (instanceList.length === 0 && options.networkFallback) instanceList = [...options[frontend].clearnet.enabled, ...options[frontend].clearnet.custom]
@@ -88,7 +94,7 @@ function redirect(url, type, initiator, forceRedirection) {
 		} else if (config.services[service].frontends[frontend].singleInstance) randomInstance = config.services[service].frontends[frontend].singleInstance
 		break
 	}
-	if (!frontend) return
+	if (!frontend || !randomInstance) return
 
 	// Here is a (temperory) space for defining constants required in 2 or more switch cases.
 	// When possible, try have the two switch cases share all their code as done with searx and searxng.
@@ -108,7 +114,7 @@ function redirect(url, type, initiator, forceRedirection) {
 		}
 		return [zoom, lon, lat]
 	}
-
+	console.log(frontend)
 	switch (frontend) {
 		// This is where all instance-specific code must be ran to convert the service url to one that can be understood by the frontend.
 		case "beatbump":
diff --git a/src/config/config.json b/src/config/config.json
index b1c4c8a4..011347f5 100644
--- a/src/config/config.json
+++ b/src/config/config.json
@@ -22,14 +22,22 @@
 			"frontends": {
 				"invidious": {
 					"preferences": {
-						"cookies": ["PREFS"],
-						"localstorage": ["dark_mode"]
+						"cookies": [
+							"PREFS"
+						],
+						"localstorage": [
+							"dark_mode"
+						]
 					},
 					"name": "Invidious",
 					"embeddable": true,
 					"instanceList": true
 				},
 				"piped": {
+					"excludeTargets": [
+						1,
+						2
+					],
 					"preferences": {
 						"localstorage": [
 							"bufferGoal",
@@ -58,8 +66,14 @@
 					"instanceList": true
 				},
 				"pipedMaterial": {
+					"excludeTargets": [
+						1,
+						2
+					],
 					"preferences": {
-						"localstorage": ["PREFERENCES"]
+						"localstorage": [
+							"PREFERENCES"
+						]
 					},
 					"name": "Piped-Material",
 					"embeddable": false,
@@ -76,11 +90,19 @@
 					"instanceList": true
 				},
 				"freetube": {
+					"excludeTargets": [
+						1,
+						2
+					],
 					"name": "FreeTube",
 					"embeddable": false,
 					"instanceList": false
 				},
 				"yattee": {
+					"excludeTargets": [
+						1,
+						2
+					],
 					"name": "Yattee",
 					"embeddable": false,
 					"instanceList": false
@@ -109,7 +131,9 @@
 			"frontends": {
 				"beatbump": {
 					"preferences": {
-						"localstorage": ["settings"],
+						"localstorage": [
+							"settings"
+						],
 						"indexeddb": "beatbump"
 					},
 					"name": "Beatbump",
@@ -117,14 +141,26 @@
 				},
 				"hyperpipe": {
 					"preferences": {
-						"localstorage": ["api", "authapi", "codec", "locale", "next", "pipedapi", "quality", "theme", "vol"],
+						"localstorage": [
+							"api",
+							"authapi",
+							"codec",
+							"locale",
+							"next",
+							"pipedapi",
+							"quality",
+							"theme",
+							"vol"
+						],
 						"indexeddb": "hyperpipedb"
 					},
 					"name": "Hyperpipe",
 					"instanceList": true
 				}
 			},
-			"targets": ["^https?:\\/{2}music\\.youtube\\.com(\\/|$)"],
+			"targets": [
+				"^https?:\\/{2}music\\.youtube\\.com(\\/|$)"
+			],
 			"name": "YT Music",
 			"options": {
 				"enabled": true,
@@ -190,7 +226,9 @@
 					"instanceList": true
 				}
 			},
-			"targets": ["^https?:\\/{2}(www\\.)?instagram\\.com\\/?(p\\/|$)"],
+			"targets": [
+				"^https?:\\/{2}(www\\.)?instagram\\.com\\/?(p\\/|$)"
+			],
 			"name": "Instagram",
 			"options": {
 				"enabled": true
@@ -203,13 +241,18 @@
 			"frontends": {
 				"proxiTok": {
 					"preferences": {
-						"cookies": ["api-test_endpoints", "theme"]
+						"cookies": [
+							"api-test_endpoints",
+							"theme"
+						]
 					},
 					"name": "ProxiTok",
 					"instanceList": true
 				}
 			},
-			"targets": ["^https?:\\/{2}(www\\.|)tiktok\\.com(\\/|$)"],
+			"targets": [
+				"^https?:\\/{2}(www\\.|)tiktok\\.com(\\/|$)"
+			],
 			"name": "TikTok",
 			"options": {
 				"enabled": true
@@ -222,7 +265,20 @@
 			"frontends": {
 				"libreddit": {
 					"preferences": {
-						"cookies": ["theme", "front_page", "layout", "wide", "post_sort", "comment_sort", "show_nsfw", "autoplay_videos", "use_hls", "hide_hls_notification", "subscriptions", "filters"]
+						"cookies": [
+							"theme",
+							"front_page",
+							"layout",
+							"wide",
+							"post_sort",
+							"comment_sort",
+							"show_nsfw",
+							"autoplay_videos",
+							"use_hls",
+							"hide_hls_notification",
+							"subscriptions",
+							"filters"
+						]
 					},
 					"name": "Libreddit",
 					"instanceList": true
@@ -250,20 +306,16 @@
 					},
 					"name": "Teddit",
 					"instanceList": true
-				},
-				"ferrit": {
-					"preferences": {
-						"cookies": ["theme", "front_page", "layout", "wide", "post_sort", "comment_sort", "show_nsfw", "autoplay_videos", "use_hls", "hide_hls_notification", "subscriptions", "filters"]
-					},
-					"name": "Ferrit",
-					"instanceList": true
 				}
 			},
-			"targets": ["^https?:\\/{2}(www\\.|old\\.|np\\.|new\\.|amp\\.|)reddit\\.com(?=\\/u(ser)?\\/|\\/r\\/|\\/?$)", "^https?:\\/{2}(i|(external-)?preview)\\.redd\\.it"],
+			"targets": [
+				"^https?:\\/{2}(www\\.|old\\.|np\\.|new\\.|amp\\.|)reddit\\.com(?=\\/u(ser)?\\/|\\/r\\/|\\/?$)",
+				"^https?:\\/{2}(i|(external-)?preview)\\.redd\\.it"
+			],
 			"name": "Reddit",
 			"options": {
 				"enabled": true,
-				"frontend": "ferrit"
+				"frontend": "libreddit"
 			},
 			"imageType": "png",
 			"embeddable": false,
@@ -273,11 +325,12 @@
 			"frontends": {
 				"rimgo": {
 					"name": "rimgo",
-					"embeddable": true,
 					"instanceList": true
 				}
 			},
-			"targets": ["^https?:\\/{2}([im]\\.)?(stack\\.)?imgur\\.(com|io)(\\/|$)"],
+			"targets": [
+				"^https?:\\/{2}([im]\\.)?(stack\\.)?imgur\\.(com|io)(\\/|$)"
+			],
 			"name": "Imgur",
 			"options": {
 				"enabled": true,
@@ -291,13 +344,18 @@
 			"frontends": {
 				"wikiless": {
 					"preferences": {
-						"cookies": ["theme", "default_lang"]
+						"cookies": [
+							"theme",
+							"default_lang"
+						]
 					},
 					"name": "Wikiless",
 					"instanceList": true
 				}
 			},
-			"targets": ["^https?:\\/{2}(?:[a-z]+\\.)*wikipedia\\.org(\\/|$)"],
+			"targets": [
+				"^https?:\\/{2}(?:[a-z]+\\.)*wikipedia\\.org(\\/|$)"
+			],
 			"name": "Wikipedia",
 			"options": {
 				"enabled": false
@@ -314,7 +372,7 @@
 				}
 			},
 			"targets": [
-				"(?:.*\\.)*(?<!(link\\.|cdn\\-images\\-\\d+\\.))medium\\.com(\\/.*)?$",
+				"^(?:.*\\.)*(?<!(link\\.|cdn\\-images\\-\\d+\\.))medium\\.com(\\/.*)?$",
 				"^https?:\\/{2}towardsdatascience\\.com(\\/|$)",
 				"^https?:\\/{2}uxdesign\\.cc(\\/|$)",
 				"^https?:\\/{2}uxplanet\\.org(\\/|$)",
@@ -345,13 +403,17 @@
 			"frontends": {
 				"quetre": {
 					"preferences": {
-						"localstorage": ["theme"]
+						"localstorage": [
+							"theme"
+						]
 					},
 					"name": "Quetre",
 					"instanceList": true
 				}
 			},
-			"targets": ["^https?:\\/{2}([a-zA-Z0-9-]+\\.)*quora\\.com(\\/|$)"],
+			"targets": [
+				"^https?:\\/{2}([a-zA-Z0-9-]+\\.)*quora\\.com(\\/|$)"
+			],
 			"name": "Quora",
 			"options": {
 				"enabled": true
@@ -364,13 +426,17 @@
 			"frontends": {
 				"libremdb": {
 					"preferences": {
-						"localstorage": ["theme"]
+						"localstorage": [
+							"theme"
+						]
 					},
 					"name": "libremdb",
 					"instanceList": true
 				}
 			},
-			"targets": ["^https?:\\/{2}(?:www\\.|m\\.|)imdb\\.com\\/title"],
+			"targets": [
+				"^https?:\\/{2}(?:www\\.|m\\.|)imdb\\.com\\/title"
+			],
 			"name": "IMDb",
 			"options": {
 				"enabled": true
@@ -386,7 +452,9 @@
 					"instanceList": true
 				}
 			},
-			"targets": ["^https?:\\/{2}(www\\.|)reuters\\.com(\\/|$)"],
+			"targets": [
+				"^https?:\\/{2}(www\\.|)reuters\\.com(\\/|$)"
+			],
 			"name": "Reuters",
 			"options": {
 				"enabled": false
@@ -402,7 +470,9 @@
 					"instanceList": true
 				}
 			},
-			"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": true
@@ -431,8 +501,18 @@
 			"frontends": {
 				"librarian": {
 					"preferences": {
-						"cookies": ["nsfw", "theme"],
-						"localstorage": ["autoplay", "autoplayNextVid", "collapseComments", "plyr", "sb_categories", "showRelated"]
+						"cookies": [
+							"nsfw",
+							"theme"
+						],
+						"localstorage": [
+							"autoplay",
+							"autoplayNextVid",
+							"collapseComments",
+							"plyr",
+							"sb_categories",
+							"showRelated"
+						]
 					},
 					"name": "Librarian",
 					"embeddable": true,
@@ -444,7 +524,10 @@
 					"instanceList": false
 				}
 			},
-			"targets": ["^https?:\\/{2}odysee\\.com(\\/|$)", "^https?:\\/{2}lbry\\.tv(\\/|$)"],
+			"targets": [
+				"^https?:\\/{2}odysee\\.com(\\/|$)",
+				"^https?:\\/{2}lbry\\.tv(\\/|$)"
+			],
 			"name": "LBRY",
 			"options": {
 				"enabled": true,
@@ -517,13 +600,26 @@
 				},
 				"librex": {
 					"preferences": {
-						"cookies": ["bibliogram", "disable_frontends", " disable_special", "invidious", "libreddit", "nitter", "proxitok", "save", "theme", "wikiless"]
+						"cookies": [
+							"bibliogram",
+							"disable_frontends",
+							" disable_special",
+							"invidious",
+							"libreddit",
+							"nitter",
+							"proxitok",
+							"save",
+							"theme",
+							"wikiless"
+						]
 					},
 					"name": "LibreX",
 					"instanceList": true
 				}
 			},
-			"targets": ["^https?:\\/{2}search\\.libredirect\\.invalid"],
+			"targets": [
+				"^https?:\\/{2}search\\.libredirect\\.invalid"
+			],
 			"name": "Search",
 			"options": {
 				"enabled": true,
@@ -537,14 +633,24 @@
 			"frontends": {
 				"simplyTranslate": {
 					"preferences": {
-						"cookies": ["from_lang", "to_lang", "tts_enabled", "use_text_fields"]
+						"cookies": [
+							"from_lang",
+							"to_lang",
+							"tts_enabled",
+							"use_text_fields"
+						]
 					},
 					"name": "SimplyTranslate",
 					"instanceList": true
 				},
 				"lingva": {
 					"preferences": {
-						"localstorage": ["isauto", "source", "target", "chakra-ui-color-mode"]
+						"localstorage": [
+							"isauto",
+							"source",
+							"target",
+							"chakra-ui-color-mode"
+						]
 					},
 					"name": "Lingva Translate",
 					"instanceList": true
@@ -554,7 +660,10 @@
 					"instanceList": true
 				}
 			},
-			"targets": ["^https?:\\/{2}translate\\.google(\\.[a-z]{2,3}){1,2}\\/", "^https?:\\/{2}translate\\.libredirect\\.invalid"],
+			"targets": [
+				"^https?:\\/{2}translate\\.google(\\.[a-z]{2,3}){1,2}\\/",
+				"^https?:\\/{2}translate\\.libredirect\\.invalid"
+			],
 			"name": "Translate",
 			"options": {
 				"enabled": true,
@@ -576,7 +685,10 @@
 					"singleInstance": "https://www.openstreetmap.org"
 				}
 			},
-			"targets": ["^https?:\\/{2}maps\\.libredirect\\.invalid", "^https?:\\/{2}(((www|maps)\\.)?(google\\.).*(\\/maps)|maps\\.(google\\.).*)"],
+			"targets": [
+				"^https?:\\/{2}maps\\.libredirect\\.invalid",
+				"^https?:\\/{2}(((www|maps)\\.)?(google\\.).*(\\/maps)|maps\\.(google\\.).*)"
+			],
 			"name": "Maps",
 			"options": {
 				"enabled": false,
@@ -590,10 +702,14 @@
 			"frontends": {
 				"send": {
 					"name": "Send",
-					"instanceList": "true"
+					"instanceList": true
 				}
 			},
-			"targets": ["^https?:\\/{2}send\\.libredirect\\.invalid", "^https?:\\/{2}send\\.firefox\\.com\\/?$", "^https?:\\/{2}sendfiles\\.online\\/?$"],
+			"targets": [
+				"^https?:\\/{2}send\\.libredirect\\.invalid",
+				"^https?:\\/{2}send\\.firefox\\.com\\/?$",
+				"^https?:\\/{2}sendfiles\\.online\\/?$"
+			],
 			"name": "Send Files",
 			"options": {
 				"enabled": true
@@ -609,7 +725,9 @@
 					"instanceList": true
 				}
 			},
-			"targets": ["^https?:\\/{2}paste\\.libredirect\\.invalid"],
+			"targets": [
+				"^https?:\\/{2}paste\\.libredirect\\.invalid"
+			],
 			"name": "Paste Text",
 			"options": {
 				"enabled": true
@@ -630,4 +748,4 @@
 			"color": "grey"
 		}
 	}
-}
+}
\ No newline at end of file
diff --git a/src/instances/get_instances.py b/src/instances/get_instances.py
index 5e868257..913ee1c4 100755
--- a/src/instances/get_instances.py
+++ b/src/instances/get_instances.py
@@ -334,7 +334,7 @@ def bibliogram():
 
 
 def libreddit():
-    fetchJsonList('libreddit', 'Libreddit', 'https://github.com/ferritreader/libreddit-instances/raw/master/instances.json',
+    fetchJsonList('libreddit', 'Libreddit', 'https://github.com/libreddit/libreddit-instances/raw/master/instances.json',
                   {'clearnet': 'url', 'tor': 'onion', 'i2p': 'i2p', 'loki': None}, True)
 
 
@@ -343,11 +343,6 @@ def teddit():
                   {'clearnet': 'url', 'tor': 'onion', 'i2p': 'i2p', 'loki': None}, False)
 
 
-def ferrit():
-    fetchJsonList('ferrit', 'Ferrit', 'https://raw.githubusercontent.com/ferritreader/ferrit-instances/master/instances.json',
-                  {'clearnet': 'url', 'tor': 'onion', 'i2p': 'i2p', 'loki': None}, True)
-
-
 def wikiless():
     fetchJsonList('wikiless', 'Wikiless', 'https://wikiless.org/instances.json',
                   {'clearnet': 'url', 'tor': 'onion', 'i2p': 'i2p', 'loki': None}, False)
@@ -505,7 +500,6 @@ nitter()
 bibliogram()
 libreddit()
 teddit()
-ferrit()
 wikiless()
 scribe()
 quetre()
diff --git a/src/pages/background/background.js b/src/pages/background/background.js
index 71fff06c..3a695048 100644
--- a/src/pages/background/background.js
+++ b/src/pages/background/background.js
@@ -56,7 +56,6 @@ browser.webRequest.onBeforeRequest.addListener(
 		} catch {
 			return null
 		}
-
 		if (tabIdRedirects[details.tabId] == false) return null
 		let newUrl = servicesHelper.redirect(url, details.type, initiator, tabIdRedirects[details.tabId])
 
diff --git a/src/pages/options/widgets/about.ejs b/src/pages/options/widgets/about.ejs
index 09cdab1d..a90e8b9e 100644
--- a/src/pages/options/widgets/about.ejs
+++ b/src/pages/options/widgets/about.ejs
@@ -1,28 +1,37 @@
-<section class="option-block" id="about_page"> 
-<div class="some-block option-block">
-  <h1 data-localise="__MSG_about__">About</h1>
-</div>
-<hr>
-<div class="about">
+<section class="option-block" id="about_page">
+
   <div class="some-block option-block">
-    <h4>Donate: ♥️</h4>
-    <h4><a href='https://libredirect.codeberg.page/donate'>https://libredirect.codeberg.page/donate</a> </h4>
+    <h1 data-localise="__MSG_about__">About</h1>
   </div>
-  <div class="some-block option-block">
-    <h4>FAQ:</h4>
-    <h4><a href='https://libredirect.codeberg.page/faq'>https://libredirect.codeberg.page/faq</a></h4>
-  </div>
-  <div class="some-block option-block">
-    <h4>Docs:</h4>
-    <h4><a href='https://libredirect.codeberg.page/docs'>https://libredirect.codeberg.page/docs</a></h4>
-  </div>
-  <div class="some-block option-block">
-    <h4>Source Code:</h4>
-    <h4><a href='https://libredirect.codeberg.page/source_code'>https://libredirect.codeberg.page/source_code</a></h4>
-  </div>
-  <div class="some-block option-block">
-    <h4>Forked from:</h4>
-    <h4><a href="https://github.com/SimonBrazell/privacy-redirect">Privacy Redirect</a></h4>
+
+  <hr>
+
+  <div class="about">
+
+    <div class="some-block option-block">
+      <h4>Donate: ♥️</h4>
+      <h4><a href='https://libredirect.codeberg.page/donate'>https://libredirect.codeberg.page/donate</a> </h4>
+    </div>
+
+    <div class="some-block option-block">
+      <h4>FAQ:</h4>
+      <h4><a href='https://libredirect.codeberg.page/faq'>https://libredirect.codeberg.page/faq</a></h4>
+    </div>
+
+    <div class="some-block option-block">
+      <h4>Docs:</h4>
+      <h4><a href='https://libredirect.codeberg.page/docs'>https://libredirect.codeberg.page/docs</a></h4>
+    </div>
+
+    <div class="some-block option-block">
+      <h4>Source Code:</h4>
+      <h4><a href='https://libredirect.codeberg.page/source_code'>https://libredirect.codeberg.page/source_code</a></h4>
+    </div>
+
+    <div class="some-block option-block">
+      <h4>Forked from:</h4>
+      <h4><a href="https://github.com/SimonBrazell/privacy-redirect">Privacy Redirect</a></h4>
+    </div>
+
   </div>
-</div>
-</section>
+</section>
\ No newline at end of file
diff --git a/src/pages/options/widgets/general.ejs b/src/pages/options/widgets/general.ejs
index e24046db..fef052df 100644
--- a/src/pages/options/widgets/general.ejs
+++ b/src/pages/options/widgets/general.ejs
@@ -2,7 +2,8 @@
   <div class="some-block option-block">
     <h1 data-localise="__MSG_general__">General</h1>
   </div>
-  <hr>
+  <hr />
+
   <div class="some-block option-block">
     <h4 data-localise="__MSG_theme__">Theme</h4>
     <select id="theme">
@@ -11,38 +12,46 @@
       <option value="dark" data-localise="__MSG_dark__">Dark</option>
     </select>
   </div>
+
   <div class="some-block option-block">
     <h4 data-localise="__MSG_network__">Network</h4>
     <select id="network">
       <% for (const network in config.networks) { -%>
-<option value="<%= network %>"><%= config.networks[network].name %></option>
+      <option value="<%= network %>"><%= config.networks[network].name %></option>
       <% }; %>
-</select>
+    </select>
   </div>
+
   <div id="network-fallback">
     <div class="some-block option-block">
       <h4 data-localise="__MSG_networkFallback__">Fallback to clearnet if no instances are available for the current network</h4>
-      <input id="network-fallback-checkbox" type="checkbox">
+      <input id="network-fallback-checkbox" type="checkbox" />
     </div>
   </div>
+
   <div class="some-block option-block">
     <h4 data-localise="__MSG_autoRedirect__"></h4>
-    <input id="auto-redirect" type="checkbox">
+    <input id="auto-redirect" type="checkbox" />
   </div>
+
   <form>
     <div class="some-block option-block">
       <h4 data-localise="__MSG_latencyThreshold">Latency Threshold</h4>
       <output id="latency-output" for="latencyInput" name="latencyOutput"></output>
-      <input id="latency-input" type="range" min="50" max="5000" value="1000" name="latencyInput" step="50">
+      <input id="latency-input" type="range" min="50" max="5000" value="1000" name="latencyInput" step="50" />
     </div>
   </form>
+
+  <hr>
+
   <div class="some-block option-block">
-    <h4 data-localise="__MSG_exceptions__"></h4>
+    <h4 data-localise="__MSG_exclude_from_redirecting_">Excluded from redirecting</h4>
   </div>
+
   <form id="custom-exceptions-instance-form">
     <div class="some-block option-block">
-      <div class="some-block" style="padding:0;">
-        <input id="exceptions-custom-instance" placeholder="https://www.google.com" type="url">&nbsp;
+      <div class="some-block" style="padding: 0">
+        <input id="exceptions-custom-instance" placeholder="https://www.google.com" type="url" />&nbsp;
         <select id="exceptions-custom-instance-type">
           <option value="url">URL</option>
           <option value="regex">Regex</option>
@@ -55,48 +64,38 @@
       </button>
     </div>
   </form>
+
+  <hr>
+
   <div class="checklist" id="exceptions-custom-checklist"></div>
-  <div class="buttons buttons-inline"><a class="button button-inline" id="update-instances">
+
+  <div class="buttons buttons-inline">
+    <a class="button button-inline" id="update-instances">
       <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor">
         <path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"></path>
       </svg>
-      <x data-localise="__MSG_updateInstances__">Update Instances</x></a>&nbsp; &nbsp;</div>
-  <div class="buttons buttons-inline">  
-    <label class="button button-inline" id="import_settings_text" for="import-settings"> 
+      <x data-localise="__MSG_updateInstances__">Update Instances</x>
+    </a>&nbsp; &nbsp;
+  </div>
+
+  <div class="buttons buttons-inline">
+    <label class="button button-inline" id="import_settings_text" for="import-settings">
       <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor">
         <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"></path>
       </svg>&nbsp;
       <x data-localise="__MSG_importSettings__">Import Settings</x>
     </label>
-    <input class="button button-inline" id="import-settings" type="file" style="display:none;">&nbsp; &nbsp;<a class="button button-inline" id="export-settings">
+    <input class="button button-inline" id="import-settings" type="file" style="display: none" />&nbsp; &nbsp;<a class="button button-inline" id="export-settings">
       <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor">
         <path d="M10.09 15.59L11.5 17l5-5-5-5-1.41 1.41L12.67 11H3v2h9.67l-2.58 2.59zM19 3H5c-1.11 0-2 .9-2 2v4h2V5h14v14H5v-4H3v4c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"></path>
-      </svg>&nbsp;
-      <x data-localise="__MSG_exportSettings__">Export Settings</x></a>&nbsp; &nbsp;<a class="button button-inline" id="reset-settings">
+      </svg>&nbsp; <x data-localise="__MSG_exportSettings__">Export Settings</x></a>&nbsp; &nbsp;<a class="button button-inline" id="reset-settings">
       <svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor">
         <path d="M12,5V2L8,6l4,4V7c3.31,0,6,2.69,6,6c0,2.97-2.17,5.43-5,5.91v2.02c3.95-0.49,7-3.85,7-7.93C20,8.58,16.42,5,12,5z"></path>
         <path d="M6,13c0-1.65,0.67-3.15,1.76-4.24L6.34,7.34C4.9,8.79,4,10.79,4,13c0,4.08,3.05,7.44,7,7.93v-2.02 C8.17,18.43,6,15.97,6,13z"></path>
       </svg>
-      <x data-localise="__MSG_resetSettings__">Reset Settings</x></a>
+      <x data-localise="__MSG_resetSettings__">Reset Settings</x>
+    </a>
   </div>
-  <hr>
-  <div class="some-block option-block">
-    <h4 data-localise="__MSG_customPopup__">Customize Popup</h4>
-  </div>
-  <div class="checklist-popup" id="popup-frontends-checklist">
-    <% for (const service in config.services) { -%>
-<div>
-  <div>
-  <% if (config.services[service].imageType != "svgMono") { _%>
-  <img src="../../../assets/images/<%= service %>-icon.<%= config.services[service].imageType %>">
-  <% } else { _%>
-  <%- include ('src/assets/images/' + service + '-icon.svg') %>
-  <% } _%>
-  <label data-localise="__MSG_<%= service %>__" for="<%= service %>"><%= config.services[service].name %></label>
-      </div>
-      <input id="<%= service %>" type="checkbox">
-    </div>
-    <% }; %>
-</div>
+
   <script type="module" src="./widgets/general.js"></script>
-</section>
+</section>
\ No newline at end of file
diff --git a/src/pages/options/widgets/services.ejs b/src/pages/options/widgets/services.ejs
index 44c6a9f3..109f6689 100644
--- a/src/pages/options/widgets/services.ejs
+++ b/src/pages/options/widgets/services.ejs
@@ -3,12 +3,16 @@
   <div class="some-block option-block">
     <h1 data-localise="__MSG_<%= service %>__"><%= config.services[service].name %></h1>
   </div>
-  <hr>
+  <hr />
   <div class="some-block option-block">
     <h4 data-localise="__MSG_enable__">Enable</h4>
-    <input id="<%= service %>-enabled" type="checkbox">
+    <input id="<%= service %>-enabled" type="checkbox" />
   </div>
-  <% if (Object.keys(config.services[service].frontends).length > 1) { %>
+  <div class="some-block option-block">
+    <h4 data-localise="__MSG_show_in_popup__">Show in Popup</h4>
+    <input id="<%= service %>" type="checkbox" />
+  </div>
+  <% if (Object.keys(config.services[service].frontends).length> 1) { %>
   <div class="some-block option-block">
     <h4 data-localise="__MSG_frontend__">Frontend</h4>
     <select id="<%= service %>-frontend">
@@ -21,16 +25,12 @@
   <div class="some-block option-block">
     <h4 data-localise="__MSG_embed_frontend__">Embed Frontend</h4>
     <select id="<%= service %>-embedFrontend">
-      <% for (const frontend in config.services[service].frontends) { -%>
-      <% if (config.services[service].frontends[frontend].embeddable) { _%>
+      <% for (const frontend in config.services[service].frontends) { -%> <% if (config.services[service].frontends[frontend].embeddable) { _%>
       <option value="<%= frontend %>"><%= config.services[service].frontends[frontend].name %></option>
-      <% } _%>
-      <% } %>
+      <% } _%> <% } %>
     </select>
   </div>
-  <% } _%>
-  <% } _%>
-  <% if (config.services[service].embeddable) { _%>
+  <% } _%> <% } _%> <% if (config.services[service].embeddable) { _%>
   <div class="some-block option-block">
     <h4 data-localise="__MSG_redirectType__">Redirect Type</h4>
     <select id="<%= service %>-redirectType">
@@ -40,23 +40,32 @@
     </select>
   </div>
   <% } _%>
-  <hr>
-  <% for (const frontend in config.services[service].frontends) { -%>
-  <% if (config.services[service].frontends[frontend].instanceList) { _%>
+  <hr />
+  <% for (const frontend in config.services[service].frontends) { -%> <% if (config.services[service].frontends[frontend].instanceList) { _%>
   <div id="<%= frontend %>">
     <% for (const network in config.networks) { -%>
+    <div class="buttons buttons-inline">
+      <label class="button button-inline" id="latency-<%= frontend %>-label" for="latency-<%= frontend %>">
+        <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor">
+          <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"></path>
+        </svg>
+        &nbsp;
+        <x data-localise="__MSG_testInstancesLatency__">Test Instances Latency</x>
+      </label>
+      <input class="button button-inline" id="latency-<%= frontend %>" style="display: none" />
+    </div>
     <div class="<%= network %>">
       <div class="some-block option-block">
         <h4 data-localise="__MSG_defaultInstances__">Default Instances</h4>
       </div>
       <div class="checklist"></div>
-      <hr>
+      <hr />
       <div class="some-block option-block">
         <h4 data-localise="__MSG_customInstances__">Custom Instances</h4>
       </div>
       <form class="custom-instance-form">
         <div class="some-block option-block">
-          <input class="custom-instance" placeholder="http://<%= frontend %>.<%= config.networks[network].tld %>" type="url">
+          <input class="custom-instance" placeholder="http://<%= frontend %>.<%= config.networks[network].tld %>" type="url" />
           <button class="add add-instance" type="submit">
             <svg xmlns="https://www.w3.org/2000/svg" height="20px" viewBox="0 0 24 24" width="20px" fill="currentColor">
               <path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"></path>
@@ -65,22 +74,12 @@
         </div>
       </form>
       <div class="checklist custom-checklist"></div>
-      <% if (network == "clearnet") { _%>
-      <div class="buttons buttons-inline">
-        <label class="button button-inline" id="latency-<%= frontend %>-label" for="latency-<%= frontend %>"> 
-          <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentColor">
-            <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"></path>
-          </svg>&nbsp;
-          <x data-localise="__MSG_testInstancesLatency__">Test Instances Latency</x>
-        </label>
-        <input class="button button-inline" id="latency-<%= frontend %>" style="display:none;">
-      </div>
+      <% if (network=="clearnet" ) { _%>
       <% } _%>
     </div>
     <% } %>
   </div>
-  <% } _%>
-  <% } %>
+  <% } _%> <% } %>
 </section>
 <% } %>
-<script type="module" src="./widgets/services.js"></script>
+<script type="module" src="./widgets/services.js"></script>
\ No newline at end of file
diff --git a/src/pages/options/widgets/services.js b/src/pages/options/widgets/services.js
index 37385faa..12904130 100644
--- a/src/pages/options/widgets/services.js
+++ b/src/pages/options/widgets/services.js
@@ -31,28 +31,32 @@ function changeFrontendsSettings(service) {
 	for (const frontend in config.services[service].frontends) {
 		if (config.services[service].frontends[frontend].instanceList) {
 			const frontendDiv = document.getElementById(frontend)
-			if (frontend == divs[service].frontend.value) {
-				frontendDiv.style.display = "block"
-			} else {
-				frontendDiv.style.display = "none"
+			if (typeof divs[service].frontend !== "undefined") {
+				if (frontend == divs[service].frontend.value) {
+					frontendDiv.style.display = "block"
+				} else {
+					frontendDiv.style.display = "none"
+				}
 			}
 		}
 	}
 
 	if (config.services[service].embeddable) {
-		if (!config.services[service].frontends[divs[service].frontend.value].embeddable) {
-			divs[service].embedFrontend.disabled = false
-			for (const frontend in config.services[service].frontends) {
-				if (config.services[service].frontends[frontend].embeddable) {
-					const frontendDiv = document.getElementById(frontend)
-					if (frontend == divs[service].embedFrontend.value) {
-						frontendDiv.style.display = "block"
-					} else {
-						frontendDiv.style.display = "none"
+		if (typeof divs[service].frontend !== "undefined") {
+			if (!config.services[service].frontends[divs[service].frontend.value].embeddable) {
+				divs[service].embedFrontend.disabled = false
+				for (const frontend in config.services[service].frontends) {
+					if (config.services[service].frontends[frontend].embeddable) {
+						const frontendDiv = document.getElementById(frontend)
+						if (frontend == divs[service].embedFrontend.value) {
+							frontendDiv.style.display = "block"
+						} else {
+							frontendDiv.style.display = "none"
+						}
 					}
 				}
-			}
-		} else if (Object.keys(config.services[service].frontends).length > 1) divs[service].embedFrontend.disabled = true
+			} else if (Object.keys(config.services[service].frontends).length > 1) divs[service].embedFrontend.disabled = true
+		}
 	}
 }
 
diff --git a/src/pages/stylesheets/styles.css b/src/pages/stylesheets/styles.css
index 0df2f9fa..5f2871e4 100644
--- a/src/pages/stylesheets/styles.css
+++ b/src/pages/stylesheets/styles.css
@@ -79,7 +79,6 @@ select {
 	margin: 0;
 	max-width: 500px;
 	border-radius: 3px;
-	cursor: pointer;
 }
 
 input[type="url"],
@@ -110,11 +109,19 @@ section.option-block h2 {
 body.option {
 	display: flex;
 	padding: 40px;
-	width: 900px;
+	width: 1100px;
+}
+
+section.links {
+	display: flex;
+	flex-wrap: wrap;
+	flex-direction: column;
+	width: 300px;
+	max-height: 720px;
 }
 
 section.links div {
-	margin: 20px 0;
+	margin: 10px;
 	width: max-content;
 }
 
@@ -458,7 +465,7 @@ body div section {
 	display: none;
 }
 
-div.about > div {
+div.about>div {
 	justify-content: start;
 	width: 520px;
 }
@@ -480,4 +487,4 @@ input:disabled {
 div.about a {
 	width: 500px;
 	display: inline-block;
-}
+}
\ No newline at end of file