Privacy Redirector

Redirect social media platforms to their privacy respecting frontends

  1. // ==UserScript==
  2. // @name Privacy Redirector
  3. // @name:bg Пренасочване на поверителността
  4. // @name:br Rediretor de privacidade
  5. // @name:cs Přesměrování soukromí
  6. // @name:de Datenschutz Umleiter
  7. // @name:da Omdirigeringsenhed for privatlivets fred
  8. // @name:et Privaatsuse ümbersuunaja
  9. // @name:es Redirección de privacidad
  10. // @name:fi Yksityisyydensuojan uudelleenohjaus
  11. // @name:fr Redirecteur de confidentialité
  12. // @name:el Επανακατευθυντής απορρήτου
  13. // @name:hu Adatvédelmi átirányító
  14. // @name:id Pengarah Privasi
  15. // @name:it Reindirizzatore di privacy
  16. // @name:ja プライバシーリダイレクト
  17. // @name:lt Privatumo nukreipiklis
  18. // @name:lv Konfidencialitātes pāradresētājs
  19. // @name:nl Privacy-omleiding
  20. // @name:pl Przekierownik prywatności
  21. // @name:pt Redirector de Privacidade
  22. // @name:ro Redirector de confidențialitate
  23. // @name:ru Перенаправление конфиденциальности
  24. // @name:sv Omdirigering av sekretess
  25. // @name:sl Preusmerjevalnik zasebnosti
  26. // @name:sk Presmerovanie súkromia
  27. // @name:tr Gizlilik Yönlendiricisi
  28. // @name:uk Редиректор конфіденційності
  29. // @name:zh 隐私重定向器
  30. // @name:zh-CN 隐私重定向器
  31. // @description Redirect social media platforms to their privacy respecting frontends
  32. // @description:bg Пренасочване на платформите за социални медии към заглавните им страници, съобразени с поверителността
  33. // @description:br Redirecionando as plataformas de mídia social para suas primeiras páginas de privacidade
  34. // @description:cs Přesměrování platforem sociálních médií na jejich titulní stránky šetrné k soukromí
  35. // @description:de Leitet von Social-Media-Plattformen auf deren jeweilige datenschutzfreundlicheren Frontends
  36. // @description:da Omdirigering af sociale medieplatforme til deres privatlivsvenlige forsider
  37. // @description:et Sotsiaalmeediaplatvormide ümbersuunamine nende privaatsussõbralikele esilehtedele
  38. // @description:es Redirigir las plataformas de medios sociales a sus portadas respetuosas con la privacidad
  39. // @description:fi Sosiaalisen median alustojen ohjaaminen yksityisyyden suojaa edistäville etusivuille.
  40. // @description:fr Rediriger les plateformes de médias sociaux vers leurs pages d'accueil respectueuses de la vie privée
  41. // @description:el Αναπροσανατολισμός των πλατφορμών κοινωνικής δικτύωσης στις μπροστινές σελίδες τους που είναι φιλικές προς το απόρρητο
  42. // @description:hu A közösségi médiaplatformok átirányítása az adatvédelem-barát kezdőlapokra
  43. // @description:id Mengarahkan platform media sosial ke halaman depan yang ramah privasi
  44. // @description:it Reindirizzare le piattaforme di social media verso le loro pagine frontali che rispettano la privacy
  45. // @description:ja ソーシャルメディアプラットフォームをプライバシーに配慮したフロントページにリダイレクトする
  46. // @description:lt Socialinės žiniasklaidos platformų nukreipimas į privatumą užtikrinančius pirmuosius puslapius
  47. // @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.
  48. // @description:nl Sociale-mediaplatforms omleiden naar hun privacyvriendelijke voorpagina's
  49. // @description:pl Przekierowanie platform mediów społecznościowych na ich przyjazne dla prywatności strony tytułowe
  50. // @description:pt Redireccionar as plataformas de redes sociais para as suas primeiras páginas amigas da privacidade
  51. // @description:ro Redirecționarea platformelor de socializare către paginile lor de început care respectă viața privată
  52. // @description:ru Перенаправление платформ социальных сетей на их главные страницы, дружественные к конфиденциальности
  53. // @description:sv Omdirigera sociala medieplattformar till deras integritetsvänliga förstasidor.
  54. // @description:sl preusmeritev platform družabnih medijev na njihove naslovne strani, ki so prijazne do zasebnosti.
  55. // @description:sk Presmerovanie platforiem sociálnych médií na ich úvodné stránky, ktoré chránia súkromie
  56. // @description:tr Sosyal medya platformlarını, gizliliğe saygı duyan önyüzlerine yönlendirir
  57. // @description:uk Перенаправлення соціальних медіа-платформ на їхні головні сторінки, дружні до приватності
  58. // @description:zh 将社交媒体平台重定向到其隐私友好的首页
  59. // @description:zh-CN 将社交媒体平台重定向到其隐私友好的首页
  60. // @namespace https://github.com/dybdeskarphet/privacy-redirector
  61. // @author Ahmet Arda Kavakcı
  62. // @license GPLv3
  63. // @version 1.6.2
  64. // @downloadURL
  65. // https://raw.githubusercontent.com/dybdeskarphet/privacy-redirector/main/privacy-redirector.user.js
  66. // @supportURL https://github.com/dybdeskarphet/privacy-redirector
  67. // @updateURL
  68. // https://raw.githubusercontent.com/dybdeskarphet/privacy-redirector/main/privacy-redirector.user.js
  69. // @run-at document-start
  70. // @match *://*.bandcamp.com/*
  71. // @match *://*.fandom.com/*
  72. // @match *://*.genius.com/*
  73. // @match *://*.google.com/*
  74. // @match *://*.imdb.com/*
  75. // @match *://*.imgur.com/*
  76. // @match *://*.imgur.io/*
  77. // @match *://*.instagram.com/*
  78. // @match *://*.medium.com/*
  79. // @match *://*.pinterest.com/*
  80. // @match *://*.quora.com/*
  81. // @match *://*.reddit.com/*
  82. // @match *://*.reuters.com/*
  83. // @match *://*.soundcloud.com/*
  84. // @match *://*.tiktok.com/*
  85. // @match *://*.twitch.tv/*
  86. // @match *://*.deepl.com/*
  87. // @match *://*.deviantart.com/*
  88. // @match *://twitch.tv/*
  89. // @match *://*.twitter.com/*
  90. // @match *://*.x.com/*
  91. // @match *://*.tumblr.com/*
  92. // @match *://x.com/*
  93. // @match *://*.wikipedia.org/*
  94. // @match *://*.youtube-nocookie.com/*
  95. // @match *://*.youtube.com/*
  96. // @match *://f4.bcbits.com/*
  97. // @match *://genius.com/*
  98. // @match *://i.pinimg.com/*
  99. // @match *://imgur.com/*
  100. // @match *://instagram.com/*
  101. // @match *://medium.com/*
  102. // @match *://news.ycombinator.com/*
  103. // @match *://reddit.com/*
  104. // @match *://stackoverflow.com/*
  105. // @match *://t4.bcbits.com/*
  106. // @match *://translate.google.com/*
  107. // @match *://twitter.com/*
  108. // @match *://www.goodreads.com/*
  109. // @match *://www.pixiv.net/*
  110. // @match *://youtube.com/*
  111. // @exclude *://*.youtube.com/redirect*
  112. // @exclude *://youtube.com/redirect*
  113. // ==/UserScript==
  114.  
  115. /*
  116. ___ _ _ ___ _____ _____
  117. / _ \| \ | | / _ \| ___| ___|
  118. | | | | \| |_____| | | | |_ | |_
  119. | |_| | |\ |_____| |_| | _| | _|
  120. \___/|_| \_| \___/|_| |_|
  121.  
  122. CHANGE THE RELEVANT VALUE TO "false" TO
  123. DISABLE THE REDIRECTION/FARSIDE FOR THAT
  124. PARTICULAR PLATFORM */
  125.  
  126. // REDIRECTON / FARSIDE
  127.  
  128. let bandcamp = [true, true];
  129. let deepl = [false, true]; // Mozhi Deepl engine doesn't work
  130. let deviantart = [true, false];
  131. let fandom = [true, true];
  132. let genius = [true, true];
  133. let goodreads = [true, false];
  134. let google = [true, true];
  135. let gtranslate = [true, true];
  136. let hackernews = [true, true];
  137. let imdb = [true, true];
  138. let imgur = [true, false];
  139. let instagram = [true, true];
  140. let medium = [true, true];
  141. let pinterest = [true, true];
  142. let pixiv = [true, true];
  143. let quora = [true, false];
  144. let reddit = [true, false];
  145. let reuters = [true, true];
  146. let soundcloud = [true, true];
  147. let stackoverflow = [true, true];
  148. let tiktok = [true, false];
  149. let tumblr = [true, false];
  150. let twitch = [true, true];
  151. let twitter = [true, true];
  152. let wikipedia = [true, false];
  153. let youtube = [true, false];
  154.  
  155. // PREFERRED FRONTEND
  156. let youtubeFrontend = "freetube"; // accepts "invidious", "piped", "tubo", "freetube"
  157. let youtubeMusicFrontend = "hyperpipe"; // accepts "hyperpipe", "invidious", "piped"
  158. let redditFrontend = "libreddit"; // accepts "libreddit", "teddit"
  159. let googleFrontend = "librey"; // accepts "librey", "searx", "searxng"
  160. let googleTranslateFrontend = "mozhi"; // accepts "lingva" (farside available), "mozhi" (no farside)
  161. let geniusFrontend = "intellectual"; // accepts dumb, intellectual
  162. let mediumFrontend = "scribe"; // accepts libmedium, scribe, mediumrip
  163. let hackernewsFrontend = "better"; // accepts better, worker
  164.  
  165. // OTHER SETTINGS
  166. let keepHistory = false; // keeps farside.link in the browser history
  167.  
  168. // // // // // // // // // // // // //
  169.  
  170. /*
  171. ___ _
  172. |_ _|_ __ ___| |_ __ _ _ __ ___ ___ ___
  173. | || '_ \/ __| __/ _` | '_ \ / __/ _ \/ __|
  174. | || | | \__ \ || (_| | | | | (_| __/\__ \
  175. |___|_| |_|___/\__\__,_|_| |_|\___\___||___/
  176.  
  177. LIST OF INSTANCES TO USE IF FARSIDE IS NOT ENABLED
  178. */
  179.  
  180. const Instances = {
  181. anonymousoverflow: [
  182. "code.whatever.social",
  183. "ao.vern.cc",
  184. "overflow.smnz.de",
  185. "overflow.lunar.icu",
  186. "overflow.adminforge.de",
  187. "overflow.projectsegfau.lt",
  188. "ao.bloat.cat",
  189. "overflow.ducks.party",
  190. "ao.owo.si",
  191. "overflow.freedit.eu",
  192. "ao.rootdo.org",
  193. "a.opnxng.com",
  194. "overflow.einfachzocken.eu",
  195. "exchange.seitan-ayoub.lol",
  196. "overflow.r4fo.com",
  197. ],
  198. hyperpipe: [
  199. "hyperpipe.surge.sh",
  200. "hyperpipe.onrender.com",
  201. "music.adminforge.de",
  202. "music.pfcd.me",
  203. "hyperpipe.projectsegfau.lt",
  204. "hp.ggtyler.dev",
  205. "hyperpipe.lunar.icu",
  206. "music.seitan-ayoub.lol",
  207. ],
  208. proxigram: [
  209. "proxigram.protokolla.fi",
  210. "proxigram.kyun.li",
  211. "proxigram.lunar.icu",
  212. "ig.opnxng.com",
  213. ],
  214. biblioreads: [
  215. "biblioreads.eu.org",
  216. "biblioreads.vercel.app",
  217. "biblioreads.mooo.com",
  218. "bl.vern.cc",
  219. "biblioreads.lunar.icu",
  220. "read.seitan-ayoub.lol",
  221. ],
  222. binternet: [
  223. "binternet.ahwx.org",
  224. "bn.bloat.cat",
  225. "bn.opnxng.com",
  226. "bn.vern.cc",
  227. ],
  228. breezewiki: [
  229. "breezewiki.com",
  230. "antifandom.com",
  231. "breezewiki.pussthecat.org",
  232. "bw.hamstro.dev",
  233. "bw.projectsegfau.lt",
  234. "breeze.hostux.net",
  235. "bw.artemislena.eu",
  236. "breezewiki.woodland.cafe",
  237. "breeze.nohost.network",
  238. "z.opnxng.com",
  239. "breezewiki.catsarch.com",
  240. "breeze.mint.lgbt",
  241. "breezewiki.lunar.icu",
  242. "fandom.adminforge.de",
  243. ],
  244. dumb: [
  245. "dumb.privacydev.net",
  246. "db.vern.cc",
  247. "sing.whatever.social",
  248. "dumb.lunar.icu",
  249. ],
  250. intellectual: [
  251. "intellectual.insprill.net",
  252. "in.bloat.cat",
  253. "in2.bloat.cat",
  254. "intellectual.lumaeris.com",
  255. ],
  256. invidious: [
  257. "yewtu.be",
  258. "vid.puffyan.us",
  259. "yt.artemislena.eu",
  260. "invidious.flokinet.to",
  261. "invidious.projectsegfau.lt",
  262. "invidious.privacydev.net",
  263. "iv.ggtyler.dev",
  264. "invidious.lunar.icu",
  265. "inv.tux.pizza",
  266. "invidious.protokolla.fi",
  267. "proxied.invidious.fi",
  268. "onion.tube",
  269. "invidious.no-logs.com",
  270. "invidious.io.lol",
  271. "iv.nboeck.de",
  272. "invidious.private.coffee",
  273. "invidious.asir.dev",
  274. "iv.datura.network",
  275. "invidious.perennialte.ch",
  276. "yt.cdaut.de",
  277. "invidious.einfachzocken.eu",
  278. "yt.drgnz.club",
  279. ],
  280. piped: [
  281. "piped.video",
  282. "cf.piped.video",
  283. "fl.piped.video",
  284. "do.piped.video",
  285. "az.piped.video",
  286. "piped.mha.fi",
  287. "watch.leptons.xyz",
  288. "piped.lunar.icu",
  289. "piped.r4fo.com",
  290. "piped.privacydev.net",
  291. "piped.smnz.de",
  292. "piped.adminforge.de",
  293. "piped.astartes.nl",
  294. "piped.osphost.fi",
  295. "pi.ggtyler.dev",
  296. "piped.seitan-ayoub.lol",
  297. "yt.owo.si",
  298. "piped.minionflo.net",
  299. ],
  300. libmedium: [
  301. "libmedium.batsense.net",
  302. "md.vern.cc",
  303. "medium.hostux.net",
  304. "libmedium.ducks.party",
  305. ],
  306. libreddit: [
  307. "redditor.fly.dev",
  308. "libreddit.kavin.rocks",
  309. "libreddit.northboot.xyz",
  310. "libreddit.kylrth.com",
  311. "libreddit.tiekoetter.com",
  312. "l.opnxng.com",
  313. "libreddit.projectsegfau.lt",
  314. "libreddit.privacydev.net",
  315. "libreddit.freedit.eu",
  316. "libreddit.mha.fi",
  317. "lr.artemislena.eu",
  318. "libreddit.nohost.network",
  319. "libreddit.lunar.icu",
  320. "snoo.habedieeh.re",
  321. "libreddit.tux.pizza",
  322. "libreddit.perennialte.ch",
  323. "libreddit.private.coffee",
  324. "lr.seitan-ayoub.lol",
  325. "l.bloat.cat",
  326. ],
  327. libremdb: [
  328. "libremdb.iket.me",
  329. "libremdb.pussthecat.org",
  330. "ld.vern.cc",
  331. "binge.whatever.social",
  332. "libremdb.lunar.icu",
  333. "libremdb.jeikobu.net",
  334. "libremdb.nerdyfam.tech",
  335. "libremdb.tux.pizza",
  336. "d.opnxng.com",
  337. "libremdb.catsarch.com",
  338. ],
  339. librey: [
  340. "search.ahwx.org",
  341. "ly.owo.si",
  342. "librey.danyaal.xyz",
  343. "librey.org",
  344. "search.davidovski.xyz",
  345. "search.funami.tech",
  346. "librex.nohost.network",
  347. "search.pabloferreiro.es",
  348. "librey.baczek.me",
  349. "search.seitan-ayoub.lol",
  350. ],
  351. lingva: [
  352. "lingva.ml",
  353. "lingva.thedaviddelta.com",
  354. "lingva.retiolus.net",
  355. "translate.plausibility.cloud",
  356. "lingva.lunar.icu",
  357. "lingva.garudalinux.org",
  358. "lingva.seitan-ayoub.lol",
  359. ],
  360. mediumrip: ["medium.rip"],
  361. neuters: ["neuters.de", "nu.vern.cc"],
  362. nitter: [
  363. "nitter.net",
  364. "nitter.unixfox.eu",
  365. "nitter.poast.org",
  366. "nitter.privacydev.net",
  367. "nitter.projectsegfau.lt",
  368. "nitter.soopy.moe",
  369. "nitter.rawbit.ninja",
  370. "nitter.freedit.eu",
  371. "nitter.nohost.network",
  372. "nitter.io.lol",
  373. "nitter.woodland.cafe",
  374. "nitter.perennialte.ch",
  375. "nitter.salastil.com",
  376. "n.opnxng.com",
  377. "nitter.ktachibana.party",
  378. ],
  379. pixivfe: [
  380. "pixivfe.drgns.space",
  381. "pixivfe.ducks.party",
  382. "pixiv.perennialte.ch",
  383. ],
  384. proxitok: [
  385. "proxitok.pabloferreiro.es",
  386. "proxitok.pussthecat.org",
  387. "tok.habedieeh.re",
  388. "proxitok.privacydev.net",
  389. "tok.artemislena.eu",
  390. "tok.adminforge.de",
  391. "cringe.whatever.social",
  392. "proxitok.lunar.icu",
  393. "proxitok.privacy.com.de",
  394. "cringe.seitan-ayoub.lol",
  395. "tt.opnxng.com",
  396. "tiktok.wpme.pl",
  397. ],
  398. quetre: [
  399. "quetre.iket.me",
  400. "qr.vern.cc",
  401. "quetre.pussthecat.org",
  402. "quetre.privacydev.net",
  403. "ask.habedieeh.re",
  404. "quetre.blackdrgn.nl",
  405. "quetre.lunar.icu",
  406. "q.opnxng.com",
  407. "quetre.rootdo.org",
  408. "quora.seitan-ayoub.lol",
  409. "ask.sudovanilla.org",
  410. "quetre.smnz.de",
  411. ],
  412. rimgo: [
  413. "rimgo.totaldarkness.net",
  414. "imgur.artemislena.eu",
  415. "rimgo.lunar.icu",
  416. "imgur.010032.xyz",
  417. "rimgo.kling.gg",
  418. "rimgo.projectsegfau.lt",
  419. "rimgo.nohost.network",
  420. "rimgo.catsarch.com",
  421. "rimgo.quantenzitrone.eu",
  422. ],
  423. scribe: [
  424. "scribe.rip",
  425. "scribe.citizen4.eu",
  426. "scribe.nixnet.services",
  427. "scribe.privacyredirect.com",
  428. "scribe.projectsegfau.lt",
  429. "scribe.rawbit.ninja",
  430. "m.opnxng.com",
  431. ],
  432. teddit: [
  433. "i.opnxng.com",
  434. "teddit.net",
  435. "teddit.rawbit.ninja",
  436. "teddit.pussthecat.org",
  437. "teddit.zaggy.nl",
  438. "t.sneed.network",
  439. "td.vern.cc",
  440. ],
  441. tent: ["tent.sny.sh", "tent.bloat.cat", "tn.vern.cc"],
  442. tubo: ["tubo.media", "tubo.reallyaweso.me", "tubo.ducks.party"],
  443. wikiless: [
  444. "wikiless.tiekoetter.com",
  445. "wikiless.funami.tech",
  446. "wl.vern.cc",
  447. "wiki.froth.zone",
  448. "wikiless.northboot.xyz",
  449. "wikiless.rawbit.ninja",
  450. "wiki.adminforge.de",
  451. "wikiless.rootdo.org",
  452. "w.sneed.network",
  453. "wikiless.r4fo.com",
  454. "wiki.seitan-ayoub.lol",
  455. "wikiless.ditatompel.com",
  456. ],
  457. safetwitch: [
  458. "safetwitch.drgns.space",
  459. "safetwitch.projectsegfau.lt",
  460. "safetwitch.datura.network",
  461. "ttv.vern.cc",
  462. "twitch.seitan-ayoub.lol",
  463. "st.ggtyler.dev",
  464. "safetwitch.lunar.icu",
  465. "safetwitch.r4fo.com",
  466. "safetwitch.ducks.party",
  467. "safetwitch.nogafam.fr",
  468. "safetwitch.privacyredirect.com",
  469. ],
  470. searx: [
  471. "searx.gnu.style",
  472. "searx.nixnet.services",
  473. "search.projectsegfau.lt",
  474. "searx.roflcopter.fr",
  475. "northboot.xyz",
  476. "opnxng.com",
  477. ],
  478. searxng: [
  479. "search.sapti.me",
  480. "priv.au",
  481. "search.demoniak.ch",
  482. "www.gruble.de",
  483. "searx.divided-by-zero.eu",
  484. "xo.wtf",
  485. "freesearch.club",
  486. "baresearch.org",
  487. "searx.perennialte.ch",
  488. "searx.techsaviours.org",
  489. "search.mdosch.de",
  490. "searx.si",
  491. "searx.namejeff.xyz",
  492. "search.ononoki.org",
  493. "etsi.me",
  494. "searx.work",
  495. "search.smnz.de",
  496. "searx.prvcy.eu",
  497. "searx.headpat.exchange",
  498. ],
  499. hackernews: {
  500. better: "better-hackernews.vercel.app",
  501. worker: "news.workers.tools",
  502. },
  503. mozhi: [
  504. "mozhi.aryak.me",
  505. "nyc1.mz.ggtyler.dev",
  506. "translate.projectsegfau.lt",
  507. "translate.nerdvpn.de",
  508. "mozhi.ducks.party",
  509. "mozhi.pussthecat.org",
  510. "mozhi.adminforge.de",
  511. "translate.privacyredirect.com",
  512. "mozhi.canine.tools",
  513. "mozhi.gitro.xyz",
  514. ],
  515. skunkyart: [
  516. "art.bloat.cat",
  517. "skunky.bloat.cat",
  518. "lost-skunk.cc/skunkyart",
  519. "skunkyart.lumaeris.com",
  520. ],
  521. priviblur: [
  522. "pb.bloat.cat",
  523. "tb.opnxng.com",
  524. "priviblur.pussthecat.org",
  525. "priviblur.thebunny.zone",
  526. "priviblur.gitro.xyz",
  527. "priviblur.canine.tools",
  528. ],
  529. };
  530.  
  531. let farsideInstance = keepHistory ? "farside.link/_" : "farside.link";
  532.  
  533. // // // // // // // // // // // // //
  534.  
  535. const hash = window.location.hash,
  536. scheme = `${window.location.protocol}//`;
  537.  
  538. let debug_mode = false;
  539.  
  540. if (debug_mode) {
  541. alert(
  542. "\n== DEBUG MODE IS ON ==" +
  543. "\nIf you're seeing this" +
  544. "\nset the debug_mode value to" +
  545. "\nfalse for Privacy Redirector." +
  546. "\n======================" +
  547. "\n\nHostname: " +
  548. window.location.hostname +
  549. "\nPath: " +
  550. window.location.pathname +
  551. "\nQuery: " +
  552. window.location.search +
  553. "\nHash: " +
  554. hash,
  555. );
  556. }
  557.  
  558. let selectedInstance = "",
  559. newURL = "";
  560.  
  561. const getrandom = async (instances) =>
  562. instances[Math.floor(Math.random() * instances.length)];
  563.  
  564. async function redirectInstagram() {
  565. if (instagram[0]) {
  566. window.stop();
  567. let pathname = window.location.pathname;
  568. let search = window.location.search;
  569. let params = new URLSearchParams(search);
  570.  
  571. selectedInstance = await getrandom(Instances.proxigram);
  572.  
  573. switch (true) {
  574. case pathname.startsWith("/accounts/login/"):
  575. case pathname.startsWith("/accounts/signup/"):
  576. pathname = pathname.replace(/^\/accounts\/(login|signup)\/[a-z]*/, "");
  577. params.delete("next");
  578. search = params.size ? `?${params}` : "";
  579. break;
  580. case pathname.startsWith("/reel/"):
  581. case pathname.startsWith("/tv/"):
  582. pathname = pathname.replace(/^\/(reel|tv)\//, "/p/");
  583. break;
  584. case pathname.endsWith("/reels/"):
  585. pathname = pathname.replace("/reels", "");
  586. break;
  587. }
  588. newURL = `${scheme}${selectedInstance}${pathname}${search}${hash}`;
  589. window.location.replace(newURL);
  590. }
  591. }
  592.  
  593. async function redirectTwitter() {
  594. if (twitter[0]) {
  595. window.stop();
  596.  
  597. const pathname = window.location.pathname;
  598. let searchpath = `${pathname}${window.location.search}`;
  599.  
  600. selectedInstance = twitter[1]
  601. ? `${farsideInstance}/nitter`
  602. : await getrandom(Instances.nitter);
  603.  
  604. if (pathname === "/i/flow/login")
  605. searchpath = searchpath.replace(
  606. "/i/flow/login?redirect_after_login=",
  607. "",
  608. );
  609.  
  610. if (searchpath.includes("%")) searchpath = decodeURIComponent(searchpath);
  611.  
  612. newURL = `${scheme}${selectedInstance}${searchpath}${hash}`;
  613. window.location.replace(newURL);
  614. }
  615. }
  616.  
  617. async function redirectReddit() {
  618. if (reddit[0] && !window.location.pathname.startsWith("/domain")) {
  619. window.stop();
  620. let pathname = window.location.pathname;
  621. let search = window.location.search;
  622.  
  623. selectedInstance = reddit[1]
  624. ? `${farsideInstance}/${redditFrontend}`
  625. : await getrandom(Instances[redditFrontend]);
  626.  
  627. if (pathname === "/media" && search) {
  628. const params = new URLSearchParams(search);
  629. const mediaURL = new URL(params.get("url"));
  630. if (["i.redd.it", "preview.redd.it"].includes(mediaURL.hostname)) {
  631. pathname = `/img${mediaURL.pathname}`;
  632. search = mediaURL.search;
  633. }
  634. }
  635. newURL = `${scheme}${selectedInstance}${pathname}${search}${hash}`;
  636.  
  637. window.location.replace(newURL);
  638. }
  639. }
  640.  
  641. async function redirectYoutube(frontend) {
  642. if (youtube[0]) {
  643. window.stop();
  644. let searchpath = `${window.location.pathname}${window.location.search}`;
  645. if (window.location.pathname.startsWith("/embed")) {
  646. selectedInstance = youtube[1]
  647. ? `${farsideInstance}/invidious`
  648. : await getrandom(Instances["invidious"]);
  649. newURL = `${scheme}${selectedInstance}${window.location.pathname}${
  650. window.location.search
  651. }${hash}`;
  652. window.location.replace(newURL);
  653. } else {
  654. if (frontend === "tubo") {
  655. selectedInstance = await getrandom(Instances.tubo);
  656.  
  657. searchpath = `/stream?url=${window.location.href}`;
  658. if (
  659. window.location.pathname.startsWith("/@") ||
  660. window.location.pathname.startsWith("/channel")
  661. )
  662. searchpath = `/channel?url=${window.location.href}`;
  663. } else if (frontend === "freetube") {
  664. let youtube_link = window.location.href;
  665. window.location.replace(`freetube://${youtube_link}`);
  666. return;
  667. } else {
  668. selectedInstance =
  669. youtube[1] && frontend !== "hyperpipe"
  670. ? `${farsideInstance}/${frontend}`
  671. : await getrandom(Instances[frontend]);
  672. }
  673.  
  674. newURL = `${scheme}${selectedInstance}${searchpath}${hash}`;
  675. window.location.replace(newURL);
  676. }
  677. }
  678. }
  679.  
  680. async function redirectTiktok() {
  681. if (tiktok[0]) {
  682. window.stop();
  683. let pathname = window.location.pathname;
  684. selectedInstance = tiktok[1]
  685. ? `${farsideInstance}/proxitok`
  686. : await getrandom(Instances.proxitok);
  687.  
  688. await Promise.any(
  689. [
  690. ["/@/", "/@placeholder/"],
  691. ["/discover/", "/tag/"],
  692. ["/foryou", "/trending"],
  693. ].map(async ([key, value]) => {
  694. if (pathname.startsWith(key)) pathname = pathname.replace(key, value);
  695. }),
  696. );
  697.  
  698. newURL = `${scheme}${selectedInstance}${pathname}${window.location.search}${
  699. hash
  700. }`;
  701. window.location.replace(newURL);
  702. }
  703. }
  704.  
  705. async function redirectImgur() {
  706. if (imgur[0]) {
  707. window.stop();
  708.  
  709. selectedInstance = imgur[1]
  710. ? `${farsideInstance}/rimgo`
  711. : await getrandom(Instances.rimgo);
  712.  
  713. newURL = `${scheme}${selectedInstance}${window.location.pathname}${
  714. window.location.search
  715. }${hash}`;
  716.  
  717. window.location.replace(newURL);
  718. }
  719. }
  720.  
  721. async function redirectMedium(frontend) {
  722. if (medium[0]) {
  723. let pathname = window.location.pathname;
  724. const host_path = `${window.location.hostname}${pathname}`;
  725.  
  726. if (
  727. (/^.+?\.medium\.com\/.+/.test(host_path) ||
  728. /^\/@?[^\/]+?\//.test(pathname) ||
  729. host_path === "medium.com/") &&
  730. !(
  731. /^\/(tag|m|hc)\//.test(pathname) ||
  732. /\/(about|followers|following)/.test(pathname)
  733. )
  734. ) {
  735. window.stop();
  736. selectedInstance =
  737. medium[1] && frontend === "scribe"
  738. ? `${farsideInstance}/scribe`
  739. : await getrandom(Instances[frontend]);
  740. const username = window.location.hostname.replace(/\.?medium\.com/, "");
  741. if (username) pathname = `/${username}${pathname}`;
  742. newURL = `${scheme}${selectedInstance}${pathname}${
  743. window.location.search
  744. }${hash}`;
  745. window.location.replace(newURL);
  746. }
  747. }
  748. }
  749.  
  750. async function redirectHackerNews() {
  751. if (hackernews[0]) {
  752. let pathname = window.location.pathname;
  753. if (
  754. ["/newest", "/item", "/user", "/ask", "/show", "/jobs", "/"].includes(
  755. pathname,
  756. )
  757. ) {
  758. if (
  759. hackernewsFrontend === "better" &&
  760. window.location.pathname === "/newest"
  761. )
  762. pathname = "/new";
  763. selectedInstance = Instances.hackernews[hackernewsFrontend];
  764. } else if (
  765. ["/best", "/news", "/submitted", "/threads", "/classic"].includes(
  766. pathname,
  767. )
  768. ) {
  769. selectedInstance = Instances.hackernews.worker;
  770. }
  771. if (selectedInstance) {
  772. window.stop();
  773. newURL = `${scheme}${selectedInstance}${pathname}${window.location.search}`;
  774. window.location.replace(newURL);
  775. }
  776. }
  777. }
  778.  
  779. async function redirectGTranslate() {
  780. if (gtranslate[0]) {
  781. window.stop();
  782. let pathname = window.location.pathname;
  783.  
  784. switch (googleTranslateFrontend) {
  785. case "lingva":
  786. selectedInstance = gtranslate[1]
  787. ? `${farsideInstance}/lingva`
  788. : await getrandom(Instances.lingva);
  789.  
  790. if (window.location.search) {
  791. const params = new URLSearchParams(window.location.search);
  792. pathname = `/${params.get("sl")}/${params.get("tl")}/${params.get(
  793. "text",
  794. )}`;
  795. } else if (/^\/\w+?\/\w+?\/.*/.test(pathname)) {
  796. pathname = pathname.replace(/\+/g, " ");
  797. }
  798. newURL = `${scheme}${selectedInstance}${pathname}`;
  799. break;
  800.  
  801. case "mozhi":
  802. selectedInstance = await getrandom(Instances.mozhi);
  803.  
  804. if (window.location.search) {
  805. const params = new URLSearchParams(window.location.search);
  806. pathname = `?text=${params.get(
  807. "text",
  808. )}&from=${params.get("sl")}&to=${params.get("tl")}&engine=google`;
  809. newURL = `${scheme}${selectedInstance}${pathname}`;
  810. } else {
  811. newURL = `${scheme}${selectedInstance}`;
  812. }
  813. break;
  814.  
  815. default:
  816. break;
  817. }
  818.  
  819. window.location.replace(newURL);
  820. }
  821. }
  822.  
  823. async function redirectDeviantart() {
  824. window.stop();
  825. let pathname = window.location.pathname;
  826. let query = window.location.search;
  827. let parts = pathname.split("/").filter((n) => n);
  828. let pathnameMatch = "";
  829. selectedInstance = await getrandom(Instances.skunkyart);
  830.  
  831. let patterns = {
  832. post: /\/art\/\S+/,
  833. tag: /\/tag\/\S+/,
  834. search: /(?<=\?q=)[^&]+/,
  835. gallery: /\/\w+\/gallery$/,
  836. gallery_folder: /\/\w+\/gallery\/\d+/,
  837. favorites: /\/(\w+)\/favourites/,
  838. profile: /^\/(\w+)$/,
  839. };
  840.  
  841. if (deviantart[0]) {
  842. if (patterns.post.test(pathname)) {
  843. pathnameMatch = `/post/${parts[0].toLowerCase()}/${parts[2]}`;
  844. } else if (patterns.tag.test(pathname)) {
  845. pathnameMatch = `/search?q=${parts[1]}&type=tag`;
  846. } else if (pathname.startsWith("/search")) {
  847. query = query.match(patterns.search)[0];
  848. pathnameMatch = `/search?q=${query}&type=all`;
  849. } else if (patterns.gallery.test(pathname)) {
  850. pathnameMatch = `/group_user?type=gallery&q=${parts[0]}`;
  851. } else if (patterns.gallery_folder.test(pathname)) {
  852. pathnameMatch = `/group_user?folder=${parts[2]}&q=${parts[0]}&type=g`;
  853. } else if (patterns.favorites.test(pathname)) {
  854. pathnameMatch = `/group_user?q=${pathname.match(patterns.favorites)[1]}&type=favorites`;
  855. } else if (patterns.profile.test(pathname)) {
  856. pathnameMatch = `/group_user?type=about&q=${pathname.match(patterns.profile)[1]}`;
  857. }
  858. }
  859.  
  860. newURL = `${scheme}${selectedInstance}${pathnameMatch}`;
  861. window.location.replace(newURL);
  862. }
  863.  
  864. async function redirectDeepl() {
  865. if (deepl[0]) {
  866. window.stop();
  867. selectedInstance = await getrandom(Instances.mozhi);
  868. if (window.location.hash) {
  869. let hash_parts = window.location.hash.substring(1).split("/");
  870. let pathname = `?text=${hash_parts[2]}&from=${hash_parts[0]}&to=${
  871. hash_parts[1]
  872. }&engine=deepl`;
  873. newURL = `${scheme}${selectedInstance}${pathname}`;
  874. }
  875.  
  876. window.location.replace(newURL);
  877. }
  878. }
  879.  
  880. async function redirectTumblr() {
  881. if (tumblr[0]) {
  882. window.stop();
  883. selectedInstance = await getrandom(Instances.priviblur);
  884. newURL = `${scheme}${selectedInstance}${window.location.pathname}${
  885. window.location.search
  886. }${hash}`;
  887. window.location.replace(newURL);
  888. }
  889. }
  890.  
  891. async function redirectReuters() {
  892. if (reuters[0]) {
  893. window.stop();
  894. selectedInstance = await getrandom(Instances.neuters);
  895. newURL = `${scheme}${selectedInstance}${window.location.pathname}${
  896. window.location.search
  897. }${hash}`;
  898. window.location.replace(newURL);
  899. }
  900. }
  901.  
  902. async function redirectWikipedia() {
  903. if (wikipedia[0]) {
  904. window.stop();
  905. let langCode = /^([a-z\-]+)\./.exec(window.location.hostname)[1];
  906.  
  907. selectedInstance = wikipedia[1]
  908. ? `${farsideInstance}/wikiless`
  909. : await getrandom(Instances.wikiless);
  910.  
  911. if (langCode === "www") langCode = "en";
  912. newURL = `${scheme}${selectedInstance}${window.location.pathname}?lang=${
  913. langCode
  914. }${hash}`;
  915. window.location.replace(newURL);
  916. }
  917. }
  918.  
  919. async function redirectImdb() {
  920. if (imdb[0]) {
  921. window.stop();
  922.  
  923. selectedInstance = imdb[1]
  924. ? `${farsideInstance}/libremdb`
  925. : await getrandom(Instances.libremdb);
  926.  
  927. newURL = `${scheme}${selectedInstance}${window.location.pathname}${
  928. window.location.search
  929. }${hash}`;
  930.  
  931. window.location.replace(newURL);
  932. }
  933. }
  934.  
  935. async function redirectQuora() {
  936. if (quora[0]) {
  937. window.stop();
  938.  
  939. selectedInstance = quora[1]
  940. ? `${farsideInstance}/quetre`
  941. : await getrandom(Instances.quetre);
  942.  
  943. newURL = `${scheme}${selectedInstance}${window.location.pathname}${
  944. window.location.search
  945. }${hash}`;
  946.  
  947. window.location.replace(newURL);
  948. }
  949. }
  950.  
  951. async function redirectFandom() {
  952. if (fandom[0]) {
  953. window.stop();
  954. const fandomName = window.location.hostname.replace(/\..+/, "");
  955. selectedInstance = await getrandom(Instances.breezewiki);
  956.  
  957. let pathname = window.location.pathname;
  958. if (fandomName !== "www") pathname = `/${fandomName}${pathname}`;
  959. newURL = `${scheme}${selectedInstance}${pathname}${window.location.search}${
  960. hash
  961. }`;
  962.  
  963. window.location.replace(newURL);
  964. }
  965. }
  966.  
  967. async function redirectGoogle() {
  968. if (
  969. google[0] &&
  970. window.location.hostname.startsWith("www") &&
  971. window.location.pathname.startsWith("/search")
  972. ) {
  973. window.stop();
  974.  
  975. selectedInstance = google[1]
  976. ? `${farsideInstance}/${googleFrontend}`
  977. : (selectedInstance = await getrandom(Instances[googleFrontend]));
  978.  
  979. let pathname = window.location.pathname;
  980. if (googleFrontend === "librey" && pathname === "/search")
  981. pathname += ".php";
  982. const params = new URLSearchParams(window.location.search);
  983. const query = params.entries().q;
  984. const search = query ? `?q=${query}` : window.location.search;
  985. newURL = `${scheme}${selectedInstance}${pathname}${search}${hash}`;
  986. window.location.replace(newURL);
  987. }
  988. }
  989.  
  990. async function redirectGoodreads() {
  991. if (goodreads[0]) {
  992. window.stop();
  993.  
  994. selectedInstance = await getrandom(Instances.biblioreads);
  995.  
  996. if (window.location.pathname.startsWith("/search")) {
  997. const params = new URLSearchParams(search);
  998. search = `/${params.get("q")}`;
  999. }
  1000. newURL = `${scheme}${selectedInstance}${window.location.pathname}${search}${
  1001. hash
  1002. }`;
  1003. window.location.replace(newURL);
  1004. }
  1005. }
  1006.  
  1007. async function redirectStackoverflow() {
  1008. if (
  1009. stackoverflow[0] &&
  1010. (window.location.pathname.startsWith("/questions/") ||
  1011. window.location.pathname === "/")
  1012. ) {
  1013. window.stop();
  1014. selectedInstance = stackoverflow[1]
  1015. ? `${farsideInstance}/anonymousoverflow`
  1016. : await getrandom(Instances.anonymousoverflow);
  1017.  
  1018. newURL = `${scheme}${selectedInstance}${window.location.pathname}${
  1019. window.location.search
  1020. }${hash}`;
  1021. window.location.replace(newURL);
  1022. }
  1023. }
  1024.  
  1025. async function redirectBandcamp() {
  1026. if (bandcamp[0]) {
  1027. // thanks to libredirect
  1028.  
  1029. selectedInstance = await getrandom(Instances.tent);
  1030. const params = new URLSearchParams(window.location.search);
  1031. const artist = window.location.hostname.replace(/\..+/, "");
  1032. const regex = /^\/([^\/]+?)\/(.+)/.exec(window.location.pathname);
  1033. const audio = /^\/stream\/([a-f0-9]+?)\/([^\/]+?)\/([0-9]+)/.exec(
  1034. window.location.pathname,
  1035. );
  1036. const image = /^\/img\/(.+)/.exec(window.location.pathname);
  1037. let searchpath = "";
  1038.  
  1039. switch (true) {
  1040. case window.location.pathname === "/search":
  1041. searchpath = `/search.php?query=${params.get("q")}`;
  1042. break;
  1043. case window.location.hostname.search(/(daily)?\.bandcamp\.com/) > 0:
  1044. if (window.location.pathname === "/") {
  1045. searchpath = `/artist.php?name=${artist}`;
  1046. } else if (regex.length > 2) {
  1047. searchpath = `/release.php?artist=${artist}&type=${regex[1]}&name=${regex[2]}`;
  1048. }
  1049. break;
  1050. case window.location.hostname === "f4.bcbits.com":
  1051. if (image.length > 1) searchpath = `/image.php?file=${image[1]}`;
  1052. break;
  1053. case window.location.hostname === "t4.bcbits.com":
  1054. if (audio.length > 3)
  1055. searchpath = `/audio.php?directory=${audio[1]}&format=${
  1056. audio[2]
  1057. }&file=${audio[3]}&token=${params.get("token")}`;
  1058. break;
  1059. default:
  1060. return;
  1061. }
  1062. window.stop();
  1063. newURL = `${scheme}${selectedInstance}${searchpath}`;
  1064. window.location.replace(newURL);
  1065. }
  1066. }
  1067.  
  1068. async function redirectGenius() {
  1069. if (genius[0]) {
  1070. const pathname = window.location.pathname;
  1071. selectedInstance = await getrandom(Instances[geniusFrontend]);
  1072.  
  1073. await Promise.any(
  1074. [
  1075. ["lyrics", pathname.endsWith("-lyrics")],
  1076. ["album", pathname.startsWith("/albums/")],
  1077. ["artist", pathname.startsWith("/artists/")],
  1078. [, ["/", "/search"].includes(pathname)],
  1079. ].map(async ([key, value]) => {
  1080. if (value) {
  1081. const searchpath =
  1082. geniusFrontend === "intellectual" && key
  1083. ? `/${key}?path=${pathname.slice(1)}`
  1084. : `${pathname}${window.location.search}`;
  1085. window.stop();
  1086. newURL = `${scheme}${selectedInstance}${searchpath}${hash}`;
  1087. window.location.replace(newURL);
  1088. }
  1089. }),
  1090. );
  1091. }
  1092. }
  1093.  
  1094. async function redirectPinterest() {
  1095. if (pinterest[0]) {
  1096. selectedInstance = await getrandom(Instances.binternet);
  1097.  
  1098. let searchpath = "";
  1099. if (window.location.hostname === "i.pinimg.com") {
  1100. searchpath = `/image_proxy.php?url=${window.location.href}`;
  1101. } else if (window.location.pathname.startsWith("/search")) {
  1102. searchpath = `${window.location.pathname
  1103. .replace("search", "search.php")
  1104. .replace("/pins/", "")}${window.location.search}`;
  1105. } else if (window.location.pathname !== "/") return;
  1106.  
  1107. window.stop();
  1108. newURL = `${scheme}${selectedInstance}${searchpath}`;
  1109. window.location.replace(newURL);
  1110. }
  1111. }
  1112.  
  1113. async function redirectSoundcloud() {
  1114. if (soundcloud[0]) {
  1115. window.stop();
  1116. selectedInstance = await getrandom(Instances.tubo);
  1117.  
  1118. let searchpath = "/kiosk?serviceId=1";
  1119. if (window.location.pathname !== "/")
  1120. searchpath = `/stream?url=${window.location.href}`;
  1121. newURL = `${scheme}${selectedInstance}${searchpath}`;
  1122. window.location.replace(newURL);
  1123. }
  1124. }
  1125.  
  1126. async function redirectPixiv() {
  1127. if (pixiv[0]) {
  1128. window.stop();
  1129. selectedInstance = await getrandom(Instances.pixivfe);
  1130.  
  1131. const pathname = window.location.pathname.replace(/^\/\w{2}\//, "/");
  1132. newURL = `${scheme}${selectedInstance}${pathname}${window.location.search}`;
  1133. window.location.replace(newURL);
  1134. }
  1135. }
  1136.  
  1137. async function redirectTwitch() {
  1138. if (twitch[0]) {
  1139. window.stop();
  1140. selectedInstance = await getrandom(Instances.safetwitch);
  1141.  
  1142. const pathname =
  1143. window.location.pathname == "/search"
  1144. ? window.location.pathname + "/"
  1145. : window.location.pathname;
  1146.  
  1147. let searchpath =
  1148. window.location.pathname == "/search"
  1149. ? window.location.search.replace("term", "query")
  1150. : window.location.search;
  1151.  
  1152. newURL = `${scheme}${selectedInstance}${pathname}${searchpath}`;
  1153. window.location.replace(newURL);
  1154. }
  1155. }
  1156.  
  1157. const urlHostname = window.location.hostname;
  1158.  
  1159. switch (urlHostname) {
  1160. case "www.instagram.com":
  1161. redirectInstagram();
  1162. break;
  1163.  
  1164. case "twitter.com":
  1165. case "mobile.twitter.com":
  1166. case "x.com":
  1167. case "mobile.x.com":
  1168. redirectTwitter();
  1169. break;
  1170.  
  1171. case "www.youtube.com":
  1172. case "m.youtube.com":
  1173. case "www.youtube-nocookie.com":
  1174. redirectYoutube(youtubeFrontend);
  1175. break;
  1176.  
  1177. case "www.tiktok.com":
  1178. redirectTiktok();
  1179. break;
  1180.  
  1181. case "music.youtube.com":
  1182. redirectYoutube(youtubeMusicFrontend);
  1183. break;
  1184.  
  1185. case "news.ycombinator.com":
  1186. redirectHackerNews();
  1187. break;
  1188.  
  1189. case "translate.google.com":
  1190. redirectGTranslate();
  1191. break;
  1192.  
  1193. case "www.reuters.com":
  1194. redirectReuters();
  1195. break;
  1196.  
  1197. case "www.imdb.com":
  1198. case "m.imdb.com":
  1199. redirectImdb();
  1200. break;
  1201.  
  1202. case "www.quora.com":
  1203. redirectQuora();
  1204. break;
  1205.  
  1206. case "www.google.com":
  1207. redirectGoogle();
  1208. break;
  1209.  
  1210. case "www.goodreads.com":
  1211. redirectGoodreads();
  1212. break;
  1213.  
  1214. case "genius.com":
  1215. redirectGenius();
  1216. break;
  1217.  
  1218. case "stackoverflow.com":
  1219. redirectStackoverflow();
  1220. break;
  1221.  
  1222. case "f4.bcbits.com":
  1223. case "t4.bcbits.com":
  1224. redirectBandcamp();
  1225. break;
  1226.  
  1227. case "www.deviantart.com":
  1228. redirectDeviantart();
  1229. break;
  1230.  
  1231. case "i.pinimg.com":
  1232. redirectPinterest();
  1233. break;
  1234.  
  1235. case "soundcloud.com":
  1236. case "m.soundcloud.com":
  1237. redirectSoundcloud();
  1238. break;
  1239.  
  1240. case "www.pixiv.net":
  1241. redirectPixiv();
  1242. break;
  1243.  
  1244. case "www.deepl.com":
  1245. redirectDeepl();
  1246. break;
  1247.  
  1248. case "twitch.tv":
  1249. case "www.twitch.tv":
  1250. redirectTwitch();
  1251. break;
  1252.  
  1253. case urlHostname.includes("reddit.com") ? urlHostname : 0:
  1254. redirectReddit();
  1255. break;
  1256.  
  1257. case urlHostname.includes("medium.com") ? urlHostname : 0:
  1258. redirectMedium(mediumFrontend);
  1259. break;
  1260.  
  1261. case urlHostname.includes("imgur.com") ? urlHostname : 0:
  1262. case urlHostname.includes("imgur.io") ? urlHostname : 0:
  1263. redirectImgur();
  1264. break;
  1265.  
  1266. case urlHostname.includes("wikipedia.org") ? urlHostname : 0:
  1267. redirectWikipedia();
  1268. break;
  1269.  
  1270. case urlHostname.includes("fandom.com") ? urlHostname : 0:
  1271. redirectFandom();
  1272. break;
  1273.  
  1274. case urlHostname.includes("bandcamp.com") ? urlHostname : 0:
  1275. redirectBandcamp();
  1276. break;
  1277.  
  1278. case urlHostname.includes("pinterest.com") ? urlHostname : 0:
  1279. redirectPinterest();
  1280. break;
  1281.  
  1282. case urlHostname.includes("tumblr.com") ? urlHostname : 0:
  1283. redirectTumblr();
  1284. break;
  1285. }
  1286.  
  1287. // export module for the test in github action
  1288. typeof module !== "undefined"
  1289. ? (module.exports = { Instances: Instances })
  1290. : true;