KCE - Search Model on Web

Floating search panel restricted only to model profiles

Terá de instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

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

Terá de instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Terá de instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Terá de instalar uma extensão como Tampermonkey para instalar este script.

Terá de instalar uma extensão de gestão de scripts de utilizador para instalar este script.

(Já tenho um gestor de scripts de utilizador, deixe-me instalá-lo!)

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão como Stylus para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

Terá de instalar uma extensão de gestão de estilos de utilizador para instalar este estilo.

(Já tenho um gestor de estilos de utilizador, deixe-me instalá-lo!)

// ==UserScript==
// @name         KCE - Search Model on Web
// @namespace    kce_search_model_on_web_userscript
// @version      15.5
// @description  Floating search panel restricted only to model profiles
// @author       KCE
// @icon         data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><text y=".9em" font-size="85">👤</text></svg>
// @match        *://*.xhamster.com/pornstars/*
// @match        *://*.xhamster.com/creators/*
// @match        *://*.xhamster.com/channels/*
// @match        *://*.xhamster.com/users/*
// @match        *://*.pornhub.com/model/*
// @match        *://*.pornhub.com/pornstar/*
// @match        *://*.pornhub.com/channels/*
// @match        *://*.xvideos.com/models/*
// @match        *://*.xvideos.com/profiles/*
// @match        *://*.xvideos.com/channels/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const siteSelectors = {
        'pornhub.com': [
            '.name h1[itemprop="name"]',
            '.floatLeft.titleWrapper > div.title.floatLeft > h1'
        ],
        'xvideos.com': [
            '.text-danger',
            '#profile-title > div.profile-infos:last-child > div:first-child > h2.with-aka:last-child > strong.text-danger:nth-child(2)'
        ],
        'xhamster.com': [
            'div.main-wrap:nth-child(4) > div.layoutPage:nth-child(4) > div.user-header.user-header--small:first-child > div.width-wrap > div.user-info-section:nth-child(2) > div.user-top-infoblock:first-child > div.user-name:first-child > a.value:first-child',
            'div.user-profile-header__name-row > h1',
            '.h3-bold-8643e.primary-8643e.landing-info__user-title',
            '.item-50dd2',
            'div.wrapper.settingsPage:nth-child(12) > div.container.amateur-view-page:last-child > div.amateurModel.noBio:nth-child(8) > div.withCover > section.topProfileHeader > div.coverImage:nth-child(2) > div.bottomGradient:nth-child(2) > div.nameSubscribe > div.name:first-child',
            'div.main-wrap:nth-child(4) > div.layoutPage:nth-child(4) > main:first-child > div.width-wrap > article.pornstar-container > div.category-info.pornstar.with-tabs:first-child > div.pornstar-info:first-child > div.landing-info > div.landing-info__wrapper > div.landing-info__user.landing-info__user--space-between:last-child > div:first-child > div.landing-info__user-name > h2.h3-bold-8643e.primary-8643e.landing-info__user-title:first-child'
        ]
    };

    const hostname = window.location.hostname;
    let selectors = null;

    for (const site in siteSelectors) {
        if (hostname.includes(site)) {
            selectors = siteSelectors[site];
            break;
        }
    }

    if (!selectors) return;

    let panelInstance = null;
    let lastUsername = null;

    function getUsername() {
        for (const selector of selectors) {
            const el = document.querySelector(selector);
            if (el) {
                const text = el.textContent.trim();
                if (text) return text;
            }
        }
        return null;
    }

    function createOrUpdatePanel() {
        const username = getUsername();
        if (!username) {
            if (panelInstance) {
                panelInstance.remove();
                panelInstance = null;
                lastUsername = null;
            }
            return;
        }

        if (username === lastUsername && panelInstance && document.body.contains(panelInstance)) return;
        lastUsername = username;

        if (panelInstance && document.body.contains(panelInstance)) {
            updatePanelLinks(panelInstance, username);
            return;
        }

        panelInstance = document.createElement('div');
        panelInstance.id = 'kce-floating-panel';
        panelInstance.style.position = 'fixed';
        panelInstance.style.bottom = '20px';
        panelInstance.style.right = '20px';
        panelInstance.style.zIndex = '999999';
        panelInstance.style.background = 'rgba(20, 20, 20, 0.9)';
        panelInstance.style.backdropFilter = 'blur(10px)';
        panelInstance.style.border = '1px solid rgba(255, 255, 255, 0.15)';
        panelInstance.style.borderRadius = '12px';
        panelInstance.style.padding = '10px 14px';
        panelInstance.style.boxShadow = '0 8px 32px rgba(0, 0, 0, 0.4)';
        panelInstance.style.display = 'flex';
        panelInstance.style.flexDirection = 'column';
        panelInstance.style.gap = '8px';
        panelInstance.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
        panelInstance.style.color = '#fff';
        panelInstance.style.transition = 'opacity 0.3s ease';

        const header = document.createElement('div');
        header.style.display = 'flex';
        header.style.justifyContent = 'space-between';
        header.style.alignItems = 'center';
        header.style.fontSize = '11px';
        header.style.color = '#aaa';
        header.style.borderBottom = '1px solid rgba(255, 255, 255, 0.1)';
        header.style.paddingBottom = '4px';

        const title = document.createElement('span');
        title.textContent = 'Search model on web 🤔';
        header.appendChild(title);

        const closeBtn = document.createElement('span');
        closeBtn.textContent = '×';
        closeBtn.style.cursor = 'pointer';
        closeBtn.style.fontSize = '14px';
        closeBtn.style.fontWeight = 'bold';
        closeBtn.onclick = () => {
            if (panelInstance) panelInstance.remove();
            panelInstance = null;
        };
        header.appendChild(closeBtn);

        panelInstance.appendChild(header);

        const linksContainer = document.createElement('div');
        linksContainer.id = 'kce-links-container';
        linksContainer.style.display = 'flex';
        linksContainer.style.gap = '6px';
        panelInstance.appendChild(linksContainer);

        updatePanelLinks(panelInstance, username);
        document.body.appendChild(panelInstance);
    }

    function updatePanelLinks(panel, username) {
        const container = panel.querySelector('#kce-links-container');
        if (!container) return;
        container.innerHTML = '';

        const engines = [
            { name: 'Y', fullName: 'Yandex', url: `https://yandex.com/search/?text=${encodeURIComponent(username)}`, color: '#fc3f1d' },
            { name: 'G', fullName: 'Google', url: `https://www.google.com/search?q=${encodeURIComponent(username)}`, color: '#4285F4' },
            { name: 'B', fullName: 'Bing', url: `https://www.bing.com/search?q=${encodeURIComponent(username)}`, color: '#00b294' },
            { name: 'V', fullName: 'Brave', url: `https://search.brave.com/search?q=${encodeURIComponent(username)}`, color: '#FB542B' },
            { name: 'D', fullName: 'DuckDuckGo', url: `https://duckduckgo.com/?q=${encodeURIComponent(username)}`, color: '#DE5833' }
        ];

        engines.forEach(engine => {
            const anchor = document.createElement('a');
            anchor.href = engine.url;
            anchor.target = '_blank';
            anchor.title = engine.fullName;
            anchor.textContent = engine.name;
            anchor.style.display = 'flex';
            anchor.style.alignItems = 'center';
            anchor.style.justifyContent = 'center';
            anchor.style.width = '32px';
            anchor.style.height = '32px';
            anchor.style.borderRadius = '8px';
            anchor.style.background = 'rgba(255, 255, 255, 0.08)';
            anchor.style.color = engine.color;
            anchor.style.fontSize = '14px';
            anchor.style.fontWeight = '900';
            anchor.style.textDecoration = 'none';
            anchor.style.transition = 'all 0.2s ease';

            anchor.onmouseover = () => {
                anchor.style.background = 'rgba(255, 255, 255, 0.15)';
                anchor.style.transform = 'translateY(-2px)';
                anchor.style.boxShadow = `0 4px 12px ${engine.color}44`;
            };
            anchor.onmouseout = () => {
                anchor.style.background = 'rgba(255, 255, 255, 0.08)';
                anchor.style.transform = 'translateY(0)';
                anchor.style.boxShadow = 'none';
            };

            container.appendChild(anchor);
        });
    }

    createOrUpdatePanel();
    setInterval(createOrUpdatePanel, 1500);

})();