Automatically selects the highest quality in a video players on many p*rnsites (hybrid API + UI version), includong Noodlemagazine
// ==UserScript==
// @name Noodlemagazine auto HD
// @namespace Streaming AutoHD
// @version 1.001
// @description Automatically selects the highest quality in a video players on many p*rnsites (hybrid API + UI version), includong Noodlemagazine
// @author Claude
// @license MIT
// @match *://*/*
// @grant unsafeWindow
// @allFrames true
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
let qualitySet = false;
let apiAttempts = 0;
const MAX_API_ATTEMPTS = 10;
const MAX_UI_ATTEMPTS = 15;
// METODA 1: Próba przez API JW Player
function tryAPIMethod() {
if (apiAttempts >= MAX_API_ATTEMPTS || qualitySet) return;
apiAttempts++;
const jw = (typeof unsafeWindow !== 'undefined' && unsafeWindow.jwplayer) || window.jwplayer;
if (typeof jw !== 'function') return;
try {
// Szukamy wszystkich możliwych instancji
const containers = document.querySelectorAll('.jwplayer, [id^="jwplayer"], [id*="player"]');
containers.forEach(container => {
try {
const player = jw(container.id) || jw(0);
if (!player || typeof player.getQualityLevels !== 'function') return;
const setMaxQuality = () => {
const levels = player.getQualityLevels();
if (!levels || levels.length <= 1) return;
let highestIndex = -1;
let maxVal = -1;
levels.forEach((level, index) => {
// Pomijamy "Auto"
if (level.label && level.label.toLowerCase().includes('auto')) return;
const currentRes = level.height || parseInt(level.label) || level.bitrate || 0;
if (currentRes > maxVal) {
maxVal = currentRes;
highestIndex = index;
}
});
if (highestIndex !== -1 && player.getCurrentQuality() !== highestIndex) {
player.setCurrentQuality(highestIndex);
console.log('[JW Auto Quality] API: Ustawiono najwyższą jakość (indeks ' + highestIndex + ')');
qualitySet = true;
}
};
// Podpinamy się pod zdarzenia
player.on('levels', setMaxQuality);
player.on('levelsChanged', setMaxQuality);
player.on('playlistItem', setMaxQuality);
player.on('ready', setMaxQuality);
// Próba natychmiastowa
setMaxQuality();
} catch (err) {
// Cicha obsługa błędów
}
});
// Jeśli nie ma kontenerów, próbujemy jwplayer(0)
if (containers.length === 0) {
try {
const player = jw(0);
if (player && typeof player.getQualityLevels === 'function') {
const levels = player.getQualityLevels();
if (levels && levels.length > 1) {
let highestIndex = 0;
let maxVal = 0;
levels.forEach((level, index) => {
if (level.label && level.label.toLowerCase().includes('auto')) return;
const res = level.height || parseInt(level.label) || 0;
if (res > maxVal) {
maxVal = res;
highestIndex = index;
}
});
if (player.getCurrentQuality() !== highestIndex) {
player.setCurrentQuality(highestIndex);
console.log('[JW Auto Quality] API: Ustawiono najwyższą jakość');
qualitySet = true;
}
}
}
} catch (err) {
// Cicha obsługa błędów
}
}
} catch (err) {
// Cicha obsługa błędów
}
}
// METODA 2: Klikanie w UI (backup gdy API nie działa)
function tryUIMethod() {
if (qualitySet) return;
// Szukamy przycisku ustawień
const settingsBtn = document.querySelector('.jw-icon-settings, .jw-settings-menu button');
if (!settingsBtn) return;
// Sprawdzamy czy menu jest otwarte
let menu = document.querySelector('.jw-settings-menu, .jw-settings-content');
const menuVisible = menu && menu.offsetParent !== null;
if (!menuVisible) {
settingsBtn.click();
}
setTimeout(() => {
// Szukamy opcji Quality/Jakość
const findByText = (selector, texts) => {
const elements = document.querySelectorAll(selector);
return Array.from(elements).find(el => {
const text = el.textContent.trim().toLowerCase();
return texts.some(t => text.includes(t.toLowerCase()));
});
};
const qualityBtn = findByText('.jw-settings-item, .jw-menu-item', ['quality', 'jakość', 'qualität']);
if (qualityBtn) {
qualityBtn.click();
setTimeout(() => {
const items = document.querySelectorAll('.jw-settings-item, .jw-menu-item');
let highestItem = null;
let maxRes = 0;
items.forEach(item => {
const text = item.textContent.trim();
// Pomijamy "Auto"
if (text.toLowerCase().includes('auto')) return;
const res = parseInt(text);
if (!isNaN(res) && res > maxRes) {
maxRes = res;
highestItem = item;
}
});
if (highestItem && !highestItem.classList.contains('jw-settings-item-active')) {
highestItem.click();
console.log('[JW Auto Quality] UI: Kliknięto najwyższą jakość (' + maxRes + 'p)');
qualitySet = true;
// Zamykamy menu
setTimeout(() => {
if (settingsBtn) settingsBtn.click();
}, 200);
}
}, 400);
}
}, 300);
}
// Główna pętla sprawdzająca
let attempts = 0;
const checkInterval = setInterval(() => {
attempts++;
// Sprawdzamy czy video istnieje i jest gotowe
const video = document.querySelector('video');
const videoReady = video && video.readyState >= 2;
if (videoReady && !qualitySet) {
// Najpierw próbujemy API
tryAPIMethod();
// Jeśli po 5 próbach API nie zadziałało, próbujemy UI
if (apiAttempts >= 5 && !qualitySet) {
tryUIMethod();
}
}
// Zatrzymujemy po 30 sekundach lub gdy jakość została ustawiona
if (attempts >= MAX_UI_ATTEMPTS || qualitySet) {
clearInterval(checkInterval);
if (qualitySet) {
console.log('[JW Auto Quality] Skrypt zakończył pracę - jakość ustawiona');
}
}
}, 2000);
// Dodatkowe nasłuchiwanie na dynamiczne ładowanie
if (window.MutationObserver) {
const observer = new MutationObserver(() => {
if (!qualitySet && document.querySelector('video')) {
tryAPIMethod();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
// Zatrzymujemy observer po 30 sekundach
setTimeout(() => observer.disconnect(), 30000);
}
})();