Danbooru General Tags Copier with Textbox

快速复制Danbooru General类别下的所有标签,并在文本框中显示

// ==UserScript==
// @name         Danbooru General Tags Copier with Textbox
// @namespace    http://tampermonkey.net/
// @version      1.4
// @description  快速复制Danbooru General类别下的所有标签,并在文本框中显示
// @author       You
// @match        https://danbooru.donmai.us/posts/*
// @grant        GM_setClipboard
// @grant        GM_notification
// ==/UserScript==

(function() {
    'use strict';

    let tagsModal = null;
    let tagsTextarea = null;

    // 创建复制按钮
    function createCopyButton() {
        // 检查是否已存在按钮,避免重复创建
        if (document.getElementById('danbooru-copy-button')) {
            return;
        }

        const button = document.createElement('button');
        button.id = 'danbooru-copy-button';
        button.innerHTML = '复制General标签';
        button.style.cssText = `
            position: fixed;
            top: 100px;
            right: 20px;
            z-index: 10000;
            padding: 10px 15px;
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            box-shadow: 0 2px 5px rgba(0,0,0,0.3);
        `;

        button.addEventListener('mouseenter', () => {
            button.style.background = '#45a049';
        });

        button.addEventListener('mouseleave', () => {
            button.style.background = '#4CAF50';
        });

        button.addEventListener('click', showTagsModal);

        document.body.appendChild(button);
    }

    // 创建标签显示模态框
    function createTagsModal() {
        tagsModal = document.createElement('div');
        tagsModal.id = 'danbooru-tags-modal';
        tagsModal.style.cssText = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 500px;
            background: white;
            border-radius: 8px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.3);
            z-index: 10001;
            padding: 20px;
            display: none;
        `;

        const title = document.createElement('h3');
        title.textContent = 'General标签';
        title.style.cssText = `
            margin-top: 0;
            margin-bottom: 15px;
            color: #333;
        `;

        tagsTextarea = document.createElement('textarea');
        tagsTextarea.id = 'danbooru-tags-textarea';
        tagsTextarea.style.cssText = `
            width: 100%;
            height: 200px;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            resize: vertical;
            font-family: monospace;
            font-size: 14px;
        `;
        tagsTextarea.readOnly = true;

        const buttonContainer = document.createElement('div');
        buttonContainer.style.cssText = `
            display: flex;
            justify-content: space-between;
            margin-top: 15px;
        `;

        const copyButton = document.createElement('button');
        copyButton.textContent = '复制到剪贴板';
        copyButton.style.cssText = `
            padding: 8px 16px;
            background: #2196F3;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        `;
        copyButton.addEventListener('click', copyTagsToClipboard);

        const selectAllButton = document.createElement('button');
        selectAllButton.textContent = '全选';
        selectAllButton.style.cssText = `
            padding: 8px 16px;
            background: #FF9800;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        `;
        selectAllButton.addEventListener('click', () => {
            tagsTextarea.select();
        });

        const closeButton = document.createElement('button');
        closeButton.textContent = '关闭';
        closeButton.style.cssText = `
            padding: 8px 16px;
            background: #f44336;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        `;
        closeButton.addEventListener('click', () => {
            tagsModal.style.display = 'none';
            overlay.style.display = 'none';
        });

        // 创建模态框背景遮罩
        const overlay = document.createElement('div');
        overlay.id = 'danbooru-modal-overlay';
        overlay.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,0.5);
            z-index: 10000;
            display: none;
        `;
        overlay.addEventListener('click', () => {
            tagsModal.style.display = 'none';
            overlay.style.display = 'none';
        });

        buttonContainer.appendChild(copyButton);
        buttonContainer.appendChild(selectAllButton);
        buttonContainer.appendChild(closeButton);

        tagsModal.appendChild(title);
        tagsModal.appendChild(tagsTextarea);
        tagsModal.appendChild(buttonContainer);

        document.body.appendChild(overlay);
        document.body.appendChild(tagsModal);

        // 点击模态框内部不会关闭
        tagsModal.addEventListener('click', (e) => {
            e.stopPropagation();
        });
    }

    // 获取General标签 - 修复版本
    function getGeneralTags() {
        const generalTags = [];

        // 多种选择器尝试,确保能找到General标签
        const selectors = [
            'ul.general-tag-list',
            '.general-tag-list ul',
            '#tag-list .general-tag-list',
            '[class*="general-tag-list"]'
        ];

        let generalSection = null;
        for (const selector of selectors) {
            generalSection = document.querySelector(selector);
            if (generalSection) break;
        }

        if (!generalSection) {
            console.log('未找到General标签区域');
            // 调试:输出页面中所有可能的标签区域
            const allLists = document.querySelectorAll('ul');
            console.log('页面中的所有ul元素:', allLists);
            return generalTags;
        }

        console.log('找到General标签区域:', generalSection);

        // 查找标签链接
        const tagLinks = generalSection.querySelectorAll('a.search-tag');
        console.log('找到的标签链接数量:', tagLinks.length);

        tagLinks.forEach((link, index) => {
            const tagName = link.textContent.trim();
            console.log(`标签 ${index + 1}:`, tagName);

            // 过滤掉数字(帖子数量)和特殊字符
            if (tagName &&
                !/^\d+$/.test(tagName) &&
                !tagName.includes('k') &&
                !tagName.includes('M') &&
                !tagName.includes('»') &&
                tagName.length > 1) {
                generalTags.push(tagName);
            }
        });

        console.log('最终提取的标签:', generalTags);
        return generalTags;
    }

    // 显示标签模态框
    function showTagsModal() {
        const generalTags = getGeneralTags();

        if (generalTags.length > 0) {
            // 用逗号分隔标签
            const tagsString = generalTags.join(', ');
            tagsTextarea.value = tagsString;

            // 显示模态框和遮罩
            const overlay = document.getElementById('danbooru-modal-overlay');
            tagsModal.style.display = 'block';
            overlay.style.display = 'block';

            // 自动选择文本
            setTimeout(() => {
                tagsTextarea.select();
            }, 100);
        } else {
            showNotification('未找到General标签,请查看控制台获取详细信息');
            console.log('页面结构分析:');
            console.log('所有包含"general"的元素:', document.querySelectorAll('*[class*="general"]'));
            console.log('所有h3元素:', document.querySelectorAll('h3'));
        }
    }

    // 复制标签到剪贴板
    async function copyTagsToClipboard() {
        const tagsString = tagsTextarea.value;

        if (!tagsString) {
            showNotification('没有内容可复制');
            return;
        }

        try {
            // 方法1: 使用GM_setClipboard
            if (typeof GM_setClipboard !== 'undefined') {
                GM_setClipboard(tagsString, 'text');
                showNotification(`已复制 ${tagsString.split(',').length} 个标签到剪贴板`);
                return;
            }

            // 方法2: 使用navigator.clipboard
            if (navigator.clipboard && window.isSecureContext) {
                await navigator.clipboard.writeText(tagsString);
                showNotification(`已复制 ${tagsString.split(',').length} 个标签到剪贴板`);
                return;
            }

            // 方法3: 使用execCommand
            tagsTextarea.select();
            const successful = document.execCommand('copy');
            if (successful) {
                showNotification(`已复制 ${tagsString.split(',').length} 个标签到剪贴板`);
            } else {
                showNotification('复制失败,请手动复制文本框中的内容');
            }
        } catch (error) {
            console.error('复制失败:', error);
            showNotification('复制失败,请手动复制文本框中的内容');
        }
    }

    // 显示通知
    function showNotification(message) {
        if (typeof GM_notification !== 'undefined') {
            GM_notification({
                text: message,
                title: 'Danbooru标签复制',
                timeout: 3000
            });
        } else {
            // 创建简单的通知
            const notification = document.createElement('div');
            notification.textContent = message;
            notification.style.cssText = `
                position: fixed;
                top: 150px;
                right: 20px;
                background: #333;
                color: white;
                padding: 10px 15px;
                border-radius: 5px;
                z-index: 10002;
                box-shadow: 0 2px 5px rgba(0,0,0,0.3);
            `;
            document.body.appendChild(notification);
            setTimeout(() => {
                document.body.removeChild(notification);
            }, 3000);
        }
    }

    // 等待页面完全加载
    function waitForPageLoad() {
        // 如果页面已经加载完成
        if (document.readyState === 'complete' || document.readyState === 'interactive') {
            initializeScript();
        } else {
            document.addEventListener('DOMContentLoaded', initializeScript);
            // 备用:如果DOMContentLoaded已经触发
            setTimeout(initializeScript, 2000);
        }
    }

    // 初始化脚本
    function initializeScript() {
        console.log('Danbooru标签复制脚本初始化...');

        // 创建模态框
        createTagsModal();

        // 创建按钮
        createCopyButton();

        // 检查是否找到了General标签
        setTimeout(() => {
            const generalTags = getGeneralTags();
            if (generalTags.length === 0) {
                console.warn('脚本初始化时未找到General标签');
            } else {
                console.log('脚本初始化成功,找到', generalTags.length, '个General标签');
            }
        }, 1000);
    }

    // 启动脚本
    waitForPageLoad();
})();