AO3: Jump to a Random Work

adds a "Random Work" button (top right corner) when viewing works or bookmarks - shows up in a tag/filter and your Marked For Later list

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         AO3: Jump to a Random Work
// @namespace    https://greasyfork.org/en/users/906106-escctrl
// @version      1.1
// @description  adds a "Random Work" button (top right corner) when viewing works or bookmarks - shows up in a tag/filter and your Marked For Later list
// @author       escctrl
// @match        *://*.archiveofourown.org/tags/*/works*
// @match        *://*.archiveofourown.org/works?*
// @match        *://*.archiveofourown.org/users/*/readings*show=to-read*
// @match        *://*.archiveofourown.org/tags/*/bookmarks*
// @match        *://*.archiveofourown.org/bookmarks?*
// @match        *://*.archiveofourown.org/users/*/bookmarks*
// @grant        none
// @license      MIT
// ==/UserScript==

'use strict';

// utility to reduce verboseness
const q = (s, n=document) => n.querySelector(s);
const qa = (s, n=document) => n.querySelectorAll(s);

// add a button
var button = document.createElement('li');
button.innerHTML = '<a href="#">Random Work</a>';
button.addEventListener("click", RandomWork);
q('div#main ul.navigation.actions').appendChild(button);

// when the button was pressed, read the number of works, pick a random one, and redirect there
function RandomWork(e) {
    e.preventDefault();

    // Find number of pages. content of second-to-last <li> tells us
    let pageCount = q('ol.pagination');
    pageCount = pageCount !== null ? parseInt([...qa('li', pageCount)].at(-2).innerText) : 1;

    // pick random whole number of the available pages
    const pageRandom = Math.floor((Math.random() * pageCount) + 1);

    // figure out which page we're currently viewing
    var thisPage = location.search.match(/page=(\d+)/);
    thisPage = thisPage === null ? 1 : parseInt(thisPage[1]); // match only works if URL contained a page (i.e. if not on page 1)

    // check: are we currently on the randomly chosen page?
    if (thisPage !== pageRandom) LoadRandomPage(pageRandom); // if not - read that page to find a random work link
    else Redirect2Work(qa('ol.index.group > li.blurb')); // if yes - skip page loads, read a random work link from this page
}

async function LoadRandomPage(r) {
    // build the URL of the page to load
    var pageURL = location.search.indexOf('page=') > 0 ? location.href.replace(/page=(\d+)/, 'page='+r) // replace existing page number
        : location.href + (location.href.indexOf('?') > 0 ? '&' : '?') + 'page='+r; // add page number if not yet in URL search parameters

    try {
        let response = await fetch(pageURL);
        // the response has hit an error eg. 429 retry later
        if (!response.ok) throw new Error(`Random Work script HTTP error: ${response.status}`);
        else {
            let txt = await response.text();
            let parser = new DOMParser(); // Initialize the DOM parser
            txt = parser.parseFromString(txt, "text/html"); // Parse the text into HTML

            Redirect2Work(qa('ol.index.group > li.blurb', txt));
        }
    }
    catch(error) {
        console.error("Random Work script error", error.message);
        alert("Sorry, the Random Work script encountered an error. You've probably been rate-limited. Please try again later.");
        return false;
    }
}

function Redirect2Work(worksList) {

    // pick a random work from within the list
    var pick = Math.floor((Math.random() * worksList.length) + 1);

    // read that random work's URL and title
    pick = q('h4 a', worksList[pick-1]);

    // jump to that work but warn the user
    alert('Redirecting you to a random work: '+pick.innerText);
    window.location.assign(pick.href);
}