OFans.party IPFS Gateway Switcher

IPFS gateway switcher for ofans.party.

27.04.2021 itibariyledir. En son verisyonu görün.

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

You will need to install an extension such as Tampermonkey to install this script.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name        OFans.party IPFS Gateway Switcher
// @namespace   Violentmonkey Scripts
// @description IPFS gateway switcher for ofans.party.
// @match       https://ofans.party/*
// @grant       GM_xmlhttpRequest
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_deleteValue
// @run-at      document-start
// @version     0.4
// @author      sudorain
// @noframes
// ==/UserScript==

// A (somewhat working) polyfill for beforescriptexecute event
// https://github.com/jspenguin2017/Snippets/blob/master/onbeforescriptexecute.html

(() => {
  "use strict";

  const Event = class {
    constructor(script, target) {
      this.script = script;
      this.target = target;

      this._cancel = false;
      this._replace = null;
      this._stop = false;
    }

    preventDefault() {
      this._cancel = true;
    }
    stopPropagation() {
      this._stop = true;
    }
    replacePayload(payload) {
      this._replace = payload;
    }
  };

  let callbacks = [];
  window.addBeforeScriptExecuteListener = (f) => {
    if (typeof f !== "function") {
      throw new Error("Event handler must be a function.");
    }
    callbacks.push(f);
  };
  window.removeBeforeScriptExecuteListener = (f) => {
    let i = callbacks.length;
    while (i--) {
      if (callbacks[i] === f) {
        callbacks.splice(i, 1);
      }
    }
  };

  const dispatch = (script, target) => {
    if (script.tagName !== "SCRIPT") {
      return;
    }

    const e = new Event(script, target);

    if (typeof window.onbeforescriptexecute === "function") {
      try {
        window.onbeforescriptexecute(e);
      } catch (err) {
        console.error(err);
      }
    }

    for (const func of callbacks) {
      if (e._stop) {
        break;
      }
      try {
        func(e);
      } catch (err) {
        console.error(err);
      }
    }

    if (e._cancel) {
      script.textContent = "";
      script.remove();
    } else if (typeof e._replace === "string") {
      script.textContent = e._replace;
    }
  };
  const observer = new MutationObserver((mutations) => {
    for (const m of mutations) {
      for (const n of m.addedNodes) {
        dispatch(n, m.target);
      }
    }
  });
  observer.observe(document, {
    childList: true,
    subtree: true,
  });
})();


(async () => {
  "use strict";

  var loaded, regex_main_js, gateways_json, public_gateways, current_gateway, gallery_mode;

  loaded = false;
  regex_main_js = new RegExp(/main\.[a-z0-9]+\.chunk\.js/);

  // A site displaying public IPFS gateways and their online/offline status.
  // https://ipfs.github.io/public-gateway-checker/
  gateways_json = "https://ipfs.github.io/public-gateway-checker/gateways.json";
  public_gateways = await GM_getValue("public_gateways");
  current_gateway = await GM_getValue("current_gateway");
  gallery_mode = await GM_getValue("gallery_mode");

  await GM_xmlhttpRequest({
    method: "GET",
    url: gateways_json,
    onload: function (response) {
      public_gateways = response.responseText.replace(/:hash/g, "");
      GM_setValue("public_gateways", public_gateways)
    }
  });

  window.onbeforescriptexecute = (e) => {
    const script = e.script.outerHTML;
    if (regex_main_js.test(script) && !loaded && current_gateway) {
      const source = e.script.attributes.src.value;
      e.preventDefault();
      e.stopPropagation();
      GM_xmlhttpRequest({
        method: "GET",
        url: source,
        onload: function (response) {
          loaded = !loaded
          let text = response.responseText.replace(/ipfsHost:"(.*?)"/g, `ipfsHost:"${current_gateway}"`);
          let newScript = createElement('script', text, { type: "text/javascript", id: "main" });
          document.head.append(newScript);
        }
      });
    }
  }

  document.addEventListener('DOMContentLoaded', function () {

    let css = `
      .custom-scrollbar::-webkit-scrollbar {
        width: 5px;
      }

      .custom-scrollbar::-webkit-scrollbar-track {
        background: #dee2e6; 
      }

      .custom-scrollbar::-webkit-scrollbar-thumb {
        background: #888; 
      }

      .custom-scrollbar::-webkit-scrollbar-thumb:hover {
        background: #555; 
      }
    `;

    let style = createElement('style', css);
    document.head.append(style);

    const gateways = JSON.parse(public_gateways)

    let wrapper = createElement('div', false, { class: "position-absolute fixed-bottom float-left text-monospace mb-3 ml-3", style: "width: fit-content;" });

    let dropdown_group = createElement('div', false, { id: "switch", class: "btn-group dropup" });
    let button = createElement('button', "Gateways ", { class: "btn btn-dark dropdown-toggle", "data-toggle": "dropdown", "aria-haspopup": "true", "aria-expanded": "false" });
    let badge = createElement('span', gateways.length, { class: "badge badge-light" });
    button.append(badge)
    dropdown_group.append(button)

    let dropdown_menu = createElement('div', false, { class: "dropdown-menu overflow-auto custom-scrollbar shadow-lg px-0 pt-0 pb-2 mb-3", style: "max-height: 388px" });
    for (const [index, url] of gateways.entries()) {
      let current = current_gateway == url;
      let fancy_url = url.match(/(^https?:\/\/)(.*)/);
      let url_protocol = createElement('small', fancy_url[1], { class: `${current ? ' ' : ' text-black-50'}` });
      let menu_item = createElement('button', fancy_url[2], { "data-value": url, class: `dropdown-item border-bottom button-switch ${current ? ' active' : ' text-dark'}`, type: "button" });
      menu_item.prepend(url_protocol)
      if (current) {
        dropdown_menu.prepend(menu_item)
      } else {
        dropdown_menu.append(menu_item)
      }
    }
    let dafault_gateway = createElement('button', 'Default', { "data-value": '', class: `dropdown-item border-bottom border-top button-switch ${!current_gateway ? ' active' : ''}`, type: "button" });
    dropdown_menu.prepend(dafault_gateway)
    let menu_header = createElement('h6', "Gateway Switcher", { class: "bg-light text-dark shadow-sm sticky-top dropdown-header border-bottom py-3 mb-2" });
    let menu_checker = createElement('a', "Public Gateway Checker ", { class: "float-right text-success", href: "https://ipfs.github.io/public-gateway-checker/", target: "_blank" });
    menu_header.append(menu_checker)
    dropdown_menu.prepend(menu_header)
    dropdown_group.append(dropdown_menu)
    wrapper.append(dropdown_group)
    document.body.append(wrapper)

  });

  document.addEventListener("click", switchGateway);

  function switchGateway(e) {
    const class_list = e.target.classList;
    const data_set = e.target.dataset;
    if (class_list.contains('button-switch')) {
      const value = data_set.value;
      if (value) {
        GM_setValue("current_gateway", value)
      } else {
        GM_deleteValue("current_gateway")
      }
      location.reload();
    }
  }

  function createElement(el, text, attrs) {
    let element = document.createElement(el);
    if (text) element.textContent = text;
    if (attrs) Object.keys(attrs).forEach(key => element.setAttribute(key, attrs[key]));
    return element;
  }

})();