Greasy Fork

AB - Mark Sneedex Releases

Tags the best releases on animebytes according to https://sneedex.moe/

目前为 2022-11-18 提交的版本。查看 最新版本

// ==UserScript==
// @name        AB - Mark Sneedex Releases
// @description Tags the best releases on animebytes according to https://sneedex.moe/
// @namespace   [email protected]
// @match       *://animebytes.tv/*
// @grant       GM_addElement
// @grant       GM_xmlhttpRequest
// @grant       GM_setValue
// @grant       GM_getValue
// @version     1.0.1
// @author      TalkingJello
// @icon        http://animebytes.tv/favicon.ico
// @connect     sneedex.moe
// @license     MIT
// ==/UserScript==

// Thanks to garret who made the nyaa script https://tilde.club/~garret/userscripts/nyaablue.user.js
// which I stole sneedex related code from

const DEX = "https://sneedex.moe"
const CACHE_TIME = 1000*60*60*2; // 2 hours

function log(...rest) {
    console.log("[Mark Sneedex Releases]", ...rest)
}

function gmFetchJson(opts, timeout = 10000) {
    return new Promise((resolve, reject) => {
        GM_xmlhttpRequest({
            ...opts,
            timeout,
            ontimeout: function() {
                reject(new Error(`Request timed out after ${timeout}ms`));
            },
            onerror: function(err) {
                reject(err ? err : new Error('Failed to fetch'))
            },
            onload: function(response) {
                console.log('onload', response)
                resolve(JSON.parse(response.responseText));
            }
        })
    });
}

async function fetchSneedex(route) {
    // cache check
    const lastUpdate = GM_getValue(`cache_last_update_${route}`)
    if (typeof lastUpdate === "number" && Date.now() < lastUpdate + CACHE_TIME) {
        const cached = GM_getValue(`cache_links_${route}`)
        if (Array.isArray(cached)) {
            log(`cache hit for route ${route}`);
            return new Set(cached)
        }
    }

    // fetch api
    log(`fetching sneedex api for route ${route}`);
    const res = await gmFetchJson({
        headers: {
            "Accept": "application/json",
            "User-Agent": "ab-mark-sneedex-releases.user.js"
        },
        method: "GET",
        url: DEX + route
    });
    const links = res.flatMap(e => e.permLinks)
    GM_setValue(`cache_links_${route}`, links)
    GM_setValue(`cache_last_update_${route}`, Date.now())
    return new Set(links)
}

// Thanks to https://github.com/momentary0/AB-Userscripts/blob/master/torrent-highlighter/src/tfm_torrent_highlighter.user.js#L470
// for the handy selectors
function torrentsOnPage() {
    const torrentPageTorrents = [...document.querySelectorAll(
        '.group_torrent>td>a[href*="&torrentid="]'
    )].map(a => ({
        a,
        seperator: a.href.includes('torrents.php') ? ' | ' : ' / '
    }));
    const searchResultTorrents = [...document.querySelectorAll(
        '.torrent_properties>a[href*="&torrentid="]'
    )].map(a => ({
        a,
        seperator: ' | '
    }));
    /*const bbcodeTorrents = [...document.querySelectorAll(
        ':not(.group_torrent)>:not(.torrent_properties)>a[href*="/torrent/"]:not([title])',
    )].map(a => ({
        a,
        seperator: a.href.includes('torrents.php') ? ' | ' : ' / '
    }));*/

    return [...torrentPageTorrents, ...searchResultTorrents]
}

function insertTag(parent, {title, src, alt}) {
    GM_addElement(parent, 'img', {
        src,
        alt,
        title,
    });
}

(async function () {
    try {
        const mainLinks = await fetchSneedex("/api/public/ab")
        const torrents = torrentsOnPage();

        torrents.forEach(t => {
            if (mainLinks.has(t.a.href)) {
                t.a.append(t.seperator);
                insertTag(t.a, {
                    dataAttr: "data-sneedex",
                    title: "This release is sneedex approved",
                    src: "https://ptpimg.me/n40di4.png",
                    alt: "Sneedex Choice!"
                });
            }
        });
    } catch (err) {
        alert(`Failed to fetch sneedex for best releases - ${err.message ? err.message : err}`);
    }
})();