Stripchat 黑名单

增强Stripchat体验:查找主播信息和隐藏不感兴趣的主播

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey, Greasemonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

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

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्क्रिप्ट व्यवस्थापक एक्स्टेंशन इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्क्रिप्ट व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्टाईल व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

// ==UserScript==
// @name         Stripchat 黑名单
// @namespace    https://greasyfork.org/fr/users/1468290-payamarre
// @version      1.1
// @license MIT
// @description  增强Stripchat体验:查找主播信息和隐藏不感兴趣的主播
// @author       NoOne
// @match        https://stripchat.com/*
// @match        https://*.stripchat.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @icon         https://stripchat.com/favicon.ico
// @run-at       document-end
// ==/UserScript==

(function () {
    'use strict';

    // ================ 公共功能 ================
    const common = {
        getModelName() {
            const path = window.location.pathname.split('/');
            const model = path[1];
            if (model && !['female', 'male', 'trans', 'new', 'tags', 'login', 'signup'].includes(model)) {
                return model;
            }
            return null;
        },

        createButton(id, svg, onClick, className = '') {
            const a = document.createElement('a');
            a.href = '#';
            a.className = className;
            a.innerHTML = svg;
            a.id = id;
            a.addEventListener('click', e => {
                e.preventDefault();
                onClick();
            });
            return a;
        }
    };

    // ================ 查找主播信息功能 ================
    function initFindMore() {
        let buttonsInserted = false;

        function insertButtons() {
            if (buttonsInserted) return true;

            const modelName = common.getModelName();
            if (!modelName) return false;

            const targetWrapper = document.querySelector('.view-cam-buttons-wrapper');
            if (!targetWrapper || !targetWrapper.parentNode) return false;

            ['scfinder-button', 'recume-button', 'dodao-button', 'search-button'].forEach(id => {
                const oldBtn = document.getElementById(id);
                if (oldBtn) oldBtn.remove();
            });

            const scfinderBtn = common.createButton(
                'scfinder-button',
                `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="24" height="24">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M17.982 18.725A7.488 7.488 0 0 0 12 15.75a7.488 7.488 0 0 0-5.982 2.975m11.963 0a9 9 0 1 0-11.963 0m11.963 0A8.966 8.966 0 0 1 12 21a8.966 8.966 0 0 1-5.982-2.275M15 9.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
                </svg>`,
                () => window.open(`https://camgirlfinder.net/models/sc/${modelName}`, '_blank'),
                'enhanced-button'
            );

            const recumeBtn = common.createButton(
                'recume-button',
                `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="24" height="24">
                  <path stroke-linecap="round" stroke-linejoin="round" d="m15.75 10.5 4.72-4.72a.75.75 0 0 1 1.28.53v11.38a.75.75 0 0 1-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25h-9A2.25 2.25 0 0 0 2.25 7.5v9a2.25 2.25 0 0 0 2.25 2.25Z" />
                </svg>`,
                () => window.open(`https://recu.me/performer/${modelName}`, '_blank'),
                'enhanced-button'
            );

            const dodaoBtn = common.createButton(
                'dodao-button',
                `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="24" height="24">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M12 21v-8.25M15.75 21v-8.25M8.25 21v-8.25M3 9l9-6 9 6m-1.5 12V10.332A48.36 48.36 0 0 0 12 9.75c-2.551 0-5.056.2-7.5.582V21M3 21h18M12 6.75h.008v.008H12V6.75Z" />
                </svg>`,
                () => window.open(`https://dodao.xyz/?cat=&s=${modelName}`, '_blank'),
                'enhanced-button'
            );

            const searchBtn = common.createButton(
                'search-button',
                `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="24" height="24">
                  <path stroke-linecap="round" stroke-linejoin="round" d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418" />
                </svg>`,
                () => {
                    const urls = [
                        `https://www.google.com/search?q=%22${modelName}%22&num=10&uact=5`,
                        `https://yandex.com/search/?text=%22${modelName}%22`,
                        `https://recu.me/performer/${modelName}`,
                        `https://camgirlfinder.net/models/sc/${modelName}`,
                        `https://btdig.com/search?order=0&q="${modelName}"`,
                        `https://dodao.xyz/?cat=&s=${modelName}`
                    ];
                    urls.forEach((url, index) => {
                        setTimeout(() => window.open(url, '_blank'), index * 200);
                    });
                },
                'enhanced-button'
            );

            const buttonGroup = document.createElement('div');
            buttonGroup.style.display = 'flex';
            buttonGroup.style.gap = '18px';
            buttonGroup.style.alignItems = 'center';
            buttonGroup.appendChild(dodaoBtn);
            buttonGroup.appendChild(scfinderBtn);
            buttonGroup.appendChild(recumeBtn);
            buttonGroup.appendChild(searchBtn);

            targetWrapper.parentNode.insertBefore(buttonGroup, targetWrapper);

            buttonsInserted = true;
            return true;
        }

        const observer = new MutationObserver(() => insertButtons());
        observer.observe(document.body, { childList: true, subtree: true });
        setTimeout(insertButtons, 1000);
    }

    // ================ 隐藏不感兴趣主播功能 ================
    function initHideModels() {
        // 存储不感兴趣的主播列表
        let blockedModels = GM_getValue('blockedModels', {});

        // 创建管理面板按钮
        function createToggleButton() {
            const toggleBtn = document.createElement('button');
            toggleBtn.className = 'blocked-models-toggle';
            toggleBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" width="20" height="20">
                <path stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 0 0 1.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.451 10.451 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88" />
            </svg>`;
            toggleBtn.title = '管理已隐藏主播';
            toggleBtn.addEventListener('click', toggleBlockedModelsPanel);
            document.body.appendChild(toggleBtn);
        }

        // 创建管理面板
        function createBlockedModelsPanel() {
            const panel = document.createElement('div');
            panel.className = 'blocked-models-panel';
            panel.id = 'blocked-models-panel';

            const header = document.createElement('div');
            header.className = 'blocked-models-header';

            const title = document.createElement('h3');
            title.textContent = '已隐藏的主播';

            const closeBtn = document.createElement('button');
            closeBtn.className = 'unblock-btn';
            closeBtn.textContent = '关闭';
            closeBtn.addEventListener('click', () => {
                document.getElementById('blocked-models-panel').style.display = 'none';
            });

            header.appendChild(title);
            header.appendChild(closeBtn);

            const content = document.createElement('div');
            content.className = 'blocked-models-content';

            panel.appendChild(header);
            panel.appendChild(content);
            document.body.appendChild(panel);

            updateBlockedModelsList();
        }

        // 切换管理面板显示
        function toggleBlockedModelsPanel() {
            const panel = document.getElementById('blocked-models-panel');
            if (panel.style.display === 'block') {
                panel.style.display = 'none';
            } else {
                updateBlockedModelsList();
                panel.style.display = 'block';
            }
        }

        // 更新已隐藏主播列表
        function updateBlockedModelsList() {
            const content = document.querySelector('.blocked-models-content');
            content.innerHTML = '';

            const modelCount = Object.keys(blockedModels).length;

            if (modelCount === 0) {
                const emptyMsg = document.createElement('p');
                emptyMsg.textContent = '您还没有隐藏任何主播';
                emptyMsg.style.color = '#aaa';
                emptyMsg.style.textAlign = 'center';
                content.appendChild(emptyMsg);
                return;
            }

            for (const modelId in blockedModels) {
                const modelItem = document.createElement('div');
                modelItem.className = 'blocked-model-item';

                const modelName = document.createElement('span');
                modelName.className = 'blocked-model-name';
                modelName.textContent = blockedModels[modelId].name;

                const unblockBtn = document.createElement('button');
                unblockBtn.className = 'unblock-btn';
                unblockBtn.textContent = '取消隐藏';
                unblockBtn.dataset.modelId = modelId;
                unblockBtn.addEventListener('click', function() {
                    unblockModel(this.dataset.modelId);
                });

                modelItem.appendChild(modelName);
                modelItem.appendChild(unblockBtn);
                content.appendChild(modelItem);
            }
        }

        // 添加隐藏按钮到主播缩略图
        function addHideButtons() {
            const modelItems = document.querySelectorAll('.model-list-item:not(.processed-for-hiding)');

            modelItems.forEach(item => {
                // 标记为已处理
                item.classList.add('processed-for-hiding');

                // 获取主播ID和名称
                const linkEl = item.querySelector('a[href*="/"]');
                if (!linkEl) return;

                const href = linkEl.getAttribute('href');
                const modelId = href.split('/').pop();

                // 如果已经在屏蔽列表中,隐藏
                if (blockedModels[modelId]) {
                    item.style.display = 'none';
                    return;
                }

                // 创建隐藏按钮
                const hideBtn = document.createElement('button');
                hideBtn.className = 'hide-model-btn';
                hideBtn.innerHTML = '&times;';
                hideBtn.title = '隐藏此主播';
                hideBtn.dataset.modelId = modelId;

                // 获取主播名称
                const nameEl = item.querySelector('.model-name') || item.querySelector('a[href*="/"]');
                const modelName = nameEl ? nameEl.textContent.trim() : modelId;
                hideBtn.dataset.modelName = modelName;

                hideBtn.addEventListener('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    blockModel(this.dataset.modelId, this.dataset.modelName);
                });

                item.style.position = 'relative';
                item.appendChild(hideBtn);
            });
        }

        // 隐藏主播
        function blockModel(modelId, modelName) {
            blockedModels[modelId] = {
                name: modelName,
                blockedAt: new Date().toISOString()
            };

            GM_setValue('blockedModels', blockedModels);

            // 隐藏所有匹配的主播元素
            const modelItems = document.querySelectorAll(`.model-list-item`);
            modelItems.forEach(item => {
                const link = item.querySelector('a[href*="/"]');
                if (link && link.getAttribute('href').endsWith(`/${modelId}`)) {
                    item.style.display = 'none';
                }
            });

            // 如果面板打开,更新列表
            if (document.getElementById('blocked-models-panel').style.display === 'block') {
                updateBlockedModelsList();
            }
        }

        // 取消隐藏主播
        function unblockModel(modelId) {
            delete blockedModels[modelId];
            GM_setValue('blockedModels', blockedModels);

            // 重新显示匹配的主播元素
            const modelItems = document.querySelectorAll(`.model-list-item`);
            modelItems.forEach(item => {
                const link = item.querySelector('a[href*="/"]');
                if (link && link.getAttribute('href').endsWith(`/${modelId}`)) {
                    item.style.display = '';
                }
            });

            updateBlockedModelsList();
        }

        // 初始化隐藏主播功能
        function initHideFeature() {
            createToggleButton();
            createBlockedModelsPanel();

            // 初始隐藏已屏蔽主播
            addHideButtons();

            // 监听DOM变化,为新加载的主播添加隐藏按钮
            const observer = new MutationObserver(mutations => {
                let needToAddButtons = false;

                mutations.forEach(mutation => {
                    if (mutation.addedNodes.length) {
                        needToAddButtons = true;
                    }
                });

                if (needToAddButtons) {
                    addHideButtons();
                }
            });

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

        // 初始化隐藏主播功能
        initHideFeature();
    }

    // ================ 样式 ================
    function addStyles() {
        const styles = `
            /* 查找更多信息按钮样式 */
            .enhanced-button {
                display: inline-flex !important;
                justify-content: center;
                align-items: center;
                width: 40px;
                height: 40px;
                border-radius: 50%;
                border: 2px solid #feb601;
                background-color: inherit;
                color: inherit;
                transition: background-color 0.2s, color 0.2s, stroke 0.2s;
                cursor: pointer;
            }

            .enhanced-button:hover {
                background-color: #feb601;
                border: 2px solid #feb601;
            }

            .enhanced-button:hover svg {
                stroke: black;
            }

            .enhanced-button svg {
                width: 24px;
                height: 24px;
                stroke: currentColor;
            }

            /* 隐藏主播按钮样式 */
            .hide-model-btn {
                position: absolute;
                top: 35px;
                right: 8px;
                z-index: 100;
                background-color: #f03e3e;
                color: white;
                border: none;
                border-radius: 50%;
                width: 24px;
                height: 24px;
                font-size: 14px;
                line-height: 1;
                cursor: pointer;
                opacity: 0;
                transition: opacity 0.2s;
                display: flex;
                align-items: center;
                justify-content: center;
            }

            .model-list-item:hover .hide-model-btn {
                opacity: 0.8;
            }

            .hide-model-btn:hover {
                opacity: 1 !important;
                background-color: #e03131;
            }

            /* 管理面板样式 */
            .blocked-models-panel {
                position: fixed;
                top: 70px;
                right: 20px;
                width: 300px;
                max-height: 400px;
                background-color: #1a1a1a;
                border: 1px solid #333;
                border-radius: 8px;
                z-index: 10000;
                overflow: hidden;
                box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
                display: none;
            }

            .blocked-models-header {
                padding: 10px 15px;
                background-color: #2a2a2a;
                border-bottom: 1px solid #333;
                display: flex;
                justify-content: space-between;
                align-items: center;
            }

            .blocked-models-header h3 {
                margin: 0;
                color: #feb601;
                font-size: 16px;
            }

            .blocked-models-content {
                padding: 10px 15px;
                max-height: 300px;
                overflow-y: auto;
            }

            .blocked-model-item {
                display: flex;
                justify-content: space-between;
                align-items: center;
                padding: 8px 0;
                border-bottom: 1px solid #333;
            }

            .blocked-model-item:last-child {
                border-bottom: none;
            }

            .blocked-model-name {
                color: #fff;
                font-size: 14px;
            }

            .unblock-btn {
                background-color: #feb601;
                color: #000;
                border: none;
                border-radius: 4px;
                padding: 3px 8px;
                font-size: 12px;
                cursor: pointer;
            }

            .unblock-btn:hover {
                background-color: #ffcc33;
            }

            .blocked-models-toggle {
                position: fixed;
                top: 7px;
                right: 350px;
                background-color: #a2252d;
                color: #fff;
                border: none;
                border-radius: 50%;
                width: 40px;
                height: 40px;
                display: flex;
                align-items: center;
                justify-content: center;
                cursor: pointer;
                z-index: 9999;
            }

            .blocked-models-toggle svg {
                stroke: #fff;
            }

            .blocked-models-toggle:hover {
                background-color: #c42a35;
            }
        `;

        const styleEl = document.createElement('style');
        styleEl.textContent = styles;
        document.head.appendChild(styleEl);
    }

    // ================ 初始化 ================
    function init() {
        // 添加样式
        addStyles();

        // 初始化查找主播信息功能
        initFindMore();

        // 初始化隐藏主播功能
        initHideModels();
    }

    // 等待页面加载完成
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();