Automatically selects maximum available video quality on tab focus.
// ==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`);
})();