import random import re from typing import Any, Callable from urllib import parse from qutebrowser.api import interceptor from qutebrowser.extensions.interceptors import QUrl, RedirectException from qutebrowser.utils import message def fixScribePath(url: QUrl): """Fix external medium blog to scribe translation. Some paths from medium will go through a 'global identity' path which messes up the actual url path we want to go to and puts it in queries. This puts it back on the path. """ # double unquoting necessary! # I suppose we double-wrap it earlier somewhere? # unquoted = parse.unquote( # url.path(options=QUrl.ComponentFormattingOption.FullyEncoded) # ) path = parse.unquote(f"{url.path()}{url.query()}", encoding="ascii") url.setQuery(None) new_path = re.sub(r"m/global-identity-2redirectUrl=", "", path) url.setPath( parse.quote(new_path), mode=QUrl.ParsingMode.StrictMode, ) return url redirects = { "youtube": { "source": ["youtube.com"], "farside": ["invidious"], }, "stackoverflow": { "source": ["stackoverflow.com", "askubuntu.com"], "farside": ["anonymousoverflow"], }, "lbry": { "source": ["odysee.com"], "farside": ["librarian"], }, "reddit": { "source": ["reddit.com"], "farside": ["redlib"], }, "instagram": { "source": ["instagram.com"], "farside": ["proxigram"], }, "twitter": { "source": ["twitter.com"], "farside": ["nitter"], }, "imdb": { "source": ["imdb.com"], "farside": ["libremdb"], }, "translate": { "source": ["translate.google.com"], "farside": ["lingva"], }, "tiktok": { "source": ["tiktok.com"], "farside": ["proxitok"], }, "imgur": { "source": ["imgur.com"], "farside": ["rimgo"], }, "medium": { "source": ["medium.com"], "farside": ["scribe"], # "postprocess": fixScribePath }, "fandom": { "source": ["fandom.com"], "farside": ["breezewiki"], }, "quora": { "source": ["quora.com"], "farside": ["quetre"], # "postprocess": lambda url: message.info(f"CALLING QUORA WITH {url}") }, "google": { "source": ["google.com"], "target": [ "search.albony.xyz", "search.garudalinux.org", "search.dr460nf1r3.org", "s.tokhmi.xyz", "search.sethforprivacy.com", "whoogle.dcs0.hu", "gowogle.voring.me", "whoogle.privacydev.net", "wg.vern.cc", "whoogle.hxvy0.gq", "whoogle.hostux.net", "whoogle.lunar.icu", "wgl.frail.duckdns.org", "whoogle.no-logs.com", "whoogle.ftw.lol", "whoogle-search--replitcomreside.repl.co", "search.notrustverify.ch", "whoogle.datura.network", "whoogle.yepserver.xyz", "search.nezumi.party", ], }, "biblioreads": { "source": ["goodreads.com"], "target": [ "biblioreads.eu.org", "biblioreads.vercel.app", "biblioreads.mooo.com", "bl.vern.cc", "biblioreads.lunar.icu", "read.whateveritworks.org", "biblioreads.privacyfucking.rocks", "read.seitan-ayoub.lol", "read.freedit.eu", "biblioreads.ducks.party", "biblioreads.snine.nl", "biblioreads.privacyredirect.com", ], }, "safetwitch": { "source": ["twitch.tv"], "target": [ "safetwitch.drgns.space", "safetwitch.projectsegfau.lt", "stream.whateveritworks.org", "safetwitch.datura.network", "ttv.vern.cc", "safetwitch.frontendfriendly.xyz", "ttv.femboy.band", "twitch.seitan-ayoub.lol", "st.ggtyler.dev", "safetwitch.lunar.icu", "twitch.sudovanilla.com", "safetwitch.r4fo.com", "safetwitch.ducks.party", "safetwitch.nogafam.fr", "safetwitch.privacyredirect.com", "st.ngn.tf", ], }, } def rewrite(request: interceptor.Request) -> None: # if config.get(name="content.oss_redirects") is False: # return if ( request.resource_type != interceptor.ResourceType.main_frame or request.request_url.scheme() in {"data", "blob"} ): return url = request.request_url if service := _should_be_redirected(url.host()): if "farside" in service: url = _farside_redirect(url, _pick_random(service["farside"])) else: srv = _pick_random(service["target"]) url = _target_redirect(url, srv) try: request.redirect(url) except RedirectException as e: message.error(str(e)) if "postprocess" in service and isinstance(service["postprocess"], Callable): url = service["postprocess"](url) def _farside_redirect(url: QUrl, service: str) -> QUrl: try: url.setHost("farside.link") url.setPath(f"/{service}{url.path()}") except RedirectException as e: message.error(str(e)) return url def _target_redirect(url: QUrl, target: str) -> QUrl: if target is not None and url.setHost(target) is not False: return url return url def _pick_random(choices: list) -> Any: return choices[random.randint(0, len(choices) - 1)] def _should_be_redirected( host: str, redirects: dict = redirects ) -> dict[str, list] | None: for service in redirects.values(): for source in service["source"]: if re.search(source, host): return service return None interceptor.register(rewrite)