// ==UserScript== // @name Wiki Randomizer // @namespace https://script.zgc.im/ // @version 0.2 // @description Press 'R' to navigate to Special:Random or others. // @author MidAutumnMoon // // @match https://zh.wikipedia.org/* // @match https://en.wikipedia.org/* // @match https://ja.wikipedia.org/* // @match https://fr.wikipedia.org/* // @match https://zh.moegirl.org.cn/* // @match https://ja.moegirl.org.cn/* // @match https://en.moegirl.org.cn/* // @match https://tcrf.net/* // // @icon https://zh.wikipedia.org/favicon.ico // @grant none // @downloadURL none // ==/UserScript== // Almost any Mediawiki sites use /Special:Random. const MediawikiCommon = 'Special:Random'; // The total rules const RULES = new Map([ // *.wikipedia.org [ 'wikipedia.org', 'wiki/Special:Random' ], // Cutting Room Floor [ 'tcrf.net', 'Special:RandomRootpage' ], // Moegirl wiki [ 'moegirl.org.cn', MediawikiCommon ], ]); // Main (function() { 'use strict'; // Navigate to the `location` of current site. const navigate_to = ( location ) => { window.location.href = new URL( window.location.href ).origin + '/' + location; }; // Get the rule associated with current site. const get_rule = () => { let domain = new URL( window.location.href ).host; let rule = ''; for (;;) { rule = RULES.get(domain); if ( rule === undefined ) { // If no rules were found for current domain, // try matching sub-domain instead. if ( ! validated_domain(domain) ) { return null; } // truncate one level of subdomain domain = domain.substring( domain.indexOf('.') + 1 ); } else { // Otherwise just return the matched rule. return rule; } } }; // There must be at least 2 dots in a valid domain name. const validated_domain = ( domain ) => { return ( (domain.match(/\./g) || []).length >= 2 ); } // ...when press 'R'. document.addEventListener('keydown', ( event ) => { if ( event.code === 'KeyR' ) { const location = get_rule(); switch ( location ) { case null: console.log( 'No rules for current site!' ); break; default: navigate_to( location ); break; } } }); })();