R34 Auto Max Quality

Automatically selects maximum available video quality on tab focus.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         R34 Auto Max Quality
// @namespace    r34-auto-max-quality
// @version      2.0
// @description  Automatically selects maximum available video quality on tab focus.
// @description:ru Автоматически выбирает максимальное доступное качество видео при фокусе вкладки.
// @author       Grok Assisted
// @match        https://rule34video.com/video/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=rule34video.com
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    // Максимальное желаемое качество — меняй здесь / Maximum desired quality — change here
    // 5 = 4K, 4 = 1080p, 3 = 720p, 2 = 480p, 1 = 360p
    const MAX_QUALITY = 4;

    const FORMATS = [5, 4, 3, 2, 1]; // Список форматов от высокого к низкому / Format list from high to low

    // Получает текущий выбранный формат из DOM / Gets currently selected format from DOM
    function getSelectedFormat() {
        const sel = document.querySelector('.fp-settings-list-item.is-selected a[data-format]');
        return sel ? parseInt(sel.getAttribute('data-format')) : 0;
    }

    // Определяет реальное качество по суффиксу src видео / Determines real quality from video src suffix
    function getRealFormatFromSrc() {
        const vid = document.querySelector('video.fp-engine');
        if (!vid || !vid.src) return 0;

        const src = vid.src;
        if (src.includes('_2160p.mp4')) return 5;
        if (src.includes('_1080p.mp4')) return 4;
        if (src.includes('_720p.mp4'))  return 3;
        if (src.includes('_480p.mp4'))  return 2;
        if (src.includes('_360.mp4'))   return 1;
        return 0;
    }

    // Находит самый высокий доступный формат ≤ MAX_QUALITY / Finds highest available format ≤ MAX_QUALITY
    function getMaxAvailable() {
        for (let fmt of FORMATS) {
            if (fmt > MAX_QUALITY) continue;
            if (document.querySelector(`a[data-format="${fmt}"]`)) return fmt;
        }
        return 1;
    }

    // Кликает по кнопке качества / Clicks quality button
    function clickQuality(fmt) {
        const btn = document.querySelector(`a[data-format="${fmt}"]`);
        if (!btn) return false;

        // Убираем tooltip, если курсор над timeline / Remove tooltip if cursor over timeline
        const timeline = document.querySelector('.fp-timeline');
        if (timeline) {
            timeline.dispatchEvent(new MouseEvent('mouseleave', { bubbles: true }));
        }

        // Открываем меню качества, если оно закрыто / Open quality menu if closed
        const settingsBtn = document.querySelector('a.fp-settings');
        if (settingsBtn && !document.querySelector('.fp-settings-list.is-open')) {
            settingsBtn.click();
        }

        btn.click();
        console.log(`[R34-Q] Кликнули ${fmt}p / Clicked ${fmt}p`);
        return true;
    }

    // Основная функция синхронизации качества / Main quality sync function
    function syncQuality(attempt = 1) {
        if (document.visibilityState !== 'visible') return;

        const selected = getSelectedFormat();
        const real    = getRealFormatFromSrc();
        const target  = getMaxAvailable();

        console.log(`[R34-Q] Попытка ${attempt} | Выбрано: ${selected}, Реально: ${real}, Цель: ${target} / Attempt ${attempt} | Selected: ${selected}, Real: ${real}, Target: ${target}`);

        if (real === target) {
            console.log('[R34-Q] Качество совпало с максимумом / Quality matches max');
            return;
        }

        if (attempt > 20) {
            console.log('[R34-Q] Лимит попыток (20), останавливаюсь / Max attempts (20) reached, stopping');
            return;
        }

        if (clickQuality(target)) {
            setTimeout(() => syncQuality(attempt + 1), 1800);
        } else {
            setTimeout(() => syncQuality(attempt + 1), 1200);
        }
    }

    // Срабатывание при фокусе вкладки / Trigger on tab focus
    document.addEventListener('visibilitychange', () => {
        if (document.visibilityState === 'visible') {
            setTimeout(() => syncQuality(1), 1000);
        }
    });

    // Первичная проверка, если вкладка уже активна / Initial check if tab is already visible
    if (document.visibilityState === 'visible') {
        setTimeout(() => syncQuality(1), 4000);
    }

    console.log(`[R34-Q] Скрипт запущен, максимум: ${MAX_QUALITY}p / Script active, max: ${MAX_QUALITY}p`);
})();