您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Library to modify static and dynamic components of osu web pages
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.cn-greasyfork.org/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}`;
- }
- }