Tidal Special

Click on elements and copy links to clipboard with user confirmation and success message, and download links as a .txt file

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

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

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         Tidal Special
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  Click on elements and copy links to clipboard with user confirmation and success message, and download links as a .txt file
// @author       You
// @match        https://tidal.com/browse/playlist/*
// @match        https://pixeldrain.com/*
// @icon         https://w7.pngwing.com/pngs/973/746/png-transparent-tidal-round-logo-tech-companies-thumbnail.png
// @grant        none
// @license      MIT
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    // Function to read text from the clipboard
    async function readClipboard() {
        try {
            const text = await navigator.clipboard.readText();
            return text;
        } catch (err) {
            console.error('Failed to read clipboard:', err);
        }
    }

    function createLoader() {
        // Check if the loader already exists
        if (document.querySelector('.loader-overlay')) {
            return; // Exit if the loader is already present
        }

        // Create the overlay div
        const overlay = document.createElement('div');
        overlay.className = 'loader-overlay'; // Add a class for easy removal
        overlay.style.position = 'fixed';
        overlay.style.top = '0';
        overlay.style.left = '0';
        overlay.style.width = '100vw';
        overlay.style.height = '100vh';
        overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.8)'; // Black background with slight transparency
        overlay.style.color = '#fff'; // White text color
        overlay.style.display = 'flex';
        overlay.style.flexDirection = 'column'; // Stack items vertically
        overlay.style.alignItems = 'center';
        overlay.style.justifyContent = 'center';
        overlay.style.fontSize = '1.5em';
        overlay.style.zIndex = '9999'; // Ensure it's on top of other content

        // Add the loading text
        const loadingText = document.createElement('div');
        loadingText.className = 'loader-text';
        loadingText.innerHTML = '<h1>STAY ON PAGE </h1>';
        loadingText.style.textAlign = "center";
        overlay.appendChild(loadingText);

        // Create the button
        const button = document.createElement('button');
        button.textContent = 'Start Extraction';
        button.style.marginTop = '20px'; // Space between text and button
        button.style.padding = '10px 20px';
        button.style.cursor = 'pointer';

        // Attach the click event handler to the button
        button.addEventListener('click', () => {
            handleClick()
            button.hidden = true
        });

        // Add the button to the overlay
        overlay.appendChild(button);

        // Append the overlay to the body
        document.body.appendChild(overlay);
    }

    function updateLoaderMessage(message) {
        const loadingText = document.querySelector('.loader-text');
        if (loadingText) {
            loadingText.textContent = message;
        }
    }

    function removeLoader() {
        // Find the overlay by its class name and remove it
        const overlay = document.querySelector('.loader-overlay');
        if (overlay) {
            document.body.removeChild(overlay);
        }
    }

    function downloadLinks(links) {
        const blob = new Blob([links.join('\n')], { type: 'text/plain' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'links.txt';
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
    }

    // Collect all links
    let collectedLinks = [];

    async function handleClick() {
        updateLoaderMessage('Starting extraction...');

        // Click on all elements with class "track-options"
        let trackOptions = document.querySelectorAll('.track-options');
        let index = 0;

        function processNext() {
            if (index >= trackOptions.length) {
                updateLoaderMessage('All links collected!');
                setTimeout(() => {
                    updateLoaderMessage('Downloading links...');
                    downloadLinks(collectedLinks);
                    updateLoaderMessage('Success! All links have been collected and downloaded.');
                    setTimeout(removeLoader, 3000); // Show success message for a few seconds before removing the loader
                }, 1000); // Adjust the delay for the success message as needed
                return;
            }

            let element = trackOptions[index++];
            element.click();

            // Wait for the modal to appear and then click the button
            setTimeout(async () => {
                let copyButton = document.querySelector('#__layout > div > div.font-weight-bold.modal-wrapper-mobile-only > div > ul > li:nth-child(4) > button');
                if (copyButton) {
                    copyButton.click();

                    // Assuming there's a delay before the link is copied
                    setTimeout(async () => {
                        // Use a way to obtain the copied link if possible or retrieve it from modal
                        let link = await readClipboard();
                        if (link) {
                            collectedLinks.push(link);
                            updateLoaderMessage(`Collected ${collectedLinks.length} links...`);
                        } else {
                            console.warn('No link was copied.');
                        }
                        processNext();
                    }, 10); // Adjust the delay as needed
                } else {
                    console.error('Copy button not found');
                    processNext();
                }
            }, 10); // Adjust the delay as needed
        }

        processNext();
    }

    if (window.location.host == "tidal.com") {
        createLoader();
    }

    if (window.location.host == "pixeldrain.com") {
        // ==UserScript==
        // @name         Pixel Drain Auto Audio Downloader
        // @namespace    http://tampermonkey.net/
        // @version      0.2
        // @description  Automatically download audio files from Pixel Drain
        // @author       Your Name
        // @match        https://pixeldrain.com/*
        // @grant        none
        // @run-at       document-end
        // ==/UserScript==

        (function() {
            'use strict';

            function autoDownloadAudio() {
                // Select all audio elements
                const audioElements = document.querySelectorAll('audio.player');

                audioElements.forEach(audio => {
                    // Find the source element
                    const source = audio.querySelector('source');
                    if (!source) return;

                    // Check if the file is already downloaded or not
                    if (source.dataset.downloaded) return;

                    // Mark the file as downloaded to avoid multiple downloads
                    source.dataset.downloaded = 'true';

                    // Construct the absolute URL
                    const audioUrl = source.src;
                    const absoluteUrl = new URL(audioUrl, window.location.origin).href;

                    // Create a temporary anchor element to trigger download
                    const a = document.createElement('a');
                    a.href = absoluteUrl;
                    a.download = ''; // Use the filename if needed, e.g., `source.src.split('/').pop()`
                    document.body.appendChild(a);
                    a.click();
                    document.body.removeChild(a);
                });
            }

            // Run the function when the page is loaded
            window.addEventListener('load', autoDownloadAudio);

            // Also check for dynamically loaded content
            const observer = new MutationObserver((mutations) => {
                mutations.forEach(() => {
                    autoDownloadAudio();
                });
            });

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

    }
})();