XNXX - Search Filters

Various search filters

Pada tanggal 24 Februari 2019. Lihat %(latest_version_link).

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name          XNXX - Search Filters
// @namespace     brazenvoid
// @version       2.2.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: '720p', // SD / 480p / 720p / 1080p
  views: {
    minimum: 0,
    maximum: 0,
  },
  showUIAlways: false, // Desktop/Tablet
  debugLogging: false
}

// Base Resources Initialization

const scriptPrefix = 'xnxx-sf-'

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 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) {

    duration = duration.split(' ')

    if (duration[1] === 'min') {
      duration[0] *= 60
    }
    return filters.validateRange('Duration', duration[0], [settings.duration.minimum, settings.duration.maximum])
  }
  return true
}

// -- Resolution validation

let validateResolution = function (resolution) {

  let validationCheck = true

  if (settings.resolution !== 'SD') {

    switch (settings.resolution) {

      case '480p':
        validationCheck = resolution !== 'SD'
        break

      case '720p':
        validationCheck = resolution !== 'SD' && resolution !== '480p'
        break

      case '1080p':
        validationCheck = resolution !== 'SD' && resolution !== '480p' && resolution !== '720p'
        break
    }
    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, videoResolution, videoViews

  for (let videoItem of videoItems) {

    videoMetadata = videoItem.querySelector('.metadata').textContent.split('-')
    videoDuration = videoMetadata[0].trim()

    if (typeof videoMetadata[1] === 'undefined') {
      videoResolution = 'SD'
      videoViews = 0
    } else if (videoMetadata[1].includes('hits')) {
      videoResolution = typeof videoMetadata[2] === 'undefined' ? 'SD' : videoMetadata[2].trim()
      videoViews = videoMetadata[1].trim().replace(' hits', '').replace(',', '')
    } else {
      videoResolution = videoMetadata[1].trim()
    }

    videoName = videoItem.querySelector('.thumb-under > p:nth-child(1) > a:nth-child(1)').textContent
    logger.logVideoCheck(videoName)

    videoComplies =
      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 Duration', 'number', settings.duration.minimum.toString()),
  uiGenerator.createSettingsDropDownFormGroup('Min Resolution', [
    ['SD', 'Show All'], ['480p', 'SD 480p'], ['720p', 'HD 720p'], ['1080p', '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.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('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.')