GreasyFork脚本过滤

GreasyFork脚本过滤器

当前为 2025-05-30 提交的版本,查看 最新版本

// ==UserScript==
// @name         GreasyFork脚本过滤
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  GreasyFork脚本过滤器
// @author       YourName
// @match        https://gf.qytechs.cn/zh-CN/scripts*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_addStyle
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    // 配置
    const CONFIG = {
        keywords: GM_getValue('filterKeywords', []) || [],
        caseSensitive: GM_getValue('caseSensitive', false),
        panelExpanded: GM_getValue('panelExpanded', true),
        debug: true
    };

    // 添加优化后的样式 - 修复按钮动画问题
    GM_addStyle(`
        /* 修复侧边栏定位 */
        .gf-sidebar {
            position: fixed;
            left: 0;
            top: 50%;
            transform: translateY(-50%) translateX(-100%);
            z-index: 99999;
            display: flex;
            transition: transform 0.3s ease;
            overflow: visible;
        }

        /* 展开状态 */
        .gf-sidebar.expanded {
            transform: translateY(-50%) translateX(0);
        }

        /* 控制面板 */
        .gf-control-panel {
            background: #2c3e50;
            color: white;
            width: 300px;
            padding: 15px;
            border-radius: 0 10px 10px 0;
            box-shadow: 3px 3px 10px rgba(0,0,0,0.3);
            display: flex;
            flex-direction: column;
            gap: 15px;
        }

        /* 面板标题 */
        .gf-panel-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding-bottom: 10px;
            border-bottom: 1px solid #3498db;
        }

        .gf-panel-title {
            color: #3498db;
            font-weight: bold;
            font-size: 18px;
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .gf-close-btn {
            background: #e74c3c;
            color: white;
            border: none;
            width: 28px;
            height: 28px;
            border-radius: 50%;
            font-size: 16px;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        /* 输入组 */
        .gf-input-group {
            display: flex;
            gap: 5px;
        }

        .gf-input-group input {
            flex: 1;
            padding: 10px 12px;
            border: 1px solid #3498db;
            border-radius: 4px;
            background: rgba(0,0,0,0.2);
            color: white;
            font-size: 14px;
        }

        .gf-button {
            background: #3498db;
            color: white;
            border: none;
            padding: 10px 15px;
            border-radius: 4px;
            cursor: pointer;
            font-weight: bold;
            white-space: nowrap;
            transition: background 0.3s;
            flex-shrink: 0;
        }

        .gf-button:hover {
            background: #2980b9;
        }

        .gf-button-add {
            background: #27ae60;
        }

        .gf-button-clear {
            background: #e74c3c;
        }

        /* 关键词容器 */
        .gf-keywords-container {
            display: flex;
            flex-direction: column;
            gap: 8px;
            max-height: 250px;
            overflow-y: auto;
            padding: 5px;
        }

        .gf-keyword-item {
            background: #3498db;
            padding: 8px 12px;
            border-radius: 4px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            font-size: 14px;
        }

        .gf-remove-keyword {
            background: none;
            border: none;
            color: white;
            cursor: pointer;
            font-weight: bold;
            font-size: 16px;
        }

        .gf-remove-keyword:hover {
            color: #e74c3c;
        }

        /* 控制按钮组 */
        .gf-control-buttons {
            display: flex;
            gap: 10px;
            margin-top: 10px;
        }

        .gf-toggle-container {
            display: flex;
            align-items: center;
            padding: 8px;
            background: rgba(0,0,0,0.1);
            border-radius: 4px;
        }

        /* 改进的展开按钮设计 - 移除宽度变化的悬停效果 */
        .gf-toggle-btn {
            background: #95a5a6;
            color: white;
            border: none;
            padding: 8px 12px;
            border-radius: 0 4px 4px 0;
            font-weight: bold;
            cursor: pointer;
            box-shadow: 2px 2px 5px rgba(0,0,0,0.2);
            writing-mode: vertical-rl;
            text-orientation: mixed;
            height: 80px;
            display: flex;
            align-items: center;
            justify-content: center;
            position: absolute;
            left: 100%;
            top: 50%;
            transform: translateY(-50%);
            z-index: 100001;
            font-size: 14px;
            transition: background 0.3s ease; /* 只保留背景色过渡 */
        }

        /* 简化悬停效果 - 仅改变背景色 */
        .gf-toggle-btn:hover {
            background: #7f8c8d;
        }

        .gf-hidden-script {
            display: none !important;
        }

        /* 滚动条样式 */
        .gf-keywords-container::-webkit-scrollbar {
            width: 6px;
        }

        .gf-keywords-container::-webkit-scrollbar-track {
            background: rgba(0,0,0,0.1);
            border-radius: 3px;
        }

        .gf-keywords-container::-webkit-scrollbar-thumb {
            background: #3498db;
            border-radius: 3px;
        }

        .gf-keywords-container::-webkit-scrollbar-thumb:hover {
            background: #2980b9;
        }
    `);

    // 创建侧边栏
    function createSidebar() {
        if (document.querySelector('.gf-sidebar')) {
            if (CONFIG.debug) console.log('侧边栏已存在');
            return;
        }

        const sidebar = document.createElement('div');
        sidebar.className = 'gf-sidebar';

        // 初始状态
        if (CONFIG.panelExpanded) {
            sidebar.classList.add('expanded');
        }

        const controlPanel = document.createElement('div');
        controlPanel.className = 'gf-control-panel';
        controlPanel.innerHTML = `
            <div class="gf-panel-header">
                <div class="gf-panel-title">
                    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path d="M4 6H20M7 12H17M9 18H15" stroke="#3498db" stroke-width="2" stroke-linecap="round"/>
                    </svg>
                    脚本过滤设置
                </div>
                <button class="gf-close-btn" id="gf-close-btn">×</button>
            </div>

            <div class="gf-input-group">
                <input type="text" id="gf-keyword-input" placeholder="输入屏蔽词..." autocomplete="off">
                <button class="gf-button gf-button-add" id="gf-add-keyword">添加</button>
            </div>

            <div class="gf-keywords-container" id="gf-keywords-list">
                <div style="color:#bdc3c7; padding:10px; text-align:center;">无屏蔽关键词</div>
            </div>

            <div class="gf-control-buttons">
                <button class="gf-button gf-button-clear" id="gf-clear-keywords">清除所有</button>
                <div class="gf-toggle-container">
                    <input type="checkbox" id="gf-case-sensitive" ${CONFIG.caseSensitive ? 'checked' : ''}>
                    <label for="gf-case-sensitive" style="margin-left: 5px; font-size: 14px;">区分大小写</label>
                </div>
            </div>
        `;

        sidebar.appendChild(controlPanel);

        const toggleBtn = document.createElement('button');
        toggleBtn.className = 'gf-toggle-btn';
        toggleBtn.id = 'gf-toggle-btn';
        toggleBtn.textContent = '过滤设置';
        sidebar.appendChild(toggleBtn);

        document.body.appendChild(sidebar);

        if (CONFIG.debug) console.log('侧边栏已创建');

        renderKeywords();

        return sidebar;
    }

    // 渲染关键词列表
    function renderKeywords() {
        const container = document.getElementById('gf-keywords-list');
        if (!container) return;

        container.innerHTML = '';

        if (CONFIG.keywords.length === 0) {
            container.innerHTML = '<div style="color:#bdc3c7; padding:10px; text-align:center;">无屏蔽关键词</div>';
            return;
        }

        CONFIG.keywords.forEach(keyword => {
            const item = document.createElement('div');
            item.className = 'gf-keyword-item';
            item.innerHTML = `
                ${keyword}
                <button class="gf-remove-keyword" data-keyword="${keyword}" title="删除此关键词">×</button>
            `;
            container.appendChild(item);
        });

        document.querySelectorAll('.gf-remove-keyword').forEach(btn => {
            btn.addEventListener('click', function() {
                const keyword = this.getAttribute('data-keyword');
                removeKeyword(keyword);
            });
        });
    }

    // 添加关键词
    function addKeyword(keyword) {
        keyword = keyword.trim();
        if (keyword && !CONFIG.keywords.includes(keyword)) {
            CONFIG.keywords.push(keyword);
            GM_setValue('filterKeywords', CONFIG.keywords);
            renderKeywords();
            filterScripts();
        }
    }

    // 移除关键词
    function removeKeyword(keyword) {
        const index = CONFIG.keywords.indexOf(keyword);
        if (index !== -1) {
            CONFIG.keywords.splice(index, 1);
            GM_setValue('filterKeywords', CONFIG.keywords);
            renderKeywords();
            filterScripts();
        }
    }

    // 切换侧边栏状态
    function toggleSidebar() {
        const sidebar = document.querySelector('.gf-sidebar');
        if (!sidebar) {
            if (CONFIG.debug) console.error('侧边栏元素未找到');
            return;
        }

        const isExpanded = sidebar.classList.contains('expanded');

        if (isExpanded) {
            sidebar.classList.remove('expanded');
            CONFIG.panelExpanded = false;
        } else {
            sidebar.classList.add('expanded');
            CONFIG.panelExpanded = true;
        }

        GM_setValue('panelExpanded', CONFIG.panelExpanded);

        if (CONFIG.debug) {
            console.log('侧边栏状态:', CONFIG.panelExpanded ? '展开' : '折叠');
        }
    }

    // 简单高效的匹配函数
    function containsKeyword(text, keyword, caseSensitive) {
        if (!text || !keyword) return false;
        return caseSensitive ?
            text.indexOf(keyword) !== -1 :
            text.toLowerCase().indexOf(keyword.toLowerCase()) !== -1;
    }

    // 高效过滤脚本 - 仅检测标题
    function filterScripts() {
        const caseSensitiveCheckbox = document.getElementById('gf-case-sensitive');
        if (caseSensitiveCheckbox) {
            CONFIG.caseSensitive = caseSensitiveCheckbox.checked;
            GM_setValue('caseSensitive', CONFIG.caseSensitive);
        }

        const scriptItems = document.querySelectorAll('.script-list > li');
        if (!scriptItems.length) return;

        if (CONFIG.keywords.length === 0) {
            scriptItems.forEach(item => {
                item.classList.remove('gf-hidden-script');
            });
            return;
        }

        scriptItems.forEach(item => {
            const titleElement = item.querySelector('h2 a');
            if (!titleElement) return;

            const titleText = titleElement.textContent || titleElement.innerText;

            let isMatch = false;
            for (const keyword of CONFIG.keywords) {
                if (containsKeyword(titleText, keyword, CONFIG.caseSensitive)) {
                    isMatch = true;
                    break;
                }
            }

            if (isMatch) {
                item.classList.add('gf-hidden-script');
            } else {
                item.classList.remove('gf-hidden-script');
            }
        });
    }

    // 设置事件监听器
    function setupEventListeners() {
        // 添加关键词按钮
        document.getElementById('gf-add-keyword')?.addEventListener('click', function() {
            const input = document.getElementById('gf-keyword-input');
            if (input) {
                addKeyword(input.value.trim());
                input.value = '';
                input.focus();
            }
        });

        // 输入框回车事件
        document.getElementById('gf-keyword-input')?.addEventListener('keypress', function(e) {
            if (e.key === 'Enter') {
                document.getElementById('gf-add-keyword')?.click();
            }
        });

        // 清除所有关键词
        document.getElementById('gf-clear-keywords')?.addEventListener('click', function() {
            CONFIG.keywords = [];
            GM_setValue('filterKeywords', CONFIG.keywords);
            renderKeywords();
            filterScripts();
        });

        // 区分大小写切换
        const caseSensitiveCheckbox = document.getElementById('gf-case-sensitive');
        if (caseSensitiveCheckbox) {
            caseSensitiveCheckbox.addEventListener('change', filterScripts);
        }

        // 切换按钮
        document.getElementById('gf-toggle-btn')?.addEventListener('click', function(e) {
            e.stopPropagation();
            toggleSidebar();
        });

        // 关闭按钮
        document.getElementById('gf-close-btn')?.addEventListener('click', function(e) {
            e.stopPropagation();
            toggleSidebar();
        });
    }

    // 主初始化函数
    function init() {
        try {
            if (CONFIG.debug) {
                console.groupCollapsed('[GF Filter] 初始化调试信息');
                console.log('匹配URL:', window.location.href);
                console.log('配置:', CONFIG);
            }

            // 创建侧边栏
            createSidebar();

            // 设置事件监听
            setupEventListeners();

            // 初始过滤
            const filterRetry = () => {
                if (document.querySelector('.script-list')) {
                    if (CONFIG.debug) console.log('找到脚本列表,开始过滤');
                    filterScripts();
                } else {
                    if (CONFIG.debug) console.log('未找到脚本列表,等待中...');
                    setTimeout(filterRetry, 500);
                }
            };

            filterRetry();

            if (CONFIG.debug) {
                console.log('初始化完成');
                console.groupEnd();
            }
        } catch (error) {
            console.error('[脚本过滤器] 初始化错误:', error);
        }
    }

    // 确保页面加载完成后执行
    if (document.readyState === 'complete') {
        init();
    } else {
        window.addEventListener('load', init);
        document.addEventListener('DOMContentLoaded', init);
    }

    // 全局对象定义
    window.GF_Filter = {
        version: '8.0',
        reload: init,
        config: CONFIG,
        toggleSidebar: toggleSidebar
    };
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址