AO3: Jump to a Random Work

adds a button when viewing works, which will pick a random work in your current view and redirect you there

当前为 2022-11-08 提交的版本,查看 最新版本

// ==UserScript==
// @name         AO3: Jump to a Random Work
// @namespace    https://greasyforks.org/en/users/906106-escctrl
// @version      0.1
// @description  adds a button when viewing works, which will pick a random work in your current view and redirect you there
// @author       escctrl
// @match        *://*.archiveofourown.org/tags/*/works*
// @match        *://*.archiveofourown.org/works?*
// @require      https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js
// @grant        none
// @license      MIT
// ==/UserScript==

(function($) {
    'use strict';

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

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

        // .contents().first() grabs only the textNode (1-20 of X Works in) instead of the whole heading text
        // that way we don't care what numbers might be part of the tag, it's not going to confuse the code
        const worksTitle = $('#main h2.heading').contents().first().text();

        const worksMatch = worksTitle.match(/\d+/g);
        /* if "1-20 of X Works", [0] match is "1" and [1] is "20" from the "1-20" part, and [2] is the total number
           if "X Works" (below 20), [0] is the total number
           either way it's the last entry in the array
        */
        const worksCount = parseInt(worksMatch[worksMatch.length-1]);

        // pick random whole number of work within the filter (between 1 and total number of works)
        const chooseRandom = Math.floor((Math.random() * worksCount) + 1);

        // there are always 20 works per page. find the n-th page and m-th work on that page
        const pageRandom = Math.ceil(chooseRandom/20);
        const workRandom = chooseRandom - (20*(pageRandom-1));

        // check: are we currently on that page?
        var thisPage = location.search.match(/page=(\d)+/);
        thisPage = thisPage === null ? 1 : parseInt(thisPage[1]); // match only worked if URL contains pagination already

        //console.log({chosen: chooseRandom, onpage: pageRandom, workonpage: workRandom, thispage: thisPage});

        // if not - built the URL of that page and read it to find the random work link
        if (thisPage !== pageRandom) {
            var pageURL = location.search.indexOf('page=') > 0 ? location.href.replace(/page=(\d)+/, 'page='+pageRandom) // replace existing page number
            : location.href + (location.href.indexOf('?') ? '&' : '?') + 'page='+pageRandom; // add page number if not yet in URL search parameters

            // grab the list of works from the page
            console.log('loading page...');
            $.get(pageURL, function(response) {
            }).done(function(response) {
                Redirect2Work($(response).find('ol.work.index.group li.work.blurb'), workRandom);

            // if that sent us to jail, set the ao3jail marker
            }).fail(function(data, textStatus, xhr) {
                console.log("Random Work script has hit Retry later", data.status);
                return false;
            });
        }
        // if yes - read the random work link from this page
        else {
            Redirect2Work($('ol.work.index.group li.work.blurb'), workRandom);
        }
    }

    function Redirect2Work(worksList, pick) {
        //console.log(worksList);
        pick = $(worksList[pick-1]).find('h4 a').first();
        var path = $(pick).attr('href');
        var title = $(pick).text();
        alert('redirecting to a random work: '+title);
        window.location.assign(path);
    }

})(jQuery);
长期地址
遇到问题?请前往 GitHub 提 Issues。