Highlight Text Search Buttons - Quick Cam Model Lookup / Find

Show search buttons when text is highlighted on specific websites

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         Highlight Text Search Buttons - Quick Cam Model Lookup / Find
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Show search buttons when text is highlighted on specific websites
// @match        *://onlyfans.com/*
// @match        *://camwhores.tv/*
// @match        https://www.camwhores.tv/*
// @match         https://www.showcamrips.com/*
// @match        *://livecamrips.to/*
// @match        *://simpcity.cr/*
// @match        *://camgirlfinder.net/*
// @match        *://nrtool.to/*
// @match         *://archivebate.com/*
// @match         *://nobodyhome.ws/*
// @match         *://camsmut.com/*
// @match         *://stripchat.com/*
// @match         *://*.bongocams.com/*
// @match         *://www.sexycamx.com/*
// @match         *://chaturbate.com/*
// @grant        GM_openInTab
// @grant        unsafeWindow
// @license      None
// ==/UserScript==
(function() {
    'use strict';

    // ============ CONFIGURATION ============

    // Default search sites configuration
    const defaultSites = [
        { name: 'showcamrips', url: 'https://showcamrips.com/model/en/{username}/' },
        { name: 'livecamrips', url: 'https://www.livecamrips.to/search/{username}/1' },
        { name: 'archivebate', url: 'https://archivebate.com/profile/{username}' },
        { name: 'camsmut', url: 'https://camsmut.com/search?q={username}//' },
        { name: 'camwhores', url: 'https://camwhores.tv/search/{username}/' },
        { name: 'nobodyhome', url: 'https://nobodyhome.ws/search.php?action=do_search&postthread=1&keywords={username}' },
        { name: 'camgirlfinder', url: 'https://camgirlfinder.net/models?model={username}&platform=&gender=' },
        { name: 'nrtool', url: 'https://nrtool.to/nrtool/search?s={username}' },
        { name: 'simpcity', url: 'https://simpcity.cr/search/1/?q={username}' },
        { name: 'bongocams', url: 'https://ru2.bongocams.com/{username}' },
        { name: 'stripchat', url: 'https://stripchat.com/{username}' },
        { name: 'onlyfans', url: 'https://onlyfans.com/{username}' },
        { name: 'sexycamx', url: 'https://www.sexycamx.com/{username}' },
    ];

    // ============ SCRIPT LOGIC ============

    let buttonContainer = null;
    let selectedText = '';
    let useLowercase = false;

    // Enhanced function to open URL in new tab (bypasses site restrictions)
    function openUrlInNewTab(url) {
        // Method 1: Try GM_openInTab if available (most reliable)
        if (typeof GM_openInTab !== 'undefined') {
            try {
                GM_openInTab(url, { active: false, insert: true });
                return;
            } catch (e) {
                console.log('GM_openInTab failed, trying alternatives');
            }
        }

        // Method 2: Create a temporary anchor element with download attribute trick
        try {
            const a = document.createElement('a');
            a.href = url;
            a.target = '_blank';
            a.rel = 'noopener noreferrer';

            // This helps bypass some restrictions
            a.style.display = 'none';
            document.body.appendChild(a);

            // Dispatch a real click event
            const evt = new MouseEvent('click', {
                bubbles: true,
                cancelable: true,
                view: window
            });
            a.dispatchEvent(evt);

            // Clean up
            setTimeout(() => document.body.removeChild(a), 100);
            return;
        } catch (e) {
            console.log('Anchor method failed, trying window.open');
        }

        // Method 3: Standard window.open with enhanced parameters
        try {
            const newWindow = window.open(url, '_blank', 'noopener,noreferrer');
            if (newWindow) {
                newWindow.opener = null;
            }
        } catch (e) {
            // Method 4: Last resort - use location.href in a timeout
            console.log('All methods failed, using location fallback');
            setTimeout(() => {
                window.location.href = url;
            }, 100);
        }
    }

    // Create button container
    function createButtonContainer() {
        const container = document.createElement('div');
        container.id = 'highlight-search-container';
        container.style.cssText = `
            position: fixed;
            bottom: 20px;
            right: 20px;
            display: none;
            flex-direction: column;
            gap: 6px;
            z-index: 999999;
            padding: 10px;
            background: rgba(255, 255, 255, 0.98);
            border-radius: 10px;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
            backdrop-filter: blur(10px);
            border: 1px solid rgba(0, 0, 0, 0.1);
            max-width: 180px;
            max-height: 80vh;
            overflow-y: auto;
        `;

        // Add title
        const title = document.createElement('div');
        title.textContent = 'Search with:';
        title.style.cssText = `
            font-size: 11px;
            font-weight: 600;
            color: #666;
            margin-bottom: 2px;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
        `;
        container.appendChild(title);

        // Add lowercase checkbox
        const checkboxContainer = document.createElement('label');
        checkboxContainer.style.cssText = `
            display: flex;
            align-items: center;
            gap: 6px;
            font-size: 11px;
            color: #666;
            margin-bottom: 4px;
            cursor: pointer;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
        `;

        const checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.checked = useLowercase;
        checkbox.style.cssText = `
            cursor: pointer;
            width: 14px;
            height: 14px;
        `;

        checkbox.addEventListener('change', (e) => {
            useLowercase = e.target.checked;
        });

        const checkboxLabel = document.createElement('span');
        checkboxLabel.textContent = 'Lowercase';

        checkboxContainer.appendChild(checkbox);
        checkboxContainer.appendChild(checkboxLabel);
        container.appendChild(checkboxContainer);

        // Create buttons
        defaultSites.forEach(site => {
            const button = document.createElement('button');
            button.textContent = site.name;
            button.style.cssText = `
                padding: 6px 10px;
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                color: white;
                border: none;
                border-radius: 6px;
                cursor: pointer;
                font-size: 12px;
                font-weight: 500;
                font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
                transition: all 0.2s ease;
                white-space: nowrap;
                text-align: center;
            `;

            button.addEventListener('mouseenter', () => {
                button.style.transform = 'translateY(-1px)';
                button.style.boxShadow = '0 2px 8px rgba(0, 0, 0, 0.2)';
            });

            button.addEventListener('mouseleave', () => {
                button.style.transform = 'translateY(0)';
                button.style.boxShadow = 'none';
            });

            button.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();

                const username = useLowercase ? selectedText.toLowerCase() : selectedText;
                const finalUrl = site.url.replace('{username}', encodeURIComponent(username));

                openUrlInNewTab(finalUrl);
            });

            container.appendChild(button);
        });

        // Add close button
        const closeBtn = document.createElement('button');
        closeBtn.textContent = '✕';
        closeBtn.style.cssText = `
            position: absolute;
            top: 6px;
            right: 6px;
            width: 20px;
            height: 20px;
            border: none;
            background: rgba(0, 0, 0, 0.1);
            border-radius: 50%;
            cursor: pointer;
            font-size: 12px;
            color: #666;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.2s ease;
        `;

        closeBtn.addEventListener('mouseenter', () => {
            closeBtn.style.background = 'rgba(0, 0, 0, 0.2)';
        });

        closeBtn.addEventListener('mouseleave', () => {
            closeBtn.style.background = 'rgba(0, 0, 0, 0.1)';
        });

        closeBtn.addEventListener('click', () => {
            container.style.display = 'none';
        });

        container.appendChild(closeBtn);
        document.body.appendChild(container);
        return container;
    }

    // Handle text selection
    function handleTextSelection() {
        const selection = window.getSelection();
        const text = selection.toString().trim();

        if (text.length > 0) {
            selectedText = text;
            if (!buttonContainer) {
                buttonContainer = createButtonContainer();
            }
            buttonContainer.style.display = 'flex';
        } else {
            if (buttonContainer) {
                buttonContainer.style.display = 'none';
            }
        }
    }

    // Event listeners
    document.addEventListener('mouseup', handleTextSelection);
    document.addEventListener('keyup', handleTextSelection);
    document.addEventListener('selectionchange', handleTextSelection);

    // Hide buttons when clicking outside
    document.addEventListener('click', (e) => {
        if (buttonContainer && !buttonContainer.contains(e.target)) {
            const selection = window.getSelection();
            if (selection.toString().trim().length === 0) {
                buttonContainer.style.display = 'none';
            }
        }
    });

})();