// ==UserScript== // @name Shortside // @version 1.5.1 // @description Redirects the configured websites to third-party privacy-respecting front ends. // @author examosa // @license AGPLv3-or-later // @homepageURL https://gist.github.com/examosa/50eb28bc16a006b62b3f43893ab457e7/ // @updateURL https://gist.github.com/examosa/50eb28bc16a006b62b3f43893ab457e7/raw/shortside.user.js // @downloadURL https://gist.github.com/examosa/50eb28bc16a006b62b3f43893ab457e7/raw/shortside.user.js // @icon https://nobsdelivr.private.coffee/gh/webalys-hq/streamline-vectors/plump/gradient/interface-essential/shuffle.svg // @match https://www.fandom.com/* // @match https://www.geeksforgeeks.org/* // @match https://genius.com/* // @match https://www.instagram.com/* // @match https://www.medium.com/* // @match https://medium.com/* // @match https://stackoverflow.com/* // @match https://www.reddit.com/* // @match https://*.youtube.com/* // @match https://www.quora.com/* // @match https://www.reuters.com/* // @match https://www.tumblr.com/* // @match https://twitter.com/* // @match https://www.urbandictionary.com/* // @match https://x.com/* // @run-at document-start // @allFrames false // @noframes // ==/UserScript== stop(); function getRedirect() { const assignUrl = (url, updates) => Object.assign(url, { pathname: '/', search: '', ...updates, }); const chooseRandom = (target) => { const list = Array.isArray(target) ? target : Object.values(target); return list.at(Math.floor(Math.random() * list.length)); }; const hashPath = (...hostnames) => (url) => { const [hostname, pathname = '/'] = chooseRandom(hostnames).split('/'); assignUrl(url, { hostname, pathname, hash: url.pathname.slice(1), }); }; const isFunction = (input) => typeof input === 'function'; const replacements = { fandom: { breezewiki: [ 'breezewiki.com', 'antifandom.com', 'breezewiki.pussthecat.org', 'bw.projectsegfau.lt', 'breeze.hostux.net', 'bw.artemislena.eu', 'breeze.nohost.network', 'breeze.whateveritworks.org', 'z.opnxng.com', 'breezewiki.hyperreal.coffee', 'breezewiki.catsarch.com', 'breeze.mint.lgbt', 'breezewiki.nadeko.net', 'fandom.reallyaweso.me', 'breezewiki.r4fo.com', 'breezewiki.private.coffee', 'fan.blitzw.in', 'antifandom.com', 'breezewiki.com', 'breezewiki.nadeko.net', 'breezewiki.pussthecat.org', 'bw.projectsegfau.lt', ], }, geeksforgeeks: { ducksforducks: ['ducksforducks.private.coffee'], nerdsfornerds: ['nn.vern.cc'], }, genius: { dumb: [ 'dm.vern.cc', 'dumb.lunar.icu', 'dumb.ducks.party', 'dumb.hyperreal.coffee', 'dumb.bloat.cat', 'dumb.jeikobu.net', 'dumb.canine.tools', 'lyr.dc09.ru', 'db.kuuro.net', 'dumb.ducks.party', 'dumb.lunar.icu', ], intellectual: [ 'in.bloat.cat', 'intellectual.catsarch.com', 'intellectual.insprill.net', ], }, instagram: { kittygram(url) { assignUrl(url, { hostname: 'kittygram.fsky.io', pathname: url.pathname.replace('/reel/', '/p/'), }); }, }, medium: { libmedium: [ 'libmedium.batsense.net', 'md.vern.cc', 'medium.hostux.net', 'libmedium.batsense.net', ], scribe: [ 'scribe.rip', 'scribe.nixnet.services', 'scribe.citizen4.eu', 'scribe.froth.zone', 'scribe.rawbit.ninja', 'sc.vern.cc', 'scribe.r4fo.com', 'scribe.privacyredirect.com', 'scribe.privacyredirect.com', 'scribe.rawbit.ninja', 'scribe.rip', ], small: ['small.private.coffee'], }, quora: { quetre: [ 'quetre.iket.me', 'qr.vern.cc', 'quetre.pussthecat.org', 'ask.habedieeh.re', 'quetre.blackdrgn.nl', 'quetre.lunar.icu', 'quetre.drgns.space', 'quetre.r4fo.com', 'quetre.ducks.party', 'quetre.private.coffee', 'quetre.canine.tools', 'qt.bloat.cat', 'quetre.jeikobu.net', 'q.307200.xyz', 'quora.nerdvpn.de', 'quetre.privacyredirect.com', 'quora.vern.cc', 'quetre.pufe.org', 'questions.whateveritworks.org', 'quetre.odyssey346.dev', 'quetre.pussthecat.org', ], }, reddit: { eddrit: ['eddrit.com'], ledit: hashPath('ledit.lol'), 'photon-reddit': ['photon-reddit.com'], rdx(url) { const path = url.pathname; const user = path.replace(/^\/u(?:ser)?\/([^/]+)/, '$1'); const subreddit = path.replace(/^\/r\/([^/]+)/, '$1'); if (path.includes('/comments/')) { url.searchParams.set('url', url.href); url.pathname = '/comments.html'; } else if (user !== path) { url.searchParams.set('u', user); url.pathname = '/user.html'; } else if (subreddit !== path) { url.searchParams.set('r', subreddit); url.pathname = '/subreddit.html'; } url.hostname = 'rdx.overdevs.com'; }, reddiculous: hashPath( 'ashish-um.github.io/reddiculous', 'mescalito.github.io/Reddiculous', ), reditr: ['reditr.com'], redlib: [ 'redlib.catsarch.com', 'redlib.perennialte.ch', 'redlib.privacyredirect.com', 'redlib.private.coffee', 'reddit.nerdvpn.de', 'reddit.adminforge.de', 'rl.blitzw.in', 'redlib.orangenet.cc', 'redlib.privadency.com', 'l.opnxng.com', 'red.artemislena.eu', 'redlib.nadeko.net', 'rl.bloat.cat', 'safereddit.com', 'redlib.freedit.eu', ], rf: hashPath('rf.alexkoen.com'), }, reuters: { neuters: ['neuters.de', 'nu.vern.cc'], }, stackoverflow: { anonymousoverflow: [ 'code.whatever.social', 'ao.vern.cc', 'overflow.lunar.icu', 'overflow.adminforge.de', 'overflow.hostux.net', 'ao.bloat.cat', 'ao.owo.si', 'overflow.freedit.eu', 'anonoverflow.hyperreal.coffee', 'overflow.r4fo.com', 'overflow.ducks.party', 'anonymousoverflow.privacyredirect.com', 'soflow.nerdvpn.de', 'overflow.einfachzocken.eu', 'overflow.seasi.dev', 'anonymousoverflow.catsarch.com', 'overflow.darkness.services', 'anonflow.aketawi.space', 'overflow.canine.tools', 'ao.bloat.cat', ], }, tumblr: { priviblur: [ 'pb.bloat.cat', 'tb.opnxng.com', 'priviblur.pussthecat.org', 'priviblur.thebunny.zone', 'priviblur.canine.tools', 'pb.cleberg.net', 'tumblr.nerdvpn.de', ], }, twitter: { nitter: [ 'xcancel.com', 'nitter.privacyredirect.com', 'lightbrd.com', 'nitter.space', 'nitter.tiekoetter.com', 'nuku.trabun.org', 'nitter.net', ], }, urbandictionary: { ruraldictionary: ['rd.vern.cc', 'rd.bloat.cat', 'rd.thirtysix.pw'], }, get 'x.com'() { return replacements.twitter; }, youtube: { invidious: [ 'inv.nadeko.net', 'invidious.nerdvpn.de', 'invidious.f5.si', 'yewtu.be', 'invidious.snopyta.org', ], skipvids(url) { url.hostname = 'skipvids.com'; url.pathname = '/'; }, }, }; const redirect = new URL(location); const replacement = Object.entries(replacements).find(([host]) => location.hostname.includes(host), ); if (replacement) { const [, options] = replacement; const option = chooseRandom(options); if (isFunction(option)) { option(redirect); } else if (Array.isArray(option)) { redirect.hostname = chooseRandom(option); } } else { redirect.href = `https://farside.link/_/${location}`; } return redirect; } function main() { const redirect = getRedirect(); location.replace(redirect); } main();