Sleazy Fork is available in English.

Rule34Video 2160p y 1080p Filter (Optimized)

Filtra videos 2160p y 1080p en Rule34Video, ocultando los que no coinciden con la calidad seleccionada.

// ==UserScript==
// @name         Rule34Video 2160p y 1080p Filter (Optimized)
// @namespace    http://tampermonkey.net/
// @version      2.2
// @description  Filtra videos 2160p y 1080p en Rule34Video, ocultando los que no coinciden con la calidad seleccionada.
// @author       Luis123456xp (Optimized by GPT)
// @license      MIT
// @match        https://rule34video.com/*
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @run-at       document-end
// @connect      sleazyfork.org
// ==/UserScript==

(async function($) {
    'use strict';

    const currentVersion = '2.2';
    const scriptUrl = 'https://sleazyfork.org/es/scripts/496806-rule34video-2160p-y-1080p-filter/code';
    const userLang = navigator.language || navigator.userLanguage;
    const isEnglish = userLang.startsWith('en');
    const MAX_CONCURRENT_REQUESTS = 20; // Aumentar concurrencia puede acelerar las cosas.

    // Función para comparar versiones
    function compareVersions(v1, v2) {
        const v1parts = v1.split('.').map(Number);
        const v2parts = v2.split('.').map(Number);
        for (let i = 0; i < Math.max(v1parts.length, v2parts.length); i++) {
            if ((v1parts[i] || 0) > (v2parts[i] || 0)) return 1;
            if ((v1parts[i] || 0) < (v2parts[i] || 0)) return -1;
        }
        return 0;
    }

    // Verificar si hay una nueva versión disponible
    GM_xmlhttpRequest({
        method: 'GET',
        url: scriptUrl,
        onload: function(response) {
            const match = response.responseText.match(/@version\s+(\d+\.\d+)/);
            if (match) {
                const latestVersion = match[1];
                if (compareVersions(latestVersion, currentVersion) > 0) {
                    $('body').prepend(`
                        <div id="updateNotification" style="position:fixed; top:0; left:0; width:100%; background-color:yellow; z-index:9999; text-align:center; padding:10px;">
                            ${isEnglish ? 'A new version of the script is available. --Rule34Video 2160p y 1080p Filter--' : 'Hay una nueva versión disponible del script. --Rule34Video 2160p y 1080p Filter--'} <a href="${scriptUrl}" target="_blank">${isEnglish ? 'Click here to update' : 'Haz clic aquí para actualizar'}.</a>
                        </div>
                    `);
                }
            }
        }
    });

    // Crear botones de filtrado
    const button2160p = $(`<button id="search2160pButton" style="position:fixed; top:10px; right:10px; z-index:9999;">${isEnglish ? 'Filter 2160p' : 'Filtrar 2160p'}</button>`);
    const button1080p = $(`<button id="search1080pButton" style="position:fixed; top:50px; right:10px; z-index:9999;">${isEnglish ? 'Filter 1080p' : 'Filtrar 1080p'}</button>`);
    $('body').append(button2160p, button1080p);

    let currentQuality = '';

    $('#search2160pButton').on('click', function() {
        currentQuality = '2160p';
        filterVideos(currentQuality);
    });

    $('#search1080pButton').on('click', function() {
        currentQuality = '1080p';
        filterVideos(currentQuality);
    });

    async function filterVideos(quality) {
        console.log(`${isEnglish ? 'Starting video filter with quality:' : 'Iniciando filtrado de videos con calidad:'} ${quality}`);

        // Recopilar todos los enlaces y referencias a los elementos
        const videoElements = $('.item.thumb').has('a[href*="/video/"]');
        const videoData = videoElements.map(function() {
            const link = $(this).find('a[href*="/video/"]').attr('href');
            return {
                element: $(this),
                link: link
            };
        }).get();

        console.log(`${isEnglish ? 'Total videos found:' : 'Total de videos encontrados:'} ${videoData.length}`);

        // Mostrar mensaje de carga
        const loadingDiv = $(`
            <div id="loadingMessage" style="position:fixed; top:50%; left:50%;
            transform:translate(-50%, -50%); z-index:9999; background-color: yellow; padding: 10px; font-size: 20px;">
                ${isEnglish ? 'Filtering videos...' : 'Filtrando videos...'}
            </div>
        `);
        $('body').append(loadingDiv);

        let matchCount = 0;
        let processedCount = 0;

        // Función auxiliar para procesar un video
        async function processVideo(videoInfo) {
            const html = await fetchPageHTML(videoInfo.link);
            const hasQuality = html.includes(quality);
            if (!hasQuality) {
                videoInfo.element.hide();
            } else {
                matchCount++;
            }
            processedCount++;
            // Actualiza el mensaje de progreso
            $('#loadingMessage').text(`${isEnglish ? 'Filtering...' : 'Filtrando...'} ${processedCount}/${videoData.length}`);
        }

        // Crear una cola para controlar la concurrencia
        const queue = [...videoData];
        const workers = [];

        for (let i = 0; i < MAX_CONCURRENT_REQUESTS; i++) {
            workers.push((async () => {
                while (queue.length > 0) {
                    const item = queue.shift();
                    if (item) await processVideo(item);
                }
            })());
        }

        await Promise.all(workers);

        // Filtrado completado
        $('#loadingMessage').text(`${isEnglish ? 'Filtering complete. Videos matching' : 'Filtrado completado. Videos que coinciden con'} ${quality}: ${matchCount}`);
        setTimeout(() => { $('#loadingMessage').remove(); }, 3000);
        console.log(isEnglish ? 'Filtering complete.' : 'Filtrado completado.');
    }

    // Función para obtener el HTML de una página
    function fetchPageHTML(url) {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: 'GET',
                url: url,
                onload: function(response) {
                    if (response.status === 200) {
                        resolve(response.responseText);
                    } else {
                        reject(new Error('Request failed: ' + response.status));
                    }
                },
                onerror: reject
            });
        });
    }

})(window.jQuery);