Add "Find on Spotify" Button to LINE Music Charts

Adds a button to find the song on Spotify on the LINE Music website.

// ==UserScript==
// @name         Add "Find on Spotify" Button to LINE Music Charts
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  Adds a button to find the song on Spotify on the LINE Music website.
// @match        https://music.line.me/*
// @author       Forkinthe.net
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    function createSpotifyButton(songTitle, artistName) {
        let btn = document.createElement('button');
        btn.innerText = 'Find on Spotify';
        btn.style.marginLeft = '10px';
        btn.style.backgroundColor = '#00c55e';
        btn.style.border = '1px solid #00c55e';
        btn.style.color = '#fff';
        btn.style.display = 'inline-block';
        btn.style.borderRadius = '4px';
        btn.style.fontSize = '15px';
        btn.style.lineHeight = '20px';
        btn.style.verticalAlign = 'top';
        btn.style.textAlign = 'center';
        btn.style.cursor = 'pointer';
        btn.onclick = function() {
            let query = encodeURIComponent(`${songTitle} ${artistName}`);
            window.open(`https://open.spotify.com/search/${query}`, '_blank');
        };
        return btn;
    }

    function addSpotifyButtons() {
        let tracklist = document.querySelector('.tracklist');
        if (!tracklist) {
            console.log('Tracklist not found.');
            return;
        }

        let rows = tracklist.getElementsByTagName('tr');
        console.log(`Found ${rows.length} rows.`);
        for (let row of rows) {
            // Remove existing Spotify button cells
            let existingButtonCell = row.querySelector('.spotify-button-cell');
            if (existingButtonCell) {
                existingButtonCell.remove();
            }

            let songCell = row.querySelector('.song');
            let artistCell = row.querySelector('.artist');

            if (songCell && artistCell) {
                let songLink = songCell.querySelector('a.link_text');
                let songTitle = songLink ? songLink.title.trim() : null;
                let artistName = artistCell.title.trim();

                if (songTitle && artistName) {
                    console.log(`Adding button for: ${songTitle} by ${artistName}`);

                    let spotifyButton = createSpotifyButton(songTitle, artistName);
                    spotifyButton.classList.add('spotify-button');

                    // Create a new td element for the button
                    let spotifyTd = document.createElement('td');
                    spotifyTd.classList.add('spotify-button-cell');
                    spotifyTd.appendChild(spotifyButton);

                    // Append the new td element to the row
                    row.appendChild(spotifyTd);
                } else {
                    console.log('Song title or artist name not found in row:', row);
                }
            } else {
                console.log('Song or artist cell not found in row:', row);
            }
        }
    }

    // Debounce function to limit how often addSpotifyButtons is called
    function debounce(func, wait) {
        let timeout;
        return function(...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    }

    const debouncedAddSpotifyButtons = debounce(addSpotifyButtons, 500);

    let observer;

    function initMutationObserver() {
        const tracklist = document.querySelector('.tracklist');
        if (tracklist) {
            console.log('Tracklist found.');
            debouncedAddSpotifyButtons();

            // Disconnect previous observer if it exists
            if (observer) {
                observer.disconnect();
            }

            // Create a new observer to detect changes in the tracklist
            observer = new MutationObserver((mutations) => {
                let relevantMutation = mutations.some(mutation =>
                    Array.from(mutation.addedNodes).some(node => node.nodeType === 1 && node.matches('tr')) ||
                    Array.from(mutation.removedNodes).some(node => node.nodeType === 1 && node.matches('tr'))
                );
                if (relevantMutation) {
                    console.log('Tracklist changed.');
                    debouncedAddSpotifyButtons();
                }
            });

            // Start observing the tracklist for changes
            observer.observe(tracklist, { childList: true });
        } else {
            console.log('Waiting for tracklist...');
            setTimeout(initMutationObserver, 500);
        }
    }

    // Function to monitor navigation changes
    function monitorNavigation() {
        let currentPath = window.location.pathname;
        setInterval(() => {
            if (window.location.pathname !== currentPath) {
                currentPath = window.location.pathname;
                console.log('Navigation detected. Re-initializing observer.');
                initMutationObserver();
            }
        }, 1000);
    }

    // Run the initMutationObserver function after the page is fully loaded
    window.addEventListener('load', () => {
        console.log('Page loaded.');
        initMutationObserver();
        monitorNavigation();
    });
})();

QingJ © 2025

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