您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Sleazy Fork is available in English.
IPFS gateway switcher for ofans.party.
当前为
// ==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 // @grant unsafeWindow // @run-at document-start // @version 0.6 // @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, regex_creator, api_posts, gateways_json, public_gateways, current_gateway, gallery_mode, creator, posts_find, posts_replace; loaded = false; regex_main_js = new RegExp(/main\.[a-z0-9]+\.chunk\.js/); regex_creator = new RegExp(/^https:\/\/ofans.party\/#\/creator\//); // 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"; api_posts = "https://api.ofans.party/posts/"; public_gateways = await GM_getValue("public_gateways"); current_gateway = await GM_getValue("current_gateway"); gallery_mode = await GM_getValue("gallery_mode") || false; posts_find = `Object(a.jsxs)("div",{className:"container",children:[o,this.state.posts&&this.state.posts.map((function(t,s){return r++,Object(a.jsxs)("div",{className:"row post",of_id:t.post_id,children:[r%15==0&&e.renderAd(),Object(a.jsxs)("div",{className:"col-lg-6 postText",children:[e.renderPostDate(t),Object(a.jsx)("br",{}),e.renderPostText(t)]}),Object(a.jsx)("div",{className:"col-lg-6",style:{textAlign:"center"},children:t.media&&t.media.map((function(t,s){return t.ipfs_media_hash?Object(a.jsx)("a",{href:e.state.ipfsHost+t.ipfs_media_hash,children:Object(a.jsx)("img",{src:e.state.ipfsHost+t.ipfs_thumb_hash,loading:"lazy",className:"mediaThumb"})},t.id.toString()):Object(a.jsx)("div",{style:{backgroundColor:"grey",height:"144px",width:"144px",margin:"0.5em",position:"relative"},title:"Importing...",children:Object(a.jsxs)("span",{style:{color:"white",fontSize:"2em",fontWeight:"bold",position:"absolute",top:"50%",left:"50%",margin:"-25px 0 0 -25px",height:"50px",width:"50px"},children:[" ",Object(a.jsx)(c.a,{icon:["fa","download"]})," "]})})}))})]},t.id.toString())}))]})` posts_replace = `Object(a.jsxs)("div",{className:"container",children:[o,Object(a.jsxs)("div",{className:"row row-cols-5 align-items-center no-gutters bg-light",children:[this.state.posts&&this.state.posts.map((function(t,s){return r++,t.media&&t.media.map((function(t,s){return t.ipfs_media_hash?Object(a.jsx)("div",{className:"col",children:Object(a.jsx)("div",{className:"d-flex justify-content-center m-1",children:Object(a.jsx)("a",{href:e.state.ipfsHost+t.ipfs_media_hash,target:"_blank",children:Object(a.jsx)("img",{src:e.state.ipfsHost+t.ipfs_thumb_hash,loading:"lazy",className:"img-fluid"})},t.id.toString())})}):Object(a.jsx)("div",{className:"col",children:Object(a.jsx)("div",{className:"d-flex justify-content-center m-1",style:{backgroundColor:"grey",height:"150px",position:"relative"},title:"Importing...",children:Object(a.jsxs)("span",{style:{color:"white",fontSize:"2em",fontWeight:"bold",position:"absolute",top:"50%",left:"50%",margin:"-25px 0 0 -25px",height:"50px",width:"50px"},children:[" ",Object(a.jsx)(c.a,{icon:["fa","download"]})," "]})})})}))}))]})]})` 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 || gallery_mode)) { const source = e.script.attributes.src.value; e.preventDefault(); e.stopPropagation(); GM_xmlhttpRequest({ method: "GET", url: source, onload: async function (response) { loaded = !loaded var text = response.responseText if (current_gateway) { text = text.replace(/ipfsHost:"(.*?)"/g, `ipfsHost:"${current_gateway}"`) } if (gallery_mode) { text = text.replace(posts_find, posts_replace); } 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-fixed 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 ml-1" }); 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) let button_gallery = createElement('button', `Gallery Mode`, { class: `btn button-gallery ml-2 ${gallery_mode ? ' btn-info' : ' btn-dark'}` }); let gallery_status = createElement('span', `${gallery_mode ? 'On' : 'Off'}`, { class: "badge badge-light ml-1" }); button_gallery.append(gallery_status) wrapper.append(button_gallery) document.body.append(wrapper) console.log(creator) }); 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(); } else if (class_list.contains('button-gallery')) { GM_setValue("gallery_mode", !gallery_mode) location.reload(); } } /* async function createGallery() { const loc = window.location.href if (regex_creator.test(loc)) { const id = loc.substring(loc.lastIndexOf('/') + 1) await GM_xmlhttpRequest({ method: "GET", url: api_posts + id, onload: function (response) { let json = JSON.parse(response.responseText) creator = json.response let app = document.querySelectorAll('#root')[0]; let container = document.querySelectorAll('.container')[0]; let posts_container = createElement('div', false, { class: 'container' }); let posts_row = createElement('div', false, { class: 'row row-cols-5 align-items-center no-gutters bg-light' }); for (const [index, post] of creator.posts.entries()) { for (const media of post.media) { if (media.ipfs_media_hash) { let col = createElement('div', false, { class: 'col' }); let item = createElement('div', false, { class: 'd-flex justify-content-center m-1' }); let link = createElement('a', false, { href: current_gateway + media.ipfs_media_hash }); let image = createElement('img', false, { src: current_gateway + media.ipfs_thumb_hash, loading: "lazy", class: 'img-fluid' }); link.append(image) item.append(link) col.append(item) posts_row.append(col) } } } posts_container.append(posts_row) container.innerHTML = posts_row.outerHTML gallery_mode = true } }); } } */ 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; } })();