您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Various search filters and user experience enhancers
当前为
// ==UserScript== // @name PH - Search & UI Tweaks // @namespace brazenvoid // @version 1.2.0 // @author brazenvoid // @license GPL-3.0-only // @description Various search filters and user experience enhancers // @include https://www.pornhub.com/* // @run-at document-end // ==/UserScript== // Settings & Defaults let blacklistedWords = [ // case-insensitive 'urin', 'arab', 'muslim', 'desi', 'squirt', 'fake', 'pregnant', 'pee', ]; let videoNameSanitization = { // Substitutes values with key (case-insensitive) ' ' : ['neighbor', 'step'], 'Boyfriend': ['brother', 'bro', 'daddy', 'dad'], 'Girlfriend': ['daughter', 'mom', 'mother', 'sister', 'sis'] }; const defaultMinimumRating = 80; const defaultMinimumDurationInSeconds = 120; const hideNonHDVideosOnVideoPages = true; const hidePrivateVideos = true; const hideUnratedVideos = true; const removeIFrames = true; const removeLiveModelsSection = true; const removePornStarsListingInSidebar = true; const showUI = true; const enableDebugLogging = false; // Setting up configuration let observerConfig = { attributes: false, childList: true, subtree: false }; // Pre-building regular expressions for (let i = 0; i < blacklistedWords.length; i++) { blacklistedWords[i] = new RegExp(blacklistedWords[i], 'ig'); } for (const substitute in videoNameSanitization) { for (let i = 0; i < videoNameSanitization[substitute].length; i++) { videoNameSanitization[substitute][i] = new RegExp(videoNameSanitization[substitute][i], 'ig'); } } // Setting up logging let log = function (message) { if (enableDebugLogging) { console.log(message); } }; let logAction = function (action) { log('Completed: ' + action); logSeparator(); }; let logValidationResult = function (filterName, statusVariable = null) { log('Satisfies ' + filterName + ' Filter: ' + (statusVariable ? 'true' : 'false')); }; let logSeparator = function () { log('------------------------------------------------------------------------------------'); }; let logVideoName = function (videoName) { log('Checking Video: ' + videoName); }; // Blacklist validation let validateBlacklist = function (videoItem, videoName) { let validationCheck; for (const blacklistedWord of blacklistedWords) { validationCheck = videoName.match(blacklistedWord) === null; if (!validationCheck) { break; } } logValidationResult('Blacklist', validationCheck); return validationCheck; }; // Duration validation let validateDuration = function (videoItem, minDuration) { let duration = videoItem.querySelector('.duration').textContent.split(':'); duration = (parseInt(duration[0]) * 60) + parseInt(duration[1]); let validationCheck = duration >= minDuration; logValidationResult('Duration', validationCheck); return validationCheck; }; // High definition validation let validateHD = function (videoItem) { if (hideNonHDVideosOnVideoPages) { let validationCheck = videoItem.querySelector('.hd-thumbnail') !== null; logValidationResult('HD', validationCheck); return validationCheck; } return true; }; // Private video validation let validatePrivateVideo = function (videoItem) { if (hidePrivateVideos) { let validationCheck = videoItem.querySelector('.privateOverlay') === null; logValidationResult('Private Video', validationCheck); return validationCheck; } return true; }; // Rating validation let validateRating = function (videoItem, minRating) { let rating = videoItem.querySelector('.value'); let validationCheck; if (rating === null) { validationCheck = !hideUnratedVideos; } else { rating = parseInt(rating.textContent.replace('%', '')); validationCheck = rating >= minRating; } logValidationResult('Rating', validationCheck); return validationCheck; }; // Video name sanitization let sanitizationFilter = function (content) { for (const substitute in videoNameSanitization) { for (const subject of videoNameSanitization[substitute]) { content = content.replace(subject, substitute); } } return content; }; let sanitizeVideoPage = function () { let videoTitle = document.querySelector('.inlineFree'); if (videoTitle !== null) { let sanitizedVideoName = sanitizationFilter(videoTitle.textContent); videoTitle.textContent = sanitizedVideoName; document.title = sanitizedVideoName; } }; let sanitizeVideoItem = function (videoItem, videoName) { videoItem.querySelector('.title > a').textContent = sanitizationFilter(videoName); }; // Compliance logic let complianceCallback = function (target, minDuration, minRating) { let videoItems = target.querySelectorAll('.videoBox'); let videoName, videoComplies; for (let videoItem of videoItems) { videoName = videoItem.querySelector('.title > a').textContent; logVideoName(videoName); videoComplies = validateBlacklist(videoItem, videoName) && validateDuration(videoItem, minDuration) && validateHD(videoItem) && validatePrivateVideo(videoItem) && validateRating(videoItem, minRating); if (videoComplies) { videoItem.style.display = 'inline-block'; sanitizeVideoItem(videoItem, videoName); } else { videoItem.style.display = 'none'; } logSeparator(); } }; let observer = new MutationObserver(function (mutations) { for (let mutation of mutations) { complianceCallback(mutation.target, defaultMinimumDurationInSeconds, defaultMinimumRating); } }); // Building UI if (showUI) { // Settings UI let addCategoryDiv = function () { let categoryDiv = document.createElement('div'); categoryDiv.style.display = 'block'; categoryDiv.style.height = '18px'; categoryDiv.style.marginBottom = '2px'; categoryDiv.style.padding = '5px'; return categoryDiv; }; let addCategoryLabel = function (category, inputIDSuffix) { let categoryLabel = document.createElement('label'); categoryLabel.style.float = 'left'; categoryLabel.style.padding = '2px 5px 5px 0'; categoryLabel.setAttribute('for', 'ph-sui-' + inputIDSuffix); categoryLabel.textContent = category + ': '; return categoryLabel; }; let addCategoryInput = function (inputIDSuffix, defaultValue) { let categoryInput = document.createElement('input'); categoryInput.id = 'ph-sui-'+ inputIDSuffix; categoryInput.style.float = 'right'; categoryInput.style.width = '100px'; categoryInput.style.textAlign = 'center'; categoryInput.value = defaultValue; return categoryInput; }; let addCategory = function (category, inputIDSuffix, defaultInputValue) { let categoryDiv = addCategoryDiv(); let categoryLabel = addCategoryLabel(category, inputIDSuffix); let categoryInput = addCategoryInput(inputIDSuffix, defaultInputValue); categoryDiv.appendChild(categoryLabel); categoryDiv.appendChild(categoryInput); return categoryDiv; }; // --Configurable sections let durationSection = addCategory('Min Duration', 'min-duration', defaultMinimumDurationInSeconds.toString()); let ratingSection = addCategory('Min Rating', 'min-rating', defaultMinimumRating.toString()); // --Submit let applyButton = document.createElement('button'); applyButton.textContent = 'Apply'; applyButton.style.height = '30px'; applyButton.style.width = '100%'; // --Section let section = document.createElement('section'); section.id = 'ph-search-and-tweaks-settings'; section.style.display = 'none'; section.style.position = 'fixed'; section.style.top = '250px'; section.style.left = '0'; section.style.width = '200px'; section.style.padding = '1px'; section.style.backgroundColor = '#ffa31a'; section.style.zIndex = '1000'; section.appendChild(durationSection); section.appendChild(ratingSection); section.appendChild(applyButton); let bodyTag = document.getElementsByTagName('body')[0]; bodyTag.appendChild(section); // --Events applyButton.addEventListener('click', function () { let videoLists = document.querySelectorAll('.videos'); let minDuration = document.getElementById('ph-sui-min-duration').value; let minRating = document.getElementById('ph-sui-min-rating').value; for (let videoList of videoLists) { complianceCallback(videoList, minDuration, minRating); } }); logAction('Building UI'); // Settings UI Control let networkBarList = document.querySelector('#networkbar_items_wrap'); let controlListItem = document.createElement('li'); let controlButton = document.createElement('button'); controlButton.textContent = 'Search & Tweaks'; controlButton.style.width = '100%'; controlButton.style.margin = '2px 5px'; controlButton.style.padding = '2px 5px'; controlButton.style.backgroundColor = '#ffa31a'; controlButton.style.border = 0; controlListItem.appendChild(controlButton); networkBarList.appendChild(controlListItem); // --Events controlButton.addEventListener('click', function () { let settingsUI = document.querySelector('#ph-search-and-tweaks-settings'); if (settingsUI.style.display === 'none') { settingsUI.style.display = 'block'; } else { settingsUI.style.display = 'none'; } }); } // -- Move pagination section let videosSection = document.querySelector('.nf-videos'); if (videosSection !== null) { let paginationBlock = document.querySelector('.pagination3'); videosSection.appendChild(paginationBlock); } // -- Initial compliance run & observer attachment let videoLists = document.querySelectorAll('ul.videos'); for (let videoList of videoLists) { complianceCallback(videoList, defaultMinimumDurationInSeconds, defaultMinimumRating); observer.observe(videoList, observerConfig); } sanitizeVideoPage(); logAction('Initial run and observer attachment.'); // -- Ad blocking //let ads = target.querySelectorAll('.removeAdLink'); //if (debug) { console.log('Ads Found: ' + ads.length); } //for (let ad of ads) { //ad.parentNode.remove(); //} // -- IFrames removal if (removeIFrames) { let IFrames = document.querySelectorAll('iframe'); for (let IFrame of IFrames) { IFrame.remove(); } logAction('Remove all IFrames.'); } // -- Live models removal if (removeLiveModelsSection) { let liveModelStreamsSection = document.querySelector('.streamateContent'); if (liveModelStreamsSection !== null) { liveModelStreamsSection.closest('.sectionWrapper').remove(); } logAction('Live model section removal.'); } // Porn stars listing in sidebar removal if (removePornStarsListingInSidebar) { let pornStarsSection = document.getElementById('relatedPornstarSidebar'); if (pornStarsSection !== null) { pornStarsSection.remove(); } logAction('Sidebar porn start listing removal.'); }