您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Library to modify static and dynamic components of osu web pages
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/473977/1242746/osu-web.js
// ==UserScript== // @name osu-web // @namespace osu // @version 1.0.7 // @description Library to modify static and dynamic components of osu web pages // @author Magnus Cosmos // ==/UserScript== // Utils function isNonEmptyObj(obj) { if (obj === null || (typeof obj !== "function" && typeof obj !== "object")) { return false; } for (const _key in obj) { return true; } return false; } function loaded(selector, parent = document, options = { childList: true }) { return new Promise((resolve) => { const el = parent.querySelector(selector); if (el) { resolve(el); } else { new MutationObserver(function (_mutations, observer) { const el = parent.querySelector(selector); if (el) { resolve(el); observer = observer ? observer : this; observer.disconnect(); } }).observe(parent, options); } }); } // Classes class webpack { loaded = false; modules = {}; constructor() { if (this.constructor == webpack) { throw new Error("webpack class cannot be instantiated."); } } inject(entryPoint, data) { try { if (unsafeWindow) { unsafeWindow[entryPoint].push(data); } else { window[entryPoint].push(data); } } catch (err) { throw new Error(`Injection failed: ${err.message}`); } } } // Based on `Webpack-module-crack` and `moduleRaid` class Webpack extends webpack { constructor(options) { super(); if (this.loaded) { return; } let { moduleId, chunkId, entryPoint } = options || {}; moduleId = moduleId || Math.random().toString(36).substring(2, 6); chunkId = chunkId || Math.floor(101 + Math.random() * 899); entryPoint = entryPoint || "webpackJsonp"; const data = [ [chunkId], { [moduleId]: (_module, _exports, require) => { const installedModules = require.c; for (const id in installedModules) { const exports = installedModules[id].exports; if (isNonEmptyObj(exports)) { this.modules[id] = exports; } } }, }, [[moduleId]], ]; this.inject(entryPoint, data); this.loaded = true; } } class Module { loaded = false; static = []; dynamic = []; before = {}; after = {}; keys = []; style; constructor() { if (this.constructor == Module) { throw new Error("Module class cannot be instantiated."); } } init() { if (this.loaded) { return; } this.webpack = new Webpack(); this.#getTurboLinks(); this.#getReactModules(); this.#appendStyle(); this.loaded = true; } #appendStyle() { const style = document.querySelector("#osu-web"); if (!(style || this.style)) { this.style = document.createElement("style"); this.style.id = "osu-web"; document.head.append(this.style); } } #getTurboLinks() { for (const id in this.webpack.modules) { const exports = this.webpack.modules[id]; if ("controller" in exports) { this.turbolinks = exports; return; } } } #getReactModules() { const reactModules = new Set(); for (const id in this.webpack.modules) { const exports = this.webpack.modules[id]; if ("__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED" in exports) { reactModules.add(exports); } } [this.React, this.ReactDOM] = reactModules; } modifyFn(obj, fn, key, _before, _after) { if (!(key in this.keys)) { this.keys.push(key); this.before[key] = []; this.after[key] = []; this.#modify(obj, fn, key); } if (_before) { this.before[key].push(_before); } if (_after) { this.after[key].push(_after); } } #modify(obj, fn, key) { const self = this; const oldFn = obj[fn]; obj[fn] = function () { self.#beforeFn(key, arguments); const r = oldFn.apply(this, arguments); self.#afterFn(key, arguments, r); return r; }; } #beforeFn(key, args) { const arr = this.before[key] || []; for (const fn of arr) { fn(args); } } #afterFn(key, args, r) { const arr = this.after[key] || []; for (const fn of arr) { fn(args, r); } } } class OsuWeb extends Module { constructor(staticFn, dynamicFn) { super(); this.static = staticFn || (() => {}); this.dynamic = dynamicFn || (() => {}); loaded("html", document, (html) => { loaded("body", html, () => { this.init(); this.start(); }); }); } start() { this.static(document.body); const controller = this.turbolinks.controller; this.modifyFn(controller, "render", "turbolinks.render", null, (args, r) => { this.static(r.newBody); }); this.dynamic(); } addStyle(css) { this.style.innerHTML += `\n${css}`; } }