☰

Highlight Text Search Buttons

Show search buttons when text is highlighted on specific websites

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Вам потребуется установить расширение, например Tampermonkey или Violentmonkey, чтобы установить этот скрипт.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         Highlight Text Search Buttons
// @namespace    http://tampermonkey.net/
// @version      2.1
// @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        *://forums.socialmediagirls.com/*
// @match        *://camgirlfinder.net/*
// @match        *://nrtool.st/*
// @match         *://archivebate.com/*
// @match         *://nobodyhome.ws/*
// @match         *://camsmut.com/*
// @match         *://stripchat.com/*
// @match         *://*.bongocams.com/*
// @match         *://www.sexycamx.com/*
// @match         *://chaturbate.com/*
// @match         *://striptube.cc/*
// @match         *://forums.socialmediagirls.com/*
// @match         *://recu.me/*
// @match         *://camripvault.site/*
// @grant        GM_openInTab
// @grant        unsafeWindow
// @license MIT
// ==/UserScript==
(function() {
    'use strict';

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

    // Default search sites configuration
    const defaultSites = [
        { name: 'camripvault', url: 'https://camripvault.site/browse?query={username}' },
        { 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.st/nrtool/search?s={username}' },
        { name: 'simpcity', url: 'https://simpcity.cr/search/1/?q={username}' },
        { name: 'socialmediagirls', url: 'https://forums.socialmediagirls.com/search/579063442/?q={username}&o=relevance' },
        { name: 'bongocams', url: 'https://ru3.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}' },
        { name: 'recume', url: 'https://recu.me/performer/{username}' },
        { name: 'striphub', url: 'https://striptube.cc/performer/{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';
            }
        }
    });

})();