// ==UserScript==
// @name Privacy Redirector
// @name:bg Пренасочване на поверителността
// @name:br Rediretor de privacidade
// @name:cs Přesměrování soukromí
// @name:de Datenschutz Umleiter
// @name:da Omdirigeringsenhed for privatlivets fred
// @name:et Privaatsuse ümbersuunaja
// @name:es Redirección de privacidad
// @name:fi Yksityisyydensuojan uudelleenohjaus
// @name:fr Redirecteur de confidentialité
// @name:el Επανακατευθυντής απορρήτου
// @name:hu Adatvédelmi átirányító
// @name:id Pengarah Privasi
// @name:it Reindirizzatore di privacy
// @name:ja プライバシーリダイレクト
// @name:lt Privatumo nukreipiklis
// @name:lv Konfidencialitātes pāradresētājs
// @name:nl Privacy-omleiding
// @name:pl Przekierownik prywatności
// @name:pt Redirector de Privacidade
// @name:ro Redirector de confidențialitate
// @name:ru Перенаправление конфиденциальности
// @name:sv Omdirigering av sekretess
// @name:sl Preusmerjevalnik zasebnosti
// @name:sk Presmerovanie súkromia
// @name:tr Gizlilik Yönlendiricisi
// @name:uk Редиректор конфіденційності
// @name:zh 隐私重定向器
// @name:zh-CN 隐私重定向器
// @description Redirect social media platforms to their privacy respecting frontends
// @description:bg Пренасочване на платформите за социални медии към заглавните им страници, съобразени с поверителността
// @description:br Redirecionando as plataformas de mídia social para suas primeiras páginas de privacidade
// @description:cs Přesměrování platforem sociálních médií na jejich titulní stránky šetrné k soukromí
// @description:de Leitet von Social-Media-Plattformen auf deren jeweilige datenschutzfreundlicheren Frontends
// @description:da Omdirigering af sociale medieplatforme til deres privatlivsvenlige forsider
// @description:et Sotsiaalmeediaplatvormide ümbersuunamine nende privaatsussõbralikele esilehtedele
// @description:es Redirigir las plataformas de medios sociales a sus portadas respetuosas con la privacidad
// @description:fi Sosiaalisen median alustojen ohjaaminen yksityisyyden suojaa edistäville etusivuille.
// @description:fr Rediriger les plateformes de médias sociaux vers leurs pages d'accueil respectueuses de la vie privée
// @description:el Αναπροσανατολισμός των πλατφορμών κοινωνικής δικτύωσης στις μπροστινές σελίδες τους που είναι φιλικές προς το απόρρητο
// @description:hu A közösségi médiaplatformok átirányítása az adatvédelem-barát kezdőlapokra
// @description:id Mengarahkan platform media sosial ke halaman depan yang ramah privasi
// @description:it Reindirizzare le piattaforme di social media verso le loro pagine frontali che rispettano la privacy
// @description:ja ソーシャルメディアプラットフォームをプライバシーに配慮したフロントページにリダイレクトする
// @description:lt Socialinės žiniasklaidos platformų nukreipimas į privatumą užtikrinančius pirmuosius puslapius
// @description:lv Sociālo plašsaziņas līdzekļu platformu pāradresēšana uz to privātumam draudzīgajām pirmajām lapām.
// @description:nl Sociale-mediaplatforms omleiden naar hun privacyvriendelijke voorpagina's
// @description:pl Przekierowanie platform mediów społecznościowych na ich przyjazne dla prywatności strony tytułowe
// @description:pt Redireccionar as plataformas de redes sociais para as suas primeiras páginas amigas da privacidade
// @description:ro Redirecționarea platformelor de socializare către paginile lor de început care respectă viața privată
// @description:ru Перенаправление платформ социальных сетей на их главные страницы, дружественные к конфиденциальности
// @description:sv Omdirigera sociala medieplattformar till deras integritetsvänliga förstasidor.
// @description:sl preusmeritev platform družabnih medijev na njihove naslovne strani, ki so prijazne do zasebnosti.
// @description:sk Presmerovanie platforiem sociálnych médií na ich úvodné stránky, ktoré chránia súkromie
// @description:tr Sosyal medya platformlarını, gizliliğe saygı duyan önyüzlerine yönlendirir
// @description:uk Перенаправлення соціальних медіа-платформ на їхні головні сторінки, дружні до приватності
// @description:zh 将社交媒体平台重定向到其隐私友好的首页
// @description:zh-CN 将社交媒体平台重定向到其隐私友好的首页
// @namespace https://github.com/dybdeskarphet/privacy-redirector
// @author Ahmet Arda Kavakcı
// @license GPLv3
// @version 1.6.0
// @downloadURL
// https://raw.githubusercontent.com/dybdeskarphet/privacy-redirector/main/privacy-redirector.user.js
// @supportURL https://github.com/dybdeskarphet/privacy-redirector
// @updateURL
// https://raw.githubusercontent.com/dybdeskarphet/privacy-redirector/main/privacy-redirector.user.js
// @run-at document-start
// @match *://*.bandcamp.com/*
// @match *://*.fandom.com/*
// @match *://*.genius.com/*
// @match *://*.google.com/*
// @match *://*.imdb.com/*
// @match *://*.imgur.com/*
// @match *://*.imgur.io/*
// @match *://*.instagram.com/*
// @match *://*.medium.com/*
// @match *://*.pinterest.com/*
// @match *://*.quora.com/*
// @match *://*.reddit.com/*
// @match *://*.reuters.com/*
// @match *://*.soundcloud.com/*
// @match *://*.tiktok.com/*
// @match *://*.twitch.tv/*
// @match *://*.deepl.com/*
// @match *://*.deviantart.com/*
// @match *://twitch.tv/*
// @match *://*.twitter.com/*
// @match *://*.x.com/*
// @match *://*.tumblr.com/*
// @match *://x.com/*
// @match *://*.wikipedia.org/*
// @match *://*.youtube-nocookie.com/*
// @match *://*.youtube.com/*
// @match *://f4.bcbits.com/*
// @match *://genius.com/*
// @match *://i.pinimg.com/*
// @match *://imgur.com/*
// @match *://instagram.com/*
// @match *://medium.com/*
// @match *://news.ycombinator.com/*
// @match *://reddit.com/*
// @match *://stackoverflow.com/*
// @match *://t4.bcbits.com/*
// @match *://translate.google.com/*
// @match *://twitter.com/*
// @match *://www.goodreads.com/*
// @match *://www.pixiv.net/*
// @match *://youtube.com/*
// @exclude *://*.youtube.com/redirect*
// @exclude *://youtube.com/redirect*
// ==/UserScript==
/*
___ _ _ ___ _____ _____
/ _ \| \ | | / _ \| ___| ___|
| | | | \| |_____| | | | |_ | |_
| |_| | |\ |_____| |_| | _| | _|
\___/|_| \_| \___/|_| |_|
CHANGE THE RELEVANT VALUE TO "false" TO
DISABLE THE REDIRECTION/FARSIDE FOR THAT
PARTICULAR PLATFORM */
// REDIRECTON / FARSIDE
let bandcamp = [true, true];
let deepl = [false, true]; // Mozhi Deepl engine doesn't work
let deviantart = [true, false];
let fandom = [true, true];
let genius = [true, true];
let goodreads = [true, false];
let google = [true, true];
let gtranslate = [true, true];
let hackernews = [true, true];
let imdb = [true, true];
let imgur = [true, false];
let instagram = [true, true];
let medium = [true, true];
let pinterest = [true, true];
let pixiv = [true, true];
let quora = [true, false];
let reddit = [true, false];
let reuters = [true, true];
let soundcloud = [true, true];
let stackoverflow = [true, true];
let tiktok = [true, false];
let tumblr = [true, false];
let twitch = [true, true];
let twitter = [true, true];
let wikipedia = [true, false];
let youtube = [true, false];
// PREFERRED FRONTEND
let youtubeFrontend = "piped"; // accepts "invidious", "piped", "tubo"
let youtubeMusicFrontend = "hyperpipe"; // accepts "hyperpipe", "invidious", "piped"
let redditFrontend = "libreddit"; // accepts "libreddit", "teddit"
let googleFrontend = "librey"; // accepts "librey", "searx", "searxng"
let googleTranslateFrontend = "mozhi"; // accepts "lingva" (farside available), "mozhi" (no farside)
let geniusFrontend = "intellectual"; // accepts dumb, intellectual
let mediumFrontend = "scribe"; // accepts libmedium, scribe, mediumrip
let hackernewsFrontend = "better"; // accepts better, worker
// OTHER SETTINGS
let keepHistory = false; // keeps farside.link in the browser history
// // // // // // // // // // // // //
/*
___ _
|_ _|_ __ ___| |_ __ _ _ __ ___ ___ ___
| || '_ \/ __| __/ _` | '_ \ / __/ _ \/ __|
| || | | \__ \ || (_| | | | | (_| __/\__ \
|___|_| |_|___/\__\__,_|_| |_|\___\___||___/
LIST OF INSTANCES TO USE IF FARSIDE IS NOT ENABLED
*/
const Instances = {
anonymousoverflow: [
"code.whatever.social",
"ao.vern.cc",
"overflow.smnz.de",
"overflow.lunar.icu",
"overflow.adminforge.de",
"overflow.projectsegfau.lt",
"ao.bloat.cat",
"anonoverflow.frontendfriendly.xyz",
"ao.owo.si",
"overflow.freedit.eu",
"ao.rootdo.org",
"a.opnxng.com",
"overflow.sudovanilla.com",
"exchange.seitan-ayoub.lol",
"overflow.r4fo.com",
],
hyperpipe: [
"hyperpipe.surge.sh",
"hyperpipe.onrender.com",
"music.adminforge.de",
"music.pfcd.me",
"hyperpipe.projectsegfau.lt",
"hp.ggtyler.dev",
"hyperpipe.lunar.icu",
"music.seitan-ayoub.lol",
],
proxigram: [
"proxigram.protokolla.fi",
"proxigram.kyun.li",
"proxigram.lunar.icu",
"ig.opnxng.com",
],
biblioreads: [
"biblioreads.eu.org",
"biblioreads.vercel.app",
"biblioreads.mooo.com",
"bl.vern.cc",
"biblioreads.lunar.icu",
"read.seitan-ayoub.lol",
],
binternet: [
"binternet.ahwx.org",
"bn.bloat.cat",
"bn.opnxng.com",
"bn.vern.cc",
],
breezewiki: [
"breezewiki.com",
"antifandom.com",
"breezewiki.pussthecat.org",
"bw.hamstro.dev",
"bw.projectsegfau.lt",
"breeze.hostux.net",
"bw.artemislena.eu",
"nerd.whatever.social",
"breezewiki.frontendfriendly.xyz",
"breeze.nohost.network",
"z.opnxng.com",
"breezewiki.catsarch.com",
"breeze.mint.lgbt",
"breezewiki.woodland.cafe",
"breezewiki.lunar.icu",
"fandom.adminforge.de",
],
dumb: [
"dumb.privacydev.net",
"db.vern.cc",
"sing.whatever.social",
"dumb.lunar.icu",
],
intellectual: [
"intellectual.insprill.net",
"in.bloat.cat",
"intellectual.frontendfriendly.xyz",
],
invidious: [
"yewtu.be",
"vid.puffyan.us",
"yt.artemislena.eu",
"invidious.flokinet.to",
"invidious.projectsegfau.lt",
"invidious.privacydev.net",
"iv.ggtyler.dev",
"invidious.lunar.icu",
"inv.tux.pizza",
"invidious.protokolla.fi",
"proxied.invidious.fi",
"onion.tube",
"invidious.no-logs.com",
"invidious.io.lol",
"iv.nboeck.de",
"invidious.private.coffee",
"invidious.asir.dev",
"iv.datura.network",
"invidious.fdn.fr",
"invidious.perennialte.ch",
"yt.cdaut.de",
"invidious.einfachzocken.eu",
"yt.drgnz.club",
],
piped: [
"piped.video",
"cf.piped.video",
"fl.piped.video",
"do.piped.video",
"az.piped.video",
"piped.mha.fi",
"watch.leptons.xyz",
"piped.lunar.icu",
"piped.r4fo.com",
"piped.privacydev.net",
"piped.smnz.de",
"piped.adminforge.de",
"piped.astartes.nl",
"piped.osphost.fi",
"pi.ggtyler.dev",
"piped.seitan-ayoub.lol",
"yt.owo.si",
"piped.minionflo.net",
],
libmedium: [
"libmedium.batsense.net",
"md.vern.cc",
"medium.hostux.net",
"read.sudovanilla.com",
"libmedium.frontendfriendly.xyz",
],
libreddit: [
"redditor.fly.dev",
"libreddit.kavin.rocks",
"libreddit.strongthany.cc",
"libreddit.northboot.xyz",
"libreddit.kylrth.com",
"libreddit.tiekoetter.com",
"l.opnxng.com",
"libreddit.projectsegfau.lt",
"libreddit.privacydev.net",
"libreddit.frontendfriendly.xyz",
"libreddit.freedit.eu",
"libreddit.mha.fi",
"lr.artemislena.eu",
"libreddit.nohost.network",
"lr.aeong.one",
"libreddit.lunar.icu",
"snoo.habedieeh.re",
"libreddit.tux.pizza",
"libreddit.perennialte.ch",
"libreddit.private.coffee",
"lr.seitan-ayoub.lol",
"l.bloat.cat",
],
libremdb: [
"libremdb.iket.me",
"libremdb.pussthecat.org",
"ld.vern.cc",
"binge.whatever.social",
"libremdb.lunar.icu",
"libremdb.jeikobu.net",
"libremdb.nerdyfam.tech",
"libremdb.tux.pizza",
"libremdb.frontendfriendly.xyz",
"d.opnxng.com",
"libremdb.catsarch.com",
],
librey: [
"search.ahwx.org",
"ly.owo.si",
"librey.danyaal.xyz",
"librey.org",
"search.davidovski.xyz",
"search.funami.tech",
"librex.nohost.network",
"search.pabloferreiro.es",
"librey.baczek.me",
"search.seitan-ayoub.lol",
],
lingva: [
"lingva.ml",
"lingva.thedaviddelta.com",
"lingva.frontendfriendly.xyz",
"lingva.retiolus.net",
"translate.plausibility.cloud",
"lingva.lunar.icu",
"lingva.garudalinux.org",
"lingva.seitan-ayoub.lol",
],
mediumrip: ["medium.rip"],
neuters: ["neuters.de", "nu.vern.cc"],
nitter: [
"nitter.net",
"nitter.unixfox.eu",
"nitter.poast.org",
"nitter.privacydev.net",
"nitter.projectsegfau.lt",
"nitter.soopy.moe",
"nitter.rawbit.ninja",
"nitter.freedit.eu",
"nitter.nohost.network",
"nitter.no-logs.com",
"nitter.io.lol",
"nitter.woodland.cafe",
"nitter.perennialte.ch",
"nitter.salastil.com",
"n.opnxng.com",
"nitter.ktachibana.party",
],
pixivfe: [
"pixivfe.drgns.space",
"pixivfe.ducks.party",
"pixiv.perennialte.ch",
],
proxitok: [
"proxitok.pabloferreiro.es",
"proxitok.pussthecat.org",
"tok.habedieeh.re",
"proxitok.privacydev.net",
"tok.artemislena.eu",
"tok.adminforge.de",
"cringe.whatever.social",
"proxitok.lunar.icu",
"proxitok.privacy.com.de",
"proxitok.r4fo.com",
"cringe.seitan-ayoub.lol",
"tt.opnxng.com",
"tiktok.wpme.pl",
],
quetre: [
"quetre.iket.me",
"qr.vern.cc",
"quetre.pussthecat.org",
"quetre.privacydev.net",
"ask.habedieeh.re",
"quetre.blackdrgn.nl",
"quetre.lunar.icu",
"quetre.frontendfriendly.xyz",
"q.opnxng.com",
"quetre.rootdo.org",
"quora.seitan-ayoub.lol",
"ask.sudovanilla.org",
"quetre.smnz.de",
],
rimgo: [
"rimgo.totaldarkness.net",
"imgur.artemislena.eu",
"rimgo.lunar.icu",
"imgur.010032.xyz",
"rimgo.kling.gg",
"rimgo.projectsegfau.lt",
"rimgo.nohost.network",
"rimgo.catsarch.com",
"rimgo.quantenzitrone.eu",
],
scribe: [
"scribe.rip",
"scribe.citizen4.eu",
"scribe.bus-hit.me",
"scribe.projectsegfau.lt",
"scribe.rawbit.ninja",
"m.opnxng.com",
],
teddit: [
"i.opnxng.com",
"teddit.net",
"teddit.rawbit.ninja",
"teddit.pussthecat.org",
"teddit.zaggy.nl",
"t.sneed.network",
"td.vern.cc",
],
tent: ["tent.sny.sh", "tent.bloat.cat", "tn.vern.cc"],
tubo: ["tubo.media", "tubo.reallyaweso.me", "tubo.ducks.party"],
wikiless: [
"wikiless.tiekoetter.com",
"wikiless.funami.tech",
"wl.vern.cc",
"wiki.froth.zone",
"wikiless.northboot.xyz",
"wikiless.rawbit.ninja",
"wiki.adminforge.de",
"wikiless.rootdo.org",
"w.sneed.network",
"wikiless.r4fo.com",
"wiki.seitan-ayoub.lol",
"wikiless.ditatompel.com",
],
safetwitch: [
"safetwitch.drgns.space",
"safetwitch.projectsegfau.lt",
"safetwitch.datura.network",
"ttv.vern.cc",
"safetwitch.frontendfriendly.xyz",
"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",
],
searx: [
"search.bus-hit.me",
"search.projectsegfau.lt",
"northboot.xyz",
"opnxng.com",
],
searxng: [
"search.sapti.me",
"priv.au",
"search.demoniak.ch",
"www.gruble.de",
"searx.divided-by-zero.eu",
"xo.wtf",
"freesearch.club",
"baresearch.org",
"searx.perennialte.ch",
"searx.techsaviours.org",
"search.mdosch.de",
"searx.si",
"searx.namejeff.xyz",
"search.ononoki.org",
"etsi.me",
"searx.work",
"search.smnz.de",
"searx.prvcy.eu",
"searx.headpat.exchange",
],
hackernews: {
better: "better-hackernews.vercel.app",
worker: "news.workers.tools",
},
mozhi: [
"mozhi.aryak.me",
"translate.bus-hit.me",
"nyc1.mz.ggtyler.dev",
"translate.projectsegfau.lt",
"translate.nerdvpn.de",
"mozhi.ducks.party",
"mozhi.frontendfriendly.xyz",
"mozhi.pussthecat.org",
"mozhi.adminforge.de",
"translate.privacyredirect.com",
"mozhi.canine.tools",
"mozhi.gitro.xyz",
],
skunkyart: ["art.bloat.cat"],
priviblur: [
"pb.bloat.cat",
"tb.opnxng.com",
"priviblur.pussthecat.org",
"priviblur.thebunny.zone",
"priviblur.gitro.xyz",
"priviblur.canine.tools",
],
};
let farsideInstance = keepHistory ? "farside.link/_" : "farside.link";
// // // // // // // // // // // // //
const hash = window.location.hash,
scheme = `${window.location.protocol}//`;
let debug_mode = false;
if (debug_mode) {
alert(
"\n== DEBUG MODE IS ON ==" +
"\nIf you're seeing this" +
"\nset the debug_mode value to" +
"\nfalse for Privacy Redirector." +
"\n======================" +
"\n\nHostname: " +
window.location.hostname +
"\nPath: " +
window.location.pathname +
"\nQuery: " +
window.location.search +
"\nHash: " +
hash,
);
}
let selectedInstance = "",
newURL = "";
const getrandom = async (instances) =>
instances[Math.floor(Math.random() * instances.length)];
async function redirectInstagram() {
if (instagram[0]) {
window.stop();
let pathname = window.location.pathname;
let search = window.location.search;
let params = new URLSearchParams(search);
selectedInstance = await getrandom(Instances.proxigram);
switch (true) {
case pathname.startsWith("/accounts/login/"):
case pathname.startsWith("/accounts/signup/"):
pathname = pathname.replace(/^\/accounts\/(login|signup)\/[a-z]*/, "");
params.delete("next");
search = params.size ? `?${params}` : "";
break;
case pathname.startsWith("/reel/"):
case pathname.startsWith("/tv/"):
pathname = pathname.replace(/^\/(reel|tv)\//, "/p/");
break;
case pathname.endsWith("/reels/"):
pathname = pathname.replace("/reels", "");
break;
}
newURL = `${scheme}${selectedInstance}${pathname}${search}${hash}`;
window.location.replace(newURL);
}
}
async function redirectTwitter() {
if (twitter[0]) {
window.stop();
const pathname = window.location.pathname;
let searchpath = `${pathname}${window.location.search}`;
selectedInstance = twitter[1]
? `${farsideInstance}/nitter`
: await getrandom(Instances.nitter);
if (pathname === "/i/flow/login")
searchpath = searchpath.replace(
"/i/flow/login?redirect_after_login=",
"",
);
if (searchpath.includes("%")) searchpath = decodeURIComponent(searchpath);
newURL = `${scheme}${selectedInstance}${searchpath}${hash}`;
window.location.replace(newURL);
}
}
async function redirectReddit() {
if (reddit[0] && !window.location.pathname.startsWith("/domain")) {
window.stop();
let pathname = window.location.pathname;
let search = window.location.search;
selectedInstance = reddit[1]
? `${farsideInstance}/${redditFrontend}`
: await getrandom(Instances[redditFrontend]);
if (pathname === "/media" && search) {
const params = new URLSearchParams(search);
const mediaURL = new URL(params.get("url"));
if (["i.redd.it", "preview.redd.it"].includes(mediaURL.hostname)) {
pathname = `/img${mediaURL.pathname}`;
search = mediaURL.search;
}
}
newURL = `${scheme}${selectedInstance}${pathname}${search}${hash}`;
window.location.replace(newURL);
}
}
async function redirectYoutube(frontend) {
if (youtube[0]) {
window.stop();
let searchpath = `${window.location.pathname}${window.location.search}`;
if (window.location.pathname.startsWith("/embed")) {
selectedInstance = youtube[1]
? `${farsideInstance}/invidious`
: await getrandom(Instances["invidious"]);
newURL = `${scheme}${selectedInstance}${window.location.pathname}${
window.location.search
}${hash}`;
window.location.replace(newURL);
} else {
if (frontend !== "tubo") {
selectedInstance =
youtube[1] && frontend !== "hyperpipe"
? `${farsideInstance}/${frontend}`
: await getrandom(Instances[frontend]);
} else {
selectedInstance = await getrandom(Instances.tubo);
searchpath = `/stream?url=${window.location.href}`;
if (
window.location.pathname.startsWith("/@") ||
window.location.pathname.startsWith("/channel")
)
searchpath = `/channel?url=${window.location.href}`;
}
newURL = `${scheme}${selectedInstance}${searchpath}${hash}`;
window.location.replace(newURL);
}
}
}
async function redirectTiktok() {
if (tiktok[0]) {
window.stop();
let pathname = window.location.pathname;
selectedInstance = tiktok[1]
? `${farsideInstance}/proxitok`
: await getrandom(Instances.proxitok);
await Promise.any(
[
["/@/", "/@placeholder/"],
["/discover/", "/tag/"],
["/foryou", "/trending"],
].map(async ([key, value]) => {
if (pathname.startsWith(key)) pathname = pathname.replace(key, value);
}),
);
newURL = `${scheme}${selectedInstance}${pathname}${window.location.search}${
hash
}`;
window.location.replace(newURL);
}
}
async function redirectImgur() {
if (imgur[0]) {
window.stop();
selectedInstance = imgur[1]
? `${farsideInstance}/rimgo`
: await getrandom(Instances.rimgo);
newURL = `${scheme}${selectedInstance}${window.location.pathname}${
window.location.search
}${hash}`;
window.location.replace(newURL);
}
}
async function redirectMedium(frontend) {
if (medium[0]) {
let pathname = window.location.pathname;
const host_path = `${window.location.hostname}${pathname}`;
if (
(/^.+?\.medium\.com\/.+/.test(host_path) ||
/^\/@?[^\/]+?\//.test(pathname) ||
host_path === "medium.com/") &&
!(
/^\/(tag|m|hc)\//.test(pathname) ||
/\/(about|followers|following)/.test(pathname)
)
) {
window.stop();
selectedInstance =
medium[1] && frontend === "scribe"
? `${farsideInstance}/scribe`
: await getrandom(Instances[frontend]);
const username = window.location.hostname.replace(/\.?medium\.com/, "");
if (username) pathname = `/${username}${pathname}`;
newURL = `${scheme}${selectedInstance}${pathname}${
window.location.search
}${hash}`;
window.location.replace(newURL);
}
}
}
async function redirectHackerNews() {
if (hackernews[0]) {
let pathname = window.location.pathname;
if (
["/newest", "/item", "/user", "/ask", "/show", "/jobs", "/"].includes(
pathname,
)
) {
if (
hackernewsFrontend === "better" &&
window.location.pathname === "/newest"
)
pathname = "/new";
selectedInstance = Instances.hackernews[hackernewsFrontend];
} else if (
["/best", "/news", "/submitted", "/threads", "/classic"].includes(
pathname,
)
) {
selectedInstance = Instances.hackernews.worker;
}
if (selectedInstance) {
window.stop();
newURL = `${scheme}${selectedInstance}${pathname}${window.location.search}`;
window.location.replace(newURL);
}
}
}
async function redirectGTranslate() {
if (gtranslate[0]) {
window.stop();
let pathname = window.location.pathname;
switch (googleTranslateFrontend) {
case "lingva":
selectedInstance = gtranslate[1]
? `${farsideInstance}/lingva`
: await getrandom(Instances.lingva);
if (window.location.search) {
const params = new URLSearchParams(window.location.search);
pathname = `/${params.get("sl")}/${params.get("tl")}/${params.get(
"text",
)}`;
} else if (/^\/\w+?\/\w+?\/.*/.test(pathname)) {
pathname = pathname.replace(/\+/g, " ");
}
newURL = `${scheme}${selectedInstance}${pathname}`;
break;
case "mozhi":
selectedInstance = await getrandom(Instances.mozhi);
if (window.location.search) {
const params = new URLSearchParams(window.location.search);
pathname = `?text=${params.get(
"text",
)}&from=${params.get("sl")}&to=${params.get("tl")}&engine=google`;
newURL = `${scheme}${selectedInstance}${pathname}`;
}
break;
default:
break;
}
window.location.replace(newURL);
}
}
async function redirectDeviantart() {
window.stop();
let pathname = window.location.pathname;
let query = window.location.search;
let parts = pathname.split("/").filter((n) => n);
let pathnameMatch = "";
selectedInstance = await getrandom(Instances.skunkyart);
let patterns = {
post: /\/art\/\S+/,
tag: /\/tag\/\S+/,
search: /(?<=\?q=)[^&]+/,
gallery: /\/\w+\/gallery$/,
gallery_folder: /\/\w+\/gallery\/\d+/,
favorites: /\/(\w+)\/favourites/,
profile: /^\/(\w+)$/,
};
if (deviantart[0]) {
if (patterns.post.test(pathname)) {
pathnameMatch = `/post/${parts[0].toLowerCase()}/${parts[2]}`;
} else if (patterns.tag.test(pathname)) {
pathnameMatch = `/search?q=${parts[1]}&type=tag`;
} else if (pathname.startsWith("/search")) {
query = query.match(patterns.search)[0];
pathnameMatch = `/search?q=${query}&type=all`;
} else if (patterns.gallery.test(pathname)) {
pathnameMatch = `/group_user?type=gallery&q=${parts[0]}`;
} else if (patterns.gallery_folder.test(pathname)) {
pathnameMatch = `/group_user?folder=${parts[2]}&q=${parts[0]}&type=g`;
} else if (patterns.favorites.test(pathname)) {
pathnameMatch = `/group_user?q=${pathname.match(patterns.favorites)[1]}&type=favorites`;
} else if (patterns.profile.test(pathname)) {
pathnameMatch = `/group_user?type=about&q=${pathname.match(patterns.profile)[1]}`;
}
}
newURL = `${scheme}${selectedInstance}${pathnameMatch}`;
window.location.replace(newURL);
}
async function redirectDeepl() {
if (deepl[0]) {
window.stop();
selectedInstance = await getrandom(Instances.mozhi);
if (window.location.hash) {
let hash_parts = window.location.hash.substring(1).split("/");
let pathname = `?text=${hash_parts[2]}&from=${hash_parts[0]}&to=${
hash_parts[1]
}&engine=deepl`;
newURL = `${scheme}${selectedInstance}${pathname}`;
}
window.location.replace(newURL);
}
}
async function redirectTumblr() {
if (tumblr[0]) {
window.stop();
selectedInstance = await getrandom(Instances.priviblur);
newURL = `${scheme}${selectedInstance}${window.location.pathname}${
window.location.search
}${hash}`;
window.location.replace(newURL);
}
}
async function redirectReuters() {
if (reuters[0]) {
window.stop();
selectedInstance = await getrandom(Instances.neuters);
newURL = `${scheme}${selectedInstance}${window.location.pathname}${
window.location.search
}${hash}`;
window.location.replace(newURL);
}
}
async function redirectWikipedia() {
if (wikipedia[0]) {
window.stop();
let langCode = /^([a-z\-]+)\./.exec(window.location.hostname)[1];
selectedInstance = wikipedia[1]
? `${farsideInstance}/wikiless`
: await getrandom(Instances.wikiless);
if (langCode === "www") langCode = "en";
newURL = `${scheme}${selectedInstance}${window.location.pathname}?lang=${
langCode
}${hash}`;
window.location.replace(newURL);
}
}
async function redirectImdb() {
if (imdb[0]) {
window.stop();
selectedInstance = imdb[1]
? `${farsideInstance}/libremdb`
: await getrandom(Instances.libremdb);
newURL = `${scheme}${selectedInstance}${window.location.pathname}${
window.location.search
}${hash}`;
window.location.replace(newURL);
}
}
async function redirectQuora() {
if (quora[0]) {
window.stop();
selectedInstance = quora[1]
? `${farsideInstance}/quetre`
: await getrandom(Instances.quetre);
newURL = `${scheme}${selectedInstance}${window.location.pathname}${
window.location.search
}${hash}`;
window.location.replace(newURL);
}
}
async function redirectFandom() {
if (fandom[0]) {
window.stop();
const fandomName = window.location.hostname.replace(/\..+/, "");
selectedInstance = await getrandom(Instances.breezewiki);
let pathname = window.location.pathname;
if (fandomName !== "www") pathname = `/${fandomName}${pathname}`;
newURL = `${scheme}${selectedInstance}${pathname}${window.location.search}${
hash
}`;
window.location.replace(newURL);
}
}
async function redirectGoogle() {
if (
google[0] &&
window.location.hostname.startsWith("www") &&
window.location.pathname.startsWith("/search")
) {
window.stop();
selectedInstance = google[1]
? `${farsideInstance}/${googleFrontend}`
: (selectedInstance = await getrandom(Instances[googleFrontend]));
let pathname = window.location.pathname;
if (googleFrontend === "librey" && pathname === "/search")
pathname += ".php";
const params = new URLSearchParams(window.location.search);
const query = params.entries().q;
const search = query ? `?q=${query}` : window.location.search;
newURL = `${scheme}${selectedInstance}${pathname}${search}${hash}`;
window.location.replace(newURL);
}
}
async function redirectGoodreads() {
if (goodreads[0]) {
window.stop();
selectedInstance = await getrandom(Instances.biblioreads);
if (window.location.pathname.startsWith("/search")) {
const params = new URLSearchParams(search);
search = `/${params.get("q")}`;
}
newURL = `${scheme}${selectedInstance}${window.location.pathname}${search}${
hash
}`;
window.location.replace(newURL);
}
}
async function redirectStackoverflow() {
if (
stackoverflow[0] &&
(window.location.pathname.startsWith("/questions/") ||
window.location.pathname === "/")
) {
window.stop();
selectedInstance = stackoverflow[1]
? `${farsideInstance}/anonymousoverflow`
: await getrandom(Instances.anonymousoverflow);
newURL = `${scheme}${selectedInstance}${window.location.pathname}${
window.location.search
}${hash}`;
window.location.replace(newURL);
}
}
async function redirectBandcamp() {
if (bandcamp[0]) {
// thanks to libredirect
selectedInstance = await getrandom(Instances.tent);
const params = new URLSearchParams(window.location.search);
const artist = window.location.hostname.replace(/\..+/, "");
const regex = /^\/([^\/]+?)\/(.+)/.exec(window.location.pathname);
const audio = /^\/stream\/([a-f0-9]+?)\/([^\/]+?)\/([0-9]+)/.exec(
window.location.pathname,
);
const image = /^\/img\/(.+)/.exec(window.location.pathname);
let searchpath = "";
switch (true) {
case window.location.pathname === "/search":
searchpath = `/search.php?query=${params.get("q")}`;
break;
case window.location.hostname.search(/(daily)?\.bandcamp\.com/) > 0:
if (window.location.pathname === "/") {
searchpath = `/artist.php?name=${artist}`;
} else if (regex.length > 2) {
searchpath = `/release.php?artist=${artist}&type=${regex[1]}&name=${regex[2]}`;
}
break;
case window.location.hostname === "f4.bcbits.com":
if (image.length > 1) searchpath = `/image.php?file=${image[1]}`;
break;
case window.location.hostname === "t4.bcbits.com":
if (audio.length > 3)
searchpath = `/audio.php?directory=${audio[1]}&format=${
audio[2]
}&file=${audio[3]}&token=${params.get("token")}`;
break;
default:
return;
}
window.stop();
newURL = `${scheme}${selectedInstance}${searchpath}`;
window.location.replace(newURL);
}
}
async function redirectGenius() {
if (genius[0]) {
const pathname = window.location.pathname;
selectedInstance = await getrandom(Instances[geniusFrontend]);
await Promise.any(
[
["lyrics", pathname.endsWith("-lyrics")],
["album", pathname.startsWith("/albums/")],
["artist", pathname.startsWith("/artists/")],
[, ["/", "/search"].includes(pathname)],
].map(async ([key, value]) => {
if (value) {
const searchpath =
geniusFrontend === "intellectual" && key
? `/${key}?path=${pathname.slice(1)}`
: `${pathname}${window.location.search}`;
window.stop();
newURL = `${scheme}${selectedInstance}${searchpath}${hash}`;
window.location.replace(newURL);
}
}),
);
}
}
async function redirectPinterest() {
if (pinterest[0]) {
selectedInstance = await getrandom(Instances.binternet);
let searchpath = "";
if (window.location.hostname === "i.pinimg.com") {
searchpath = `/image_proxy.php?url=${window.location.href}`;
} else if (window.location.pathname.startsWith("/search")) {
searchpath = `${window.location.pathname
.replace("search", "search.php")
.replace("/pins/", "")}${window.location.search}`;
} else if (window.location.pathname !== "/") return;
window.stop();
newURL = `${scheme}${selectedInstance}${searchpath}`;
window.location.replace(newURL);
}
}
async function redirectSoundcloud() {
if (soundcloud[0]) {
window.stop();
selectedInstance = await getrandom(Instances.tubo);
let searchpath = "/kiosk?serviceId=1";
if (window.location.pathname !== "/")
searchpath = `/stream?url=${window.location.href}`;
newURL = `${scheme}${selectedInstance}${searchpath}`;
window.location.replace(newURL);
}
}
async function redirectPixiv() {
if (pixiv[0]) {
window.stop();
selectedInstance = await getrandom(Instances.pixivfe);
const pathname = window.location.pathname.replace(/^\/\w{2}\//, "/");
newURL = `${scheme}${selectedInstance}${pathname}${window.location.search}`;
window.location.replace(newURL);
}
}
async function redirectTwitch() {
if (twitch[0]) {
window.stop();
selectedInstance = await getrandom(Instances.safetwitch);
const pathname =
window.location.pathname == "/search"
? window.location.pathname + "/"
: window.location.pathname;
let searchpath =
window.location.pathname == "/search"
? window.location.search.replace("term", "query")
: window.location.search;
newURL = `${scheme}${selectedInstance}${pathname}${searchpath}`;
window.location.replace(newURL);
}
}
const urlHostname = window.location.hostname;
switch (urlHostname) {
case "www.instagram.com":
redirectInstagram();
break;
case "twitter.com":
case "mobile.twitter.com":
case "x.com":
case "mobile.x.com":
redirectTwitter();
break;
case "www.youtube.com":
case "m.youtube.com":
case "www.youtube-nocookie.com":
redirectYoutube(youtubeFrontend);
break;
case "www.tiktok.com":
redirectTiktok();
break;
case "music.youtube.com":
redirectYoutube(youtubeMusicFrontend);
break;
case "news.ycombinator.com":
redirectHackerNews();
break;
case "translate.google.com":
redirectGTranslate();
break;
case "www.reuters.com":
redirectReuters();
break;
case "www.imdb.com":
case "m.imdb.com":
redirectImdb();
break;
case "www.quora.com":
redirectQuora();
break;
case "www.google.com":
redirectGoogle();
break;
case "www.goodreads.com":
redirectGoodreads();
break;
case "genius.com":
redirectGenius();
break;
case "stackoverflow.com":
redirectStackoverflow();
break;
case "f4.bcbits.com":
case "t4.bcbits.com":
redirectBandcamp();
break;
case "www.deviantart.com":
redirectDeviantart();
break;
case "i.pinimg.com":
redirectPinterest();
break;
case "soundcloud.com":
case "m.soundcloud.com":
redirectSoundcloud();
break;
case "www.pixiv.net":
redirectPixiv();
break;
case "www.deepl.com":
redirectDeepl();
break;
case "twitch.tv":
case "www.twitch.tv":
redirectTwitch();
break;
case urlHostname.includes("reddit.com") ? urlHostname : 0:
redirectReddit();
break;
case urlHostname.includes("medium.com") ? urlHostname : 0:
redirectMedium(mediumFrontend);
break;
case urlHostname.includes("imgur.com") ? urlHostname : 0:
case urlHostname.includes("imgur.io") ? urlHostname : 0:
redirectImgur();
break;
case urlHostname.includes("wikipedia.org") ? urlHostname : 0:
redirectWikipedia();
break;
case urlHostname.includes("fandom.com") ? urlHostname : 0:
redirectFandom();
break;
case urlHostname.includes("bandcamp.com") ? urlHostname : 0:
redirectBandcamp();
break;
case urlHostname.includes("pinterest.com") ? urlHostname : 0:
redirectPinterest();
break;
case urlHostname.includes("tumblr.com") ? urlHostname : 0:
redirectTumblr();
break;
}
// export module for the test in github action
typeof module !== "undefined"
? (module.exports = { Instances: Instances })
: true;