xHamster Tweaks

Adds HD and Newest quick filter buttons on pornstar/creator profiles + auto-shows description and date under the video.

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 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         xHamster Tweaks
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  Adds HD and Newest quick filter buttons on pornstar/creator profiles + auto-shows description and date under the video.
// @author       nereids
// @match        https://xhamster.com/pornstars/*
// @match        https://xhamster.com/creators/*
// @match        https://xhamster.com/videos/*
// @match        https://xhamster.com/movies/*
// @icon         https://icons.duckduckgo.com/ip3/xhamster.com.ico
// @license      MIT
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    // 1. Unified CSS Styles
    GM_addStyle(`
        .auto-about-info {
            width: fit-content !important;
            max-width: 100% !important;
            white-space: normal;
        }
        .xh-custom-filter-btn {
            text-decoration: none !important;
            margin-left: 2px;
        }
        #xh-custom-meta-box {
            display: inline-block;
            width: max-content;
            max-width: 100%;
            background: rgba(255, 255, 255, 0.05);
            border-radius: 8px;
            padding: 16px;
            margin-top: 12px;
            margin-bottom: 12px;
            font-family: sans-serif;
            color: #e3e3e3;
            box-sizing: border-box;
        }
        .xh-meta-desc {
            font-size: 13px;
            word-wrap: break-word;
            margin-bottom: 10px;
            line-height: 1.5;
            white-space: normal;
        }
        .xh-meta-subline {
            display: flex;
            gap: 15px;
            font-size: 13px;
            color: #a0a0a0;
        }
        .xh-meta-subline a {
            color: #ff8c00;
            text-decoration: none;
        }
    `);

    // 2. SVG Assets
    const svgs = {
        hd: {
            default: `<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M300-440h80v50q0 13 8.5 21.5T410-360q13 0 21.5-8.5T440-390v-180q0-13-8.5-21.5T410-600q-13 0-21.5 8.5T380-570v70h-80v-70q0-13-8.5-21.5T270-600q-13 0-21.5 8.5T240-570v180q0 13 8.5 21.5T270-360q13 0 21.5-8.5T300-390v-50Zm240 80h140q17 0 28.5-11.5T720-400v-160q0-17-11.5-28.5T680-600H540q-8 0-14 6t-6 14v200q0 8 6 14t14 6Zm40-60v-120h80v120h-80ZM160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h640q33 0 56.5 23.5T880-720v480q0 33-23.5 56.5T800-160H160Zm0-80h640v-480H160v480Zm0 0v-480 480Z"/></svg>`,
            selected: `<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M300-446.15h92.31V-390q0 10.31 6.77 17.08 6.77 6.77 17.07 6.77 10.31 0 17.08-6.77Q440-379.69 440-390v-180q0-10.31-6.77-17.08-6.77-6.77-17.08-6.77-10.3 0-17.07 6.77T392.31-570v76.15H300V-570q0-10.31-6.77-17.08-6.77-6.77-17.08-6.77-10.3 0-17.07 6.77T252.31-570v180q0 10.31 6.77 17.08 6.77 6.77 17.07 6.77 10.31 0 17.08-6.77Q300-379.69 300-390v-56.15Zm238.08 80h128.07q17.39 0 29.46-12.08 12.08-12.08 12.08-29.46v-144.62q0-17.38-12.08-29.46-12.07-12.08-29.46-12.08H538.08q-7.23 0-12.66 5.43Q520-583 520-575.77v191.54q0 7.23 5.42 12.65 5.43 5.43 12.66 5.43Zm29.61-47.7v-132.3h86.16q2.3 0 4.23 1.92Q660-542.31 660-540v120q0 2.31-1.92 4.23-1.93 1.92-4.23 1.92h-86.16ZM172.31-180Q142-180 121-201q-21-21-21-51.31v-455.38Q100-738 121-759q21-21 51.31-21h615.38Q818-780 839-759q21 21 21 51.31v455.38Q860-222 839-201q-21 21-51.31 21H172.31Z"/></svg>`
        },
        new: {
            default: `<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M120-160q-33 0-56.5-23.5T40-240v-480q0-33 23.5-56.5T120-800h720q33 0 56.5 23.5T920-720v480q0 33-23.5 56.5T840-160H120Zm0-80h720v-480H120v480Zm70-260 95 130q3 5 8 7.5t11 2.5h12q10 0 17-7t7-17v-191q0-11-7-18t-18-7q-11 0-18 7t-7 18v115l-93-130q-4-5-9-7.5t-11-2.5h-12q-11 0-18 7t-7 18v190q0 11 7 18t18 7q11 0 18-7t7-18v-115Zm210 140h115q11 0 18-7t7-18q0-11-7-18t-18-7h-75v-44h75q11 0 18-7t7-18q0-11-7-18t-18-7h-75v-46h75q11 0 18-7t7-18q0-11-7-18t-18-7H400q-8 0-14 6t-6 14v200q0 8 6 14t14 6Zm220 0h160q17 0 28.5-11.5T820-400v-175q0-11-7-18t-18-7q-11 0-18 7t-7 18v155h-44v-115q0-11-7-18t-18-7q-11 0-18 7t-7 18v115h-46v-155q0-11-7-18t-18-7q-11 0-18 7t-7 18v175q0 17 11.5 28.5T620-360ZM120-240v-480 480Z"/></svg>`,
            selected: `<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e3e3e3"><path d="M132.31-180Q102-180 81-201q-21-21-21-51.31v-455.38Q60-738 81-759q21-21 51.31-21h695.38Q858-780 879-759q21 21 21 51.31v455.38Q900-222 879-201q-21 21-51.31 21H132.31Zm56.92-336.16L288.46-375q2.62 4.23 6.86 6.54 4.24 2.31 9.33 2.31h10.18q8.48 0 14.52-5.99 6.03-5.99 6.03-14.55v-186.39q0-9.14-5.8-14.95-5.8-5.82-14.92-5.82-9.12 0-14.97 5.82-5.84 5.81-5.84 14.95v129.24L197-585q-3.23-4.61-7.75-6.73t-9.94-2.12h-10.26q-9.39 0-15.38 6.03-5.98 6.04-5.98 15.51v185.39q0 9.14 5.81 14.95 5.8 5.82 14.92 5.82 9.12 0 14.96-5.82 5.85-5.81 5.85-14.95v-129.24Zm215 150.01h108.85q9.14 0 14.95-5.81 5.82-5.8 5.82-14.92 0-9.12-5.82-14.97-5.81-5.84-14.95-5.84h-79.23v-50.16h79.23q9.14 0 14.95-5.8 5.82-5.8 5.82-14.92 0-9.12-5.82-14.97-5.81-5.84-14.95-5.84h-79.23v-52.93h79.23q9.14 0 14.95-5.8 5.82-5.8 5.82-14.92 0-9.12-5.82-14.97-5.81-5.85-14.95-5.85H404.23q-7.23 0-12.65 5.43-5.43 5.42-5.43 12.65v191.54q0 7.23 5.43 12.65 5.42 5.43 12.65 5.43Zm214.23 0h160q14.69 0 24.27-9.58t9.58-24.27v-173.08q0-9.14-5.81-14.95-5.8-5.82-14.92-5.82-9.12 0-14.96 5.82-5.85 5.81-5.85 14.95v159.23h-50.92v-119.23q0-9.14-5.81-14.95-5.8-5.82-14.92-5.82-9.12 0-14.97 5.82-5.84 5.81-5.84 14.95v119.23h-52.16v-159.23q0-9.14-5.8-14.95-5.8-5.82-14.92-5.82-9.12 0-14.97 5.82-5.84 5.81-5.84 14.95V-400q0 14.69 9.57 24.27 9.58 9.58 24.27 9.58Z"/></svg>`
        }
    };

    // 3. Logic for Profile Quick Filters
    function getBaseUrl() {
        const parts = window.location.pathname.split('/').filter(Boolean);
        return `/${parts[0]}/${parts[1]}`;
    }

    function createCustomButton(text, href, svgIcon, baseClassNames) {
        const btn = document.createElement('a');
        btn.href = href;
        btn.className = `${baseClassNames} xh-custom-filter-btn`;
        btn.innerHTML = `
            <span class="icon-container" style="display: flex; align-items: center;">${svgIcon}</span>
            <span class="body-bold-8643e primary-8643e">${text}</span>
        `;
        return btn;
    }

    function handleProfileFilters() {
        if (document.querySelector('.xh-custom-filter-btn')) return;

        const buttons = Array.from(document.querySelectorAll('button.container-a4c1b.button-a4c1b'));
        const filterButton = buttons.find(btn => btn.textContent.trim().includes('Filters'));

        if (filterButton) {
            // Evaluates path ending with target or target followed immediately by a slash (for pages like /hd/2)
            const isHDActive = /\/hd(\/|$)/.test(window.location.pathname);
            const isNewActive = /\/newest(\/|$)/.test(window.location.pathname);

            const baseUrl = getBaseUrl();
            const btnClasses = filterButton.className;

            const hdSvg = isHDActive ? svgs.hd.selected : svgs.hd.default;
            const newSvg = isNewActive ? svgs.new.selected : svgs.new.default;

            const hdBtn = createCustomButton('HD', `${baseUrl}/hd`, hdSvg, btnClasses);
            const newBtn = createCustomButton('New', `${baseUrl}/newest`, newSvg, btnClasses);

            filterButton.parentNode.insertBefore(hdBtn, filterButton.nextSibling);
            filterButton.parentNode.insertBefore(newBtn, hdBtn.nextSibling);
        }
    }

    // 4. Logic for Auto-Displaying Video Meta Details
    function handleVideoMetaDisplay() {
        if (document.getElementById('xh-custom-meta-box')) return;

        const controlsElement = document.querySelector('div.controls');
        const abInfo = document.querySelector('div.ab-info[data-role="controls-info"]');

        if (controlsElement && abInfo) {
            const descEl = abInfo.querySelector('.controls-info__description');
            //Uncomment below if you want uploader name in the about box
            //const authorEl = abInfo.querySelector('.entity-info-container__author');
            const dateEl = abInfo.querySelector('.entity-info-container__date');

            if (descEl && dateEl) {
                const metaBox = document.createElement('div');
                metaBox.id = 'xh-custom-meta-box';

                let sublineHTML = '';
                //Uncomment below if you want uploader name in the about box
                //if (authorEl) {
                //    sublineHTML += `<span>${authorEl.innerHTML.trim()}</span>`;
                //}
                sublineHTML += `<span>${dateEl.textContent.trim()}</span>`;
                if(dateEl.getAttribute('data-tooltip')) {
                     sublineHTML += `<span>${dateEl.getAttribute('data-tooltip')}</span>`;
                }

                metaBox.innerHTML = `
                    <div class="xh-meta-desc">${descEl.innerHTML.trim()}</div>
                    <div class="xh-meta-subline">${sublineHTML}</div>
                `;

                controlsElement.parentNode.insertBefore(metaBox, controlsElement.nextSibling);
            }
        }
    }

    // 5. Universal Observer Loop
    const observer = new MutationObserver(() => {
        const path = window.location.pathname;
        if (path.includes('/pornstars/') || path.includes('/creators/')) {
            handleProfileFilters();
        }
        if (path.includes('/videos/') || path.includes('/movies/')) {
            handleVideoMetaDisplay();
        }
    });

    observer.observe(document.body, { childList: true, subtree: true });

})();