您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Various search filters
当前为
// ==UserScript== // @name XNXX - Search Filters // @namespace brazenvoid // @version 2.4.0 // @author brazenvoid // @license GPL-3.0-only // @description Various search filters // @include https://www.xnxx.com/* // @require https://greasyfork.org/scripts/375557-brazenvoid-s-base-resource/code/Brazenvoid's%20Base%20Resource.js?version=673340 // @run-at document-idle // ==/UserScript== // Settings & Defaults let settings = { blacklist: [ // case-insensitive '360 drops of', 'urin', 'arab', 'muslim', 'desi', 'squirt', 'fake', 'pregnant', 'pee', ], sanitize: { // Substitutes values with key (case-insensitive) ' ': ['neighbor', 'step'], 'Boyfriend': ['brother', 'bro', 'daddy', 'dad'], 'Girlfriend': ['daughter', 'mom', 'mother', 'sister', 'sis'] }, duration: { // In Seconds minimum: 120, maximum: 0, }, resolution: '720', // All / 360 / 480 / 720 / 1080 rating: { minimum: 80, maximum: 0, }, views: { minimum: 0, maximum: 0, }, showUIAlways: false, // Desktop/Tablet debugLogging: false } // Base Resources Initialization const scriptPrefix = 'xnxx-sf-' const isOnVideoPage = window.location.pathname.startsWith('/video-') let storage = new LocalStore(scriptPrefix + 'settings', settings) settings = storage.retrieve().get() let logger = new Logger(settings.debugLogging) let selectorGenerator = new SelectorGenerator(scriptPrefix) let statistics = new StatisticsRecorder(logger, selectorGenerator) let uiGenerator = new UIGenerator(settings.showUIAlways, selectorGenerator) let filters = new Filters(statistics) filters.blacklist = settings.blacklist filters.sanitizationRules = settings.sanitize filters.init() function getVideoList () { return document.querySelector('.mozaique') } // Local Store Events let refreshUI = function () { let store = this.get() uiGenerator.setSettingsInputValue('Min Duration', store.duration.minimum) uiGenerator.setSettingsInputValue('Min Rating', store.rating.minimum) uiGenerator.setSettingsInputValue('Min Resolution', store.resolution) uiGenerator.setSettingsInputValue('Min Views', store.views.minimum) } storage.onDefaultsLoaded = refreshUI storage.onRetrieval = refreshUI storage.onUpdated = refreshUI // Filters // -- Duration validation let validateDuration = function (duration) { if (settings.duration.minimum > 0 || settings.duration.maximum > 0) { let splitArray if (isOnVideoPage) { console.log(typeof duration) splitArray = duration.split(' ') duration = 0 for (let i = 0; i < splitArray.length; i++) { if (splitArray[i].endsWith('min')) { duration += 60 * splitArray[i].replace('min', '') } else if (splitArray[i].endsWith('sec')) { duration += splitArray[i].replace('sec', '') } } } else { splitArray = duration.split('min') if (splitArray.length === 2) { duration = 60 * splitArray[0] } else { splitArray = duration.split('sec') if (splitArray.length === 2) { duration = splitArray[0] } } } return filters.validateRange('Duration', duration, [settings.duration.minimum, settings.duration.maximum]) } return true } // -- Rating validation let validateRating = function (rating) { if (settings.rating.minimum > 0 || settings.rating.maximum > 0) { return filters.validateRange('Rating', rating, [settings.rating.minimum, settings.rating.maximum]) } return true } // -- Resolution validation let validateResolution = function (resolution) { let validationCheck = true if (settings.resolution !== 'All') { validationCheck = parseInt(resolution.replace('p', '')) >= settings.resolution statistics.record('Resolution', validationCheck) } return validationCheck } // -- Video name sanitation let sanitizeVideoPage = function () { let videoTitle = document.querySelector('.clear-infobar > strong:nth-child(1)') if (videoTitle !== null) { let sanitizedVideoName = filters.sanitize(videoTitle.textContent) videoTitle.textContent = sanitizedVideoName document.title = sanitizedVideoName } } let sanitizeVideoItem = function (videoItem, videoName) { videoItem.querySelector('.thumb-under > p:nth-child(1) > a:nth-child(1)').textContent = filters.sanitize(videoName) } // -- View count validation let validateViews = function (views) { let validationCheck = true if (settings.views.minimum > 0 || settings.views.maximum > 0) { validationCheck = filters.validateRange('Duration', views, [settings.views.minimum, settings.views.maximum]) } return validationCheck } // -- Compliance logic let complianceCallback = function (target) { let videoItems = target.querySelectorAll('.thumb-block') let videoDuration, videoComplies, videoMetadata, videoName, videoRating, videoResolution, videoViews for (let videoItem of videoItems) { if (isOnVideoPage) { videoMetadata = videoItem.querySelector('.metadata').textContent.split(' ') videoDuration = videoMetadata[1] videoRating = 100 videoResolution = videoMetadata[5] videoViews = videoMetadata[0] } else { videoMetadata = videoItem.querySelector('.metadata').textContent.split('\n') videoMetadata[1] = videoMetadata[1].split(' ') videoDuration = videoMetadata[2] videoRating = videoMetadata[1][1].replace('%', '') videoResolution = videoMetadata[3].replace(' - ', '') videoViews = videoMetadata[1][0] } videoName = videoItem.querySelector('.thumb-under > p:nth-child(1) > a:nth-child(1)').textContent logger.logVideoCheck(videoName) videoComplies = validateRating(videoRating) && validateResolution(videoResolution) && filters.validateBlackList(videoName) && validateDuration(videoDuration) && validateViews(videoViews) if (videoComplies) { videoItem.style.display = 'inline-block' sanitizeVideoItem(videoItem, videoName) } else { videoItem.style.display = 'none' } logger.logSeparator() } statistics.updateUI() } // UI Composition // -- Control Panel let section = uiGenerator.createSection('settings', '#ffa31a', '250px', '220px', [ uiGenerator.createSettingsFormGroup('Min Rating', 'number', settings.rating.minimum.toString()), uiGenerator.createSettingsFormGroup('Min Duration', 'number', settings.duration.minimum.toString()), uiGenerator.createSettingsDropDownFormGroup('Min Resolution', [ ['All', 'Show All'], ['360', 'SD 360p'], ['480', 'SD 480p'], ['720', 'HD 720p'], ['1080', 'HD 1080p'] ], settings.resolution.toString()), uiGenerator.createSettingsFormGroup('Min Views', 'number', settings.views.minimum.toString()), uiGenerator.createSettingsFormActions(storage, function () { settings.duration.minimum = parseInt(uiGenerator.getSettingsInputValue('Min Duration')) settings.rating.minimum = parseInt(uiGenerator.getSettingsInputValue('Min Rating')) settings.resolution = uiGenerator.getSettingsInputValue('Min Resolution') settings.views.minimum = parseInt(uiGenerator.getSettingsInputValue('Min Views')) statistics.reset() complianceCallback(getVideoList()) }), uiGenerator.createSeparator(), uiGenerator.createStoreControlPanel(storage), uiGenerator.createSeparator(), uiGenerator.createStatisticsFormGroup('Duration', 'Short'), uiGenerator.createStatisticsFormGroup('Rating', 'Low Rated'), uiGenerator.createStatisticsFormGroup('Resolution', 'Low Resolution'), uiGenerator.createStatisticsFormGroup('Views', 'Low Views'), uiGenerator.createStatisticsFormGroup('Blacklist', 'Blacklisted'), uiGenerator.createStatisticsFormGroup('Total'), uiGenerator.createSettingsHideButton('settings') ]) uiGenerator.appendToBody(section) uiGenerator.getSettingsInput('Min Views').parentNode.style.marginBottom = '10px' let labels = section.getElementsByTagName('label') for (let label of labels) { label.style.margin = '0' } // -- Settings Button let controlButton = uiGenerator.createSettingsShowButton('Show Settings UI', section, false) controlButton.style.width = 'unset' let controlListItem = document.createElement('div') controlListItem.appendChild(controlButton) document.querySelector('.slogan').appendChild(controlButton) logger.logTaskCompletion('Building UI') // Script run // -- Initial compliance run & observer attachment ChildObserver.observe(getVideoList(), complianceCallback, true) sanitizeVideoPage() logger.logTaskCompletion('Initial run and observer attachment.')