dotfiles/qutebrowser/config/redirects.py
Marty Oehme 20b9d432ac
qutebrowser: Use farside for dynamic redirects
The redirector can now be fed with either a list of targets to pick from
(as before) or a "farside" entry which points to a farside service
redirect or multiple.

The dict entry then looks like:

```python
"quora": {
    "source": ["quora.com"],
    "farside": ["quetre"],
}
```

It has the source service url as usual, but then instead of a "target"
entry contains a "farside" entry.

A redirect dict entry can take both "target" and "farside" entries, but
will then always give precedence to farside choices.

This should go a long way in helping keep OSS frontends up to date. It
now mostly depends on farside entries in turn being updated.
One potential concern is the new centralization in relying on farside as
the redirect authority.
2024-02-05 12:16:09 +01:00

171 lines
4.6 KiB
Python

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"],
"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",
],
},
}
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)