XHamster Search and UI Improvements

Various search filters

От 09.01.2021. Виж последната версия.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name         XHamster Search and UI Improvements
// @namespace    brazenvoid
// @version      2.0.1
// @author       brazenvoid
// @license      GPL-3.0-only
// @description  Various search filters
// @include      https://xhamster.com/*
// @require      https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js
// @require      https://greasyfork.org/scripts/375557-base-resource/code/Base%20Resource.js?version=889081
// @require      https://greasyfork.org/scripts/416104-brazen-ui-generator/code/Brazen%20UI%20Generator.js?version=889085
// @require      https://greasyfork.org/scripts/418665-brazen-configuration-manager/code/Brazen%20Configuration%20Manager.js?version=889083
// @require      https://greasyfork.org/scripts/416105-brazen-base-search-enhancer/code/Brazen%20Base%20Search%20Enhancer.js?version=889086
// @grant        GM_addStyle
// @run-at       document-idle
// ==/UserScript==

GM_addStyle(`#settings-wrapper{top:5vh;width:270px}#settings-wrapper .check-radio-input{display:block}#settings-wrapper .form-button{border:revert}.font-primary{color:white}.tab-button:hover:not(.active){color:black}.tab-button:not(.active){color:white}.bg-brand{background-color:#3a3a3a}`)

const PAGE_PATH_NAME = window.location.pathname
const IS_VIDEO_PAGE = PAGE_PATH_NAME.startsWith('/videos')

const FILTER_HD_VIDEOS = 'Show only HD Videos'
const FILTER_VIDEOS_VIEWS = 'Views'

const ITEM_NAME_SELECTOR = 'a.video-thumb-info__name'

class XHamsterSearchAndUITweaks extends BrazenBaseSearchEnhancer
{
    constructor ()
    {
        super('xh-sui-', 'thumb-list__item')

        this._configurationManager.
            addFlagField(FILTER_HD_VIDEOS, 'Hides videos of less than 720p resolution.').
            addRangeField(FILTER_VIDEOS_VIEWS, 0, 10000000, 'Filter videos by view count.')

        this._setupUI()
        this._setupCompliance()
        this._setupComplianceFilters()
    }

    /**
     * @private
     */
    _setupCompliance ()
    {
        this._onGetItemLists = () => $('div.thumb-list')

        this._onGetItemName = (item) => item.find(ITEM_NAME_SELECTOR).text()

        this._onFirstHitBeforeCompliance = (item) => {
            Validator.sanitizeTextNode(item.find(ITEM_NAME_SELECTOR), this._configurationManager.getFieldOrFail(FILTER_TEXT_SANITIZATION).optimized)
        }
    }

    /**
     * @private
     */
    _setupComplianceFilters ()
    {
        this._addItemTextSanitizationFilter('Censor video names by substituting offensive phrases. Each rule in separate line with comma separated target phrases. Example Rule: boyfriend=stepson,stepdad')
        this._addItemWhitelistFilter('Show videos with specified phrases in their names. Separate the phrases with line breaks.')
        this._addItemTextSearchFilter()
        this._addItemPercentageRatingRangeFilter('div.rating span.metric-text')
        this._addItemDurationRangeFilter('div.thumb-image-container__duration')
        this._addItemComplianceFilter(FILTER_VIDEOS_VIEWS, (range) => range.minimum > 0 || range.maximum > 0, (item, range) => {
            let viewsCount = 0
            let viewsCountNode = item.find('div.views span.metric-text')
            if (viewsCountNode.length) {
                viewsCount = parseInt(viewsCountNode.text().replace(',', ''))
                if (isNaN(viewsCount)) {
                    viewsCount = 0
                }
            }
            return Validator.isInRange(viewsCount, range.minimum, range.maximum)
        })
        this._addItemComplianceFilter(
            FILTER_HD_VIDEOS,
            (value) => value,
            (item) => !Validator.isChildMissing(item, 'i.thumb-image-container__icon--hd,i.thumb-image-container__icon--uhd')
        )
        this._addItemBlacklistFilter('Hide videos with specified phrases in their names. Separate the phrases with line breaks.')
    }

    /**
     * @private
     */
    _setupUI ()
    {
        this._onBeforeUIBuild = () => {
            if (IS_VIDEO_PAGE) {
                Validator.sanitizeNodeOfSelector(
                    'main > div.width-wrap.with-player-container > h1:first', this._configurationManager.getFieldOrFail(FILTER_TEXT_SANITIZATION).optimized)
            }
        }

        this._onUIBuild = () =>
            this._uiGen.createSettingsSection().append([
                this._uiGen.createTabsSection(['Filters', 'Text Based', 'Global'], [
                    this._uiGen.createTabPanel('Filters', true).append([
                        this._configurationManager.createElement(FILTER_DURATION_RANGE),
                        this._configurationManager.createElement(FILTER_PERCENTAGE_RATING_RANGE),
                        this._configurationManager.createElement(FILTER_VIDEOS_VIEWS),
                        this._uiGen.createBreakSeparator(),
                        this._configurationManager.createElement(FILTER_HD_VIDEOS),
                        this._configurationManager.createElement(FILTER_UNRATED),
                        this._uiGen.createSeparator(),
                        this._configurationManager.createElement(OPTION_DISABLE_COMPLIANCE_VALIDATION),
                    ]),
                    this._uiGen.createTabPanel('Text Based').append([
                        this._configurationManager.createElement(FILTER_TEXT_SEARCH),
                        this._configurationManager.createElement(FILTER_TEXT_BLACKLIST),
                        this._configurationManager.createElement(FILTER_TEXT_WHITELIST),
                    ]),
                    this._uiGen.createTabPanel('Global').append([
                        this._configurationManager.createElement(FILTER_TEXT_SANITIZATION),
                        this._uiGen.createSeparator(),
                        this._configurationManager.createElement(OPTION_ALWAYS_SHOW_SETTINGS_PANE),
                        this._uiGen.createSeparator(),
                        this._createSettingsBackupRestoreFormActions(),
                    ]),
                ]),
                this._createSettingsFormActions(),
                this._uiGen.createSeparator(),
                this._uiGen.createStatisticsFormGroup(FILTER_TEXT_BLACKLIST),
                this._uiGen.createStatisticsFormGroup(FILTER_TEXT_WHITELIST),
                this._uiGen.createStatisticsFormGroup(FILTER_DURATION_RANGE),
                this._uiGen.createStatisticsFormGroup(FILTER_HD_VIDEOS, 'High Definition'),
                this._uiGen.createStatisticsFormGroup(FILTER_TEXT_SEARCH),
                this._uiGen.createStatisticsFormGroup(FILTER_PERCENTAGE_RATING_RANGE),
                this._uiGen.createStatisticsFormGroup(FILTER_DURATION_RANGE, 'Unrated'),
                this._uiGen.createStatisticsFormGroup(FILTER_VIDEOS_VIEWS),
                this._uiGen.createSeparator(),
                this._uiGen.createStatisticsTotalsGroup(),
                this._uiGen.createSeparator(),
                this._uiGen.createStatusSection(),
            ])

        this._onAfterUIBuild = () => {
            this._uiGen.getSelectedSection()[0].userScript = this
        }
    }
}

(new XHamsterSearchAndUITweaks).init()