Auto selects only highest quality resolution available on eporner videos
// ==UserScript==
// @name Eporner highest quality resolution
// @namespace https://violentmonkey.github.io/
// @version 3.1
// @description Auto selects only highest quality resolution available on eporner videos
// @author You
// @match *://*.eporner.com/*
// @grant none
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
// Parses the HLS Master Playlist (.m3u8) and strips out all resolutions except the absolute highest
function filterHLS(text) {
if (!text.includes('#EXT-X-STREAM-INF')) return text;
const lines = text.split('\n');
const streams = [];
let currentInfo = null;
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim();
if (line.startsWith('#EXT-X-STREAM-INF')) {
currentInfo = line;
} else if (currentInfo && line && !line.startsWith('#')) {
streams.push({ info: currentInfo, url: line });
currentInfo = null;
}
}
if (streams.length === 0) return text;
let bestStream = streams[0];
let maxVal = 0;
streams.forEach(stream => {
// Check by Resolution tag (e.g., RESOLUTION=1920x1080)
const resMatch = stream.info.match(/RESOLUTION=\d+x(\d+)/);
if (resMatch) {
const height = parseInt(resMatch[1], 10);
if (height > maxVal) { maxVal = height; bestStream = stream; }
} else {
// Fallback to Bandwidth tag if resolution is missing
const bwMatch = stream.info.match(/BANDWIDTH=(\d+)/);
if (bwMatch) {
const bw = parseInt(bwMatch[1], 10);
if (bw > maxVal) { maxVal = bw; bestStream = stream; }
}
}
});
// Reconstruct the playlist feeding the player ONLY the highest tier
return `#EXTM3U\n${bestStream.info}\n${bestStream.url}\n`;
}
// 1. Intercept Fetch API Requests
const originalFetch = window.fetch;
window.fetch = async function() {
const url = (arguments[0] instanceof Request) ? arguments[0].url : arguments[0];
const response = await originalFetch.apply(this, arguments);
if (typeof url === 'string' && url.includes('.m3u8')) {
const clone = response.clone();
const text = await clone.text();
if (text.includes('#EXT-X-STREAM-INF')) {
const newPlaylist = filterHLS(text);
return new Response(newPlaylist, {
status: response.status,
statusText: response.statusText,
headers: response.headers
});
}
}
return response;
};
// 2. Intercept XMLHttpRequest (Older HLS.js implementations)
const originalOpen = XMLHttpRequest.prototype.open;
const originalSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.open = function(method, url) {
this._isM3u8 = typeof url === 'string' && url.includes('.m3u8');
return originalOpen.apply(this, arguments);
};
XMLHttpRequest.prototype.send = function() {
if (this._isM3u8) {
this.addEventListener('readystatechange', function() {
// When the playlist arrives, overwrite the response text before the video engine reads it
if (this.readyState === 4 && this.responseText && this.responseText.includes('#EXT-X-STREAM-INF')) {
const filteredText = filterHLS(this.responseText);
Object.defineProperty(this, 'responseText', { get: () => filteredText });
if (this.responseType === '' || this.responseType === 'text') {
Object.defineProperty(this, 'response', { get: () => filteredText });
}
}
}, false);
}
return originalSend.apply(this, arguments);
};
})();