about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorSimonBrazell <simon@brazell.com.au>2020-08-27 15:22:46 +1000
committerSimonBrazell <simon@brazell.com.au>2020-08-27 15:22:46 +1000
commit564e25db3d5eb112458fcadc45200ea754fd01af (patch)
treea4afc6dfab2385e31a3c8613b130f198d1f4f876
parentCloses #88 - awesome-humane-tech badge on README (diff)
downloadlibredirect-564e25db3d5eb112458fcadc45200ea754fd01af.zip
Randomise Invidious instance if empty or https://invidio.us
-rw-r--r--background.js415
-rw-r--r--manifest.json10
-rw-r--r--pages/options/options.html2
-rw-r--r--pages/options/options.js4
4 files changed, 246 insertions, 185 deletions
diff --git a/background.js b/background.js
index 95561752..092f8d9d 100644
--- a/background.js
+++ b/background.js
@@ -1,26 +1,36 @@
-'use strict';
+"use strict";
 
-const invidiousDefault = 'https://invidio.us';
+const invidiousDefault = "https://invidious.snopyta.org";
 const youtubeDomains = [
-  'm.youtube.com',
-  'youtube.com',
-  'img.youtube.com',
-  'www.youtube.com',
-  'youtube-nocookie.com',
-  'www.youtube-nocookie.com',
-  'youtu.be',
-  's.ytimg.com',
-  'music.youtube.com'
+  "m.youtube.com",
+  "youtube.com",
+  "img.youtube.com",
+  "www.youtube.com",
+  "youtube-nocookie.com",
+  "www.youtube-nocookie.com",
+  "youtu.be",
+  "s.ytimg.com",
+  "music.youtube.com",
 ];
-const nitterDefault = 'https://nitter.net';
+const invidiousInstances = [
+  "https://invidious.snopyta.org",
+  "https://yewtu.be",
+  "https://invidious.13ad.de",
+  "https://invidious.xyz",
+  "https://invidious.site",
+  "https://invidiou.site",
+  "https://invidious.fdn.fr",
+  "https://invidious.toot.koeln",
+];
+const nitterDefault = "https://nitter.net";
 const twitterDomains = [
-  'twitter.com',
-  'www.twitter.com',
-  'mobile.twitter.com',
-  'pbs.twimg.com',
-  'video.twimg.com',
+  "twitter.com",
+  "www.twitter.com",
+  "mobile.twitter.com",
+  "pbs.twimg.com",
+  "video.twimg.com",
 ];
-const bibliogramDefault = 'https://bibliogram.art';
+const bibliogramDefault = "https://bibliogram.art";
 const instagramDomains = [
   "instagram.com",
   "www.instagram.com",
@@ -28,50 +38,50 @@ const instagramDomains = [
   "about.instagram.com",
 ];
 const instagramReservedPaths = [
-  'about',
-  'explore',
-  'support',
-  'press',
-  'api',
-  'privacy',
-  'safety',
-  'admin',
-  'graphql',
-  'accounts',
-  'help',
-  'terms',
-  'contact',
-  'blog',
-  'igtv',
-  'u',
-  'p',
-  'fragment',
-  'imageproxy',
-  'videoproxy',
-  '.well-known'
+  "about",
+  "explore",
+  "support",
+  "press",
+  "api",
+  "privacy",
+  "safety",
+  "admin",
+  "graphql",
+  "accounts",
+  "help",
+  "terms",
+  "contact",
+  "blog",
+  "igtv",
+  "u",
+  "p",
+  "fragment",
+  "imageproxy",
+  "videoproxy",
+  ".well-known",
 ];
 const bibliogramBypassPaths = /\/(accounts\/|embeds?.js)/;
 const bibliogramInstances = [
-  'https://bibliogram.art',
-  'https://bibliogram.snopyta.org'
+  "https://bibliogram.art",
+  "https://bibliogram.snopyta.org",
 ];
-const osmDefault = 'https://openstreetmap.org';
+const osmDefault = "https://openstreetmap.org";
 const googleMapsRegex = /https?:\/\/(((www|maps)\.)?(google\.).*(\/maps)|maps\.(google\.).*)/;
 const mapCentreRegex = /@(-?\d[0-9.]*),(-?\d[0-9.]*),(\d{1,2})[.z]/;
 const dataLatLngRegex = /(!3d|!4d)(-?[0-9]{1,10}.[0-9]{1,10})/g;
 const placeRegex = /\/place\/(.*)\//;
 const travelModes = {
-  'driving': 'fossgis_osrm_car',
-  'walking': 'fossgis_osrm_foot',
-  'bicycling': 'fossgis_osrm_bike',
-  'transit': 'fossgis_osrm_car' // not implemented on OSM, default to car.
+  driving: "fossgis_osrm_car",
+  walking: "fossgis_osrm_foot",
+  bicycling: "fossgis_osrm_bike",
+  transit: "fossgis_osrm_car", // not implemented on OSM, default to car.
 };
 const layers = {
-  'none': 'S',
-  'transit': 'T',
-  'traffic': 'S', // not implemented on OSM, default to standard.
-  'bicycling': 'C'
-}
+  none: "S",
+  transit: "T",
+  traffic: "S", // not implemented on OSM, default to standard.
+  bicycling: "C",
+};
 
 let disableNitter;
 let disableInvidious;
@@ -95,25 +105,25 @@ window.browser = window.browser || window.chrome;
 
 browser.storage.sync.get(
   [
-    'nitterInstance',
-    'invidiousInstance',
-    'bibliogramInstance',
-    'osmInstance',
-    'disableNitter',
-    'disableInvidious',
-    'disableBibliogram',
-    'disableOsm',
-    'alwaysProxy',
-    'onlyEmbeddedVideo',
-    'videoQuality',
-    'invidiousDarkMode',
-    'invidiousVolume',
-    'invidiousPlayerStyle',
-    'invidiousSubtitles',
-    'invidiousAutoplay',
-    'exceptions'
+    "nitterInstance",
+    "invidiousInstance",
+    "bibliogramInstance",
+    "osmInstance",
+    "disableNitter",
+    "disableInvidious",
+    "disableBibliogram",
+    "disableOsm",
+    "alwaysProxy",
+    "onlyEmbeddedVideo",
+    "videoQuality",
+    "invidiousDarkMode",
+    "invidiousVolume",
+    "invidiousPlayerStyle",
+    "invidiousSubtitles",
+    "invidiousAutoplay",
+    "exceptions",
   ],
-  result => {
+  (result) => {
     disableNitter = result.disableNitter;
     disableInvidious = result.disableInvidious;
     disableBibliogram = result.disableBibliogram;
@@ -126,67 +136,70 @@ browser.storage.sync.get(
     onlyEmbeddedVideo = result.onlyEmbeddedVideo;
     videoQuality = result.videoQuality;
     invidiousDarkMode = result.invidiousDarkMode;
-    exceptions = result.exceptions ? result.exceptions.map(e => {
-      return new RegExp(e);
-    }) : [];
+    exceptions = result.exceptions
+      ? result.exceptions.map((e) => {
+          return new RegExp(e);
+        })
+      : [];
     invidiousVolume = result.invidiousVolume;
     invidiousPlayerStyle = result.invidiousPlayerStyle;
-    invidiousSubtitles = result.invidiousSubtitles || '';
+    invidiousSubtitles = result.invidiousSubtitles || "";
     invidiousAutoplay = !result.invidiousAutoplay;
   }
 );
 
-browser.storage.onChanged.addListener(changes => {
-  if ('nitterInstance' in changes) {
+browser.storage.onChanged.addListener((changes) => {
+  if ("nitterInstance" in changes) {
     nitterInstance = changes.nitterInstance.newValue || nitterDefault;
   }
-  if ('invidiousInstance' in changes) {
+  if ("invidiousInstance" in changes) {
     invidiousInstance = changes.invidiousInstance.newValue || invidiousDefault;
   }
-  if ('bibliogramInstance' in changes) {
-    bibliogramInstance = changes.bibliogramInstance.newValue || bibliogramDefault;
+  if ("bibliogramInstance" in changes) {
+    bibliogramInstance =
+      changes.bibliogramInstance.newValue || bibliogramDefault;
   }
-  if ('osmInstance' in changes) {
+  if ("osmInstance" in changes) {
     osmInstance = changes.osmInstance.newValue || osmDefault;
   }
-  if ('disableNitter' in changes) {
+  if ("disableNitter" in changes) {
     disableNitter = changes.disableNitter.newValue;
   }
-  if ('disableInvidious' in changes) {
+  if ("disableInvidious" in changes) {
     disableInvidious = changes.disableInvidious.newValue;
   }
-  if ('disableBibliogram' in changes) {
+  if ("disableBibliogram" in changes) {
     disableBibliogram = changes.disableBibliogram.newValue;
   }
-  if ('disableOsm' in changes) {
+  if ("disableOsm" in changes) {
     disableOsm = changes.disableOsm.newValue;
   }
-  if ('alwaysProxy' in changes) {
+  if ("alwaysProxy" in changes) {
     alwaysProxy = changes.alwaysProxy.newValue;
   }
-  if ('onlyEmbeddedVideo' in changes) {
+  if ("onlyEmbeddedVideo" in changes) {
     onlyEmbeddedVideo = changes.onlyEmbeddedVideo.newValue;
   }
-  if ('videoQuality' in changes) {
+  if ("videoQuality" in changes) {
     videoQuality = changes.videoQuality.newValue;
   }
-  if ('invidiousDarkMode' in changes) {
+  if ("invidiousDarkMode" in changes) {
     invidiousDarkMode = changes.invidiousDarkMode.newValue;
   }
-  if ('invidiousVolume' in changes) {
+  if ("invidiousVolume" in changes) {
     invidiousVolume = changes.invidiousVolume.newValue;
   }
-  if ('invidiousPlayerStyle' in changes) {
+  if ("invidiousPlayerStyle" in changes) {
     invidiousPlayerStyle = changes.invidiousPlayerStyle.newValue;
   }
-  if ('invidiousSubtitles' in changes) {
+  if ("invidiousSubtitles" in changes) {
     invidiousSubtitles = changes.invidiousSubtitles.newValue;
   }
-  if ('invidiousAutoplay' in changes) {
+  if ("invidiousAutoplay" in changes) {
     invidiousAutoplay = changes.invidiousAutoplay.newValue;
   }
-  if ('exceptions' in changes) {
-    exceptions = changes.exceptions.newValue.map(e => {
+  if ("exceptions" in changes) {
+    exceptions = changes.exceptions.newValue.map((e) => {
       return new RegExp(e);
     });
   }
@@ -204,14 +217,13 @@ function addressToLatLng(address, callback) {
             `${json.boundingbox[2]},${json.boundingbox[1]},${json.boundingbox[3]},${json.boundingbox[0]}`
           );
         }
-      }
-      else {
+      } else {
         console.info("Error: Status is " + xmlhttp.status);
       }
     }
   };
   xmlhttp.open(
-    'GET',
+    "GET",
     `https://nominatim.openstreetmap.org/search/${address}?format=json&limit=1`,
     false
   );
@@ -219,52 +231,58 @@ function addressToLatLng(address, callback) {
 }
 
 function isException(url, initiator) {
-  return exceptions.some(regex => (regex.test(url.href))) ||
-    (initiator && exceptions.some(regex => (regex.test(initiator.href))));
+  return (
+    exceptions.some((regex) => regex.test(url.href)) ||
+    (initiator && exceptions.some((regex) => regex.test(initiator.href)))
+  );
 }
 
 function isFirefox() {
-  return typeof InstallTrigger !== 'undefined';
+  return typeof InstallTrigger !== "undefined";
 }
 
 function redirectYouTube(url, initiator, type) {
   if (disableInvidious || isException(url, initiator)) {
     return null;
   }
-  if (initiator && (initiator.origin === invidiousInstance || youtubeDomains.includes(initiator.host))) {
+  if (
+    initiator &&
+    (initiator.origin === invidiousInstance ||
+      youtubeDomains.includes(initiator.host))
+  ) {
     return null;
   }
   if (url.pathname.match(/iframe_api/) || url.pathname.match(/www-widgetapi/)) {
     // Don't redirect YouTube Player API.
     return null;
   }
-  if (url.host.split('.')[0] === 'studio') {
+  if (url.host.split(".")[0] === "studio") {
     // Avoid redirecting `studio.youtube.com`
     return null;
   }
-  if (onlyEmbeddedVideo && type !== 'sub_frame') {
+  if (onlyEmbeddedVideo && type !== "sub_frame") {
     return null;
   }
   // Apply settings
   if (alwaysProxy) {
-    url.searchParams.append('local', true);
+    url.searchParams.append("local", true);
   }
   if (videoQuality) {
-    url.searchParams.append('quality', videoQuality);
+    url.searchParams.append("quality", videoQuality);
   }
   if (invidiousDarkMode) {
-    url.searchParams.append('dark_mode', invidiousDarkMode);
+    url.searchParams.append("dark_mode", invidiousDarkMode);
   }
   if (invidiousVolume) {
-    url.searchParams.append('volume', invidiousVolume);
+    url.searchParams.append("volume", invidiousVolume);
   }
   if (invidiousPlayerStyle) {
-    url.searchParams.append('player_style', invidiousPlayerStyle);
+    url.searchParams.append("player_style", invidiousPlayerStyle);
   }
   if (invidiousSubtitles) {
-    url.searchParams.append('subtitles', invidiousSubtitles);
+    url.searchParams.append("subtitles", invidiousSubtitles);
   }
-  url.searchParams.append('autoplay', invidiousAutoplay ? 1 : 0);
+  url.searchParams.append("autoplay", invidiousAutoplay ? 1 : 0);
 
   return `${invidiousInstance}${url.pathname}${url.search}`;
 }
@@ -273,21 +291,28 @@ function redirectTwitter(url, initiator) {
   if (disableNitter || isException(url, initiator)) {
     return null;
   }
-  if (url.pathname.includes('/home')) {
+  if (url.pathname.includes("/home")) {
     return null;
   }
-  if (isFirefox() && initiator && (initiator.origin === nitterInstance || twitterDomains.includes(initiator.host))) {
+  if (
+    isFirefox() &&
+    initiator &&
+    (initiator.origin === nitterInstance ||
+      twitterDomains.includes(initiator.host))
+  ) {
     browser.storage.sync.set({
-      redirectBypassFlag: true
+      redirectBypassFlag: true,
     });
     return null;
   }
-  if (url.host.split('.')[0] === 'pbs') {
+  if (url.host.split(".")[0] === "pbs") {
     return `${nitterInstance}/pic/${encodeURIComponent(url.href)}`;
-  } else if (url.host.split('.')[0] === 'video') {
+  } else if (url.host.split(".")[0] === "video") {
     return `${nitterInstance}/gif/${encodeURIComponent(url.href)}`;
-  } else if (url.pathname.includes('tweets')) {
-    return `${nitterInstance}${url.pathname.replace('/tweets', '')}${url.search}`;
+  } else if (url.pathname.includes("tweets")) {
+    return `${nitterInstance}${url.pathname.replace("/tweets", "")}${
+      url.search
+    }`;
   } else {
     return `${nitterInstance}${url.pathname}${url.search}`;
   }
@@ -298,14 +323,21 @@ function redirectInstagram(url, initiator, type) {
     return null;
   }
   // Do not redirect Bibliogram view on Instagram links
-  if (initiator && (initiator.origin === bibliogramInstance || instagramDomains.includes(initiator.host))) {
+  if (
+    initiator &&
+    (initiator.origin === bibliogramInstance ||
+      instagramDomains.includes(initiator.host))
+  ) {
     return null;
   }
   // Do not redirect /accounts, /embeds.js, or anything other than main_frame
-  if (type !== 'main_frame' || url.pathname.match(bibliogramBypassPaths)) {
+  if (type !== "main_frame" || url.pathname.match(bibliogramBypassPaths)) {
     return null;
   }
-  if (url.pathname === '/' || instagramReservedPaths.includes(url.pathname.split('/')[1])) {
+  if (
+    url.pathname === "/" ||
+    instagramReservedPaths.includes(url.pathname.split("/")[1])
+  ) {
     return `${bibliogramInstance}${url.pathname}${url.search}`;
   } else {
     // Likely a user profile, redirect to '/u/...'
@@ -318,31 +350,33 @@ function redirectGoogleMaps(url, initiator) {
     return null;
   }
   let redirect;
-  let mapCentre = '';
-  let params = '';
+  let mapCentre = "";
+  let params = "";
   // Set map centre if present
   if (url.pathname.match(mapCentreRegex)) {
     const [, lat, lon, zoom] = url.pathname.match(mapCentreRegex);
     mapCentre = `#map=${zoom}/${lat}/${lon}`;
-  } else if (url.search.includes('center=')) {
-    const [lat, lon] = url.searchParams.get('center').split(',');
-    mapCentre = `#map=${url.searchParams.get('zoom') || '17'}/${lat}/${lon}`;
+  } else if (url.search.includes("center=")) {
+    const [lat, lon] = url.searchParams.get("center").split(",");
+    mapCentre = `#map=${url.searchParams.get("zoom") || "17"}/${lat}/${lon}`;
     // Set default zoom if mapCentre not present
   } else {
-    params = '&zoom=17';
+    params = "&zoom=17";
   }
   // Set map layer
-  params = `${params}&layers=${layers[url.searchParams.get('layer')] || layers['none']}`;
+  params = `${params}&layers=${
+    layers[url.searchParams.get("layer")] || layers["none"]
+  }`;
   // Handle Google Maps Embed API
-  if (url.pathname.includes('/embed')) {
-    let query = '';
-    if (url.searchParams.has('q')) {
-      query = url.searchParams.get('q');
-    } else if (url.searchParams.has('query')) {
-      query = url.searchParams.has('query');
-    } else if (url.searchParams.has('pb')) {
+  if (url.pathname.includes("/embed")) {
+    let query = "";
+    if (url.searchParams.has("q")) {
+      query = url.searchParams.get("q");
+    } else if (url.searchParams.has("query")) {
+      query = url.searchParams.has("query");
+    } else if (url.searchParams.has("pb")) {
       try {
-        query = url.searchParams.get('pb').split(/!2s(.*?)!/)[1];
+        query = url.searchParams.get("pb").split(/!2s(.*?)!/)[1];
       } catch (error) {
         console.error(error);
         // Unable to find map marker in URL.
@@ -355,47 +389,56 @@ function redirectGoogleMaps(url, initiator) {
     });
     redirect = `${osmInstance}/export/embed.html?bbox=${bbox}&layer=mapnik&marker=${marker}`;
     // Handle Google Maps Directions
-  } else if (url.pathname.includes('/dir')) {
-    const travelMode = travelModes[url.searchParams.get('travelmode')] || travelModes['driving'];
+  } else if (url.pathname.includes("/dir")) {
+    const travelMode =
+      travelModes[url.searchParams.get("travelmode")] || travelModes["driving"];
     let origin;
-    addressToLatLng(url.searchParams.get('origin'), coords => {
+    addressToLatLng(url.searchParams.get("origin"), (coords) => {
       origin = coords;
     });
     let destination;
-    addressToLatLng(url.searchParams.get('destination'), coords => {
+    addressToLatLng(url.searchParams.get("destination"), (coords) => {
       destination = coords;
     });
     redirect = `${osmInstance}/directions?engine=${travelMode}&route=${origin}%3B${destination}${mapCentre}${params}`;
     // Get marker from data attribute
-  } else if (url.pathname.includes('data=') && url.pathname.match(dataLatLngRegex)) {
+  } else if (
+    url.pathname.includes("data=") &&
+    url.pathname.match(dataLatLngRegex)
+  ) {
     const [mlat, mlon] = url.pathname.match(dataLatLngRegex);
-    redirect = `${osmInstance}/?mlat=${mlat.replace('!3d', '')}&mlon=${mlon.replace('!4d', '')}${mapCentre}${params}`;
+    redirect = `${osmInstance}/?mlat=${mlat.replace(
+      "!3d",
+      ""
+    )}&mlon=${mlon.replace("!4d", "")}${mapCentre}${params}`;
     // Get marker from ll param
-  } else if (url.searchParams.has('ll')) {
-    const [mlat, mlon] = url.searchParams.get('ll').split(',');
+  } else if (url.searchParams.has("ll")) {
+    const [mlat, mlon] = url.searchParams.get("ll").split(",");
     redirect = `${osmInstance}/?mlat=${mlat}&mlon=${mlon}${mapCentre}${params}`;
     // Get marker from viewpoint param.
-  } else if (url.searchParams.has('viewpoint')) {
-    const [mlat, mlon] = url.searchParams.get('viewpoint').split(',');
+  } else if (url.searchParams.has("viewpoint")) {
+    const [mlat, mlon] = url.searchParams.get("viewpoint").split(",");
     redirect = `${osmInstance}/?mlat=${mlat}&mlon=${mlon}${mapCentre}${params}`;
     // Use query as search if present.
   } else {
     let query;
-    if (url.searchParams.has('q')) {
-      query = url.searchParams.get('q');
-    } else if (url.searchParams.has('query')) {
-      query = url.searchParams.get('query');
+    if (url.searchParams.has("q")) {
+      query = url.searchParams.get("q");
+    } else if (url.searchParams.has("query")) {
+      query = url.searchParams.get("query");
     } else if (url.pathname.match(placeRegex)) {
       query = url.pathname.match(placeRegex)[1];
     }
-    redirect = `${osmInstance}/${query ? 'search?query=' + query : ''}${mapCentre || '#'}${params}`;
+    redirect = `${osmInstance}/${query ? "search?query=" + query : ""}${
+      mapCentre || "#"
+    }${params}`;
   }
 
   return redirect;
 }
 
 browser.webRequest.onBeforeRequest.addListener(
-  details => {
+  (details) => {
     const url = new URL(details.url);
     let initiator;
     if (details.originUrl) {
@@ -406,55 +449,69 @@ browser.webRequest.onBeforeRequest.addListener(
     let redirect;
     if (youtubeDomains.includes(url.host)) {
       redirect = {
-        redirectUrl: redirectYouTube(url, initiator, details.type)
+        redirectUrl: redirectYouTube(url, initiator, details.type),
       };
     } else if (twitterDomains.includes(url.host)) {
       redirect = {
-        redirectUrl: redirectTwitter(url, initiator)
+        redirectUrl: redirectTwitter(url, initiator),
       };
     } else if (instagramDomains.includes(url.host)) {
       redirect = {
-        redirectUrl: redirectInstagram(url, initiator, details.type)
+        redirectUrl: redirectInstagram(url, initiator, details.type),
       };
     } else if (url.href.match(googleMapsRegex)) {
       redirect = {
-        redirectUrl: redirectGoogleMaps(url, initiator)
+        redirectUrl: redirectGoogleMaps(url, initiator),
       };
     }
     if (redirect && redirect.redirectUrl) {
       console.info(
-        'Redirecting', `"${url.href}"`, '=>', `"${redirect.redirectUrl}"`
+        "Redirecting",
+        `"${url.href}"`,
+        "=>",
+        `"${redirect.redirectUrl}"`
       );
-      console.info('Details', details);
+      console.info("Details", details);
     }
     return redirect;
   },
   {
-    urls: ["<all_urls>"]
+    urls: ["<all_urls>"],
   },
-  ['blocking']
+  ["blocking"]
 );
 
-browser.runtime.onInstalled.addListener(
-  details => {
-    if (details.reason === 'install') {
-      browser.storage.sync.set({
-        bibliogramInstance: bibliogramInstances[~~(bibliogramInstances.length * Math.random())]
-      });
-    } else if (details.reason === 'update') {
-      browser.storage.sync.get(['whitelist', 'exceptions'],
-        result => {
-          if (result.whitelist) {
-            let whitelist = result.whitelist.map(
-              e => e.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')
-            );
-            browser.storage.sync.set({
-              exceptions: result.exceptions.concat(whitelist),
-              whitelist: null
-            });
-          }
+browser.runtime.onInstalled.addListener((details) => {
+  if (details.reason === "install") {
+    browser.storage.sync.set({
+      bibliogramInstance:
+        bibliogramInstances[~~(bibliogramInstances.length * Math.random())],
+      invidiousInstance:
+        invidiousInstances[~~(invidiousInstances.length * Math.random())],
+    });
+  } else if (details.reason === "update") {
+    browser.storage.sync.get(
+      ["whitelist", "exceptions", "invidiousInstance"],
+      (result) => {
+        if (result.whitelist) {
+          let whitelist = result.whitelist.map((e) =>
+            e.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&")
+          );
+          browser.storage.sync.set({
+            exceptions: result.exceptions.concat(whitelist),
+            whitelist: null,
+          });
         }
-      );
-    }
+        if (
+          result.invidiousInstance === "https://invidio.us" ||
+          result.invidiousInstance === null
+        ) {
+          browser.storage.sync.set({
+            invidiousInstance:
+              invidiousInstances[~~(invidiousInstances.length * Math.random())],
+          });
+        }
+      }
+    );
   }
-);
+});
diff --git a/manifest.json b/manifest.json
index ba55111a..88be6e84 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,7 +1,7 @@
 {
   "name": "__MSG_extensionName__",
   "description": "__MSG_extensionDescription__",
-  "version": "1.1.39",
+  "version": "1.1.40",
   "manifest_version": 2,
   "background": {
     "scripts": ["background.js"],
@@ -39,9 +39,11 @@
     },
     {
       "matches": [
-        "*://invidio.us/*",
         "*://invidious.snopyta.org/*",
         "*://yewtu.be/*",
+        "*://invidious.xyz/*",
+        "*://invidious.site/*",
+        "*://invidiou.site/*",
         "*://invidious.ggc-project.de/*",
         "*://invidious.13ad.de/*",
         "*://invidious.toot.koeln/*",
@@ -54,8 +56,8 @@
         "*://fz253lmuao3strwbfbmx46yu7acac2jz27iwtorgmbqlkurlclmancad.onion/*",
         "*://qklhadlycap4cnod.onion/*",
         "*://c7hqkpkpemu6e7emz5b4vyz7idjgdvgaaa3dyimmeojqbgpea3xqjoid.onion/*",
-        "*://mfqczy4mysscub2s.onion/*"
-        "*://4l2dgddgsrkf2ous66i6seeyi6etzfgrue332grh2n7madpwopotugyd.onion/*",
+        "*://mfqczy4mysscub2s.onion/*",
+        "*://4l2dgddgsrkf2ous66i6seeyi6etzfgrue332grh2n7madpwopotugyd.onion/*"
       ],
       "js": ["assets/javascript/persist-invidious-prefs.js"],
       "run_at": "document_start"
diff --git a/pages/options/options.html b/pages/options/options.html
index 0f38ff0a..8e074037 100644
--- a/pages/options/options.html
+++ b/pages/options/options.html
@@ -137,7 +137,7 @@
           <input
             id="invidious-instance"
             type="url"
-            placeholder="https://invidio.us"
+            placeholder="https://invidious.snopyta.org"
           />
         </div>
       </section>
diff --git a/pages/options/options.js b/pages/options/options.js
index 43545385..d6fc731b 100644
--- a/pages/options/options.js
+++ b/pages/options/options.js
@@ -15,12 +15,14 @@ const nitterInstances = [
   "http://nitter.l4qlywnpwqsluw65ts7md3khrivpirse744un3x7mlskqauz5pyuzgqd.onion",
 ];
 const invidiousInstances = [
-  "https://invidio.us",
   "https://invidious.snopyta.org",
   "https://yewtu.be",
   "https://invidious.ggc-project.de",
   "https://invidious.13ad.de",
+  "https://invidious.xyz",
   "https://invidious.toot.koeln",
+  "https://invidious.site",
+  "https://invidiou.site",
   "https://invidious.fdn.fr",
   "https://watch.nettohikari.com",
   "https://yt.iswleuven.be",