Auto-play video thumbnails with playback speed control and pause functionality on adult sites
// ==UserScript==
// @name Auto-play video thumbnails
// @namespace https://greasyfork.org/users/1168969
// @version 2.0.3.1
// @description Auto-play video thumbnails with playback speed control and pause functionality on adult sites
// @author 6969RandomGuy6969
// @match https://www.sxyprn.com/*
// @match https://sxyprn.com/*
// @match https://watchporn.to/*
// @match https://yesporn.vip/*
// @match https://www.theyarehuge.com/*
// @match https://www.eporner.com/*
// @match https://www.shyfap.net/*
// @match https://www.wow.xxx/*
// @match https://pornone.com/*
// @match https://www.tnaflix.com/*
// @match https://www.pornhits.com/*
// @match https://hqporner.com/*
// @match https://www.hqporner.com/*
// @match https://m.hqporner.com/*
// @match https://pornmz.com/*
// @match https://youperv.com/*
// @match https://*.youperv.com/*
// @match https://superporn.com/*
// @match https://www.superporn.com/*
// @grant GM_registerMenuCommand
// @grant GM_openInTab
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// @connect *
// @icon https://cdn-icons-png.flaticon.com/512/3998/3998861.png
// ==/UserScript==
(function () {
'use strict';
const SETTINGS = {
playbackSpeed: GM_getValue('playbackSpeed', 1),
isPaused: GM_getValue('isPaused', false),
panelX: GM_getValue('panelX', null),
panelY: GM_getValue('panelY', null)
};
const videoRegistry = new Set();
let configPanel = null;
const visibleVideos = new Set();
const globalPlayObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
const video = entry.target;
if (entry.isIntersecting) {
visibleVideos.add(video);
if (!SETTINGS.isPaused && typeof video.play === 'function') video.play().catch(() => {});
} else {
visibleVideos.delete(video);
if (typeof video.pause === 'function') video.pause();
}
});
}, { rootMargin: '300px', threshold: 0.01 });
// Block site's JS hover previews on handled cards to prevent disruption
['mouseenter', 'mouseleave', 'mouseover', 'mouseout', 'mousemove'].forEach(evt => {
document.addEventListener(evt, e => {
if (e.target instanceof Element && e.target.closest('.apt-handled')) {
e.stopPropagation();
}
}, true);
});
function updateAllVideos() {
videoRegistry.forEach(video => {
if (video && video.parentNode) {
if (typeof video.playbackRate !== 'undefined') {
video.playbackRate = SETTINGS.playbackSpeed;
}
if (SETTINGS.isPaused) {
if (typeof video.pause === 'function') video.pause();
} else {
if (visibleVideos.has(video)) {
if (typeof video.play === 'function') video.play().catch(() => {});
}
}
}
});
}
function setPlaybackSpeed(speed) {
speed = Math.max(0.25, Math.min(2, speed));
SETTINGS.playbackSpeed = speed;
GM_setValue('playbackSpeed', speed);
updateAllVideos();
updatePanelDisplay();
}
function togglePause() {
SETTINGS.isPaused = !SETTINGS.isPaused;
GM_setValue('isPaused', SETTINGS.isPaused);
updateAllVideos();
updatePanelDisplay();
}
function updatePanelDisplay() {
if (!configPanel) return;
const speedDisplay = configPanel.querySelector('.speed-display');
const pauseBtn = configPanel.querySelector('.pause-btn');
if (speedDisplay) speedDisplay.textContent = `${SETTINGS.playbackSpeed.toFixed(2)}x`;
if (pauseBtn) pauseBtn.textContent = SETTINGS.isPaused ? '▶️ Play' : '⏸️ Pause';
}
function createConfigPanel() {
if (configPanel) {
configPanel.style.display = 'block';
return;
}
const panel = document.createElement('div');
panel.id = 'video-config-panel';
panel.innerHTML = `
<div class="panel-header">
<span class="panel-title">Thumbnail Control</span>
<button class="close-btn">×</button>
</div>
<div class="panel-body">
<div class="speed-control">
<button class="speed-btn minus-btn">−</button>
<span class="speed-display">${SETTINGS.playbackSpeed.toFixed(2)}x</span>
<button class="speed-btn plus-btn">+</button>
</div>
<button class="pause-btn">${SETTINGS.isPaused ? '▶️ Play' : '⏸️ Pause'}</button>
</div>
`;
const style = document.createElement('style');
style.textContent = `
#video-config-panel {
position: fixed;
z-index: 999999;
background: rgba(20, 20, 20, 0.95);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 12px;
padding: 0;
font-family: Arial, sans-serif;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
user-select: none;
min-width: 160px;
max-width: 200px;
}
#video-config-panel .panel-header {
background: rgba(40, 40, 40, 0.8);
padding: 8px 10px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
justify-content: space-between;
align-items: center;
cursor: move;
border-radius: 11px 11px 0 0;
}
#video-config-panel .panel-title {
color: #fff;
font-size: 12px;
font-weight: bold;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
white-space: nowrap;
}
#video-config-panel .close-btn {
background: rgba(255, 255, 255, 0.1);
border: none;
color: #fff;
font-size: 20px;
font-weight: bold;
cursor: pointer;
padding: 0;
width: 22px;
height: 22px;
line-height: 20px;
border-radius: 4px;
transition: all 0.2s;
flex-shrink: 0;
}
#video-config-panel .close-btn:hover {
background: rgba(255, 68, 68, 0.8);
box-shadow: 0 0 10px rgba(255, 68, 68, 0.5);
}
#video-config-panel .panel-body {
padding: 12px;
background: rgba(30, 30, 30, 0.5);
border-radius: 0 0 11px 11px;
}
#video-config-panel .speed-control {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
margin-bottom: 10px;
}
#video-config-panel .speed-btn {
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.2);
color: #fff;
font-size: 18px;
font-weight: bold;
width: 32px;
height: 32px;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s;
padding: 0;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
display: flex;
align-items: center;
justify-content: center;
}
#video-config-panel .speed-btn:hover {
background: rgba(255, 255, 255, 0.2);
border-color: rgba(255, 255, 255, 0.3);
box-shadow: 0 0 10px rgba(255, 255, 255, 0.2);
}
#video-config-panel .speed-btn:active { transform: scale(0.95); }
#video-config-panel .speed-display {
color: #fff;
font-size: 14px;
font-weight: bold;
min-width: 50px;
text-align: center;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
}
#video-config-panel .pause-btn {
width: 100%;
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.2);
color: #fff;
padding: 8px;
font-size: 13px;
font-weight: 600;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}
#video-config-panel .pause-btn:hover {
background: rgba(255, 255, 255, 0.2);
border-color: rgba(255, 255, 255, 0.3);
box-shadow: 0 0 10px rgba(255, 255, 255, 0.2);
}
#video-config-panel .pause-btn:active { transform: scale(0.98); }
@media (max-width: 600px) {
#video-config-panel { min-width: 140px; max-width: 160px; }
#video-config-panel .panel-header { padding: 6px 8px; }
#video-config-panel .panel-title { font-size: 11px; }
#video-config-panel .close-btn { width: 20px; height: 20px; font-size: 18px; }
#video-config-panel .panel-body { padding: 8px; }
#video-config-panel .speed-btn { width: 28px; height: 28px; font-size: 16px; }
#video-config-panel .speed-display { font-size: 12px; min-width: 40px; }
#video-config-panel .pause-btn { padding: 6px; font-size: 12px; }
}
@media (max-width: 400px) {
#video-config-panel { min-width: 120px; max-width: 140px; }
#video-config-panel .speed-control { gap: 4px; }
#video-config-panel .speed-btn { width: 24px; height: 24px; font-size: 14px; }
#video-config-panel .speed-display { font-size: 11px; min-width: 35px; }
}
`;
document.head.appendChild(style);
document.body.appendChild(panel);
configPanel = panel;
const panelWidth = 200;
const panelHeight = 120;
const margin = 10;
if (SETTINGS.panelX !== null && SETTINGS.panelY !== null) {
const maxX = window.innerWidth - panelWidth - margin;
const maxY = window.innerHeight - panelHeight - margin;
panel.style.left = Math.max(margin, Math.min(SETTINGS.panelX, maxX)) + 'px';
panel.style.top = Math.max(margin, Math.min(SETTINGS.panelY, maxY)) + 'px';
} else {
panel.style.right = Math.min(20, window.innerWidth - panelWidth - margin) + 'px';
panel.style.bottom = Math.min(20, window.innerHeight - panelHeight - margin) + 'px';
}
panel.querySelector('.close-btn').addEventListener('click', () => { panel.style.display = 'none'; });
panel.querySelector('.minus-btn').addEventListener('click', () => { setPlaybackSpeed(SETTINGS.playbackSpeed - 0.25); });
panel.querySelector('.plus-btn').addEventListener('click', () => { setPlaybackSpeed(SETTINGS.playbackSpeed + 0.25); });
panel.querySelector('.pause-btn').addEventListener('click', togglePause);
// Draggable
let isDragging = false, currentX, currentY, initialX, initialY;
const header = panel.querySelector('.panel-header');
header.addEventListener('mousedown', e => {
if (e.target.classList.contains('close-btn')) return;
isDragging = true;
initialX = e.clientX - (SETTINGS.panelX || panel.offsetLeft);
initialY = e.clientY - (SETTINGS.panelY || panel.offsetTop);
});
document.addEventListener('mousemove', e => {
if (!isDragging) return;
e.preventDefault();
const rect = panel.getBoundingClientRect();
const maxX = window.innerWidth - rect.width - margin;
const maxY = window.innerHeight - rect.height - margin;
currentX = Math.max(margin, Math.min(e.clientX - initialX, maxX));
currentY = Math.max(margin, Math.min(e.clientY - initialY, maxY));
panel.style.left = currentX + 'px';
panel.style.top = currentY + 'px';
panel.style.right = 'auto';
panel.style.bottom = 'auto';
});
document.addEventListener('mouseup', () => {
if (isDragging) {
SETTINGS.panelX = currentX || panel.offsetLeft;
SETTINGS.panelY = currentY || panel.offsetTop;
GM_setValue('panelX', SETTINGS.panelX);
GM_setValue('panelY', SETTINGS.panelY);
}
isDragging = false;
});
window.addEventListener('resize', () => {
if (!configPanel || configPanel.style.display === 'none') return;
const rect = configPanel.getBoundingClientRect();
let newX = rect.left, newY = rect.top, needs = false;
if (rect.right > window.innerWidth - margin) { newX = window.innerWidth - rect.width - margin; needs = true; }
if (rect.left < margin) { newX = margin; needs = true; }
if (rect.bottom > window.innerHeight - margin) { newY = window.innerHeight - rect.height - margin; needs = true; }
if (rect.top < margin) { newY = margin; needs = true; }
if (needs) {
configPanel.style.left = newX + 'px'; configPanel.style.top = newY + 'px';
configPanel.style.right = 'auto'; configPanel.style.bottom = 'auto';
SETTINGS.panelX = newX; SETTINGS.panelY = newY;
GM_setValue('panelX', newX); GM_setValue('panelY', newY);
}
});
}
// ==================== GM MENU ====================
GM_registerMenuCommand('⚙️ Open Config UI', createConfigPanel);
// ── Supported Sites ──
GM_registerMenuCommand('🌐 Sxyprn', () => GM_openInTab('https://sxyprn.com', { active: true }));
GM_registerMenuCommand('🌐 WatchPorn', () => GM_openInTab('https://watchporn.to', { active: true }));
GM_registerMenuCommand('🌐 YesPorn', () => GM_openInTab('https://yesporn.vip', { active: true }));
GM_registerMenuCommand('🌐 TheyAreHuge', () => GM_openInTab('https://www.theyarehuge.com', { active: true }));
GM_registerMenuCommand('🌐 Eporner', () => GM_openInTab('https://www.eporner.com', { active: true }));
GM_registerMenuCommand('🌐 ShyFap', () => GM_openInTab('https://www.shyfap.net', { active: true }));
GM_registerMenuCommand('🌐 Wow.xxx', () => GM_openInTab('https://www.wow.xxx', { active: true }));
GM_registerMenuCommand('🌐 Pornone', () => GM_openInTab('https://pornone.com', { active: true }));
GM_registerMenuCommand('🌐 Tnaflix', () => GM_openInTab('https://www.tnaflix.com', { active: true }));
GM_registerMenuCommand('🌐 PornHits', () => GM_openInTab('https://www.pornhits.com', { active: true }));
GM_registerMenuCommand('🌐 HQPorner', () => GM_openInTab('https://hqporner.com', { active: true }));
GM_registerMenuCommand('🌐 PornMZ', () => GM_openInTab('https://pornmz.com', { active: true }));
GM_registerMenuCommand('🌐 YouPerv', () => GM_openInTab('https://youperv.com', { active: true }));
GM_registerMenuCommand('🌐 SuperPorn', () => GM_openInTab('https://www.superporn.com', { active: true }));
// ── Script Links ──
GM_registerMenuCommand('🔞 More Scripts (Sleazyfork)', () => {
GM_openInTab('https://sleazyfork.org/en/users/1168969-6969randomguy6969', { active: true });
});
GM_registerMenuCommand('📜 More Scripts (Greasyfork)', () => {
GM_openInTab('https://greasyfork.org/en/users/1168969-6969randomguy6969', { active: true });
});
// ==================== CORE FUNCTIONALITY ====================
const hostname = window.location.hostname;
// ---- FIX 1: Don't hide the image until the video is actually ready to play ----
// ---- FIX 2: Keep the image visible as fallback if video fails ----
function insertPreviewVideo(image, videoUrl) {
if (!videoUrl) return;
if (image.dataset.previewAttached) return;
image.dataset.previewAttached = '1';
const card = image.closest('a, article, .thumb, .card, .post, .mb, .media-card_preview') || image.parentNode;
if (card) card.classList.add('apt-handled');
const video = document.createElement('video');
video.src = videoUrl;
video.muted = true;
video.loop = true;
video.playsInline = true;
video.preload = 'auto';
video.playbackRate = SETTINGS.playbackSpeed;
video.style.cssText = 'width:100%;height:100%;object-fit:cover;position:absolute;top:0;left:0;z-index:10;pointer-events:none;';
video.setAttribute('importance', 'high');
video.setAttribute('fetchpriority', 'high');
videoRegistry.add(video);
const parent = image.parentNode;
parent.style.position = 'relative';
parent.appendChild(video);
const showVideo = () => {
video.style.opacity = '1';
image.style.opacity = '0';
if (!SETTINGS.isPaused && visibleVideos.has(video)) video.play().catch(() => {});
};
// Try canplay first
video.addEventListener('canplay', showVideo, { once: true });
// Fallback: if canplay doesn't fire in 800ms, show anyway
// (site JS may suppress the event by manipulating the element)
const fallbackTimer = setTimeout(() => {
video.removeEventListener('canplay', showVideo);
showVideo();
}, 800);
video.addEventListener('canplay', () => clearTimeout(fallbackTimer), { once: true });
video.load();
globalPlayObserver.observe(video);
video.onerror = () => {
clearTimeout(fallbackTimer);
globalPlayObserver.unobserve(video);
visibleVideos.delete(video);
videoRegistry.delete(video);
video.remove();
image.style.opacity = '1';
};
}
// IntersectionObserver wrapper
const activeObservers = new Set();
function observeElements(selector, getUrl) {
// Don't set up duplicate observers for the same selector
if (activeObservers.has(selector)) return;
activeObservers.add(selector);
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const el = entry.target;
const url = getUrl(el);
if (url) insertPreviewVideo(el, url);
observer.unobserve(el);
}
});
}, { rootMargin: '500px', threshold: 0.01 });
const observedElements = new WeakSet();
function watch() {
document.querySelectorAll(selector).forEach(el => {
if (!observedElements.has(el)) {
observer.observe(el);
observedElements.add(el);
}
});
}
watch();
let mutationTimeout;
new MutationObserver(() => {
clearTimeout(mutationTimeout);
mutationTimeout = setTimeout(watch, 100);
}).observe(document.body, { childList: true, subtree: true });
setTimeout(watch, 500);
setTimeout(watch, 1500);
}
// ==================== SITE HANDLERS ====================
const siteHandlers = {
"eporner.com": function () {
function getPreviewUrl(id) {
const s = id.toString();
if (s.length < 5) return null;
return `https://static-eu-cdn.eporner.com/thumbs/static4/${s[0]}/${s.slice(0,2)}/${s.slice(0,3)}/${s}/${s}-preview.webm`;
}
function initThumb(thumb) {
if (thumb.dataset.epInit) return;
thumb.dataset.epInit = '1';
thumb.classList.add('apt-handled');
const url = getPreviewUrl(thumb.dataset.id);
if (!url) return;
let vid = thumb.querySelector('video');
if (!vid) {
vid = document.createElement('video');
vid.muted = true;
vid.loop = true;
vid.playsInline = true;
vid.preload = 'auto';
vid.style.cssText = 'position:absolute !important;inset:0 !important;width:100% !important;height:100% !important;object-fit:cover !important;z-index:10 !important;background:#000;opacity:1 !important;pointer-events:none;';
const cont = thumb.querySelector('.mbimg, .mbcontent') || thumb;
cont.style.position = 'relative';
cont.style.overflow = 'hidden';
cont.appendChild(vid);
}
if (vid.src !== url) {
vid.removeAttribute('src');
vid.src = url;
vid.load();
}
// Register for global pause/speed control
videoRegistry.add(vid);
vid.playbackRate = SETTINGS.playbackSpeed;
globalPlayObserver.observe(vid);
}
// Hide static img/badges so video shows through
const style = document.createElement('style');
style.textContent = `.mb img,.mvhdico,[style*="ajax_loader"]{opacity:0 !important;pointer-events:none !important}.mb .mbimg,.mb .mbcontent{background:#000 !important}`;
document.head.appendChild(style);
// Process existing cards
document.querySelectorAll('div.mb[data-id]').forEach(initThumb);
// Watch for new cards (infinite scroll / AJAX)
new MutationObserver(() => {
document.querySelectorAll('div.mb[data-id]:not([data-ep-init])').forEach(initThumb);
}).observe(document.body, { childList: true, subtree: true });
// Safety interval for any missed cards
setInterval(() => {
document.querySelectorAll('div.mb[data-id]').forEach(initThumb);
}, 4000);
},
"sxyprn.com": function () {
function watchSxy() {
document.querySelectorAll('.mini_post_vid_thumb').forEach(img => {
if (img.dataset.sxInit) return;
img.dataset.sxInit = '1';
let handled = false;
const video = img.nextElementSibling;
if (video && video.tagName === 'VIDEO') {
// Strip inline JS that restricts playback (e.g., hvponplay)
video.removeAttribute('onplay');
video.removeAttribute('onpause');
video.preload = 'auto';
// Force it to be visible without overriding native layout dimensions
video.style.display = 'block';
video.style.opacity = '1';
video.style.pointerEvents = 'none'; // Ensure clicks hit the wrapper
img.style.opacity = '0';
const src = video.getAttribute('src') || video.getAttribute('data-src') || video.dataset.src;
if (src && !video.getAttribute('src')) {
video.setAttribute('src', src);
}
if (src || video.currentSrc || video.querySelector('source')) {
handled = true;
if (typeof video.playbackRate !== 'undefined') {
video.playbackRate = SETTINGS.playbackSpeed;
}
videoRegistry.add(video);
globalPlayObserver.observe(video);
}
} else {
// Fallback for elements without native video tag
const fallbackSrc = img.getAttribute('data-video') || img.getAttribute('data-preview');
if (fallbackSrc) {
handled = true;
insertPreviewVideo(img, fallbackSrc);
}
}
if (handled) {
const card = img.closest('a, .post_el') || img.parentNode;
if (card) card.classList.add('apt-handled');
}
});
}
watchSxy();
new MutationObserver(watchSxy).observe(document.body, { childList: true, subtree: true });
setInterval(watchSxy, 5000);
},
"watchporn.to": () =>
observeElements('img[data-preview]', el => el.getAttribute('data-preview')),
"yesporn.vip": () =>
observeElements('img[data-preview]', el => el.getAttribute('data-preview')),
"theyarehuge.com": function () {
observeElements('img[data-preview]', el => el.getAttribute('data-preview'));
const style = document.createElement('style');
style.textContent = `
body, html { background-color:#000 !important; color:#d1d1d1 !important; }
* { background-color:transparent !important; border-color:#444 !important; color:inherit !important; }
a, p, h1, h2, h3, h4, h5, h6, span, div { color:#d1d1d1 !important; }
img, video { filter:brightness(0.95) contrast(1.1); }
.header, .footer, .sidebar, .navbar, .top-menu, .main-header { background-color:#000 !important; }
`;
document.head.appendChild(style);
const logo = document.querySelector('img[src*="tah-logo-m.png"]');
if (logo) logo.style.filter = 'invert(1) hue-rotate(-180deg) brightness(1) saturate(10)';
},
"shyfap.net": function () {
function watchShyfap() {
document.querySelectorAll('.media-card_preview').forEach(card => {
if (card.dataset.sfInit) return;
card.dataset.sfInit = '1';
const videoUrl = card.getAttribute('data-preview');
const video = card.querySelector('video');
const img = card.querySelector('img');
let handled = false;
if (video) {
handled = true;
video.muted = true;
video.loop = true;
video.playsInline = true;
video.preload = 'auto';
video.playbackRate = SETTINGS.playbackSpeed;
video.style.width = '100%';
video.style.height = '100%';
video.style.objectFit = 'cover';
video.style.pointerEvents = 'none';
videoRegistry.add(video);
if (img) img.style.display = 'none';
globalPlayObserver.observe(video);
} else if (img && videoUrl) {
handled = true;
insertPreviewVideo(img, videoUrl);
}
if (handled) card.classList.add('apt-handled');
});
}
watchShyfap();
new MutationObserver(watchShyfap).observe(document.body, { childList: true, subtree: true });
setInterval(watchShyfap, 5000);
},
"wow.xxx": function () {
observeElements('.thumb__img[data-preview] img', img => {
const container = img.closest('.thumb__img');
return container ? container.getAttribute('data-preview') : null;
});
},
"pornone.com": function () {
// pornone.com has NO mp4 previews — it cycles JPG frames from data-thumbs.
// Frame URL: {data-path}d{thumbNum}.jpg
// The site's own showImage() cycles every 800ms; we replicate it autonomously,
// respecting isPaused and mapping playbackSpeed -> interval delay.
// Speed 1x=800ms, 2x=400ms, 0.5x=1600ms, etc.
const pnCyclers = new Map(); // img el -> { timer }
function getIntervalMs() {
return Math.round(800 / Math.max(0.25, SETTINGS.playbackSpeed));
}
function startCycler(img) {
if (img.dataset.pnInit) return;
img.dataset.pnInit = '1';
const path = img.getAttribute('data-path');
const thumbs = JSON.parse(img.getAttribute('data-thumbs') || '[]');
if (!path || thumbs.length < 2) return;
const card = img.closest('a, .thumb, .item') || img.parentNode;
if (card) card.classList.add('apt-handled');
// Preload first few frames
thumbs.slice(0, 5).forEach(n => { (new Image()).src = path + 'd' + n + '.jpg'; });
let idx = 1;
img.dataset.pnIdx = '1';
const state = { timer: null };
pnCyclers.set(img, state);
function tick() {
if (!SETTINGS.isPaused) {
img.src = path + 'd' + thumbs[idx] + '.jpg';
// Preload next
const next = thumbs[(idx + 1) % thumbs.length];
(new Image()).src = path + 'd' + next + '.jpg';
idx = (idx + 1) % thumbs.length;
img.dataset.pnIdx = String(idx);
}
state.timer = setTimeout(tick, getIntervalMs());
}
if (!SETTINGS.isPaused) {
state.timer = setTimeout(tick, getIntervalMs());
} else {
// Still schedule, but tick() will skip frame when paused
state.timer = setTimeout(tick, getIntervalMs());
}
}
// IntersectionObserver: only cycle visible thumbs
const pnObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
const img = entry.target;
const state = pnCyclers.get(img);
if (entry.isIntersecting) {
startCycler(img);
// If previously stopped (scrolled away), restart
if (state && !state.timer) {
const path = img.getAttribute('data-path');
const thumbs = JSON.parse(img.getAttribute('data-thumbs') || '[]');
let idx = parseInt(img.dataset.pnIdx || '1', 10);
function tick() {
if (!SETTINGS.isPaused) {
img.src = path + 'd' + thumbs[idx] + '.jpg';
const next = thumbs[(idx + 1) % thumbs.length];
(new Image()).src = path + 'd' + next + '.jpg';
idx = (idx + 1) % thumbs.length;
img.dataset.pnIdx = String(idx);
}
state.timer = setTimeout(tick, getIntervalMs());
}
state.timer = setTimeout(tick, getIntervalMs());
}
} else {
// Pause cycling off-screen to save resources
if (state && state.timer) {
clearTimeout(state.timer);
state.timer = null;
}
}
});
}, { rootMargin: '300px', threshold: 0.01 });
function watchThumbs() {
document.querySelectorAll('img.thumbimg[data-thumbs][data-path]').forEach(img => {
if (!img.dataset.pnObserved) {
img.dataset.pnObserved = '1';
pnObserver.observe(img);
}
});
}
watchThumbs();
new MutationObserver(watchThumbs).observe(document.body, { childList: true, subtree: true });
setTimeout(watchThumbs, 500);
setTimeout(watchThumbs, 2000);
setInterval(watchThumbs, 5000);
},
"tnaflix.com": function () {
// tnaflix.com provides a direct `data-trailer` mp4 URL on the <a> tag.
// Selector: a.thumb-chrome[data-trailer] → img inside it is the thumbnail.
// Just grab data-trailer and hand it to insertPreviewVideo — cleanest possible.
function initCard(anchor) {
if (anchor.dataset.tnInit) return;
anchor.dataset.tnInit = '1';
const url = anchor.getAttribute('data-trailer');
const img = anchor.querySelector('img');
if (!url || !img) return;
anchor.classList.add('apt-handled');
insertPreviewVideo(img, url);
}
// IntersectionObserver — only load trailers near the viewport
const tnObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
initCard(entry.target);
tnObserver.unobserve(entry.target);
}
});
}, { rootMargin: '400px', threshold: 0.01 });
function watchCards() {
document.querySelectorAll('a.thumb-chrome[data-trailer]').forEach(anchor => {
if (!anchor.dataset.tnObserved) {
anchor.dataset.tnObserved = '1';
tnObserver.observe(anchor);
}
});
}
watchCards();
new MutationObserver(watchCards).observe(document.body, { childList: true, subtree: true });
setTimeout(watchCards, 500);
setTimeout(watchCards, 2000);
setInterval(watchCards, 5000);
},
"pornhits.com": function () {
// pornhits.com: img[data-preview] carries the preview URL directly.
// URL scheme: //pv2.pornhits.com/v2/preview/ID.mp4 (protocol-relative)
// Just prefix https: and feed to insertPreviewVideo — done.
observeElements('img[data-preview]', img => {
const raw = img.getAttribute('data-preview');
if (!raw) return null;
return raw.startsWith('//') ? 'https:' + raw : raw;
});
},
"hqporner.com": function () {
// hqporner.com has NO mp4 previews — it cycles 10 JPG frames per card.
// Each img[id^="slide"] or img[id^="cover_"] has src like: //cdn.../imgs/AA/BB/HASH_main.jpg
// Frame URLs: //cdn.../imgs/AA/BB/HASH_1.jpg ... HASH_10.jpg (10 frames)
// Site cycles at 600ms; we replicate autonomously respecting isPaused/speed.
// Speed 1x=600ms, 2x=300ms, 0.5x=1200ms etc.
// The "play images" button just enables slideShowPlayer on click — we bypass
// it entirely and start cycling immediately on IntersectionObserver trigger.
const hqCyclers = new Map(); // img el -> { timer }
function getIntervalMs() {
return Math.round(600 / Math.max(0.25, SETTINGS.playbackSpeed));
}
function getFrameUrls(img) {
// src: //fastporndelivery.hqporner.com/imgs/AA/BB/HASH_main.jpg
// OR after "play images" click: HASH_10.jpg
const src = img.getAttribute('src') || '';
const base = src.replace(/https?:/, '').replace(/_(?:main|\d+)\.jpg$/, '');
if (!base || !base.includes('/imgs/')) return null;
const frames = [];
for (let i = 1; i <= 10; i++) frames.push('https:' + base + '_' + i + '.jpg');
return frames;
}
function startCycler(img) {
if (img.dataset.hqInit) return;
img.dataset.hqInit = '1';
const frames = getFrameUrls(img);
if (!frames) return;
const card = img.closest('a, .video-box') || img.parentNode;
if (card) card.classList.add('apt-handled');
// Preload first 3 frames eagerly
frames.slice(0, 3).forEach(u => { (new Image()).src = u; });
let idx = 0;
const state = { timer: null };
hqCyclers.set(img, state);
function tick() {
if (!SETTINGS.isPaused) {
img.setAttribute('src', frames[idx]);
idx = (idx + 1) % frames.length;
// Preload next
(new Image()).src = frames[idx];
}
state.timer = setTimeout(tick, getIntervalMs());
}
state.timer = setTimeout(tick, getIntervalMs());
}
function stopCycler(img) {
const state = hqCyclers.get(img);
if (state && state.timer) {
clearTimeout(state.timer);
state.timer = null;
}
}
function resumeCycler(img) {
const state = hqCyclers.get(img);
if (!state || state.timer) return;
const frames = getFrameUrls(img);
if (!frames) return;
let idx = 0;
function tick() {
if (!SETTINGS.isPaused) {
img.setAttribute('src', frames[idx]);
idx = (idx + 1) % frames.length;
(new Image()).src = frames[idx];
}
state.timer = setTimeout(tick, getIntervalMs());
}
state.timer = setTimeout(tick, getIntervalMs());
}
const hqObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
const img = entry.target;
if (entry.isIntersecting) {
startCycler(img);
resumeCycler(img);
} else {
stopCycler(img);
}
});
}, { rootMargin: '300px', threshold: 0.01 });
function watchThumbs() {
document.querySelectorAll('img[id^="slide"], img[id^="cover_"]').forEach(img => {
if (!img.dataset.hqObserved) {
img.dataset.hqObserved = '1';
hqObserver.observe(img);
}
});
}
watchThumbs();
new MutationObserver(watchThumbs).observe(document.body, { childList: true, subtree: true });
setTimeout(watchThumbs, 500);
setTimeout(watchThumbs, 2000);
setInterval(watchThumbs, 5000);
},
"pornmz.com": function () {
// pornmz.com: data-trailer on <article> carries a direct mp4 URL.
// The thumbnail img.video-main-thumb sits inside .post-thumbnail-container
// inside .post-thumbnail inside the <a> inside the <article>.
// Strategy: find article[data-trailer], grab img.video-main-thumb inside it,
// feed data-trailer to insertPreviewVideo — identical pattern to tnaflix.
function initCard(article) {
if (article.dataset.pmzInit) return;
article.dataset.pmzInit = '1';
const url = article.getAttribute('data-trailer');
const img = article.querySelector('img.video-main-thumb');
if (!url || !img) return;
article.classList.add('apt-handled');
insertPreviewVideo(img, url);
}
const pmzObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
initCard(entry.target);
pmzObserver.unobserve(entry.target);
}
});
}, { rootMargin: '400px', threshold: 0.01 });
function watchCards() {
document.querySelectorAll('article[data-trailer]').forEach(article => {
if (!article.dataset.pmzObserved) {
article.dataset.pmzObserved = '1';
pmzObserver.observe(article);
}
});
}
watchCards();
new MutationObserver(watchCards).observe(document.body, { childList: true, subtree: true });
setTimeout(watchCards, 500);
setTimeout(watchCards, 2000);
setInterval(watchCards, 5000);
},
"youperv.com": function () {
// 1. Inject Theme (as requested by user)
let isDarkMode = GM_getValue('ypDarkMode', true);
GM_registerMenuCommand('🌓 YouPerv Toggle Dark/Light Theme', () => {
isDarkMode = !isDarkMode;
GM_setValue('ypDarkMode', isDarkMode);
location.reload();
});
const style = document.createElement('style');
style.id = 'youperv-modern-theme';
if (isDarkMode) {
style.textContent = `
*{transition:background-color .2s ease,color .2s ease,border-color .2s ease!important}
body,.js{background:linear-gradient(135deg,#0a0a0a 0%,#1a1a1a 100%)!important;color:#b0b0b0!important;-webkit-font-smoothing:antialiased!important;-moz-osx-font-smoothing:grayscale!important}
.header img[src*="logo.png"],.header img[alt="logo"]{filter:drop-shadow(0 0 8px rgba(255,107,107,.6))drop-shadow(0 0 20px rgba(255,107,107,.3))!important}
.header,.nav,.footer,.bottom-nav{background:rgba(26,26,26,.95)!important;backdrop-filter:blur(10px)!important;-webkit-backdrop-filter:blur(10px)!important;border-color:rgba(255,107,107,.1)!important}
.header,.nav{box-shadow:0 4px 16px rgba(0,0,0,.3)!important}
.header a,.nav-in a{color:#b0b0b0!important;font-weight:500!important}
.header a:hover,.nav-in a:hover,.footer a:hover,a:hover{color:#ff8787!important}
.nav-in a{position:relative!important;overflow:hidden!important}
.nav-in a::before{content:''!important;position:absolute!important;bottom:0!important;left:0!important;width:0!important;height:2px!important;background:linear-gradient(90deg,#ff6b6b,#ff8787)!important;transition:width .3s ease!important}
.nav-in a:hover{background:rgba(255,135,135,.08)!important}
.nav-in a:hover::before{width:100%!important}
.items-title{background:linear-gradient(135deg,#fff 0%,#ff8787 100%)!important;-webkit-background-clip:text!important;-webkit-text-fill-color:transparent!important;background-clip:text!important;font-weight:600!important;letter-spacing:-.5px!important}
form[name="news_set_sort"] ul li,.catmen,.clouds_xsmall,.clouds_small,.clouds_medium,.clouds_large,.clouds_xlarge,.pagi-nav a,.pagi-nav span{transform:translateY(0)!important;transition:all .25s cubic-bezier(.4,0,.2,1)!important}
form[name="news_set_sort"] ul li,.items-sort li[class]{background:rgba(36,36,36,.8)!important;border-radius:20px!important;border:1px solid rgba(255,107,107,.1)!important;overflow:hidden!important;font-family:GothamProRegular,Tahoma,Geneva,sans-serif!important;font-weight:500!important;padding:8px 16px!important}
form[name="news_set_sort"] ul li a{color:#b0b0b0!important;font-weight:500!important;letter-spacing:.3px!important;transition:color .25s ease!important;font-family:inherit!important;display:block!important}
form[name="news_set_sort"] ul li:hover{background:rgba(42,42,42,.9)!important;border-color:rgba(255,135,135,.3)!important;transform:translateY(-2px)!important;box-shadow:0 4px 12px rgba(255,107,107,.15)!important}
form[name="news_set_sort"] ul li:hover a{color:#ff8787!important}
form[name="news_set_sort"] ul li.asc{background:linear-gradient(135deg,rgba(255,107,107,.2) 0%,rgba(255,135,135,.1) 100%)!important;border-color:rgba(255,107,107,.4)!important}
form[name="news_set_sort"] ul li.asc a{color:#ff8787!important}
.item{background:linear-gradient(135deg,rgba(26,26,26,.95) 0%,rgba(20,20,20,.95) 100%)!important;border:1px solid rgba(255,107,107,.08)!important;border-radius:12px!important;overflow:hidden!important;position:relative!important;backdrop-filter:blur(10px)!important;-webkit-backdrop-filter:blur(10px)!important;transform:translateY(0)!important;transition:all .3s cubic-bezier(.4,0,.2,1)!important}
.item::before{content:''!important;position:absolute!important;top:0!important;left:0!important;right:0!important;height:2px!important;background:linear-gradient(90deg,transparent,#ff6b6b,transparent)!important;opacity:0!important;transition:opacity .3s ease!important}
.item:hover{border-color:rgba(255,107,107,.3)!important;transform:translateY(-4px)!important;box-shadow:0 12px 32px rgba(0,0,0,.5),0 0 0 1px rgba(255,107,107,.1)!important}
.item:hover::before{opacity:1!important}
.item-img{background:#0a0a0a!important;position:relative!important;overflow:hidden!important}
.item-img::after{content:''!important;position:absolute!important;inset:0!important;background:linear-gradient(180deg,transparent 0%,rgba(0,0,0,.4) 100%)!important;opacity:0!important;transition:opacity .3s ease!important;pointer-events:none!important;z-index:5!important}
.item:hover .item-img::after{opacity:1!important}
.item-img img{transform:scale(1)!important;transition:transform .5s cubic-bezier(.34,1.56,.64,1),opacity .3s ease!important}
.item:hover .item-img img{transform:scale(1.08)!important}
.item-title{color:#e0e0e0!important;font-weight:500!important}
.item-title a{color:#e0e0e0!important;transition:color .3s ease!important}
.item-title a:hover{color:#ff8787!important}
.item-title h2{color:#e0e0e0!important;font-weight:500!important}
.item-title h2 i{color:#888!important}
.item-meta{background:linear-gradient(135deg,rgba(255,107,107,.15),rgba(255,135,135,.1))!important;color:#ff8787!important;border-radius:6px!important;font-weight:500!important;backdrop-filter:blur(5px)!important;-webkit-backdrop-filter:blur(5px)!important}
.meta-views{color:#888!important}
.tim{background:rgba(36,36,36,.6)!important;color:#888!important;border-radius:6px!important;backdrop-filter:blur(5px)!important;-webkit-backdrop-filter:blur(5px)!important}
.catmen{background:rgba(42,42,42,.8)!important;color:#b0b0b0!important;border-radius:8px!important;border:1px solid rgba(255,107,107,.1)!important;font-weight:500!important;backdrop-filter:blur(5px)!important;-webkit-backdrop-filter:blur(5px)!important}
.catmen:hover{background:rgba(58,58,58,.9)!important;color:#e0e0e0!important;border-color:rgba(255,135,135,.3)!important;transform:translateY(-2px)!important;box-shadow:0 4px 8px rgba(0,0,0,.3)!important}
.catmen2{background:linear-gradient(135deg,#ff6b6b 0%,#ff5252 100%)!important;color:#fff!important;border-radius:8px!important;font-weight:600!important;box-shadow:0 2px 8px rgba(255,107,107,.3)!important;transform:translateY(0)!important;transition:all .25s cubic-bezier(.4,0,.2,1)!important}
.catmen2:hover{background:linear-gradient(135deg,#ff5252 0%,#ff3838 100%)!important;transform:translateY(-2px)!important;box-shadow:0 4px 12px rgba(255,107,107,.5)!important}
.clouds_xsmall,.clouds_small,.clouds_medium,.clouds_large,.clouds_xlarge{background:rgba(36,36,36,.6)!important;border-radius:16px!important;border:1px solid rgba(255,107,107,.08)!important;opacity:1!important;backdrop-filter:blur(5px)!important;-webkit-backdrop-filter:blur(5px)!important}
.clouds_xsmall a,.clouds_small a,.clouds_medium a,.clouds_large a,.clouds_xlarge a{color:#b0b0b0!important;transition:color .25s ease!important}
.clouds_xsmall:hover,.clouds_small:hover,.clouds_medium:hover,.clouds_large:hover,.clouds_xlarge:hover{background:rgba(42,42,42,.8)!important;border-color:rgba(255,135,135,.2)!important;transform:translateY(-2px)!important}
.clouds_xsmall:hover a,.clouds_small:hover a,.clouds_medium:hover a,.clouds_large:hover a,.clouds_xlarge:hover a{color:#ff8787!important}
.pagi-nav{background:rgba(26,26,26,.8)!important;border:1px solid rgba(255,107,107,.1)!important;border-radius:12px!important;backdrop-filter:blur(10px)!important;-webkit-backdrop-filter:blur(10px)!important}
.pagi-nav a,.pagi-nav span{color:#b0b0b0!important;background:rgba(36,36,36,.6)!important;border-radius:8px!important;font-weight:500!important}
.pagi-nav a:hover{background:rgba(42,42,42,.8)!important;color:#ff8787!important;transform:translateY(-2px)!important;box-shadow:0 4px 8px rgba(255,107,107,.2)!important}
.pagi-nav span{background:linear-gradient(135deg,rgba(255,107,107,.2),rgba(255,135,135,.1))!important;color:#ff8787!important}
.footer a,.footer{color:#888!important}
.search-box input[type="text"],input[type="text"],input[type="password"],input[type="email"],textarea,select{background:rgba(36,36,36,.6)!important;color:#e0e0e0!important;border:1px solid rgba(255,107,107,.1)!important;border-radius:8px!important;backdrop-filter:blur(5px)!important;-webkit-backdrop-filter:blur(5px)!important;transition:all .25s ease!important}
.search-box input[type="text"]{border-radius:12px!important}
.search-box input[type="text"]:focus,input:focus,textarea:focus,select:focus{border-color:rgba(255,107,107,.5)!important;background:rgba(42,42,42,.8)!important;box-shadow:0 0 0 3px rgba(255,107,107,.1)!important;outline:none!important}
.search-box input[type="text"]:focus{box-shadow:0 0 0 3px rgba(255,107,107,.1),0 4px 12px rgba(255,107,107,.2)!important}
.search-box button,.search-box input[type="submit"],button,input[type="submit"],input[type="button"]{background:linear-gradient(135deg,#ff6b6b 0%,#ff5252 100%)!important;color:#fff!important;border:none!important;border-radius:8px!important;font-weight:600!important;box-shadow:0 4px 12px rgba(255,107,107,.3)!important;transform:translateY(0)!important;transition:all .25s cubic-bezier(.4,0,.2,1)!important}
.search-box button,.search-box input[type="submit"]{border-radius:12px!important}
.search-box button:hover,.search-box input[type="submit"]:hover,button:hover,input[type="submit"]:hover,input[type="button"]:hover{background:linear-gradient(135deg,#ff5252 0%,#ff3838 100%)!important;transform:translateY(-2px)!important;box-shadow:0 6px 16px rgba(255,107,107,.5)!important}
.side-panel{background:rgba(26,26,26,.8)!important;border:1px solid rgba(255,107,107,.1)!important;border-radius:12px!important;backdrop-filter:blur(10px)!important;-webkit-backdrop-filter:blur(10px)!important}
h1,h2,h3,h4,h5,h6{color:#e0e0e0!important;font-weight:600!important;letter-spacing:-.3px!important}
p{color:#b0b0b0!important;line-height:1.6!important}
a{color:#b0b0b0!important}
.close-overlay{background:rgba(0,0,0,.98)!important;backdrop-filter:blur(20px)!important;-webkit-backdrop-filter:blur(20px)!important}
::-webkit-scrollbar{width:10px!important}
::-webkit-scrollbar-track{background:rgba(26,26,26,.5)!important}
::-webkit-scrollbar-thumb{background:linear-gradient(180deg,rgba(255,107,107,.5),rgba(255,135,135,.3))!important;border-radius:10px!important;border:2px solid transparent!important}
::-webkit-scrollbar-thumb:hover{background:linear-gradient(180deg,rgba(255,107,107,.8),rgba(255,135,135,.6))!important}
::selection{background:rgba(255,107,107,.3)!important;color:#fff!important}
table{background:rgba(26,26,26,.8)!important;border-color:rgba(255,107,107,.1)!important;border-radius:8px!important;overflow:hidden!important}
th{background:rgba(36,36,36,.8)!important;color:#e0e0e0!important;font-weight:600!important}
td{color:#b0b0b0!important;border-color:rgba(255,107,107,.05)!important}
tr:hover td{background:rgba(36,36,36,.5)!important}
.ad-wrapper{opacity:.5!important;filter:grayscale(.3)!important}
.sect-desc{color:#888!important}
.fluid_controls_container,.fluid_controls_container *{color:#e0e0e0!important}
.fluid_controls_left,.fluid_controls_right{background:rgba(0,0,0,.6)!important}
.fluid_button{background:rgba(255,107,107,.15)!important;border-radius:6px!important;transition:all .2s ease!important}
.fluid_button:hover{background:rgba(255,107,107,.3)!important;transform:scale(1.05)!important}
.fluid_controls_progress_container{background:rgba(255,255,255,.1)!important;border-radius:4px!important}
.fluid_controls_currentpos{background:linear-gradient(90deg,#ff6b6b,#ff8787)!important;color:#fff!important;border-radius:4px!important;font-weight:600!important;text-shadow:0 1px 2px rgba(0,0,0,.8)!important}
.fluid_control_volume_currentpos{background:linear-gradient(90deg,#ff6b6b,#ff8787)!important;border-radius:4px!important}
.fluid_control_duration,.fluid_fluid_control_duration{color:#e0e0e0!important;font-weight:500!important;text-shadow:0 1px 2px rgba(0,0,0,.8)!important}
.fluid_control_volume_container{background:rgba(255,255,255,.1)!important;border-radius:4px!important}
.xd{background:rgba(26,26,26,.8)!important;color:#e0e0e0!important;border:1px solid rgba(255,107,107,.1)!important;border-radius:8px!important;padding:8px!important}
.fm-fav{color:#ff8787!important}
.rating{color:#ff8787!important}
#story{background:rgba(36,36,36,.8)!important;color:#e0e0e0!important;border:1px solid rgba(255,107,107,.2)!important;border-radius:8px!important}
#story:focus{border-color:rgba(255,107,107,.5)!important;box-shadow:0 0 0 3px rgba(255,107,107,.1)!important}
.full-tags a,.full-tags{background:rgba(42,42,42,.8)!important;color:#b0b0b0!important;border:1px solid rgba(255,107,107,.1)!important;border-radius:8px!important;padding:6px 12px!important;display:inline-block!important;margin:3px!important;font-weight:500!important;transition:all .25s ease!important}
.full-tags a:hover{background:rgba(58,58,58,.9)!important;color:#ff8787!important;border-color:rgba(255,135,135,.3)!important;transform:translateY(-2px)!important;box-shadow:0 4px 8px rgba(255,107,107,.2)!important}
.a2a_kit{background:transparent!important}
.a2a_kit a{background:rgba(42,42,42,.8)!important;border:1px solid rgba(255,107,107,.1)!important;border-radius:8px!important;padding:6px 12px!important;transition:all .25s ease!important}
.a2a_kit a:hover{background:rgba(58,58,58,.9)!important;border-color:rgba(255,135,135,.3)!important;transform:translateY(-2px)!important}
.a2a_svg{border-radius:6px!important;transition:transform .2s ease!important}
.a2a_kit a:hover .a2a_svg{transform:scale(1.1)!important}
.full-tags{color:#e0e0e0!important;background:transparent!important;border:none!important;padding:0!important;margin-bottom:10px!important}
.fmeta{background:rgba(26,26,26,.8)!important;border:1px solid rgba(255,107,107,.1)!important;border-radius:12px!important;padding:12px!important;margin:10px 0!important}
.fm-item{background:rgba(36,36,36,.6)!important;color:#b0b0b0!important;border-radius:8px!important;padding:8px 12px!important;margin:4px!important}
.fm-item i{color:#ff8787!important}
.f-desc,.full-text{color:#b0b0b0!important;background:rgba(26,26,26,.8)!important;border:1px solid rgba(255,107,107,.1)!important;border-radius:12px!important;padding:15px!important;margin:10px 0!important}
.f-desc p,.full-text p{color:#b0b0b0!important;line-height:1.6!important}
.fcols{background:transparent!important}
.fleft,.fright{background:transparent!important}
.video-box,.fplayer{background:#0a0a0a!important;border:1px solid rgba(255,107,107,.1)!important;border-radius:12px!important;overflow:hidden!important;margin:10px 0!important}
.item-title p[style*="color"]{color:#888!important}
.item-title p span{color:#b0b0b0!important}
.item-title p a{color:#b0b0b0!important;text-decoration:none!important}
.item-title p a:hover{color:#ff8787!important}
`;
} else {
style.textContent = `
*{transition:background-color .2s ease,color .2s ease,border-color .2s ease!important}
body,.js{background:linear-gradient(135deg,#f8f9fa 0%,#fff 100%)!important;color:#2c3e50!important}
.header,.nav,.footer{background:rgba(255,255,255,.95)!important;backdrop-filter:blur(10px)!important;border-color:rgba(231,76,60,.1)!important}
.header,.nav{box-shadow:0 2px 12px rgba(0,0,0,.08)!important}
.nav-in a:hover{color:#e74c3c!important;background:rgba(231,76,60,.08)!important}
.item{background:rgba(255,255,255,.98)!important;border:1px solid rgba(231,76,60,.08)!important;box-shadow:0 2px 8px rgba(0,0,0,.06)!important;border-radius:12px!important;transform:translateY(0)!important;transition:all .3s cubic-bezier(.4,0,.2,1)!important}
.item:hover{box-shadow:0 12px 32px rgba(0,0,0,.15)!important;border-color:rgba(231,76,60,.3)!important;transform:translateY(-4px)!important}
button,input[type="submit"],input[type="button"]{background:linear-gradient(135deg,#e74c3c 0%,#c0392b 100%)!important;box-shadow:0 4px 12px rgba(231,76,60,.3)!important;border-radius:8px!important;transform:translateY(0)!important;transition:all .25s cubic-bezier(.4,0,.2,1)!important}
button:hover,input[type="submit"]:hover,input[type="button"]:hover{background:linear-gradient(135deg,#c0392b 0%,#a93226 100%)!important;transform:translateY(-2px)!important;box-shadow:0 6px 16px rgba(231,76,60,.5)!important}
.fluid_controls_container,.fluid_controls_container *{color:#2c3e50!important}
.fluid_button{background:rgba(231,76,60,.15)!important}
.fluid_button:hover{background:rgba(231,76,60,.3)!important}
`;
}
document.head.appendChild(style);
// 2. Video Preview (Integrated with the pack's insertPreviewVideo)
const videoCache = new Map();
const preloadQueue = [];
const MAX_CONCURRENT_PRELOADS = 2;
let activePreloads = 0;
function extractVideoUrl(pageUrl) {
return new Promise((resolve, reject) => {
if (videoCache.has(pageUrl)) {
resolve(videoCache.get(pageUrl));
return;
}
GM_xmlhttpRequest({
method: 'GET',
url: pageUrl,
onload: function(response) {
const parser = new DOMParser();
const doc = parser.parseFromString(response.responseText, 'text/html');
const videoSource = doc.querySelector('video source');
if (videoSource && videoSource.src) {
videoCache.set(pageUrl, videoSource.src);
resolve(videoSource.src);
} else {
reject('No video found');
}
},
onerror: reject
});
});
}
function processQueue() {
if (activePreloads >= MAX_CONCURRENT_PRELOADS || preloadQueue.length === 0) return;
const { pageUrl, img } = preloadQueue.shift();
activePreloads++;
extractVideoUrl(pageUrl)
.then(videoUrl => {
if (videoUrl) {
// Apply pack's native behavior
insertPreviewVideo(img, videoUrl);
}
})
.catch(() => {})
.finally(() => {
activePreloads--;
setTimeout(processQueue, 50);
});
}
function initItem(item) {
if (item.dataset.ypInit) return;
item.dataset.ypInit = '1';
const imgContainer = item.querySelector('.item-img');
const link = item.querySelector('a[href*=".html"]');
const img = imgContainer ? imgContainer.querySelector('img') : null;
if (!img || !link) return;
preloadQueue.push({ pageUrl: link.href, img });
processQueue();
}
const ypFetchObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
initItem(entry.target);
ypFetchObserver.unobserve(entry.target);
}
});
}, { rootMargin: '400px', threshold: 0.01 });
function watchItems() {
document.querySelectorAll('.item').forEach(item => {
if (!item.dataset.ypObserved) {
item.dataset.ypObserved = '1';
ypFetchObserver.observe(item);
}
});
}
watchItems();
new MutationObserver(watchItems).observe(document.body, { childList: true, subtree: true });
setTimeout(watchItems, 500);
setInterval(watchItems, 5000);
},
"superporn.com": function () {
const videoCache = new Map();
const preloadQueue = [];
const MAX_CONCURRENT_PRELOADS = 2;
let activePreloads = 0;
function extractVideoUrl(pageUrl) {
return new Promise((resolve, reject) => {
if (videoCache.has(pageUrl)) {
resolve(videoCache.get(pageUrl));
return;
}
GM_xmlhttpRequest({
method: 'GET',
url: pageUrl,
onload: function(response) {
const parser = new DOMParser();
const doc = parser.parseFromString(response.responseText, 'text/html');
const videoSource = doc.querySelector('video source');
if (videoSource && videoSource.src) {
videoCache.set(pageUrl, videoSource.src);
resolve(videoSource.src);
} else {
reject('No video found');
}
},
onerror: reject
});
});
}
function processQueue() {
if (activePreloads >= MAX_CONCURRENT_PRELOADS || preloadQueue.length === 0) return;
const { pageUrl, img } = preloadQueue.shift();
activePreloads++;
extractVideoUrl(pageUrl)
.then(videoUrl => {
if (videoUrl) {
insertPreviewVideo(img, videoUrl);
}
})
.catch(() => {})
.finally(() => {
activePreloads--;
setTimeout(processQueue, 50);
});
}
function initItem(item) {
if (item.dataset.spInit) return;
item.dataset.spInit = '1';
const link = item.querySelector('a.thumb-duracion');
const img = item.querySelector('img');
if (!img || !link) return;
preloadQueue.push({ pageUrl: link.href, img });
processQueue();
}
const spFetchObserver = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
initItem(entry.target);
spFetchObserver.unobserve(entry.target);
}
});
}, { rootMargin: '400px', threshold: 0.01 });
function watchItems() {
document.querySelectorAll('.thumb-video').forEach(item => {
if (!item.dataset.spObserved) {
item.dataset.spObserved = '1';
spFetchObserver.observe(item);
}
});
}
watchItems();
new MutationObserver(watchItems).observe(document.body, { childList: true, subtree: true });
setTimeout(watchItems, 500);
setInterval(watchItems, 5000);
}
};
// Dispatcher — run immediately AND on DOMContentLoaded as fallback
function dispatch() {
for (const domain in siteHandlers) {
if (hostname.includes(domain)) {
siteHandlers[domain]();
break;
}
}
}
// Run now (for scripts injected after DOM is ready)
dispatch();
// Also run on DOMContentLoaded in case we injected before DOM was ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', dispatch);
}
})();