R34 Auto Max Quality

Automatically selects maximum available video quality on tab focus.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==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`);
})();