Copy Genius Lyrics

Adds a button to copy lyrics from Genius.com

当前为 2025-04-01 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Copy Genius Lyrics
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Adds a button to copy lyrics from Genius.com
// @match        https://genius.com/*
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    /** Error logging */
    const logError = (error, context) => console.error(`[Copy Genius Lyrics] Error in ${context}:`, error);

    /** Copies lyrics to clipboard */
    const copyLyrics = () => {
        try {
            const lyrics = [...document.querySelectorAll('[data-lyrics-container="true"]')]
            .map(container => container.innerText.trim())
            .join('\n\n');

            if (!lyrics) {
                showNotification('No lyrics found.');
                return;
            }

            navigator.clipboard.writeText(lyrics)
                .then(() => showNotification('Lyrics copied!'))
                .catch(error => {
                logError(error, 'copyLyrics (clipboard)');
                showNotification('Failed to copy.');
            });

        } catch (error) {
            logError(error, 'copyLyrics');
            showNotification('An error occurred.');
        }
    };

    /** Displays a notification message */
    const showNotification = (message) => {
        try {
            const notification = document.createElement('div');
            notification.className = 'copy-lyrics-notification';
            notification.textContent = message;
            document.body.appendChild(notification);

            setTimeout(() => {
                notification.style.opacity = '0';
                setTimeout(() => notification.remove(), 500);
            }, 2000);
        } catch (error) {
            logError(error, 'showNotification');
        }
    };

    /** Initializes the copy button and injects it into the DOM */
    const initCopyButton = () => {
        try {
            const headerContainer = document.querySelector('div[class*="LyricsHeader__Container"]');
            if (!headerContainer) {
                logError('Target container not found (LyricsHeader__Container)', 'DOM initialization');
                return;
            }

            if (document.querySelector('#copy-lyrics-button')) return; // Avoid duplicate buttons

            const button = document.createElement('button');
            button.id = 'copy-lyrics-button';
            button.textContent = 'Copy Lyrics';
            button.addEventListener('click', copyLyrics);
            headerContainer.appendChild(button);
        } catch (error) {
            logError(error, 'initCopyButton');
        }
    };

    /** Injects custom styles for the button and notification */
    const injectStyles = () => {
        GM_addStyle(`
            #copy-lyrics-button {
                margin-left: 10px;
                padding: 8px 15px;
                font-size: 14px;
                background-color: #1db954;
                color: white;
                border: none;
                border-radius: 5px;
                box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
                cursor: pointer;
                transition: background-color 0.2s ease-in-out;
                order: -1;
            }

            #copy-lyrics-button:hover {
                background-color: #1ed760;
            }

            .copy-lyrics-notification {
                position: fixed;
                bottom: 20px;
                right: 20px;
                padding: 10px 20px;
                background-color: #1db954;
                color: white;
                font-size: 14px;
                border-radius: 5px;
                opacity: 0;
                animation: fadeInOut 2.5s forwards;
                z-index: 1000;
            }

            @keyframes fadeInOut {
                0% { opacity: 0; transform: translateY(20px); }
                10% { opacity: 1; transform: translateY(0); }
                90% { opacity: 1; transform: translateY(0); }
                100% { opacity: 0; transform: translateY(20px); }
            }
        `);
    };

    /** Initializes the script */
    const init = () => {
        injectStyles();
        initCopyButton();
    };

    // Run script after page load
    window.addEventListener('load', init);
})();